合并develop

dev_local_2
杨树林 5 years ago
commit 25f7e75a05

@ -13,6 +13,7 @@
//= require bootstrap-datepicker
//= require bootstrap.viewer
//= require jquery.mloading
//= require jquery-confirm.min
//= require common
//= require echarts

@ -0,0 +1,12 @@
$(document).on('turbolinks:load', function(){
$(document).on('click', '.batch-all-check-box', function(){
var $checkAll = $(this);
$('.batch-check-box').prop('checked', $checkAll.is(':checked'));
})
$(document).on('click', '.batch-check-box', function(){
var allChecked = $('.batch-check-box:checked').length === $('.batch-check-box').length
$('.batch-all-check-box').prop('checked', allChecked);
})
});

@ -10,11 +10,41 @@ $(document).on('turbolinks:load', function() {
$searchFrom.find('select[name="status"]').val('processed');
if($link.data('value') === 'processed'){
$('.batch-action-container').hide();
$searchFrom.find('.status-filter').show();
} else {
$('.batch-action-container').show();
$searchFrom.find('.status-filter').hide();
$searchFrom.find('select[name="status"]').val('pending');
}
});
$('.batch-agree-btn').on('click', function(){
if($('.batch-check-box:checked').length === 0){
$.notify({ message: '请先选择数据' }, { type: 'info' });
return;
}
customConfirm({
content: '确认审核通过?',
ok: function(){
var ids = $('.batch-check-box:checked').map(function(_, e){ return $(e).val() }).get();
$.ajax({
url: '/admins/identity_authentications/batch_agree',
method: 'POST',
dataType: 'json',
data: { ids: ids },
success: function(data){
$.notify({ message: '操作成功' });
window.location.reload();
},
error: function(res){
$.notify({ message: res.responseJSON.message }, { type: 'danger' });
}
})
}
})
})
}
})

@ -10,11 +10,41 @@ $(document).on('turbolinks:load', function() {
$searchFrom.find('select[name="status"]').val('processed');
if($link.data('value') === 'processed'){
$('.batch-action-container').hide();
$searchFrom.find('.status-filter').show();
} else {
$('.batch-action-container').show();
$searchFrom.find('.status-filter').hide();
$searchFrom.find('select[name="status"]').val('pending');
}
});
$('.batch-agree-btn').on('click', function(){
if($('.batch-check-box:checked').length === 0){
$.notify({ message: '请先选择数据' }, { type: 'info' });
return;
}
customConfirm({
content: '确认审核通过?',
ok: function(){
var ids = $('.batch-check-box:checked').map(function(_, e){ return $(e).val() }).get();
$.ajax({
url: '/admins/professional_authentications/batch_agree',
method: 'POST',
dataType: 'json',
data: { ids: ids },
success: function(data){
$.notify({ message: '操作成功' });
window.location.reload();
},
error: function(res){
$.notify({ message: res.responseJSON.message }, { type: 'danger' });
}
})
}
})
})
}
})

@ -22,9 +22,9 @@ $.fn.bootstrapViewer = function (options) {
' <div class="modal-dialog modal-lg" style="display: inline-block; width: auto;">\n' +
' <div class="modal-content">\n' +
' <img' +
'\t\t\t class="carousel-inner img-responsive img-rounded img-viewer" \n' +
'\t\t\t onclick="$(\'#bootstrapViewer\').modal(\'hide\');setTimeout(function(){$(\'#bootstrapViewer\').remove();},200);"\n' +
'\t\t\t onmouseover="this.style.cursor=\'zoom-out\';" \n' +
'\t\t\t class="carousel-inner img-responsive img-rounded img-viewer" draggable="false"\n' +
'\t\t\t onclick="/*$(\'#bootstrapViewer\').modal(\'hide\');setTimeout(function(){$(\'#bootstrapViewer\').remove();},200);*/"\n' +
'\t\t\t onmouseover="this.style.cursor=\'move\';" \n' +
'\t\t\t onmouseout="this.style.cursor=\'default\'" \n' +
'\t\t\t />\n' +
' </div>\n' +
@ -37,13 +37,41 @@ $.fn.bootstrapViewer = function (options) {
} else {
throw "图片不存在"
}
$('#bootstrapViewer').on('hidden.bs.modal', function(){
$('#bootstrapViewer').remove();
});
var $moveDiv = $('#bootstrapViewer .modal-dialog');
var isMove = false;
var div_x = $moveDiv.offset().left;
var div_y = $moveDiv.offset().top;
var mousedownFunc = function (e) {
if (isMove) {
var left = e.pageX - div_x;
var top = e.pageY - div_y;
if(left < 0){ left = 0}
if(top < 0){ top = 0}
$moveDiv.css({"left": left, "top":top});
}
}
$moveDiv.mousedown(function (e) {
$moveDiv.css({ left: $moveDiv[0].offsetLeft, top: $moveDiv[0].offsetTop, marginTop: 0, position: 'absolute' });
isMove = true;
div_x = e.pageX - $moveDiv.offset().left;
div_y = e.pageY - $moveDiv.offset().top;
$(document).mousemove(mousedownFunc);
}).mouseup(function () {
isMove = false;
$(document).unbind('mousemove', mousedownFunc);
});
})
$(this).on('mouseover', function () {
$(this).css('cursor', 'zoom-in');
})
}
$.fn.bootstrapViewer.defaults = {
src: 'src'

@ -43,3 +43,25 @@ function resetFileInputFunc(file){
file.after(file.clone().val(""));
file.remove();
}
function customConfirm(opts){
var okCallback = opts.ok;
var cancelCallback = opts.cancel;
var defaultOpts = {
title: '提示',
buttons: {
ok: {
text: '确认',
btnClass: 'btn btn-primary',
action: okCallback
},
cancel: {
text: '取消',
btnClass: 'btn btn-secondary',
action: cancelCallback
},
}
}
return $.confirm($.extend({}, defaultOpts, opts))
}

File diff suppressed because one or more lines are too long

@ -6,6 +6,7 @@
@import "bootstrap-datepicker";
@import "bootstrap-datepicker.standalone";
@import "jquery.mloading";
@import "jquery-confirm.min";
@import "codemirror/lib/codemirror";
@import "editormd/css/editormd.min";

@ -110,5 +110,11 @@
.CodeMirror {
border: 1px solid #ced4da;
}
.batch-action-container {
margin-bottom: -15px;
padding: 10px 20px 0;
background: #fff;
}
}

File diff suppressed because one or more lines are too long

@ -127,21 +127,21 @@ class AccountsController < ApplicationController
# UserDayCertification.create(user_id: user.id, status: 1)
end
def set_autologin_cookie(user)
token = Token.get_or_create_permanent_login_token(user, "autologin")
cookie_options = {
:value => token.value,
:expires => 1.month.from_now,
:path => '/',
:secure => false,
:httponly => true
}
if edu_setting('cookie_domain').present?
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
end
cookies[autologin_cookie_name] = cookie_options
logger.info("cookies is #{cookies}")
end
# def set_autologin_cookie(user)
# token = Token.get_or_create_permanent_login_token(user, "autologin")
# cookie_options = {
# :value => token.value,
# :expires => 1.month.from_now,
# :path => '/',
# :secure => false,
# :httponly => true
# }
# if edu_setting('cookie_domain').present?
# cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
# end
# cookies[autologin_cookie_name] = cookie_options
# logger.info("cookies is #{cookies}")
# end
def logout
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)

@ -1,6 +1,7 @@
class Admins::IdentityAuthenticationsController < Admins::BaseController
def index
params[:status] ||= 'pending'
params[:sort_direction] = params[:status] == 'pending' ? 'asc' : 'desc'
applies = Admins::ApplyUserAuthenticationQuery.call(params.merge(type: 1))
@ -18,6 +19,24 @@ class Admins::IdentityAuthenticationsController < Admins::BaseController
render_success_js
end
def batch_agree
ApplyUserAuthentication.real_name_auth.where(id: params[:ids]).each do |apply|
begin
Admins::IdentityAuths::AgreeApplyService.call(apply)
rescue => e
Util.logger_error(e)
end
end
render_ok
end
def revoke
Admins::IdentityAuths::RevokeApplyService.call(current_apply)
render_success_js
end
private
def current_apply

