diff --git a/app/assets/javascripts/admins/laboratory_shixuns/index.js b/app/assets/javascripts/admins/laboratory_shixuns/index.js new file mode 100644 index 000000000..5fd4c2d72 --- /dev/null +++ b/app/assets/javascripts/admins/laboratory_shixuns/index.js @@ -0,0 +1,126 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-laboratory-shixuns-index-page').length > 0) { + var $searchForm = $('.laboratory-shixun-list-form .search-form'); + var laboratoryId = $('.laboratory-shixun-list-container').data('id'); + + $searchForm.find('select#tag_id').select2({ + placeholder: "请选择", + allowClear: true + }); + + // 定义状态切换监听事件 + var defineStatusChangeFunc = function (doElement, undoElement, url, callback) { + $('.laboratory-shixun-list-container').on('click', doElement, function () { + var $doAction = $(this); + var $undoAction = $doAction.siblings(undoElement); + + var laboratoryShixunId = $doAction.data('id'); + customConfirm({ + content: '确认进行该操作吗?', + ok: function () { + $.ajax({ + url: '/admins/laboratories/' + laboratoryId + '/laboratory_shixuns/' + laboratoryShixunId + url, + method: 'POST', + dataType: 'json', + success: function () { + show_success_flash(); + $doAction.hide(); + $undoAction.show(); + if (callback && typeof callback === "function") { + callback(laboratoryShixunId, url); + } + } + }); + } + }); + }); + } + + // 首页展示与取消首页展示 + var homepageShowCallback = function (laboratoryShixunId, url) { + var $laboratoryShixunItem = $('.laboratory-shixun-list-container').find('.laboratory-shixun-item-' + laboratoryShixunId); + + if (url === '/homepage') { + $laboratoryShixunItem.find('.homepage-badge').show(); + } else { + $laboratoryShixunItem.find('.homepage-badge').hide(); + } + } + defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback); + defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback); + + // 添加实训功能 + var $addModal = $('.modal.admin-add-laboratory-shixun-modal'); + var $addForm = $addModal.find('form.admin-add-laboratory-user-form'); + var $shixunSelect = $addForm.find('select.shixun-select'); + + $addModal.on('show.bs.modal', function(){ + $addModal.find('.error').html(''); + $shixunSelect.select2('val', ' '); + }); + + $shixunSelect.select2({ + theme: 'bootstrap4', + placeholder: '请输入实训名称/创建者检索', + multiple: true, + closeOnSelect: false, + ajax: { + delay: 500, + url: '/admins/laboratories/' + laboratoryId + '/shixuns_for_select', + dataType: 'json', + data: function(params){ + return { keyword: params.term, page: params.page || 1, per_page: 20 }; + }, + processResults: function(data, params){ + params.page = params.page || 1; + + return { + results: data.shixuns, + pagination: { + more: (params.page * 20) < data.count + } + }; + } + }, + templateResult: function (item) { + if(!item.id || item.id === '') return item.text; + var ele = '' + ele += '' + item.name + ''; + ele += ' -- ' + item.creator_name + ''; + ele += ' -- ' + item.status_text+ ''; + ele += ''; + + return $(ele); + }, + templateSelection: function(item){ + if (item.id) { + } + var ele = '' + (item.name || item.text) + ' -- ' + item.creator_name + '' + return $(ele); + } + }); + + $addModal.on('click', '.submit-btn', function(){ + $addModal.find('.error').html(''); + + var shixunIds = $shixunSelect.val(); + if (shixunIds && shixunIds.length > 0) { + $.ajax({ + method: 'POST', + dataType: 'json', + url: '/admins/laboratories/' + laboratoryId + '/laboratory_shixuns', + data: { shixun_ids: shixunIds }, + success: function(){ + show_success_flash(); + window.location.reload(); + }, + error: function(res){ + $addModal.find('.error').html(res.responseJSON.message); + } + }); + } else { + $addModal.find('.error').html('请选择实训'); + } + }); + } +}) \ No newline at end of file diff --git a/app/assets/javascripts/admins/laboratory_subjects/index.js b/app/assets/javascripts/admins/laboratory_subjects/index.js new file mode 100644 index 000000000..a8b229d1f --- /dev/null +++ b/app/assets/javascripts/admins/laboratory_subjects/index.js @@ -0,0 +1,148 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-laboratory-subjects-index-page').length > 0) { + var $searchForm = $('.laboratory-subject-list-form .search-form'); + var laboratoryId = $('.laboratory-subject-list-container').data('id'); + + // ************** 学校选择 ************* + $searchForm.find('.school-select').select2({ + theme: 'bootstrap4', + placeholder: '请选择创建者单位', + minimumInputLength: 1, + ajax: { + delay: 500, + url: '/api/schools/search.json', + dataType: 'json', + data: function (params) { + return {keyword: params.term}; + }, + processResults: function (data) { + return {results: data.schools} + } + }, + templateResult: function (item) { + if (!item.id || item.id === '') return item.text; + return item.name; + }, + templateSelection: function (item) { + if (item.id) { + } + return item.name || item.text; + } + }); + + // 定义状态切换监听事件 + var defineStatusChangeFunc = function (doElement, undoElement, url, callback) { + $('.laboratory-subject-list-container').on('click', doElement, function () { + var $doAction = $(this); + var $undoAction = $doAction.siblings(undoElement); + + var laboratorySubjectId = $doAction.data('id'); + customConfirm({ + content: '确认进行该操作吗?', + ok: function () { + $.ajax({ + url: '/admins/laboratories/' + laboratoryId + '/laboratory_subjects/' + laboratorySubjectId + url, + method: 'POST', + dataType: 'json', + success: function () { + show_success_flash(); + $doAction.hide(); + $undoAction.show(); + if (callback && typeof callback === "function") { + callback(laboratorySubjectId, url); + } + } + }); + } + }); + }); + } + + // 首页展示与取消首页展示 + var homepageShowCallback = function (laboratoryShixunId, url) { + var $laboratoryShixunItem = $('.laboratory-subject-list-container').find('.laboratory-subject-item-' + laboratoryShixunId); + + if (url === '/homepage') { + $laboratoryShixunItem.find('.homepage-badge').show(); + } else { + $laboratoryShixunItem.find('.homepage-badge').hide(); + } + } + defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback); + defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback); + + // 添加实践课程功能 + var $addModal = $('.modal.admin-add-laboratory-subject-modal'); + var $addForm = $addModal.find('form.admin-add-laboratory-user-form'); + var $subjectSelect = $addForm.find('select.subject-select'); + + $addModal.on('show.bs.modal', function(){ + $addModal.find('.error').html(''); + $subjectSelect.select2('val', ' '); + }); + + $subjectSelect.select2({ + theme: 'bootstrap4', + placeholder: '请输入课程名称/创建者检索', + multiple: true, + closeOnSelect: false, + ajax: { + delay: 500, + url: '/admins/laboratories/' + laboratoryId + '/subjects_for_select', + dataType: 'json', + data: function(params){ + return { keyword: params.term, page: params.page || 1, per_page: 20 } + }, + processResults: function(data, params){ + params.page = params.page || 1; + + return { + results: data.subjects, + pagination: { + more: (params.page * 20) < data.count + } + }; + } + }, + templateResult: function (item) { + if(!item.id || item.id === '') return item.text; + var ele = '' + ele += '' + item.name + ''; + ele += ' -- ' + item.creator_name + ''; + ele += ' -- ' + item.status_text+ ''; + ele += ''; + + return $(ele); + }, + templateSelection: function(item){ + if (item.id) { + } + var ele = '' + (item.name || item.text) + ' -- ' + item.creator_name + '' + return $(ele); + } + }); + + $addModal.on('click', '.submit-btn', function(){ + $addModal.find('.error').html(''); + + var subjectIds = $subjectSelect.val(); + if (subjectIds && subjectIds.length > 0) { + $.ajax({ + method: 'POST', + dataType: 'json', + url: '/admins/laboratories/' + laboratoryId + '/laboratory_subjects', + data: { subject_ids: subjectIds }, + success: function(){ + show_success_flash(); + window.location.reload(); + }, + error: function(res){ + $addModal.find('.error').html(res.responseJSON.message); + } + }); + } else { + $addModal.find('.error').html('请选择课程'); + } + }); + } +}) \ No newline at end of file diff --git a/app/controllers/admins/base_controller.rb b/app/controllers/admins/base_controller.rb index e2e3babae..ad56afbf7 100644 --- a/app/controllers/admins/base_controller.rb +++ b/app/controllers/admins/base_controller.rb @@ -6,6 +6,7 @@ class Admins::BaseController < ApplicationController layout 'admin' skip_before_action :verify_authenticity_token + skip_before_action :setup_laboratory before_action :require_login, :require_admin! diff --git a/app/controllers/admins/competition_prize_users_controller.rb b/app/controllers/admins/competition_prize_users_controller.rb index 50d11e211..34dbc1f76 100644 --- a/app/controllers/admins/competition_prize_users_controller.rb +++ b/app/controllers/admins/competition_prize_users_controller.rb @@ -6,6 +6,16 @@ class Admins::CompetitionPrizeUsersController < Admins::BaseController include_class = [:competition_team, :competition_prize, :approver, user: [:process_real_name_apply, :process_professional_apply, user_extension: :school]] @prize_users = paginate(prize_users.preload(include_class)) + + respond_to do |format| + format.js + format.html + format.xlsx do + @all_prize_users = prize_users + filename = "#{@competition.name}竞赛获奖人信息列表_#{Time.current.strftime('%Y%m%d%H%M%S')}.xlsx" + render xlsx: 'index', filename: filename + end + end end def create diff --git a/app/controllers/admins/enroll_lists_controller.rb b/app/controllers/admins/enroll_lists_controller.rb index fb7cec9b0..f9fac9316 100644 --- a/app/controllers/admins/enroll_lists_controller.rb +++ b/app/controllers/admins/enroll_lists_controller.rb @@ -12,10 +12,6 @@ class Admins::EnrollListsController < Admins::BaseController respond_to do |format| format.js format.html - format.xls{ - filename = "#{@competition.name}竞赛报名列表_#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}.xls" - send_data(shixun_list_xls(shixuns), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename)) - } end end diff --git a/app/controllers/admins/laboratories_controller.rb b/app/controllers/admins/laboratories_controller.rb index e393c6677..716275468 100644 --- a/app/controllers/admins/laboratories_controller.rb +++ b/app/controllers/admins/laboratories_controller.rb @@ -1,7 +1,6 @@ class Admins::LaboratoriesController < Admins::BaseController def index - params[:sort_by] = params[:sort_by].presence || 'id' - params[:sort_direction] = params[:sort_direction].presence || 'desc' + default_sort('id', 'desc') laboratories = Admins::LaboratoryQuery.call(params) @laboratories = paginate laboratories.preload(:school, :laboratory_users) @@ -20,6 +19,37 @@ class Admins::LaboratoriesController < Admins::BaseController render_delete_success end + def shixuns_for_select + except_shixun_ids = current_laboratory.laboratory_shixuns.pluck(:shixun_id) + + shixuns = Shixun.where.not(id: except_shixun_ids) + + keyword = params[:keyword].to_s.strip + if keyword.present? + like_sql = 'shixuns.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword '\ + 'OR mirror_repositories.name LIKE :keyword' + shixuns = shixuns.joins(:user, :mirror_repositories).where(like_sql, keyword: "%#{keyword}%") + end + + @count = shixuns.count + @shixuns = paginate(shixuns.includes(:user)) + end + + def subjects_for_select + except_subject_ids = current_laboratory.laboratory_subjects.pluck(:subject_id) + + subjects = Subject.where.not(id: except_subject_ids) + + keyword = params[:keyword].to_s.strip + if keyword.present? + like_sql = 'subjects.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword' + subjects = subjects.joins(:user).where(like_sql, keyword: "%#{keyword}%") + end + + @count = subjects.count + @subjects = paginate(subjects.includes(:user)) + end + private def current_laboratory diff --git a/app/controllers/admins/laboratory_shixuns_controller.rb b/app/controllers/admins/laboratory_shixuns_controller.rb new file mode 100644 index 000000000..f5c7d5ef3 --- /dev/null +++ b/app/controllers/admins/laboratory_shixuns_controller.rb @@ -0,0 +1,41 @@ +class Admins::LaboratoryShixunsController < Admins::BaseController + helper_method :current_laboratory, :current_laboratory_shixun + + def index + laboratory_shixuns = Admins::LaboratoryShixunQuery.call(current_laboratory, params) + @laboratory_shixuns = paginate laboratory_shixuns.includes(shixun: %i[tag_repertoires user]) + end + + def create + shixun_ids = Array.wrap(params[:shixun_ids]) + shixun_ids = Shixun.where(id: shixun_ids).pluck(:id) + exist_shixun_id = current_laboratory.laboratory_shixuns.where(shixun_id: shixun_ids).pluck(:shixun_id) + + LaboratoryShixun.bulk_insert(*%i[shixun_id laboratory_id created_at updated_at]) do |worker| + (shixun_ids - exist_shixun_id).each do |shixun_id| + worker.add(shixun_id: shixun_id, laboratory_id: current_laboratory.id) + end + end + render_ok + end + + def homepage + current_laboratory_shixun.update!(homepage: true) + render_ok + end + + def cancel_homepage + current_laboratory_shixun.update!(homepage: false) + render_ok + end + + private + + def current_laboratory + @_current_laboratory ||= Laboratory.find(params[:laboratory_id]) + end + + def current_laboratory_shixun + @_current_laboratory_shixun ||= current_laboratory.laboratory_shixuns.find(params[:id]) + end +end \ No newline at end of file diff --git a/app/controllers/admins/laboratory_subjects_controller.rb b/app/controllers/admins/laboratory_subjects_controller.rb new file mode 100644 index 000000000..d6dc4af9d --- /dev/null +++ b/app/controllers/admins/laboratory_subjects_controller.rb @@ -0,0 +1,43 @@ +class Admins::LaboratorySubjectsController < Admins::BaseController + helper_method :current_laboratory, :current_laboratory_subject + + def index + laboratory_subjects = Admins::LaboratorySubjectQuery.call(current_laboratory, params) + + includes_tables = { subject: [:repertoire, :subject_level_system, user: {user_extension: :school}] } + @laboratory_subjects = paginate(laboratory_subjects.includes(includes_tables)) + end + + def create + subject_ids = Array.wrap(params[:subject_ids]) + subject_ids = Subject.where(id: subject_ids).pluck(:id) + exist_subject_id = current_laboratory.laboratory_subjects.where(subject_id: subject_ids).pluck(:subject_id) + + LaboratorySubject.bulk_insert(*%i[subject_id laboratory_id created_at updated_at]) do |worker| + (subject_ids - exist_subject_id).each do |subject_id| + worker.add(subject_id: subject_id, laboratory_id: current_laboratory.id) + end + end + render_ok + end + + def homepage + current_laboratory_subject.update!(homepage: true) + render_ok + end + + def cancel_homepage + current_laboratory_subject.update!(homepage: false) + render_ok + end + + private + + def current_laboratory + @_current_laboratory ||= Laboratory.find(params[:laboratory_id]) + end + + def current_laboratory_subject + @_current_laboratory_subject ||= current_laboratory.laboratory_subjects.find(params[:id]) + end +end \ No newline at end of file diff --git a/app/controllers/concerns/laboratory_helper.rb b/app/controllers/concerns/laboratory_helper.rb index 157957b03..870a1d90e 100644 --- a/app/controllers/concerns/laboratory_helper.rb +++ b/app/controllers/concerns/laboratory_helper.rb @@ -2,6 +2,8 @@ module LaboratoryHelper extend ActiveSupport::Concern included do + before_action :setup_laboratory + helper_method :current_laboratory helper_method :default_setting end @@ -17,4 +19,8 @@ module LaboratoryHelper def default_setting @_default_setting ||= LaboratorySetting.find_by(laboratory_id: 1) end + + def setup_laboratory + Laboratory.current = current_laboratory + end end \ No newline at end of file diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 488289815..5dd001f5a 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -288,11 +288,11 @@ class CoursesController < ApplicationController inform = @course.informs.find_by(id: params[:inform_id]) next_inform = inform.next_inform ActiveRecord::Base.transaction do - if next_inform + if next_inform.blank? render_error('已经到达最顶部') else - inform.update_attribute(:position, (position + 1)) - next_inform.update_attribute(:position, last_inform.position - 1) + inform.update_attribute(:position, (inform.position + 1)) + next_inform.update_attribute(:position, inform.position - 1) render_ok end end @@ -302,11 +302,11 @@ class CoursesController < ApplicationController inform = @course.informs.find_by(id: params[:inform_id]) last_inform = inform.last_inform ActiveRecord::Base.transaction do - if last_inform + if last_inform.blank? render_error('已经到达最底部') else - inform.update_attribute(:position, (position - 1)) - last_inform.update_attribute(:position, last_inform.position + 1) + inform.update_attribute(:position, (inform.position - 1)) + last_inform.update_attribute(:position, inform.position + 1) render_ok end end @@ -317,7 +317,7 @@ class CoursesController < ApplicationController inform = Inform.new(container: @course) inform.name = params[:name] inform.description = params[:description] - inform.position = @course.informs.maximum(:position) + 1 + inform.position = @course.informs.maximum(:position).to_i + 1 inform.save! normal_status("创建成功") end diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index cb32f7bb3..2f616ec71 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -514,6 +514,9 @@ class ExercisesController < ApplicationController if exercise_group.present? && (exercise_group.first.publish_time < Time.now) && (exercise_publish_time != exercise_group.first.publish_time) error_count += 1 end + if exercise_group.present? && (exercise_group.first.publish_time < Time.now && exercise_group.first.end_time > Time.now) && (exercise_end_time < Time.now) + error_count += 1 + end if error_count == 0 common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的 new_group_ids = course_id - common_group #新传入的班级id @@ -529,12 +532,12 @@ class ExercisesController < ApplicationController if the_group_setting_status == 2 ex_group_params = { :publish_time => the_group_setting.publish_time, - :end_time => exercise_end_time + :end_time => exercise_end_time < Time.now ? the_group_setting.end_time : exercise_end_time } elsif the_group_setting_status == 3 ex_group_params = { :publish_time => the_group_setting.publish_time, - :end_time => the_group_setting.end_time + :end_time => exercise_end_time } end the_group_setting.update_attributes!(ex_group_params) @@ -558,7 +561,7 @@ class ExercisesController < ApplicationController if error_count > 0 error_count == 0 - normal_status(-1,"已发布/已截止的试卷不允许修改时间") + normal_status(-1,"试卷发布/截止时间不能小于当前时间") else # 未发布的分班设置才能删除 if old_exercise_groups.size > 0 diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 48c942e65..ba07d42c9 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -26,12 +26,27 @@ class HomeController < ApplicationController @rep_list << {rep_id: rep.id, rep_name: rep.name, sub_rep_list: sub_rep_list} end - @shixuns = Shixun.where(homepage_show: 1).includes(:tag_repertoires, :challenges).limit(8) + shixuns = current_laboratory.shixuns + subjects = current_laboratory.subjects + + if current_laboratory.main_site? + shixuns = shixuns.where(homepage_show: true) + subjects = subjects.where(homepage_show: true) + else + shixuns = shixuns.where(laboratory_shixuns: { homepage: true }) + subjects = subjects.where(laboratory_subjects: { homepage: true }) + end + + @shixuns = shixuns.includes(:tag_repertoires, :challenges).limit(8) + @subjects = subjects.includes(:repertoire, :shixuns).limit(8) - @subjects = Subject.where(homepage_show: 1).includes(:shixuns, :repertoire).limit(8) + @main_shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(8) + @main_subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(8) - @tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc") - @stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc") + if current_laboratory.main_site? + @tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc") + @stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc") + end end def search diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index c1e08d440..3a8a25133 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -103,11 +103,14 @@ class MessagesController < ApplicationController return normal_status(403, "您没有权限进行该操作") if current_user != @message.author && !current_user.teacher_of_course?(@message.board.course) begin - h = {is_md: true} + email_notify = @message.email_notify ? 1 : @board.course.email_notify && params[:email_notify] + send_email = !@message.email_notify && email_notify + h = {is_md: true, email_notify: email_notify} m_params = message_params.merge(h) @message.update_attributes(m_params) Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name) @message.update_content(params[:content]) + notify_course_students(@message, @board.course) if send_email rescue Exception => e uid_logger_error(e.message) tip_exception("修改失败") @@ -123,6 +126,7 @@ class MessagesController < ApplicationController @message.author = current_user @message.board_id = params[:select_board_id] @message.message_detail_attributes = {content: params[:content]} + @message.email_notify = @board.course.email_notify && params[:email_notify] ? 1 : 0 @message.save! Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name) if @board.course.email_notify && params[:email_notify] @@ -189,7 +193,7 @@ class MessagesController < ApplicationController private def validate_sort_type - normal_status(2, "参数sort_tyope暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip) + normal_status(2, "参数sort_type暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip) end def find_message @@ -207,7 +211,7 @@ class MessagesController < ApplicationController def notify_course_students message, course course.students.includes(:user).each do |student| - UserMailer.course_message_email(student&.user&.mail, message.id).deliver_now if student&.user&.mail + UserMailer.course_message_email(student&.user&.mail, message.id).deliver_later if student&.user&.mail end end end diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb index 05c3500ee..cfe6141ee 100644 --- a/app/controllers/shixuns_controller.rb +++ b/app/controllers/shixuns_controller.rb @@ -33,7 +33,12 @@ class ShixunsController < ApplicationController current_user.my_shixuns else Shixun.unhidden - end + end + + ## 云上实验室过滤 + unless current_laboratory.main_site? + @shixuns = @shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: current_laboratory.id }) + end ## 方向 if params[:tag_level].present? && params[:tag_id].present? @@ -335,6 +340,9 @@ class ShixunsController < ApplicationController end end end + + # 将实训标志为该云上实验室建立 + Laboratory.current.laboratory_shixuns.create!(shixun: @shixun, ownership: true) rescue Exception => e uid_logger_error("copy shixun failed ##{e.message}") # 删除版本库 @@ -430,6 +438,9 @@ class ShixunsController < ApplicationController GitService.add_repository(repo_path: repo_path) # todo: 为什么保存的时候要去除后面的.git呢?? @shixun.update_column(:repo_name, repo_path.split(".")[0]) + + # 将实训标志为该云上实验室建立 + Laboratory.current.laboratory_shixuns.create!(shixun: @shixun, ownership: true) rescue Exception => e uid_logger_error(e.message) tip_exception("实训创建失败") diff --git a/app/controllers/subjects_controller.rb b/app/controllers/subjects_controller.rb index cbedf74b2..b76db8a20 100644 --- a/app/controllers/subjects_controller.rb +++ b/app/controllers/subjects_controller.rb @@ -23,16 +23,17 @@ class SubjectsController < ApplicationController # 最热排序 if reorder == "myshixun_count" + laboratory_join = current_laboratory.main_site? ? '' : " JOIN laboratory_subjects ls ON ls.subject_id = subjects.id AND ls.laboratory_id = #{current_laboratory.id} " if select @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns - on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where + on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id #{laboratory_join} where subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC") else @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns - on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where + on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id #{laboratory_join} where subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' GROUP BY subjects.id ORDER BY myshixun_member_count DESC") end @@ -52,6 +53,11 @@ class SubjectsController < ApplicationController @subjects = Subject.visible.unhidden end + # 云上实验室过滤 + unless current_laboratory.main_site? + @subjects = @subjects.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: current_laboratory.id }) + end + # 类型 if select @subjects = @subjects.where(repertoire_id: select) @@ -117,6 +123,9 @@ class SubjectsController < ApplicationController @subject.user_id = current_user.id @subject.save! @subject.subject_members.create!(role: 1, user_id: current_user.id) + + # 将实践课程标记为该云上实验室建立 + Laboratory.current.laboratory_subjects.create!(subject: @subject, ownership: true) rescue Exception => e uid_logger_error(e.message) tip_exception("实训路径创建失败") diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c666f43fc..be633b2cc 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -414,6 +414,14 @@ module ApplicationHelper m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t end + def shixun_status_class(shixun) + case shixun.status + when 0 then 'text-info' + when 1 then 'text-warning' + when 2 then 'text-success' + when 3 then 'text-secondary' + end + end end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 5cd9d787c..6e957b4df 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -12,6 +12,6 @@ class UserMailer < ApplicationMailer def course_message_email(mail, message_id) @message = Message.find_by(id: message_id) @course = @message&.board&.course - mail(to: mail, subject: '课堂通知') if @message.present? && @course.present? + mail(to: mail, subject: '课堂发布了新的帖子') if @message.present? && @course.present? end end diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 7413853e0..9bc9bd1fb 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -41,6 +41,14 @@ class Exercise < ApplicationRecord exercise_questions.pluck(:question_score).sum end + def subjective_score + exercise_questions.where(question_type: [4]).pluck(:question_score).sum + end + + def objective_score + exercise_questions.where(question_type: [0, 1, 2, 3, 5]).pluck(:question_score).sum + end + def create_exercise_list str = "" # TODO: 一次性为所有学生创建数据是否存在问题? diff --git a/app/models/inform.rb b/app/models/inform.rb index a6f40fe6d..dc979ef32 100644 --- a/app/models/inform.rb +++ b/app/models/inform.rb @@ -7,11 +7,11 @@ class Inform < ApplicationRecord has_many :attachments, as: :container, dependent: :destroy def next_inform - Inform.where(position: self.position+1, container_id: self.course_id, container_type: 'Course') + Inform.find_by(position: self.position+1, container_id: self.container_id, container_type: self.container_type) end def last_inform - Inform.where(position: self.position-1, container_id: self.course_id, container_type: 'Course') + Inform.find_by(position: self.position-1, container_id: self.container_id, container_type: self.container_type) end end diff --git a/app/models/laboratory.rb b/app/models/laboratory.rb index 35965dc0d..672294b63 100644 --- a/app/models/laboratory.rb +++ b/app/models/laboratory.rb @@ -8,6 +8,9 @@ class Laboratory < ApplicationRecord has_many :portal_images, dependent: :destroy + has_many :laboratory_shixuns, dependent: :destroy + has_many :laboratory_subjects, dependent: :destroy + validates :identifier, uniqueness: { case_sensitive: false }, allow_nil: true delegate :name, :navbar, :footer, :login_logo_url, :nav_logo_url, :tab_logo_url, :default_navbar, to: :laboratory_setting @@ -27,4 +30,25 @@ class Laboratory < ApplicationRecord find_by_identifier(subdomain) end + + def self.current=(laboratory) + Thread.current[:current_laboratory] = laboratory + end + + def self.current + Thread.current[:current_laboratory] ||= Laboratory.find(1) + end + + def shixuns + main_site? ? Shixun.all : Shixun.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: id }) + end + + def subjects + main_site? ? Subject.all : Subject.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: id }) + end + + # 是否为主站 + def main_site? + id == 1 + end end \ No newline at end of file diff --git a/app/models/laboratory_shixun.rb b/app/models/laboratory_shixun.rb new file mode 100644 index 000000000..cc4a861eb --- /dev/null +++ b/app/models/laboratory_shixun.rb @@ -0,0 +1,4 @@ +class LaboratoryShixun < ApplicationRecord + belongs_to :laboratory + belongs_to :shixun +end \ No newline at end of file diff --git a/app/models/laboratory_subject.rb b/app/models/laboratory_subject.rb new file mode 100644 index 000000000..fa5862712 --- /dev/null +++ b/app/models/laboratory_subject.rb @@ -0,0 +1,4 @@ +class LaboratorySubject < ApplicationRecord + belongs_to :laboratory + belongs_to :subject +end \ No newline at end of file diff --git a/app/models/shixun.rb b/app/models/shixun.rb index 103c8b68f..c1782fe03 100644 --- a/app/models/shixun.rb +++ b/app/models/shixun.rb @@ -51,6 +51,8 @@ class Shixun < ApplicationRecord # 实训审核记录 has_many :shixun_reviews, -> {order("shixun_reviews.created_at desc")}, :dependent => :destroy + has_many :laboratory_shixuns, dependent: :destroy + scope :search_by_name, ->(keyword) { where("name like ? or description like ? ", "%#{keyword}%", "%#{keyword}%") } diff --git a/app/models/subject.rb b/app/models/subject.rb index e8f592419..28c45e4ba 100644 --- a/app/models/subject.rb +++ b/app/models/subject.rb @@ -24,6 +24,8 @@ class Subject < ApplicationRecord # 开放课堂 has_many :courses, -> { where("is_delete = 0").order("courses.created_at ASC") } + has_many :laboratory_subjects, dependent: :destroy + validates :name, length: { maximum: 60 } validates :description, length: { maximum: 8000 } validates :learning_notes, length: { maximum: 2000 } diff --git a/app/models/user.rb b/app/models/user.rb index 85b9ef551..5d9ccd0ba 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -235,6 +235,28 @@ class User < ApplicationRecord end end + # 实名认证状态 + def auth_status + status = if authentication + "已认证" + elsif process_real_name_apply.present? + "待审核" + else + "未认证" + end + end + + # 职业认证状态 + def pro_status + status = if professional_certification + "已认证" + elsif process_professional_apply.present? + "待审核" + else + "未认证" + end + end + # 判断当前用户是否通过职业认证 def pro_certification? professional_certification diff --git a/app/queries/admins/laboratory_shixun_query.rb b/app/queries/admins/laboratory_shixun_query.rb new file mode 100644 index 000000000..d489aed21 --- /dev/null +++ b/app/queries/admins/laboratory_shixun_query.rb @@ -0,0 +1,36 @@ +class Admins::LaboratoryShixunQuery < ApplicationQuery + attr_reader :laboratory, :params + + def initialize(laboratory, params) + @laboratory = laboratory + @params = params + end + + def call + laboratory_shixuns = laboratory.laboratory_shixuns.joins(:shixun) + + keyword = params[:keyword].to_s.strip + if keyword.present? + like_sql = 'shixuns.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword' + laboratory_shixuns = laboratory_shixuns.joins(shixun: :user).where(like_sql, keyword: "%#{keyword}%") + end + + # 实训状态 + laboratory_shixuns = laboratory_shixuns.where(shixuns: { status: params[:status] }) if params[:status].present? + + # 技术平台 + if params[:tag_id].present? + laboratory_shixuns = laboratory_shixuns.joins(shixun: :shixun_mirror_repositories) + .where(shixun_mirror_repositories: { mirror_repository_id: params[:tag_id] }) + end + + # 首页展示、单位自建 + %i[homepage ownership].each do |column| + if params[column].present? && params[column].to_s == 'true' + laboratory_shixuns = laboratory_shixuns.where(column => true) + end + end + + laboratory_shixuns + end +end \ No newline at end of file diff --git a/app/queries/admins/laboratory_subject_query.rb b/app/queries/admins/laboratory_subject_query.rb new file mode 100644 index 000000000..316ea9743 --- /dev/null +++ b/app/queries/admins/laboratory_subject_query.rb @@ -0,0 +1,36 @@ +class Admins::LaboratorySubjectQuery < ApplicationQuery + attr_reader :laboratory, :params + + def initialize(laboratory, params) + @laboratory = laboratory + @params = params + end + + def call + laboratory_subjects = laboratory.laboratory_subjects.joins(:subject) + + keyword = params[:keyword].to_s.strip + if keyword.present? + like_sql = 'subjects.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword' + laboratory_subjects = laboratory_subjects.joins(subject: :user).where(like_sql, keyword: "%#{keyword}%") + end + + # 状态 + laboratory_subjects = laboratory_subjects.where(subjects: { status: params[:status] }) if params[:status].present? + + # 创建者单位 + if params[:school_id].present? + laboratory_subjects = laboratory_subjects.joins(subjects: { user: :user_extension }) + .where(user_extensions: { school_id: params[:school_id] }) + end + + # 首页展示、单位自建 + %i[homepage ownership].each do |column| + if params[column].present? && params[column].to_s == 'true' + laboratory_subjects = laboratory_subjects.where(column => true) + end + end + + laboratory_subjects + end +end \ No newline at end of file diff --git a/app/queries/admins/shixun_settings_query.rb b/app/queries/admins/shixun_settings_query.rb index 32cfdb8bf..ab871b58e 100644 --- a/app/queries/admins/shixun_settings_query.rb +++ b/app/queries/admins/shixun_settings_query.rb @@ -11,6 +11,9 @@ class Admins::ShixunSettingsQuery < ApplicationQuery def call all_shixuns = Shixun.all + + all_shixuns = all_shixuns.where(id: params[:id]) if params[:id].present? + status = case params[:status] when "editing" then [0] diff --git a/app/queries/admins/subject_query.rb b/app/queries/admins/subject_query.rb index d5b60b8b6..935f52bb3 100644 --- a/app/queries/admins/subject_query.rb +++ b/app/queries/admins/subject_query.rb @@ -12,6 +12,8 @@ class Admins::SubjectQuery < ApplicationQuery def call subjects = Subject.all + subjects = subjects.where(id: params[:id]) if params[:id].present? + # 状态过滤 status = case params[:status].to_s.strip diff --git a/app/services/duplicate_course_service.rb b/app/services/duplicate_course_service.rb index acff0a726..fa57a8901 100644 --- a/app/services/duplicate_course_service.rb +++ b/app/services/duplicate_course_service.rb @@ -94,8 +94,8 @@ class DuplicateCourseService < ApplicationService exercise = course.exercises.create!(attrs.merge(user_id: user.id)) origin_exercise.exercise_questions.find_each do |origin_question| - question_attrs = origin_question.as_json(only: %i[question_title question_type question_number question_score]) - question_attrs[:question_type] ||= 1 + question_attrs = origin_question.as_json(only: %i[question_title question_type question_number question_score shixun_name shixun_id is_ordered level]) + # question_attrs[:question_type] ||= 1 question = exercise.exercise_questions.create!(question_attrs) exercise_choice_map = {} @@ -103,15 +103,20 @@ class DuplicateCourseService < ApplicationService choice_attrs = { choice_position: index + 1, choice_text: origin_choice.choice_text } choice = question.exercise_choices.create!(choice_attrs) - exercise_choice_map[origin_choice.id] = choice.id + # exercise_choice_map[origin_choice.id] = choice.id 标准答案中存的是choice_position, 直接取原题的exercise_choice_id就行 end origin_question.exercise_standard_answers.find_each do |origin_answer| question.exercise_standard_answers.create!( - exercise_choice_id: exercise_choice_map[origin_answer.exercise_choice_id], + exercise_choice_id: origin_answer.exercise_choice_id, answer_text: origin_answer.answer_text ) end + + origin_question.exercise_shixun_challenges.each_with_index do |sc, index| + question.exercise_shixun_challenges.create!({position: index+1, challenge_id: sc.challenge_id, + shixun_id: sc.shixun_id, question_score: sc.question_score}) + end end origin_exercise.exercise_bank.increment!(:quotes) if exercise.exercise_bank diff --git a/app/views/admins/competition_prize_users/index.html.erb b/app/views/admins/competition_prize_users/index.html.erb index dbb86d066..735d94d2e 100644 --- a/app/views/admins/competition_prize_users/index.html.erb +++ b/app/views/admins/competition_prize_users/index.html.erb @@ -50,6 +50,12 @@ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <%= link_to '清除', admins_competition_competition_prize_users_path(@competition), class: "btn btn-default",'data-disable-with': '清除中...' %> <% end %> + +
+ 名称 +
+ + this.changeTitle(e)} + className={"Osshackathonmodelinput"} + style={{"width": "100%"}} maxLength="60" + addonAfter={String(this.state.title_value===undefined?0:this.state.title_value.length)+"/60"} + /> + ++ 描述 +
+ +