@ -1,6 +1,7 @@
class Admins::ProfessionalAuthenticationsController < Admins::BaseController
def index
params[:status] ||= 'pending'
params[:sort_direction] = params[:status] == 'pending' ? 'asc' : 'desc'
applies = Admins::ApplyUserAuthenticationQuery.call(params.merge(type: 2))
@ -18,6 +19,23 @@ class Admins::ProfessionalAuthenticationsController < Admins::BaseController
render_success_js
end
def batch_agree
ApplyUserAuthentication.professional_auth.where(id: params[:ids]).each do |apply|
begin
Admins::ProfessionalAuths::AgreeApplyService.call(apply)
rescue => e
Util.logger_error(e)
end
end
render_ok
end
def revoke
Admins::ProfessionalAuths::RevokeApplyService.call(current_apply)
render_success_js
end
private
def current_apply

@ -14,6 +14,7 @@ class ApplicationController < ActionController::Base
#before_action :check_account
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
OPENKEY = "79e33abd4b6588941ab7622aed1e67e8"
helper_method :current_user
@ -246,9 +247,23 @@ class ApplicationController < ActionController::Base
User.current = find_current_user
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
# if !User.current.logged? && Rails.env.development?
# User.current = User.find 1
# end
# 开放课程通过链接访问的用户
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
user = open_class_user
if user
start_user_session(user)
set_autologin_cookie(user)
end
User.current = user
end
end
if !User.current.logged? && Rails.env.development?
User.current = User.find 1
end
# 测试版前端需求
@ -604,4 +619,43 @@ class ApplicationController < ActionController::Base
def set_export_cookies
cookies[:fileDownload] = true
end
def set_autologin_cookie(user)
token = Token.get_or_create_permanent_login_token(user, "autologin")
cookie_options = {
:value => token.value,
:expires => 1.month.from_now,
:path => '/',
:secure => false,
:httponly => true
}
if edu_setting('cookie_domain').present?
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
end
cookies[autologin_cookie_name] = cookie_options
logger.info("cookies is #{cookies}")
end
# 149课程的评审用户数据创建包含创建课堂学生
def open_class_user
user = User.find_by(login: "OpenClassUser")
unless user
ActiveRecord::Base.transaction do
user_params = {status: 1, login: "OpenClassUser", lastname: "开放课程",
nickname: "开放课程", professional_certification: 1, certification: 1, grade: 0,
password: "12345678", phone: "11122223333", profile_completed: 1}
user = User.create!(user_params)
UserExtension.create!(user_id: user.id, gender: 0, school_id: 3396, :identity => 1, :student_id => "openclassuser") # 3396
subject = Subject.find_by(id: 149)
if subject
subject.courses.each do |course|
CourseMember.create!(course_id: course.id, role: 3, user_id: user.id) if !course.course_members.exists?(user_id: user.id)
end
end
end
end
user
end
end

@ -40,8 +40,8 @@ class CollegesController < ApplicationController
def teachers
@teachers = User.find_by_sql("SELECT users.id, users.login, users.lastname, users.firstname, users.nickname, IFNULL((SELECT count(shixuns.id) FROM shixuns where shixuns.user_id =users.id group by shixuns.user_id), 0) AS publish_shixun_count,
(SELECT count(c.id) FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.role in (1,2,3) and c.school_id = #{current_school.id} AND m.user_id=users.id AND c.is_delete = 0) as course_count
FROM `users`, user_extensions ue where users.id=ue.user_id and ue.identity=0 and ue.school_id=#{current_school.id} ORDER BY publish_shixun_count desc, course_count desc, id desc LIMIT 10")
(SELECT count(c.id) FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.user_id=users.id AND m.role in (1,2,3) and c.school_id = #{current_school.id} AND c.is_delete = 0) as course_count
FROM `users`, user_extensions ue where ue.school_id=#{current_school.id} and users.id=ue.user_id and ue.identity=0 ORDER BY publish_shixun_count desc, course_count desc, id desc LIMIT 10")
# ).order("publish_shixun_count desc, experience desc").limit(10)
@teachers =
@teachers.map do |teacher|

@ -51,7 +51,8 @@ class CommonsController < ApplicationController
200
end
when 'journals_for_message'
if current_user.course_identity(@object.jour.course) >= Course::STUDENT && @object.user != current_user
course = @object&.jour_type.to_s == "StudentWorksScore" ? @object.jour&.student_work&.homework_common&.course : @object.jour&.course
if current_user.course_identity(course) >= Course::STUDENT && @object.user != current_user
403
else
200

@ -3,6 +3,10 @@ module PaginateHelper
page = params[:page].to_i <= 0 ? 1 : params[:page].to_i
per_page = params[:per_page].to_i > 0 && params[:per_page].to_i < 50 ? params[:per_page].to_i : opts[:per_page] || 20
if objs.is_a?(Array)
Kaminari.paginate_array(objs).page(page).per(per_page)
else
objs.page(page).per(per_page)
end
end
end

@ -128,8 +128,8 @@ class CoursesController < ApplicationController
# POST /courses
# POST /courses.json
def create
ActiveRecord::Base.transaction do
begin
ActiveRecord::Base.transaction do
@course = Course.new(name: params[:name], class_period: params[:class_period], credit: params[:credit],
end_date: params[:end_date], is_public: params[:is_public], school_id: @school.id,
authentication: params[:authentication], professional_certification: params[:professional_certification])
@ -174,13 +174,14 @@ class CoursesController < ApplicationController
course_module_types = params[:course_module_types]
@course.create_course_modules(course_module_types)
end
end
CreateSubjectCourseStudentJob.perform_later(@course.id) if @course.subject && @course.subject.subject_appointments.count > 0
rescue => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
# PATCH/PUT /courses/1
# PATCH/PUT /courses/1.json

@ -47,6 +47,10 @@ class Ecs::BaseController < ApplicationController
page = params[:page].to_i <= 0 ? 1 : params[:page].to_i
per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 20
if objs.is_a?(Array)
Kaminari.paginate_array(objs).page(page).per(per_page)
else
objs.page(page).per(per_page)
end
end
end

@ -15,19 +15,31 @@ class Ecs::EcGraduationRequirementsController < Ecs::BaseController
end
def create
graduation_requirement = current_year.graduation_requirements.new
graduation_requirement = current_year.ec_graduation_requirements.new
@graduation_requirement = Ecs::SaveGraduationRequirementeService.call(graduation_requirement, create_params)
render 'show'
end
def update
graduation_requirement = current_year.graduation_requirements.find(params[:id])
@graduation_requirement = Ecs::SaveGraduationRequirementeService.call(graduation_requirement, update_params)
@graduation_requirement = Ecs::SaveGraduationRequirementeService.call(current_graduation_requirement, update_params)
render 'show'
end
def destroy
ActiveRecord::Base.transaction do
current_graduation_requirement.destroy!
current_year.ec_graduation_requirements.where('position > ?', current_graduation_requirement.position)
.update_all('position = position - 1')
end
render_ok
end
private
def current_graduation_requirement
@_current_graduation_requirement ||= current_year.ec_graduation_requirements.find(params[:id])
end
def create_params
params.permit(:position, :content, graduation_subitems: [:content])
end

@ -1,4 +1,6 @@
class Ecs::EcMajorSchoolsController < Ecs::BaseController
skip_before_action :check_user_permission!, only: [:show]
def index
major_schools = current_school.ec_major_schools.not_template
@ -20,7 +22,18 @@ class Ecs::EcMajorSchoolsController < Ecs::BaseController
@count = major_schools.count #检索后的数量,小于或等于全部数量
@major_schools = paginate(major_schools.includes(:users, :ec_major))
@template_major_school = current_school.ec_major_schools.is_template.first #示例专业
@template_major_school = EcMajorSchool.is_template.first #示例专业
end
# :show是 /api/ec_major_schools/:id
def show
@major = EcMajorSchool.find(params[:id])
school = @major.school
return if current_user.admin? || school.manager?(current_user)
return if @major.manager?(current_user)
render_forbidden
end
def create

@ -1,7 +1,7 @@
class Ecs::EcMajorsController < Ecs::BaseController
def index
school_major_subquery = current_school.ec_major_schools.select(:ec_major_id) #学校已选择的专业
ec_majors = EcMajor.where.not(id: school_major_subquery)
@major_ids = current_school.ec_major_schools.pluck(:ec_major_id) #学校已选择的专业
ec_majors = EcMajor.all
if params[:search].present?
ec_majors = ec_majors.search_name_or_code(params[:search])

@ -2,7 +2,7 @@ class Ecs::EcTrainingObjectivesController < Ecs::BaseController
before_action :check_major_manager_permission!, only: [:create]
def show
@training_objective = current_year.ec_training_objective
@training_objective = current_year.ec_training_objective || current_year.build_ec_training_objective
respond_to do |format|
format.json

@ -10,7 +10,7 @@ class Ecs::EcYearsController < Ecs::BaseController
end
@count = ec_years.count
@ec_years = paginate ec_years
@ec_years = paginate ec_years.order(year: :desc)
return if @ec_years.blank?
@ -27,13 +27,17 @@ class Ecs::EcYearsController < Ecs::BaseController
.where(ec_graduation_requirements: { ec_year_id: year_ids }).group('ec_year_id').count
end
def show
@year = current_year
end
def create
if current_major_school.ec_years.exists?(year: params[:year].to_i)
render_error('届别已存在')
return
end
@ec_year = CopyEcYearService.call(current_major_school, params[:year].to_i)
@ec_year = Ecs::CopyEcYearService.call(current_major_school, params[:year].to_i)
end
def destroy

@ -3,6 +3,7 @@ class Ecs::GraduationCourseSupportsController < Ecs::BaseController
def show
@graduation_subitems = current_year.ec_graduation_subitems
.reorder('ec_graduation_requirements.position ASC, ec_graduation_subitems.position ASC')
.includes(:ec_graduation_requirement, ec_course_supports: :ec_course)
@course_count = current_year.ec_courses.count

@ -0,0 +1,6 @@
class Ecs::GraduationSubitemsController < Ecs::BaseController
def index
subitems = current_year.ec_graduation_subitems.reorder('ec_graduation_requirements.position ASC, ec_graduation_subitems.position ASC')
@graduation_subitems = subitems.includes(:ec_graduation_requirement)
end
end

@ -3,7 +3,8 @@ class Ecs::MajorManagersController < Ecs::BaseController
before_action :check_manager_permission!
def create
@user = Ecs::CreateMajorManagerService.call(current_major_school, params[:user_id])
Ecs::CreateMajorManagerService.call(current_major_school, params[:user_ids])
render_ok
rescue Ecs::CreateMajorManagerService::Error => ex
render_error(ex.message)
end

@ -1,4 +1,4 @@
class ReachCriteriaController < Ecs::BaseController
class Ecs::ReachCriteriaController < Ecs::BaseController
before_action :check_major_manager_permission!, only: [:create]
def create

@ -1,7 +1,7 @@
class Ecs::ReachEvaluationsController < Ecs::BaseController
def show
preload = { ec_graduation_subitems: { ec_course_support: [:ec_course, :ec_graduation_requirement_calculation] } }
preload = { ec_graduation_subitems: { ec_course_supports: [:ec_course, :ec_graduation_requirement_calculation] } }
@graduation_requirements = current_year.ec_graduation_requirements.includes(preload)
respond_to do |format|
@ -14,5 +14,13 @@ class Ecs::ReachEvaluationsController < Ecs::BaseController
end
def create
relations = current_year.ec_graduation_requirements.joins(ec_graduation_subitems: :ec_course_support)
ec_course_ids = relations.pluck('ec_course_supports.ec_course_id').uniq
EcCourse.where(id: ec_course_ids).each do |ec_course|
Ecs::CalculateCourseEvaluationService.call(ec_course)
end
render_ok
end
end

@ -14,7 +14,7 @@ class Ecs::StudentsController < Ecs::BaseController
end
def import
success_count = Ecs::ImportStudentService.call(current_year, params[:attachment_id])
success_count = Ecs::ImportStudentService.call(current_year, params)
render_ok(success_count: success_count)
rescue Ecs::ImportStudentService::Error => ex
render_error(ex.message)

@ -0,0 +1,22 @@
class Ecs::UsersController < Ecs::BaseController
skip_before_action :check_user_permission!
before_action :check_manager_permission!
def index
users = UserQuery.call(params)
@count = users.count
@users = paginate users.includes(user_extension: [:school, :department])
@manager_ids = current_major_school.ec_major_school_users.pluck(:user_id)
end
private
def current_major_school
@_ec_major_school ||= EcMajorSchool.find(params[:ec_major_school_id])
end
def current_school
@_current_school ||= current_major_school.school
end
end

@ -476,10 +476,13 @@ class GamesController < ApplicationController
if @myshixun.shixun.try(:status) < 2
tip_exception("代码获取异常,请检查实训模板的评测设置是否正确")
else
# 报错继续retry
tip_exception(-3, "#{e.message}")
end
end
# 如果报错了并且retry 为1的时候则fork一个新的仓库
if params[:retry].to_i == 1
project_fork(@myshixun, @shixun.repo_path, current_user.login)
end
tip_exception(0, e.message)
end
end
@ -559,7 +562,7 @@ class GamesController < ApplicationController
secret_rep = @shixun.shixun_secret_repository
logger.info("############secret_rep: #{secret_rep}")
if secret_rep&.repo_name
secretGitUrl = repo_url secret_rep.repo_path
secretGitUrl = repo_ip_url secret_rep.repo_path
br_params.merge!({secretGitUrl: Base64.urlsafe_encode64(secretGitUrl), secretDir: secret_rep.secret_dir_path})
logger.info("#######br_params:#{br_params}")
end

@ -19,6 +19,10 @@ class GitsController < ApplicationController
result = false
if request.env["HTTP_AUTHORIZATION"] && request.env["HTTP_AUTHORIZATION"].split(" ").length == 2
username_password = Base64.decode64(request.env["HTTP_AUTHORIZATION"].split(" ")[1])
if username_password.split(":")[0].nil? || username_password.split(":")[1].nil?
result = false
else
input_username = username_password.split(":")[0].strip()
input_password = username_password.split(":")[1].strip()
uid_logger("git start auth: input_username is #{input_username}")
@ -60,6 +64,7 @@ class GitsController < ApplicationController
end
end
end
end
authenticate_or_request_with_http_basic do |username, password|
result

@ -168,7 +168,7 @@ class GraduationTasksController < ApplicationController
end
end
else
@work_list = @work
@work_list = !@task.published? ? [] : @work
@view_work = false
@work_count = @work_list.count
@all_work_count = @work_list.count

@ -0,0 +1,6 @@
class LibraryTagsController < ApplicationController
def index
library_tags = LibraryTag.all
render_ok(library_tags: library_tags.as_json(only: %i[id name]), count: library_tags.size)
end
end

@ -692,7 +692,7 @@ class PollsController < ApplicationController
else
unified_setting = @poll.unified_setting
end
show_result = params[:show_result] ? 1 : 0
show_result = params[:show_result].to_i
un_anonymous = params[:un_anonymous] ? true : false
# 统一设置或者分班为0则更新问卷并删除问卷分组
if unified_setting || (course_group_ids.size == 0)

@ -321,11 +321,12 @@ class StudentWorksController < ApplicationController
ActiveRecord::Base.transaction do
begin
revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last
if revise_attachment.present? && @work.student_works_scores.where("created_at > '#{revise_attachment.created_on}'
and score is not null").count == 0
revise_attachment.destroy
end
# 补交作业附件不覆盖之前上传的附件
# revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last
# if revise_attachment.present? && @work.student_works_scores.where("created_at > '#{revise_attachment.created_on}'
# and score is not null").count == 0
# revise_attachment.destroy
# end
Attachment.associate_container(params[:attachment_ids], @work.id, @work.class, 7)
revise_attachment = Attachment.where(attachtype: 7, container_id: @work.id, container_type: "StudentWork").last
revise_attachment.update_attributes(description: params[:description]) if revise_attachment.present?

@ -368,7 +368,7 @@ class SubjectsController < ApplicationController
@schools.map do |s|
school_courses = Course.where(id: course_ids, school_id: s.id)
course_count = school_courses.count
student_count = StudentsForCourse.where(course_id: school_courses.pluck(:id)).count
student_count = CourseMember.where(course_id: school_courses.pluck(:id), role: 4).count
homework_count = HomeworkCommon.find_by_sql("select count(*) cnt from homework_commons hc join courses c on hc.course_id = c.id
where c.school_id = #{s.id} and hc.id in(#{homework_common_id})").first.try(:cnt)
s.attributes.dup.merge({name: s.name, course_count: course_count, student_count: student_count,homework_count: homework_count})
@ -415,6 +415,20 @@ class SubjectsController < ApplicationController
order by ue_count desc limit 10")
end
# 预约报名
def appointment
tip_exception("还存在未结束的课堂") unless @subject.max_course_end_date.nil? || @subject.max_course_end_date < Date.today
tip_exception("无需重复报名") if @subject.subject_appointments.exists?(user_id: current_user.id)
ActiveRecord::Base.transaction do
@subject.subject_appointments << SubjectAppointment.new(user_id: current_user.id)
@subject.increment!(:participant_count)
if @subject.participant_count == @subject.student_count
@subject.start_course_notify
end
normal_status("预约成功")
end
end
private
def subject_params
tip_exception("实训路径名称不能为空") if params[:name].blank?

@ -55,7 +55,13 @@ class Users::BaseController < ApplicationController
page = page_value
per_page = per_page_value
return Kaminari.paginate_array(objs).page(page).per(per_page) unless opts[:special] && observed_logged_user?
unless opts[:special] && observed_logged_user?
if objs.is_a?(Array)
return Kaminari.paginate_array(objs).page(page).per(per_page)
else
return objs.page(page).per(per_page)
end
end
# note: 为实现第一页少一条记录,让前端放置新建入口
if page == 1

@ -384,4 +384,8 @@ module TidingDecorator
def public_course_start_content
I18n.t(locale_format) % [belong_container&.name, belong_container&.start_date&.strftime("%Y-%m-%d")]
end
def subject_start_course_content
I18n.t(locale_format) % belong_container&.name
end
end

@ -126,10 +126,11 @@ module ApplicationHelper
# 用户图像url如果不存在的话source为匿名用户即默认使用匿名用户图像
def url_to_avatar(source)
if File.exist?(disk_filename(source.class, source.id))
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
if source.class.to_s == 'User'
File.join(relative_path, ["#{source.class}", "#{source.id}"])
File.join(relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
else
File.join("images/avatars", ["#{source.class}", "#{source.id}"])
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
end
elsif source.class.to_s == 'User'
str = source.user_extension.try(:gender).to_i == 0 ? "b" : "g"

@ -0,0 +1,22 @@
module Ecs::EcYearsHelper
def achieved_graduation_course_count(ec_year)
return 0 if ec_year.ec_courses.count.zero?
course_ids = ec_year.ec_courses.map(&:id)
target_count_map = EcCourseTarget.where(ec_course_id: course_ids).group(:ec_course_id).count
ec_year.ec_courses.sum { |course| course.complete_target_count == target_count_map[course.id] ? 1 : 0 }
end
def achieved_graduation_objective_count(ec_year)
return 0 if ec_year.ec_graduation_subitems.count.zero?
subitem_ids = ec_year.ec_graduation_subitems.reorder(nil).pluck(:id)
relations = EcGraduationRequirementCalculation.joins(:ec_course_support).where(ec_course_supports: { ec_graduation_subitem_id: subitem_ids })
reached_map = relations.where(status: true).group('ec_graduation_subitem_id').count
reached_map.keys.size
end
end

@ -8,7 +8,7 @@ class ApplyTeacherRoleJoinCourseNotifyJob < ApplicationJob
return if user.blank? || course.blank?
attrs = %i[user_id trigger_user_id container_id container_type belong_container_id
belong_container_type tiding_type extra created_at updated_at]
belong_container_type tiding_type status extra created_at updated_at]
same_attrs = {
trigger_user_id: user.id, container_id: course.id, container_type: 'JoinCourse', status: 0,

@ -0,0 +1,22 @@
class CreateSubjectCourseStudentJob < ApplicationJob
queue_as :default
def perform(course_id)
course = Course.find_by(id: course_id)
return if course.blank? || course.subject.blank?
attrs = %i[course_id user_id role created_at updated_at]
same_attrs = {course_id: course.id, role: 4}
Rails.logger.info("1:course.students.count:##{course.students.count}")
CourseMember.bulk_insert(*attrs) do |worker|
course.subject.subject_appointments.each do |app|
Rails.logger.info("##{course.students.where(user_id: app.user_id)}")
next if course.students.where(user_id: app.user_id).any?
worker.add same_attrs.merge(user_id: app.user_id)
end
end
Rails.logger.info("2:course.students.count:##{course.students.count}")
course.subject.subject_appointments.destroy_all
end
end

@ -45,6 +45,8 @@ module Util
def conceal(str, type = nil)
str = str.to_s
return if str.blank?
case type
when :phone then "#{str[0..2]}***#{str[-4..-1]}"
when :email then "#{str[0..2]}***#{str[str.rindex('@')..-1]}"

@ -18,6 +18,10 @@ class ApplyUserAuthentication < ApplicationRecord
nil
end
def revoke!
update!(status: 3)
end
private
def send_tiding

@ -32,6 +32,6 @@ class CourseMessage < ApplicationRecord
belong_container: course, extra: content.to_i == 2 ? '9' : '7', tiding_type: 'System', status: deal_status
)
# 将申请消息置为已处理
Tiding.where(trigger_user_id: user_id, container_id: course_id, container_type: 'JoinCourse', status: 0).update_all(status: 1)
Tiding.where(trigger_user_id: course_message_id, container_id: course_id, container_type: 'JoinCourse', status: 0).update_all(status: 1)
end
end

@ -1,7 +1,6 @@
class EcCourseStudentScore < ApplicationRecord
belongs_to :ec_year_student
belongs_to :ec_course
belongs_to :ec_course_target
has_many :ec_student_score_targets, dependent: :delete_all
end

@ -1,9 +1,10 @@
class EcCourseSupport < ApplicationRecord
default_scope { order(position: :asc) }
alias_attribute :weights, :weigths
belongs_to :ec_course
belongs_to :ec_graduation_subitem
# TODO: 将 ec_graduation_subitem_courses 移除,这个表作为关系表
has_one :ec_graduation_requirement_calculation, dependent: :destroy

@ -1,4 +1,3 @@
# TODO:: change table column :weigths => :weight
class EcCourseTarget < ApplicationRecord
belongs_to :ec_course
@ -8,6 +7,8 @@ class EcCourseTarget < ApplicationRecord
has_many :ec_course_achievement_methods, dependent: :destroy
has_many :ec_achievement_evaluation_relates, dependent: :destroy
alias_attribute :weight, :weigths
validates :content, presence: true
validates :standard_grade, numericality: { only_integer: true, greater_than: 0 }
validates :weight, presence: true, numericality: { less_than_or_equal_to: 1, greater_than_or_equal_to: 0 }

@ -1,4 +1,6 @@
class EcGraduationRequirement < ApplicationRecord
default_scope { order(position: :asc) }
belongs_to :ec_year
has_many :ec_graduation_subitems, dependent: :destroy
@ -7,5 +9,5 @@ class EcGraduationRequirement < ApplicationRecord
validates :position, presence: true, numericality: { only_integer: true, greater_than: 0 }
validates :content, presence: true
default_scope { order(position: :asc) }
accepts_nested_attributes_for :ec_graduation_subitems, allow_destroy: true
end

@ -12,6 +12,8 @@ class EcMajorSchool < ApplicationRecord
scope :is_template, -> { where(template_major: true) }
scope :not_template, -> { where(template_major: false) }
delegate :code, :name, to: :ec_major
# 是否为该专业管理员
def manager?(user)
ec_major_school_users.exists?(user_id: user.id)

@ -1,4 +1,6 @@
class EcTrainingSubitem < ApplicationRecord
default_scope { order(position: :asc) }
belongs_to :ec_training_objective
has_many :ec_requirement_vs_objectives, foreign_key: :ec_training_objective_id, dependent: :destroy

@ -9,4 +9,11 @@ class EcYear < ApplicationRecord
has_many :ec_graduation_requirements, dependent: :destroy
has_many :ec_graduation_subitems, through: :ec_graduation_requirements
has_many :ec_year_students, dependent: :destroy
has_many :ec_course_users, dependent: :destroy
has_many :managers, through: :ec_course_users, source: :user
def prev_year
self.class.find_by(year: year.to_i - 1)
end
end

@ -48,7 +48,7 @@ class GraduationWork < ApplicationRecord
def delete_atta atta
last_score = graduation_work_scores.where.not(score: nil).last
atta.author_id == user_id && (!last_score.present? || last_score.try(:created_at) < atta.created_on)
(atta.author_id == User.current.id) && (last_score.blank? || last_score.try(:created_at) < atta.created_on)
end
# 分班名

@ -134,6 +134,11 @@ class HomeworkCommon < ApplicationRecord
self.homework_type == 'practice' && self.publish_time.present? && self.publish_time < Time.now && self.homework_group_reviews.count == 0
end
# 作业查看最新成绩
def update_score identity
identity < Course::NORMAL && publish_time.present? && publish_time < Time.now && !course.is_end
end
# 作业能否立即发布
def publish_immediately user
homework_detail_manual.try(:comment_status) == 0 || homework_group_settings.where(course_group_id: course.charge_group_ids(user)).

@ -104,7 +104,7 @@ class Poll < ApplicationRecord
status = 4
else
if user.present? && user.student_of_course?(course)
ex_time = get_poll_times(user_id,false)
ex_time = get_poll_times(user.id,false)
pb_time = ex_time[:publish_time]
ed_time = ex_time[:end_time]
if pb_time.present? && ed_time.present? && pb_time <= Time.now && ed_time > Time.now

@ -21,7 +21,7 @@ class StudentGraduationTopic < ApplicationRecord
def send_tiding
self.tidings << Tiding.new(:user_id => self.graduation_topic.tea_id, :trigger_user_id => self.user_id, :parent_container_id => self.graduation_topic_id, :parent_container_type => "GraduationTopic",
:belong_container_id => self.graduation_topic.course_id, :belong_container_type => "Course", :viewed => 0, :status => 0, :tiding_type => "GraduationTopic")
:belong_container_id => self.graduation_topic.course_id, :belong_container_type => "Course", :viewed => 0, :status => 0, :tiding_type => "Apply")
end
# 学生名称

@ -106,7 +106,7 @@ class StudentWork < ApplicationRecord
def delete_atta atta
last_score = student_works_scores.where.not(score: nil).last
atta.author_id == user_id && (!last_score.present? || last_score.try(:created_at) < atta.created_on)
(atta.author_id == User.current.id) && (last_score.blank? || last_score.try(:created_at) < atta.created_on)
end
# 作品总体评价

@ -1,6 +1,6 @@
class StudentWorksScore < ApplicationRecord
#appeal_status: 0正常1申诉中2撤销申诉3申诉成功4申诉被拒绝5申诉失效
belongs_to :student_work
belongs_to :student_work
belongs_to :user
has_many :journals_for_messages, -> { order('created_on desc') }, as: :jour, dependent: :destroy
has_one :student_works_scores_appeal, dependent: :destroy

@ -13,6 +13,8 @@ class Subject < ApplicationRecord
has_many :stage_shixuns, dependent: :destroy
has_many :shixuns, through: :stage_shixuns
has_many :subject_appointments, dependent: :destroy
has_many :subject_members, ->{ order("subject_members.position asc")}, dependent: :destroy
has_many :users, through: :subject_members
has_many :tidings, as: :container, dependent: :destroy
@ -44,6 +46,10 @@ class Subject < ApplicationRecord
courses.where("start_date <= '#{Date.today}' and end_date >= '#{Date.today}'").count > 0
end
def has_participate?
subject_appointments.exists?(user_id: User.current.id)
end
# 挑战过路径的成员数(金课统计去重后的报名人数)
def member_count
excellent ? CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).length : shixuns.pluck(:myshixuns_count).sum
@ -109,4 +115,10 @@ class Subject < ApplicationRecord
def learning? user_id
Myshixun.where(user_id: user_id, shixun_id: shixuns).exists?
end
def start_course_notify
Tiding.create(user_id: user_id, trigger_user_id: 0, container_id: id,
container_type: 'SubjectStartCourse', belong_container_id: id,
belong_container_type: 'Subject', tiding_type: 'System')
end
end

@ -0,0 +1,4 @@
class SubjectAppointment < ApplicationRecord
belongs_to :subject
belongs_to :user
end

@ -36,7 +36,7 @@ class User < ApplicationRecord
has_many :myshixuns, :dependent => :destroy
has_many :study_shixuns, through: :myshixuns, source: :shixun # 已学习的实训
has_many :course_messages
has_many :courses, foreign_key: :tea_id, dependent: :destroy
has_many :courses, dependent: :destroy
#试卷
has_many :exercise_banks, :dependent => :destroy
@ -108,8 +108,8 @@ class User < ApplicationRecord
has_many :manage_courses, through: :manage_course_members, source: :course
# 关注
#has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注
#has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户
has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注
has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户
# 认证
has_many :apply_user_authentication
@ -346,7 +346,7 @@ class User < ApplicationRecord
elsif business?
Course::BUSINESS
else
role = course.course_members.find_by(user_id: id, is_active: 1)&.role
role = course&.course_members&.find_by(user_id: id, is_active: 1)&.role
case role
when nil then Course::NORMAL
when 'CREATOR' then Course::CREATOR

@ -0,0 +1,28 @@
class UserQuery < ApplicationQuery
attr_reader :params
def initialize(params)
@params = params
end
def call
users = User.where(type: 'User')
# 真实姓名
if name = strip_param(:name)
users = users.where('LOWER(CONCAT(users.lastname, users.firstname)) LIKE ?', "%#{name.downcase}%")
end
# 单位名称
if school = strip_param(:school)
users = users.joins(user_extension: :school).where('schools.name LIKE ?', "%#{school}%")
end
# 职业
if (identity = strip_param(:identity)) && UserExtension.identities.keys.include?(identity)
users = users.joins(:user_extension).where(user_extensions: { identity: identity })
end
users
end
end

@ -0,0 +1,26 @@
class Admins::IdentityAuths::RevokeApplyService < ApplicationService
attr_reader :apply, :user
def initialize(apply)
@apply = apply
@user = apply.user
end
def call
ActiveRecord::Base.transaction do
apply.revoke!
user.update!(authentication: false)
deal_tiding!
end
end
private
def deal_tiding!
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'CancelUserAuthentication',
belong_container_id: apply.user_id, belong_container_type: 'User',
status: 1, tiding_type: 'System')
end
end

@ -0,0 +1,26 @@
class Admins::ProfessionalAuths::RevokeApplyService < ApplicationService
attr_reader :apply, :user
def initialize(apply)
@apply = apply
@user = apply.user
end
def call
ActiveRecord::Base.transaction do
apply.revoke!
user.update!(professional_certification: false)
deal_tiding!
end
end
private
def deal_tiding!
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'CancelUserProCertification',
belong_container_id: apply.user_id, belong_container_type: 'User',
status: 1, tiding_type: 'System')
end
end

@ -1,4 +1,4 @@
class CopyEcYearService < ApplicationService
class Ecs::CopyEcYearService < ApplicationService
attr_reader :major_school, :to_year
def initialize(major_school, year)

@ -27,7 +27,7 @@ class Ecs::CreateCourseService < ApplicationService
private
def create_default_score_levels!(ec_course)
EcScoreLevel.bulk_insert(:ec_course_id, :score, :level, :position) do |worker|
EcScoreLevel.bulk_insert(:ec_course_id, :score, :level, :position, :created_at, :updated_at) do |worker|
[
{ ec_course_id: ec_course.id, score: 90, level: '优秀', position: 1 },
{ ec_course_id: ec_course.id, score: 80, level: '良好', position: 2 },

@ -3,29 +3,30 @@ class Ecs::CreateMajorManagerService < ApplicationService
MAJOR_MANAGER_COUNT_LIMIT = 5 # 专业管理员数量限制
attr_reader :major_school, :user_id
attr_reader :major_school, :user_ids
def initialize(major_school, user_id)
def initialize(major_school, user_ids)
@major_school = major_school
@user_id = user_id
@user_ids = user_ids
end
def call
raise Error, '示例专业不能添加管理员' if major_school.template_major?
user = User.find_by(id: params[:user_id])
raise Error, '该用户不存在' if user.blank?
@user_ids = User.where(id: user_ids).pluck(:id)
if major_school.ec_major_school_users.exists?(user_id: user.id)
raise Error, '该用户已经是该专业的管理员了'
if major_school.ec_major_school_users.exists?(user_id: user_ids)
raise Error, '所选用户中存在该专业的管理员'
end
if major_school.ec_major_school_users.count >= MAJOR_MANAGER_COUNT_LIMIT
raise Error, '该专业管理员数量已达上限'
if major_school.ec_major_school_users.count + user_ids.count > MAJOR_MANAGER_COUNT_LIMIT
raise Error, "该专业管理员数量超过上限(#{MAJOR_MANAGER_COUNT_LIMIT}人)"
end
major_school.ec_major_school_users.create!(user: user)
user
ActiveRecord::Base.transaction do
user_ids.each do |user_id|
major_school.ec_major_school_users.create!(user_id: user_id)
end
end
end
end

@ -11,13 +11,16 @@ class Ecs::CreateTrainingObjectiveService < ApplicationService
def call
training_objective.content = params[:content].to_s.strip
if params.key?(:training_subitems)
attributes = build_accepts_nested_attributes(
training_objective,
training_objective.ec_training_subitems,
params[:training_subitems],
&method(:training_subitem_param_handler)
)
attributes.each_with_index { |attr, index| attr[:position] = index + 1 }
training_objective.assign_attributes(ec_training_subitems_attributes: attributes)
end
training_objective.save!
training_objective

@ -1,21 +1,20 @@
class Ecs::ImportStudentService < ApplicationService
Error = Class.new(StandardError)
attr_reader :ec_year, :attachment
attr_reader :ec_year, :params
def initialize(ec_year, attachment_id)
def initialize(ec_year, params)
@ec_year = ec_year
@attachment = Attachment.find_by(id: attachment_id)
@params = params
end
def call
raise Error, '文件不存在' if attachment.blank?
raise Error, '文件不存在' if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
path = attachment.diskfile
excel = Ecs::ImportStudentExcel.new(path)
excel = Ecs::ImportStudentExcel.new(params[:file].path)
success_count = 0
EcYearStudent.bulk_insert(:student_id, :name, :created_at, :updated_at) do |worker|
EcYearStudent.bulk_insert(:ec_year_id, :student_id, :name, :created_at, :updated_at) do |worker|
excel.read_each do |student_id, name|
success_count += 1
@ -25,7 +24,7 @@ class Ecs::ImportStudentService < ApplicationService
next
end
worker.add(student_id: student_id, name: name)
worker.add(ec_year_id: ec_year.id, student_id: student_id, name: name)
end
end

@ -17,12 +17,12 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
end
def graduation_subitem_evaluations
student_scores = ec_course.ec_course_student_scores.joins(:ec_course_target).group(:ec_course_target_id)
student_scores = ec_course.ec_course_student_scores.joins(ec_student_score_targets: :ec_course_target).group(:ec_course_target_id)
student_scores = student_scores.select('AVG(score) as average_score, ec_course_target_id')
student_score_map = student_scores.group_by { |item| item.ec_course_target_id }
subitem_targets = ec_course.ec_graduation_subitem_course_targets
.includes(ec_graduation_subitem: :ec_graduation_requirement)
.includes(:ec_course_target, ec_graduation_subitem: :ec_graduation_requirement)
subitem_targets.group_by(&:ec_graduation_subitem_id).map do |_id, arr|
subitem = arr.first.ec_graduation_subitem
@ -37,7 +37,7 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
arr.map(&:ec_course_target).uniq.each do |target|
target_total_rates += target.weight.to_f
student_score = student_score_map[target.id]
student_score = student_score_map[target.id]&.first
reach_real_target += student_score.average_score.to_f * target.weight.to_f if student_score
end
@ -60,8 +60,19 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
def score_levels_map
@_score_levels_map ||= begin
index = 0
ec_course.ec_score_levels.each_with_object({}) do |level, obj|
obj[level.id.to_s] = level.as_json(only: %i[id position score level])
hash = level.as_json(only: %i[id position score level])
hash[:description] =
case index
when 0 then "#{level.score}分以上"
when ec_course.ec_score_levels.to_a.size - 1 then "低于#{level.score}"
else "#{level.score}~#{ec_course.ec_score_levels[index - 1].score - 1}"
end
index += 1
obj[level.id.to_s] = hash
end
end
end
@ -87,23 +98,29 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
@_course_achievement += data[:average_score].to_f * course_target.weight.to_f
# 计算学生成绩分布区间
student_count = 0
data[:score_levels] = score_levels.map do |score_level|
level_condition_proc =
if (score_level.position - 1).zero? # 第一区间
-> (score_target){ score_target.score >= score_level.score ? 1 : 0 }
elsif score_levels.position == score_levels.size # 末尾区间
elsif score_level.position == score_levels.size # 末尾区间
-> (score_target){ score_target.score < score_level.score ? 1 : 0 }
else
# 中间区间
-> (score_target){ score_target.score >= score_level.score && score_target.score < score_targets[score_level.position - 1] ? 1 : 0 }
-> (score_target){ score_target.score >= score_level.score && score_target.score < score_levels[score_level.position - 1].score ? 1 : 0 }
end
# 计算该成绩区间人数
count = score_targets.sum(&level_condition_proc)
student_count += count
{ id: score_level.id, count: count }
end
data[:score_levels].each do |score_level|
score_level[:rate] = score_level[:count].fdiv(student_count).round(2)
end
data
end
end

@ -9,6 +9,8 @@ class Ecs::SaveGraduationCourseSupportsService < ApplicationService
end
def call
set_course_supports_position!
Ecs::SaveGraduationCourseSupportForm.new(params).validate!
accepts_attributes = build_accepts_nested_attributes(
@ -20,4 +22,10 @@ class Ecs::SaveGraduationCourseSupportsService < ApplicationService
graduation_subitem.save!
graduation_subitem
end
def set_course_supports_position!
params[:course_supports].each_with_index do |item, index|
item[:position] = index + 1
end
end
end

@ -40,8 +40,8 @@ class Users::ApplyProfessionalAuthService < ApplicationService
# sms_cache = Rails.cache.read("apply_pro_certification")
# if sms_cache.nil?
# sms_notify_admin
Rails.cache.write("apply_pro_certification", 1)
sms_notify_admin
# Rails.cache.write("apply_pro_certification", 1)
# end
end
end

@ -27,8 +27,8 @@ class StatisticSchoolDailyReportTask
# 新增实训评测数量
shixun_evaluate_count = EvaluateRecord.joins('LEFT JOIN homework_commons_shixuns hcs ON hcs.shixun_id = evaluate_records.shixun_id')
.joins('LEFT JOIN homework_commons hc ON hcs.homework_common_id = hc.id AND hc.homework_type = 4')
.joins('LEFT JOIN members ON members.user_id = evaluate_records.user_id')
.joins('LEFT JOIN courses ON members.course_id = courses.id AND hc.course_id = courses.id')
.joins('LEFT JOIN course_members ON course_members.user_id = evaluate_records.user_id')
.joins('LEFT JOIN courses ON course_members.course_id = courses.id AND hc.course_id = courses.id')
.where(courses: { school_id: school.id })
.where(created_at: yesterday).reorder(nil).count

@ -2,10 +2,10 @@ class StatisticSchoolReportTask
def call
School.find_each do |school|
evaluate_count = Game.joins(:challenge)
.joins('LEFT JOIN members ON members.user_id = games.user_id')
.joins('LEFT JOIN course_members ON course_members.user_id = games.user_id')
.joins('LEFT JOIN homework_commons_shixuns hcs ON hcs.shixun_id = challenges.shixun_id')
.joins('LEFT JOIN homework_commons hc ON hcs.homework_common_id = hc.id AND hc.homework_type = 4')
.joins('LEFT JOIN courses ON hc.course_id = courses.id AND members.course_id = courses.id')
.joins('LEFT JOIN courses ON hc.course_id = courses.id AND course_members.course_id = courses.id')
.where(courses: { school_id: school.id })
.sum(:evaluate_count)

@ -25,6 +25,10 @@
<% end %>
</div>
<div class="batch-action-container">
<%= javascript_void_link '批量同意', class: 'btn btn-outline-primary btn-sm batch-agree-btn' %>
</div>
<div class="box identity-authentication-list-container">
<%= render(partial: 'admins/identity_authentications/shared/list', locals: { applies: @applies }) %>
</div>

@ -3,6 +3,12 @@
<table class="table table-hover text-center identity-authentication-list-table">
<thead class="thead-light">
<tr>
<% unless is_processed %>
<th width="4%">
<%= check_box_tag('all-check', 1, false, id: nil, class: 'batch-all-check-box',
data: { toggle: 'tooltip', title: '全选' }) %>
</th>
<% end %>
<th width="8%">头像</th>
<th width="10%">姓名</th>
<th width="14%">身份证号</th>
@ -14,12 +20,14 @@
<i class="fa fa-question-circle" data-toggle="tooltip" data-html="true" data-placement="top" title="审核完成后自动删除图片"></i>
</th>
<% end %>
<th width="16%">时间</th>
<% if is_processed %>
<th width="14%">拒绝原因</th>
<th width="10%">时间</th>
<th width="12%">拒绝原因</th>
<th width="8%">状态</th>
<th width="8%">操作</th>
<% else %>
<th width="20%">操作</th>
<th width="16%">时间</th>
<th width="16%">操作</th>
<% end %>
</tr>
</thead>
@ -28,6 +36,9 @@
<% applies.each do |apply| %>
<% user = apply.user %>
<tr class="identity-authentication-item identity-authentication-<%= apply.id %>">
<% unless is_processed %>
<td><%= check_box_tag('ids[]', apply.id, false, id: nil, class: 'batch-check-box') %></td>
<% end %>
<td>
<%= link_to "/users/#{user.login}", class: 'identity-authentication-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %>
<img src="/images/<%= url_to_avatar(user) %>" class="rounded-circle" width="40" height="40" />
@ -53,6 +64,11 @@
<% if is_processed %>
<td class="text-secondary"><%= overflow_hidden_span apply.remarks, width: 140 %></td>
<td><span class="apply-status-<%= apply.status %>"><%= apply.status_text %></span></td>
<td>
<% if apply.status == 1 %>
<%= agree_link '撤销', revoke_admins_identity_authentication_path(apply, element: ".identity-authentication-#{apply.id}"), 'data-confirm': '是否确认撤销认证??' %>
<% end %>
</td>
<% else %>
<td class="action-container">
<%= agree_link '同意', agree_admins_identity_authentication_path(apply, element: ".identity-authentication-#{apply.id}"), 'data-confirm': '确认审核通过?' %>

@ -25,6 +25,10 @@
<% end %>
</div>
<div class="batch-action-container">
<%= javascript_void_link '批量同意', class: 'btn btn-outline-primary btn-sm batch-agree-btn' %>
</div>
<div class="box professional-authentication-list-container">
<%= render(partial: 'admins/professional_authentications/shared/list', locals: { applies: @applies }) %>
</div>

@ -3,12 +3,18 @@
<table class="table table-hover text-center professional-authentication-list-table">
<thead class="thead-light">
<tr>
<% unless is_processed %>
<th width="4%">
<%= check_box_tag('all-check', 1, false, id: nil, class: 'batch-all-check-box',
data: { toggle: 'tooltip', title: '全选' }) %>
</th>
<% end %>
<th width="8%">头像</th>
<th width="14%">姓名</th>
<th width="28%">学校/单位</th>
<th width="20%">学校/单位</th>
<th width="12%">职称</th>
<% unless is_processed %>
<th width="10%">
<th width="14%">
照片
<i class="fa fa-question-circle" data-toggle="tooltip" data-html="true" data-placement="top" title="审核完成后自动删除图片"></i>
</th>
@ -17,8 +23,9 @@
<% if is_processed %>
<th width="14%">拒绝原因</th>
<th width="8%">状态</th>
<th width="8%">操作</th>
<% else %>
<th width="18%">操作</th>
<th width="22%">操作</th>
<% end %>
</tr>
</thead>
@ -27,6 +34,9 @@
<% applies.each do |apply| %>
<% user = apply.user %>
<tr class="professional-authentication-item professional-authentication-<%= apply.id %>">
<% unless is_processed %>
<td><%= check_box_tag('ids[]', apply.id, false, id: nil, class: 'batch-check-box') %></td>
<% end %>
<td>
<%= link_to "/users/#{user.login}", class: 'professional-authentication-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %>
<img src="/images/<%= url_to_avatar(user) %>" class="rounded-circle" width="40" height="40" />
@ -51,6 +61,11 @@
<% if is_processed %>
<td class="text-secondary"><%= overflow_hidden_span apply.remarks, width: 140 %></td>
<td><span class="apply-status-<%= apply.status %>"><%= apply.status_text %></span></td>
<td>
<% if apply.status == 1 %>
<%= agree_link '撤销', revoke_admins_professional_authentication_path(apply, element: ".professional-authentication-#{apply.id}"), 'data-confirm': '是否确认撤销认证??' %>
<% end %>
</td>
<% else %>
<td class="action-container">
<%= agree_link '同意', agree_admins_professional_authentication_path(apply, element: ".professional-authentication-#{apply.id}"), 'data-confirm': '确认审核通过?', 'data-disable-with': "提交中..." %>
@ -58,7 +73,7 @@
data: {
toggle: 'modal', target: '.admin-common-refuse-modal', id: apply.id,
url: refuse_admins_professional_authentication_path(apply, element: ".professional-authentication-#{apply.id}")
}, 'data-disable-with': "提交中...") %>
}, 'data-disable-with': "拒绝中...") %>
</td>
<% end %>
</tr>

@ -13,7 +13,7 @@ wb.styles do |style|
name = course_evaluation.name
items_size = course_evaluation.ec_course_evaluation_subitems.count
sheet.add_row name, style: bg_style
sheet.add_row [name], style: bg_style
sheet.merge_cells wb.rows.first.cells[(1..(items_size * course_evaluation.evaluation_count))]
data = []

@ -1 +1 @@
json.course_evaluations @course_evaluations, partial: 'shared/ec_course_evaluation', as: :ec_course_evaluation
json.course_evaluations @course_evaluations, partial: 'ecs/course_evaluations/shared/ec_course_evaluation', as: :ec_course_evaluation

@ -1 +1 @@
json.partial! 'shared/ec_course_evaluation', ec_course_evaluation: @course_evaluation
json.partial! 'ecs/course_evaluations/shared/ec_course_evaluation', ec_course_evaluation: @course_evaluation

@ -1 +1 @@
json.course_evaluations @course_evaluations, partial: 'shared/ec_course_evaluation_slim', as: :ec_course_evaluation
json.course_evaluations @course_evaluations, partial: 'ecs/course_evaluations/shared/ec_course_evaluation_slim', as: :ec_course_evaluation

@ -1,2 +1,2 @@
json.course_targets @course_targets, partial: 'shared/course_target', as: :ec_course_target
json.course_targets @course_targets, partial: 'ecs/course_targets/shared/course_target', as: :ec_course_target

@ -15,7 +15,7 @@ wb.styles do |style|
name = "#{@_current_course.name}课程目标"
wb.add_worksheet(name: name) do |sheet|
sheet.add_row name, style: title_style
sheet.add_row [name], style: title_style
sheet.add_row []
sheet.add_row []

@ -1,2 +1,2 @@
json.count @count
json.ec_courses @ec_courses, partial: 'shared/ec_course_slim', as: :ec_course
json.ec_courses @ec_courses, partial: 'ecs/ec_courses/shared/ec_course_slim', as: :ec_course

@ -1,3 +1,3 @@
json.count @graduation_requirements.size
json.graduation_requirements @graduation_requirements, partial: 'shared/ec_graduation_requirement', as: :ec_graduation_requirement
json.graduation_requirements @graduation_requirements, partial: '/ecs/ec_graduation_requirements/shared/ec_graduation_requirement', as: :ec_graduation_requirement

@ -6,15 +6,15 @@ wb = xlsx_package.workbook
wb.styles do |style|
title_style = style.add_style(sz: 16, height: 20, b: true)
ec_year_style = style.add_style(sz: 10, height: 14)
label_style = style.add_style(sz: 11, b: true, bg_color: '90EE90', alignment: { horizontal: :center })
label_style = style.add_style(sz: 11, b: true, bg_color: '90EE90', alignment: { horizontal: :center, vertical: :center })
content_style = style.add_style(sz: 11, height: 16, border: { style: :thin, color: '000000' })
wb.add_worksheet(:name => '毕业要求及指标点') do |sheet|
sheet.add_row '毕业要求及指标点', style: title_style
sheet.add_row ['毕业要求及指标点'], style: title_style
sheet.add_row []
sheet.add_row ['专业代码', major.code], style: ec_year_style
sheet.add_row ['专业代码', major.code.to_s + ' '], style: ec_year_style
sheet.add_row ['专业名称', major.name], style: ec_year_style
sheet.add_row ['学年', "#{ec_year.year}学年"], style: ec_year_style
@ -32,12 +32,15 @@ wb.styles do |style|
end
items_size = requirement.ec_graduation_subitems.size
sheet.merge_cells("A#{index}:A#{index + items_size}")
sheet.merge_cells("B#{index}:B#{index + items_size}")
if items_size.zero?
sheet.add_row [requirement_content, ''], style: content_style
else
sheet.merge_cells("A#{index + 1}:A#{index + items_size}")
end
index += items_size
end
sheet.column_widths [400, 400]
sheet.column_widths 100, 100
end
end

@ -1,2 +1,2 @@
json.partial! 'shared/ec_graduation_requirement', ec_graduation_requirement: @graduation_requirement
json.partial! 'ecs/ec_graduation_requirements/shared/ec_graduation_requirement', ec_graduation_requirement: @graduation_requirement

@ -3,7 +3,7 @@ json.count @count
# 示例专业
json.template_ec_major_school do
json.partial! 'ecs/ec_major_schools/shared/ec_major_school', ec_major_school: @template_major_school
json.partial! 'ecs/ec_major_schools/shared/ec_major_school', ec_major_school: @template_major_school if @template_major_school
end
# 专业
@ -11,5 +11,5 @@ json.ec_major_schools @major_schools do |ec_major_school|
json.partial! 'ecs/ec_major_schools/shared/ec_major_school', ec_major_school: ec_major_school
# 专业管理员
json.major_managers ec_major_school.users, partial: 'ecs/ec_major_schools/shared/ec_major_school', as: :user
json.major_managers ec_major_school.users, partial: 'users/user_simple', as: :user
end

@ -0,0 +1,6 @@
json.extract! @major, :id, :code, :name, :template_major
json.school_id @major.school.id
json.school_name @major.school.name
can_manager = @major.manager?(current_user) || @major.school.manager?(current_user) || current_user.admin_or_business?
json.can_manager can_manager

@ -1,2 +1,7 @@
json.count @count
json.es_majors @ec_majors, partial: 'ecs/majors/shared/ec_major', as: :ec_major
json.ec_majors do
json.array! @ec_majors.each do |major|
json.extract! major, :id, :name, :code
json.selected @major_ids.include?(major.id)
end
end

@ -1,3 +1,3 @@
json.extract! ec_training_objective, :id, :content
json.ec_training_items ec_training_objective.ec_training_subitems, partial: 'ec_training_subitem', as: :ec_training_subitem
json.ec_training_items ec_training_objective.ec_training_subitems, partial: '/ecs/ec_training_objectives/shared/ec_training_subitem', as: :ec_training_subitem

@ -1 +1 @@
json.partial! 'shared/ec_training_objective', ec_training_objective: @training_objective
json.partial! '/ecs/ec_training_objectives/shared/ec_training_objective', ec_training_objective: @training_objective

@ -6,11 +6,11 @@ wb = xlsx_package.workbook
wb.styles do |style|
title_style = style.add_style(sz: 16, height: 20, b: true)
ec_year_style = style.add_style(sz: 10, height: 14)
label_style = style.add_style(sz: 11, b: true, bg_color: '90EE90', alignment: { horizontal: :center })
label_style = style.add_style(sz: 11, b: true, bg_color: '90EE90', border: { style: :thin, color: '000000' }, alignment: { horizontal: :center, vertical: :center })
content_style = style.add_style(sz: 11, height: 16, border: { style: :thin, color: '000000' })
wb.add_worksheet(:name => '培养目标及目标分解') do |sheet|
sheet.add_row '培养目标及目标分解', style: title_style
sheet.add_row ['培养目标及目标分解'], style: title_style
sheet.add_row []
sheet.add_row []
@ -27,6 +27,6 @@ wb.styles do |style|
end
items_size = training_objective.ec_training_subitems.size
sheet.merge_cells("A9:A#{9 + items_size}")
sheet.merge_cells("A9:A#{9 + items_size - 1}")
end
end

@ -8,7 +8,16 @@ json.ec_years do
json.training_subitem_count @training_subitem_count_map.fetch(ec_year.id, 0)
json.graduation_requirement_count @graduation_requirement_count_map.fetch(ec_year.id, 0)
json.course_count @course_count_map.fetch(ec_year.id, 0)
json.course_target_count @course_target_count_map.fetch(ec_year.id, 0)
json.graduation_subitem_count @graduation_subitem_count_map.fetch(ec_year.id, 0)
course_target = @course_target_count_map.fetch(ec_year.id, 0)
graduation_subitem = @graduation_subitem_count_map.fetch(ec_year.id, 0)
achieved_course = achieved_graduation_course_count(ec_year)
achieved_objective = achieved_graduation_objective_count(ec_year)
json.course_target_count course_target
json.graduation_subitem_count graduation_subitem
json.achieved_graduation_course_count achieved_course
json.achieved_graduation_objective_count achieved_objective
json.status graduation_subitem == achieved_objective ? 'achieved' : 'not_achieved'
end
end

@ -0,0 +1,13 @@
json.extract! @year, :id, :year
major = @year.ec_major_school
json.major_id major.id
json.major_name major.name
json.major_code major.code
school = major.school
json.school_id school.id
json.school_name school.name
can_manager = major.manager?(current_user) || school.manager?(current_user) || current_user.admin_or_business?
json.can_manager can_manager

@ -1 +1 @@
json.partial! 'shared/ec_graduation_subitem', ec_graduation_subitem: @graduation_subitem
json.partial! 'ecs/graduation_course_supports/shared/ec_graduation_subitem', ec_graduation_subitem: @graduation_subitem

@ -2,4 +2,5 @@ json.extract! ec_graduation_subitem, :id, :position, :content, :ec_graduation_re
json.graduation_requirement_position ec_graduation_subitem.ec_graduation_requirement.position
json.course_supports ec_graduation_subitem.ec_course_supports, partial: 'ec_course_support', as: :ec_course_support
json.course_supports ec_graduation_subitem.ec_course_supports, partial: 'ecs/graduation_course_supports/shared/ec_course_support', as: :ec_course_support
json.weights_total ec_graduation_subitem.ec_course_supports.to_a.sum(&:weights)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save