diff --git a/.gitignore b/.gitignore index cb2789f9b..77df2c1c5 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ /public/react/node_modules/ /public/react/config/stats.json /public/react/stats.json +/public/react/.idea/* /public/npm-debug.log @@ -58,6 +59,7 @@ vendor/bundle/ .ruby-version .ruby-gemset +/Users /files /public/images/avatars /public/files diff --git a/Gemfile b/Gemfile index a901bc5b5..7f2c08a0d 100644 --- a/Gemfile +++ b/Gemfile @@ -95,6 +95,7 @@ gem 'bulk_insert' gem 'searchkick' gem 'aasm' +gem 'enumerize' # oauth2 gem 'omniauth', '~> 1.9.0' diff --git a/Gemfile.lock b/Gemfile.lock index 96534ef5d..19a413f2f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,8 +54,8 @@ GEM tzinfo (~> 1.1) acts-as-taggable-on (6.0.0) activerecord (~> 5.0) - addressable (2.5.2) - public_suffix (>= 2.0.2, < 4.0) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) archive-zip (0.11.0) io-like (~> 0.3.0) arel (9.0.0) @@ -106,6 +106,8 @@ GEM elasticsearch-transport (7.2.0) faraday multi_json + enumerize (2.3.1) + activesupport (>= 3.2) erubi (1.7.1) execjs (2.7.0) faraday (0.15.4) @@ -184,7 +186,7 @@ GEM omniauth (~> 1.9) pdfkit (0.8.4.1) popper_js (1.14.5) - public_suffix (3.0.2) + public_suffix (4.0.1) puma (3.12.0) rack (2.0.5) rack-cors (1.0.2) @@ -372,6 +374,7 @@ DEPENDENCIES byebug capybara (>= 2.15, < 4.0) chromedriver-helper + enumerize faraday (~> 0.15.4) font-awesome-sass (= 4.7.0) gitlab! diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js index 3e9601bf8..c69986a57 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -13,10 +13,15 @@ //= require bootstrap-datepicker //= require bootstrap.viewer //= require jquery.mloading +//= require jquery-confirm.min +//= require common //= require echarts -//= require lib/codemirror -//= require mode/shell/shell +//= require codemirror/lib/codemirror +//= require codemirror/mode/shell/shell +//= require editormd/editormd +//= require editormd/languages/zh-tw +//= require dragula/dragula //= require_tree ./i18n //= require_tree ./admins @@ -40,8 +45,16 @@ $.notifyDefaults({ delay: 2000 }); +function show_success_flash(){ + $.notify({ + message: '操作成功' + },{ + type: 'success' + }); +} + $(document).on('turbolinks:load', function(){ - $('[data-toggle="tooltip"]').tooltip(); + $('[data-toggle="tooltip"]').tooltip({ trigger : 'hover' }); $('[data-toggle="popover"]').popover(); // 图片查看大图 @@ -83,4 +96,4 @@ $(document).on("turbolinks:before-cache", function () { // }); $(function () { -}); \ No newline at end of file +}); diff --git a/app/assets/javascripts/admins/about.js b/app/assets/javascripts/admins/about.js new file mode 100644 index 000000000..d706e653c --- /dev/null +++ b/app/assets/javascripts/admins/about.js @@ -0,0 +1,5 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-abouts-edit-page, body.admins-abouts-update-page').length > 0) { + createMDEditor('about-us-editor', {}); + } +}) \ No newline at end of file diff --git a/app/assets/javascripts/admins/agreement.js b/app/assets/javascripts/admins/agreement.js new file mode 100644 index 000000000..387d4b337 --- /dev/null +++ b/app/assets/javascripts/admins/agreement.js @@ -0,0 +1,5 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-agreements-edit-page, body.admins-agreements-update-page').length > 0) { + createMDEditor('agreement-editor', {}); + } +}) \ No newline at end of file diff --git a/app/assets/javascripts/admins/auth_schools/index.js b/app/assets/javascripts/admins/auth_schools/index.js new file mode 100644 index 000000000..924a1a73e --- /dev/null +++ b/app/assets/javascripts/admins/auth_schools/index.js @@ -0,0 +1,6 @@ + +function show_add_manager(id) { + $(".auth-schools-user-add").modal("show"); + + $(".auth-schools-user-add").find("#school_id_input").val(id) +} \ No newline at end of file diff --git a/app/assets/javascripts/admins/batch-check-box.js b/app/assets/javascripts/admins/batch-check-box.js new file mode 100644 index 000000000..63963f0d9 --- /dev/null +++ b/app/assets/javascripts/admins/batch-check-box.js @@ -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); + }) +}); \ No newline at end of file diff --git a/app/assets/javascripts/admins/common-refuse-modal.js b/app/assets/javascripts/admins/common-refuse-modal.js index 4e1af891e..886c00570 100644 --- a/app/assets/javascripts/admins/common-refuse-modal.js +++ b/app/assets/javascripts/admins/common-refuse-modal.js @@ -3,6 +3,7 @@ $(document).on('turbolinks:load', function() { if ($refuseModal.length > 0) { var $form = $refuseModal.find('form.admin-common-refuse-form'); var $applyIdInput = $refuseModal.find('.modal-body input[name="apply_id"]'); + var $applyTitle = $refuseModal.find('.modal-title'); $form.validate({ errorElement: 'span', @@ -21,9 +22,19 @@ $(document).on('turbolinks:load', function() { var applyId = $link.data('id'); var url = $link.data('url'); + var title = $link.data('title'); + var type = $link.data('type'); + var form_method = "POST"; + if(typeof title !== 'undefined'){ + $applyTitle.html(title) + } + if(typeof type !== 'undefined'){ + form_method = type; + } $applyIdInput.val(applyId); $form.data('url', url); + $form.data('type', form_method); }); // modal visited fire $refuseModal.on('shown.bs.modal', function(){ @@ -40,9 +51,10 @@ $(document).on('turbolinks:load', function() { if ($form.valid()) { var url = $form.data('url'); + var form_method = $form.data('type'); $.ajax({ - method: 'POST', + method: form_method, dataType: 'script', url: url, data: $form.serialize(), diff --git a/app/assets/javascripts/admins/cooperatives.js b/app/assets/javascripts/admins/cooperatives.js new file mode 100644 index 000000000..f650e00e3 --- /dev/null +++ b/app/assets/javascripts/admins/cooperatives.js @@ -0,0 +1,96 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-cooperatives-index-page').length > 0) { + // ------------ 保存链接 ----------- + $('.coo-img-card').on('click', '.save-url-btn', function(){ + var $link = $(this); + var cooId = $link.data('id'); + var url = $('.coo-img-item-' + cooId).find('.url-input').val(); + $link.attr('disabled', true); + + $.ajax({ + url: '/admins/cooperatives/' + cooId, + method: 'PATCH', + dataType: 'json', + data: { url: url }, + success: function(data){ + $.notify({ message: '保存成功' }); + }, + error: ajaxErrorNotifyHandler, + complete: function(){ + $link.removeAttr('disabled'); + } + }) + }); + + // ------------ 拖拽 ------------- + var onDropFunc = function(el, _target, _source, sibling){ + var moveId = $(el).data('id'); + var insertId = $(sibling).data('id') || ''; + + $.ajax({ + url: '/admins/cooperatives/drag', + method: 'POST', + dataType: 'json', + data: { move_id: moveId, after_id: insertId }, + success: function(data){ + }, + error: function(res){ + var data = res.responseJSON; + $.notify({message: '移动失败,原因:' + data.message}, {type: 'danger'}); + } + }) + }; + var ele1 = document.getElementById('coo-img-container-alliance_coop'); + dragula([ele1], { mirrorContainer: ele1 }).on('drop', onDropFunc); + var ele2 = document.getElementById('coo-img-container-com_coop'); + dragula([ele2], { mirrorContainer: ele2 }).on('drop', onDropFunc); + var ele3 = document.getElementById('coo-img-container-edu_coop'); + dragula([ele3], { mirrorContainer: ele3 }).on('drop', onDropFunc); + + + // ----------- 新增 -------------- + var $createModal = $('.modal.admin-add-cooperative-modal'); + var $createForm = $createModal.find('form.admin-add-cooperative-form'); + + $createForm.validate({ + errorElement: 'span', + errorClass: 'danger text-danger', + rules: { + "coo_img[image]": { + required: true + } + } + }); + + $createModal.on('show.bs.modal', function(event){ + resetFileInputFunc($createModal.find('.img-file-input')); + $createModal.find('.file-names').html('选择文件'); + + var $link = $(event.relatedTarget); + var imgType = $link.data('imgType'); + $createForm.find('input[name="coo_img[img_type]"]').val(imgType); + }); + + $createModal.on('click', '.submit-btn', function() { + $createForm.find('.error').html(''); + + if ($createForm.valid()) { + $createForm.submit(); + } else { + $createForm.find('.error').html('请选择图片'); + } + }); + $createModal.on('change', '.img-file-input', function(){ + var file = $(this)[0].files[0]; + $createModal.find('.file-names').html(file ? file.name : '请选择文件'); + }) + + // -------------- 重新上传图片 -------------- + //replace_image_url + $('.modal.admin-upload-file-modal').on('upload:success', function(e, data){ + var $cooImgItem = $('.coo-img-item-' + data.source_id); + $.post('/admins/cooperatives/'+ data.source_id + '/replace_image_url'); + $cooImgItem.find('.coo-img-item-img img').attr('src', data.url); + }) + } +}) \ No newline at end of file diff --git a/app/assets/javascripts/admins/ec_templates/index.js b/app/assets/javascripts/admins/ec_templates/index.js new file mode 100644 index 000000000..88ac29f58 --- /dev/null +++ b/app/assets/javascripts/admins/ec_templates/index.js @@ -0,0 +1,70 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-ec-templates-index-page').length > 0) { + var add_modal = $(".ec-templates-new-add"); + var template_file_name = add_modal.find(".template-file-upload"); + var attachment_id_input = add_modal.find(".template_attachment_id"); + var template_container = $(".ec-templates-list-container"); + + //编辑附件 + template_container.on("click", ".edit-template-content", function () { + var t_id = $(this).attr("data-id"); + var t_name = $(this).attr("data-name"); + var template_name = $(this).attr("data-template-name"); + var t_msg = $(this).attr("data-msg"); + var template_id = $(this).attr("data-template-id"); + add_modal.modal("show"); + add_modal.find(".template_add_title").html(t_msg); + attachment_id_input.val(template_id); + add_modal.find(".template_show_id").val(t_id); + add_modal.find("input[name='name']").val(t_name); + add_modal.find("i.delete-template-icon").attr("data-id", template_id); + if(template_id !== "-1"){ + template_file_name.find("span.template-file-input").hide(); + template_file_name.find("span.template_file_show").show(); + template_file_name.find("span.template_file_show_title").html(template_name); + } + }); + + + //删除附件 + add_modal.on("click",".delete-template-icon",function () { + var attachment_id = $(this).attr("data-id"); + $.ajax({ + url: "/api/attachments/" + attachment_id, + type: "delete", + contentType:"application/json", + dataType:"json", + success: function (data) { + template_file_name.find("span.template-file-input").show(); + template_file_name.find("span.template_file_show").hide(); + attachment_id_input.attr("value","-1") + } + }) + }); + + //上传附件 + add_modal.on("change", "#upload_template_file",function () { + + var template = document.getElementById('upload_template_file').files[0]; + + var file_content = new FormData(); + + file_content.append("file", template); + + $.ajax({ + type: "POST", + url: "/api/attachments", + data:file_content, + contentType: false, + processData: false, + success: function (data) { + template_file_name.find("span.template-file-input").hide(); + template_file_name.find("span.template_file_show").show(); + template_file_name.find("span.template_file_show_title").html(template.name); + template_file_name.find("i.delete-template-icon").attr("data-id",data.id); + attachment_id_input.val(data.id) + } + }) + }) + } +}); diff --git a/app/assets/javascripts/admins/graduation_standards/index.js b/app/assets/javascripts/admins/graduation_standards/index.js new file mode 100644 index 000000000..c5b1c2da5 --- /dev/null +++ b/app/assets/javascripts/admins/graduation_standards/index.js @@ -0,0 +1,13 @@ +$(document).on('turbolinks:load', function() { + if($(".admins-graduation-standards-index-page").length > 0){ + $(".admin-body-container").on("click", ".standard-create-modal", function () { + var content = $(this).attr("data-content"); + var g_id = $(this).attr("data-id"); + var g_msg = $(this).attr("data-msg"); + + $("#graduation-modal-type").html(g_msg); + $("#graduation_standard_id").val(g_id); + $("textarea[name='content']").val(content); + }) + } +}); \ No newline at end of file diff --git a/app/assets/javascripts/admins/help-center.js b/app/assets/javascripts/admins/help-center.js new file mode 100644 index 000000000..5fd6055df --- /dev/null +++ b/app/assets/javascripts/admins/help-center.js @@ -0,0 +1,5 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-help-centers-edit-page, body.admins-help-centers-update-page').length > 0) { + createMDEditor('help-center-editor', {}); + } +}) \ No newline at end of file diff --git a/app/assets/javascripts/admins/identity_authentications/index.js b/app/assets/javascripts/admins/identity_authentications/index.js index 91ce5c7ec..2957e4728 100644 --- a/app/assets/javascripts/admins/identity_authentications/index.js +++ b/app/assets/javascripts/admins/identity_authentications/index.js @@ -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' }); + } + }) + } + }) + }) } }) \ No newline at end of file diff --git a/app/assets/javascripts/admins/major_informations/index.js b/app/assets/javascripts/admins/major_informations/index.js new file mode 100644 index 000000000..f0ab9c5f5 --- /dev/null +++ b/app/assets/javascripts/admins/major_informations/index.js @@ -0,0 +1,13 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-major-informations-index-page').length > 0) { + var box_contain = $(".major-informations-list-container"); + box_contain.on("click",".collapse-item",function () { + var a_fa = $(this).find("i"); + if(a_fa.hasClass("fa-caret-right")){ + a_fa.removeClass("fa-caret-right").addClass("fa-caret-down"); + }else{ + a_fa.removeClass("fa-caret-down").addClass("fa-caret-right"); + } + }); + } +}); \ No newline at end of file diff --git a/app/assets/javascripts/admins/message-modal.js b/app/assets/javascripts/admins/message-modal.js index 227d75776..2c9ce27a7 100644 --- a/app/assets/javascripts/admins/message-modal.js +++ b/app/assets/javascripts/admins/message-modal.js @@ -1,14 +1,22 @@ $(document).on('turbolinks:load', function() { var $modal = $('.modal.admin-message-modal'); + var $submitBtn = $modal.find('.submit-btn'); if ($modal.length > 0) { $modal.on('hide.bs.modal', function(){ $modal.find('.modal-body').html(''); + $submitBtn.unbind(); }); } }); -function showMessageModal(html) { +function showMessageModal(html, callback) { var $modal = $('.modal.admin-message-modal'); + var $submitBtn = $modal.find('.submit-btn'); + $submitBtn.unbind(); + if(callback !== undefined && typeof callback === 'function'){ + $submitBtn.on('click', callback); + } + $modal.find('.modal-body').html(html); $modal.modal('show'); } \ No newline at end of file diff --git a/app/assets/javascripts/admins/modals/admin-import-customer-member-modal.js b/app/assets/javascripts/admins/modals/admin-import-customer-member-modal.js new file mode 100644 index 000000000..01038c7de --- /dev/null +++ b/app/assets/javascripts/admins/modals/admin-import-customer-member-modal.js @@ -0,0 +1,78 @@ +$(document).on('turbolinks:load', function() { + var $modal = $('.modal.admin-import-course-member-modal'); + if ($modal.length > 0) { + var $form = $modal.find('form.admin-import-course-member-form'); + + var resetFileInputFunc = function(file){ + file.after(file.clone().val("")); + file.remove(); + } + + $modal.on('show.bs.modal', function(){ + $modal.find('.file-names').html('选择文件'); + $modal.find('.upload-file-input').trigger('click'); + }); + $modal.on('hide.bs.modal', function(){ + resetFileInputFunc($modal.find('.upload-file-input')); + }); + $modal.on('change', '.upload-file-input', function(e){ + var file = $(this)[0].files[0]; + $modal.find('.file-names').html(file ? file.name : '请选择文件'); + }) + + var importFormValid = function(){ + if($form.find('input[name="file"]').val() == undefined || $form.find('input[name="file"]').val().length == 0){ + $form.find('.error').html('请选择文件'); + return false; + } + + return true; + }; + + var buildResultMessage = function(data){ + var messageHtml = "
数据 | 失败原因 |
---|---|
' + item.data + ' | ' + item.message + ' |
[#{params[:question_kind]}]
问题页面网址:#{params[:url]}
#{params[:description]}" + + ActiveRecord::Base.transaction do + attr = { sender_id: User.current.id, receiver_id: 1, content: content, send_time: Time.now } + PrivateMessage.create!(attr.merge(user_id: User.current.id, target_id: 1, status: 1)) + PrivateMessage.create!(attr.merge(user_id: 1, target_id: User.current.id, status: 0)) + end + + render_ok + end + + private + + def current_help + @_current_help ||= Help.first + end +end \ No newline at end of file diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 37cfed3fb..665eaa294 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -29,7 +29,7 @@ class HomeController < ApplicationController @subjects = Subject.where(homepage_show: 1).includes(:shixuns, :repertoire).limit(8) @tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc") - @stu_users = User.includes(:user_extension).where(user_extensions: {identity: 1}).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 def search diff --git a/app/controllers/homework_banks_controller.rb b/app/controllers/homework_banks_controller.rb index 7e10509ba..61bded033 100644 --- a/app/controllers/homework_banks_controller.rb +++ b/app/controllers/homework_banks_controller.rb @@ -1,6 +1,6 @@ class HomeworkBanksController < ApplicationController before_action :require_login - before_action :find_bank + before_action :find_bank, :bank_visit_auth before_action :bank_params, only: [:update] before_action :bank_admin, only: [:update, :destroy, :set_public] @@ -44,8 +44,6 @@ class HomeworkBanksController < ApplicationController def find_bank @bank = HomeworkBank.find_by!(id: params[:id]) - tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? || - (current_user.certification_teacher? && @bank.is_public) end def bank_admin @@ -57,8 +55,8 @@ class HomeworkBanksController < ApplicationController tip_exception("description参数不能为空") if params[:homework_bank][:description].blank? if @bank.homework_type == 3 tip_exception("base_on_project参数不能为空") if params[:homework_bank][:base_on_project].nil? - tip_exception("min_num参数不能为空") if params[:homework_bank][:min_num].blank? - tip_exception("max_num参数不能为空") if params[:homework_bank][:max_num].blank? + tip_exception("最小人数不能为空") if params[:homework_bank][:min_num].blank? + tip_exception("最大人数参数不能为空") if params[:homework_bank][:max_num].blank? tip_exception("最小人数不能小于1") if params[:homework_bank][:min_num].to_i < 1 tip_exception("最大人数不能小于最小人数") if params[:homework_bank][:max_num].to_i < params[:homework_bank][:min_num].to_i end diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb index 8268382bd..06ee8feee 100644 --- a/app/controllers/homework_commons_controller.rb +++ b/app/controllers/homework_commons_controller.rb @@ -82,8 +82,9 @@ class HomeworkCommonsController < ApplicationController end @task_count = @homework_commons.size - @homework_commons = @homework_commons.order("IF(ISNULL(homework_commons.publish_time),0,1), homework_commons.publish_time DESC, - homework_commons.created_at DESC").page(page).per(15) + order_str = @homework_type == 4 ? "position DESC" : "IF(ISNULL(homework_commons.publish_time),0,1), homework_commons.publish_time DESC, + homework_commons.created_at DESC" + @homework_commons = @homework_commons.order(order_str).page(page).per(15) if @homework_type == 4 @homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings, :shixuns) @@ -112,7 +113,7 @@ class HomeworkCommonsController < ApplicationController if @user_course_identity == Course::STUDENT @work = @homework.user_work(current_user.id) # 学生访问列表时计算个人成绩 - if @homework.homework_type == "practice" + if @homework.homework_type == "practice" && !@homework.end_or_late myshixun = Myshixun.find_by(shixun_id: @shixun.id, user_id: current_user.id) if @work && myshixun challenge_settings = @homework.homework_challenge_settings @@ -926,17 +927,10 @@ class HomeworkCommonsController < ApplicationController unless params[:category_id].blank? @category = @course.course_second_categories.find_by(id: params[:category_id], category_type: "shixun_homework") end - ActiveRecord::Base.transaction do - begin - shixuns.each do |shixun| - homework = HomeworksService.new.create_homework shixun, @course, @category, current_user - @homework_ids << homework.id - end - rescue Exception => e - uid_logger(e.message) - tip_exception("创建失败") - raise ActiveRecord::Rollback - end + shixuns.each do |shixun| + homework = HomeworksService.new.create_homework shixun, @course, @category, current_user + @homework_ids << homework.id + CreateStudentWorkJob.perform_later(homework.id) end end @@ -1017,28 +1011,21 @@ class HomeworkCommonsController < ApplicationController none_shixun_ids = ShixunSchool.where("school_id != #{current_user.school_id}").pluck(:shixun_id) course_module = @course.course_modules.find_by(module_type: "shixun_homework") - ActiveRecord::Base.transaction do - begin - subjects.each do |subject| + subjects.each do |subject| - subject.stages.each do |stage| + subject.stages.each do |stage| - # 为实训作业创建与stage同名的子目录 - category = CourseSecondCategory.find_by(name: stage.name, course_id: @course.id, category_type: "shixun_homework") || - CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework", - course_module_id: course_module.id, position: course_module.course_second_categories.count + 1) + # 为实训作业创建与stage同名的子目录 + category = CourseSecondCategory.find_by(name: stage.name, course_id: @course.id, category_type: "shixun_homework") || + CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework", + course_module_id: course_module.id, position: course_module.course_second_categories.count + 1) - # 去掉不对当前用户的单位公开的实训,已发布的实训 - stage.shixuns.where.not(shixuns: {id: none_shixun_ids}).unhidden.each do |shixun| - homework = HomeworksService.new.create_homework shixun, @course, category, current_user - @homework_ids << homework.id - end - end + # 去掉不对当前用户的单位公开的实训,已发布的实训 + stage.shixuns.where.not(shixuns: {id: none_shixun_ids}).unhidden.each do |shixun| + homework = HomeworksService.new.create_homework shixun, @course, category, current_user + @homework_ids << homework.id + CreateStudentWorkJob.perform_later(homework.id) end - rescue Exception => e - uid_logger(e.message) - tip_exception("创建失败") - raise ActiveRecord::Rollback end end end @@ -1067,7 +1054,7 @@ class HomeworkCommonsController < ApplicationController charge_group_ids = @course.charge_group_ids(current_user) publish_groups = charge_group_ids & params[:group_ids] if params[:group_ids] - ActiveRecord::Base.transaction do + # ActiveRecord::Base.transaction do begin homeworks.each do |homework| # 作业未发布时 @@ -1138,7 +1125,7 @@ class HomeworkCommonsController < ApplicationController tip_exception("发布失败") raise ActiveRecord::Rollback end - end + # end end def end_groups @@ -1167,9 +1154,9 @@ class HomeworkCommonsController < ApplicationController charge_group_ids = @course.charge_group_ids(current_user) end_groups = charge_group_ids & params[:group_ids] if params[:group_ids] - ActiveRecord::Base.transaction do - begin - homeworks.each do |homework| + begin + homeworks.each do |homework| + ActiveRecord::Base.transaction do homework_detail_manual = homework.homework_detail_manual # 分组设置 @@ -1184,7 +1171,7 @@ class HomeworkCommonsController < ApplicationController none_end_settings.update_all(end_time: time) student_works = homework.student_works.where(user_id: course_students.where(course_group_id: none_end_settings. - pluck(:course_group_id)).pluck(:user_id)).has_committed if homework.homework_type == "practice" + pluck(:course_group_id)).pluck(:user_id)).has_committed if homework.homework_type == "practice" homework.end_time = homework.max_group_end_time if homework.end_time > time && homework_detail_manual.try(:comment_status) > 1 @@ -1207,40 +1194,40 @@ class HomeworkCommonsController < ApplicationController student_works.joins(:myshixun).where("myshixuns.status != 1").update_all(late_penalty: homework.late_penalty) if homework.allow_late =begin - student_works.where("work_status != 0").includes(:myshixun).each do |student_work| - unless student_work.myshixun.is_complete? - student_work.update_attributes(work_status: 2, late_penalty: homework.late_penalty) - student_work.late_penalty = homework.late_penalty - end - HomeworksService.new.set_shixun_final_score student_work, student_work.myshixun, homework_detail_manual.answer_open_evaluation, - homework_challenge_settings + student_works.where("work_status != 0").includes(:myshixun).each do |student_work| + unless student_work.myshixun.is_complete? + student_work.update_attributes(work_status: 2, late_penalty: homework.late_penalty) + student_work.late_penalty = homework.late_penalty end + HomeworksService.new.set_shixun_final_score student_work, student_work.myshixun, homework_detail_manual.answer_open_evaluation, + homework_challenge_settings + end - student_works.where("work_status = 0").each do |student_work| - myshixun = Myshixun.where(shixun_id: shixun.id, user_id: student_work.user_id).first - if myshixun.present? - student_work.update_attributes(work_status: (myshixun.is_complete? ? 1 : 2), - late_penalty: myshixun.is_complete? ? 0 : homework.late_penalty, - commit_time: myshixun.created_at, myshixun_id: myshixun.id) - student_work.late_penalty = myshixun.is_complete? ? 0 : homework.late_penalty - HomeworksService.new.set_shixun_final_score student_work, myshixun, homework_detail_manual.answer_open_evaluation, - homework_challenge_settings - end + student_works.where("work_status = 0").each do |student_work| + myshixun = Myshixun.where(shixun_id: shixun.id, user_id: student_work.user_id).first + if myshixun.present? + student_work.update_attributes(work_status: (myshixun.is_complete? ? 1 : 2), + late_penalty: myshixun.is_complete? ? 0 : homework.late_penalty, + commit_time: myshixun.created_at, myshixun_id: myshixun.id) + student_work.late_penalty = myshixun.is_complete? ? 0 : homework.late_penalty + HomeworksService.new.set_shixun_final_score student_work, myshixun, homework_detail_manual.answer_open_evaluation, + homework_challenge_settings end + end =end # 更新所有学生的效率分(重新取homework确保是更新后的) - HomeworkEndUpdateScoreJob.perform_later(homework.id) if !homework.allow_late && homework.end_time <= time end end homework.save! end - normal_status(0, "更新成功") - rescue Exception => e - uid_logger(e.message) - tip_exception("操作失败") - raise ActiveRecord::Rollback + HomeworkEndUpdateScoreJob.perform_later(homework.id) if !homework.allow_late && homework.end_time <= time end + normal_status(0, "更新成功") + rescue Exception => e + uid_logger(e.message) + tip_exception("操作失败") + raise ActiveRecord::Rollback end end diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb index 69bd01dde..bf067b389 100644 --- a/app/controllers/myshixuns_controller.rb +++ b/app/controllers/myshixuns_controller.rb @@ -25,7 +25,8 @@ class MyshixunsController < ApplicationController begin @shixun = Shixun.select(:id, :identifier, :challenges_count).find(@myshixun.shixun_id) @myshixun.destroy! - StudentWork.where(:myshixun_id => @myshixun.id).update_all(:myshixun_id => 0, :work_status => 0) + StudentWork.where(:myshixun_id => @myshixun.id).update_all(myshixun_id: 0, work_status: 0, work_score: nil, + final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, cost_time: 0, compelete_status: 0) rescue Exception => e logger.error("######reset_my_game_failed:#{e.message}") raise("ActiveRecord::RecordInvalid") @@ -266,10 +267,15 @@ class MyshixunsController < ApplicationController :identifier => @sec_key, :exec_time => exec_time) uid_logger("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") end - unless @hide_code + # 隐藏代码文件 和 VNC的都不需要走版本库 + unless @hide_code || @myshixun.shixun&.vnc_evaluate # 远程版本库文件内容 last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"] - content = params[:content] + content = if @myshixun.mirror_name.select {|a| a.include?("MachineLearning") || a.include?("Python")}.present? && params[:content].present? + params[:content].gsub(/\t/, ' ').gsub(/ /, ' ') # 这个不是空格,在windows机器上带来的问题 + else + params[:content] + end Rails.logger.info("###11222333####{content}") Rails.logger.info("###222333####{last_content}") diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index 7cb7ee800..6ffe277a3 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -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) diff --git a/app/controllers/project_packages_controller.rb b/app/controllers/project_packages_controller.rb index 3cc7e79cb..c8b010b32 100644 --- a/app/controllers/project_packages_controller.rb +++ b/app/controllers/project_packages_controller.rb @@ -55,7 +55,7 @@ class ProjectPackagesController < ApplicationController package.destroy! - Tiding.create!(user_id: package.creator_id, trigger_user_id: 1, container_id: package.id, + Tiding.create!(user_id: package.creator_id, trigger_user_id: 0, container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'Destroyed', extra: package.title) render_ok diff --git a/app/controllers/question_banks_controller.rb b/app/controllers/question_banks_controller.rb index f09a53dbe..60b9a807c 100644 --- a/app/controllers/question_banks_controller.rb +++ b/app/controllers/question_banks_controller.rb @@ -88,7 +88,7 @@ class QuestionBanksController < ApplicationController end def send_to_course - banks = object_banks + banks = @object_type.classify.constantize.where(id: params[:object_id]) course = current_user.manage_courses.find_by!(id: params[:course_id]) banks.each do |bank| case @object_type @@ -264,7 +264,9 @@ class QuestionBanksController < ApplicationController # new_exercise.create_exercise_list # exercise.update_column(:quotes, exercise.quotes+1) # end - new_exercise if new_exercise.save! + new_exercise.save! + exercise.update_column(:quotes, exercise.quotes+1) + new_exercise end end @@ -291,7 +293,9 @@ class QuestionBanksController < ApplicationController # new_poll.create_polls_list # poll.update_column(:quotes, poll.quotes+1) # end - new_poll if new_poll.save! + new_poll.save! + poll.update_column(:quotes, poll.quotes+1) + new_poll end end diff --git a/app/controllers/shixun_lists_controller.rb b/app/controllers/shixun_lists_controller.rb new file mode 100644 index 000000000..e92e857ad --- /dev/null +++ b/app/controllers/shixun_lists_controller.rb @@ -0,0 +1,10 @@ +class ShixunListsController < ApplicationController + def index + @results = ShixunSearchService.call(search_params) + end + + private + def search_params + params.permit(:keyword, :type, :page, :limit, :order, :type, :status, :diff) + end +end \ No newline at end of file diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb index 8591f9821..8a120d6bd 100644 --- a/app/controllers/shixuns_controller.rb +++ b/app/controllers/shixuns_controller.rb @@ -1,6 +1,7 @@ class ShixunsController < ApplicationController include ShixunsHelper include ApplicationHelper + include ElasticsearchAble before_action :require_login, :check_auth, except: [:download_file, :index, :menus, :show, :show_right, :ranking_list, :discusses, :collaborators, :fork_list, :propaedeutics] @@ -8,11 +9,11 @@ class ShixunsController < ApplicationController before_action :find_shixun, except: [:index, :new, :create, :menus, :get_recommend_shixuns, :propaedeutics, :departments, :apply_shixun_mirror, - :get_mirror_script, :download_file] + :get_mirror_script, :download_file, :shixun_list] before_action :shixun_access_allowed, except: [:index, :new, :create, :menus, :get_recommend_shixuns, :propaedeutics, :departments, :apply_shixun_mirror, - :get_mirror_script, :download_file] + :get_mirror_script, :download_file, :shixun_list] before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy, :add_file] before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish, @@ -98,6 +99,53 @@ class ShixunsController < ApplicationController .each_with_object({}) { |r, obj| obj[r.shixun_id] = r.name } end + def shixun_list + # 全部实训/我的实训 + type = params[:type] || "all" + # 状态:已发布/未发布 + status = params[:status] || "all" + + # 超级管理员用户显示所有未隐藏的实训、非管理员显示所有已发布的实训(对本单位公开且未隐藏未关闭) + if type == "mine" + @shixuns = current_user.shixuns.none_closed + else + if current_user.admin? + @shixuns = Shixun.none_closed.where(hidden: 0) + else + none_shixun_ids = ShixunSchool.where("school_id != #{current_user.school_id}").pluck(:shixun_id) + + @shixuns = Shixun.where.not(id: none_shixun_ids).none_closed.where(hidden: 0) + end + end + + unless status == "all" + @shixuns = status == "published" ? @shixuns.where(status: 2) : @shixuns.where(status: [0, 1]) + end + + ## 筛选 难度 + if params[:diff].present? && params[:diff].to_i != 0 + @shixuns = @shixuns.where(trainee: params[:diff]) + end + + page = params[:page] || 1 + limit = params[:limit] || 10 + offset = (page.to_i - 1) * (limit.to_i) + order = params[:order] || "desc" + ## 搜索关键字创建者、实训名称、院校名称 + keyword = params[:keyword].to_s.strip.presence || '*' + + model_options = { + index_name: [Shixun], + model_includes: Shixun.searchable_includes + } + model_options.merge(where: { id: @shixuns.pluck(:id) }).merge(order: {"myshixuns_count" => order}).merge(limit: limit, offset: offset) + model_options.merge(default_options) + @shixuns = Searchkick.search(keyword, model_options) + # @shixuns = Shixun.search keyword, where: {id: @shixuns.pluck(:id)}, order: {"myshixuns_count" => order}, limit: limit, offset: offset + + @total_count = @shixuns.total_count + end + ## 获取顶部菜单 def menus @repertoires = Repertoire.includes(sub_repertoires: [:tag_repertoires]).order("updated_at asc") @@ -181,6 +229,16 @@ class ShixunsController < ApplicationController evaluate_script: @shixun.evaluate_script) end + # 同步私密版本库 + if @shixun.shixun_secret_repository + repo_name = "#{current_user.login}/secret_#{@shixun.identifier}" + fork_repository_name = "#{current_user.login}/secret_#{@new_shixun.identifier}" + ShixunSecretRepository.create!(shixun_id: @new_shixun.id, + repo_name: "#{repo_name}", + secret_dir_path: @shixun.shixun_secret_repository.secret_dir_path) + GitService.fork_repository(repo_path: "#{repo_name}.git", fork_repository_path: (fork_repository_name + ".git")) + end + # 同步镜像 if @shixun.mirror_repositories.present? @shixun.mirror_repositories.each do |mirror| @@ -409,6 +467,7 @@ class ShixunsController < ApplicationController ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror) end end + logger.info("#########shixun_params#{shixun_params}") @shixun.update_attributes(shixun_params) logger.info("##########shixun_info_params: #{shixun_info_params}") logger.info("##########params[:shixun_info][:evaluate_script]: #{params[:shixun_info][:evaluate_script]}") @@ -424,17 +483,31 @@ class ShixunsController < ApplicationController ShixunSchool.create!(arr) end # 超级管理员和运营人员才能保存 中间层服务器pod信息的配置 - if current_user.admin? || current_user.business? + # 如果镜像改动了,则也需要更改 + mirror = @shixun.shixun_service_configs.map(&:mirror_repository_id).sort + new_mirror = params[:shixun_service_configs].map{|c| c[:mirror_repository_id]}.sort + if current_user.admin? || current_user.business? || (mirror != new_mirror) @shixun.shixun_service_configs.destroy_all service_config_params[:shixun_service_configs].each do |config| - logger.info("####{config[:mirror_repository_id]}") name = MirrorRepository.find_by_id(config[:mirror_repository_id])&.name # 不保存没有镜像的配置 @shixun.shixun_service_configs.create!(config) if name.present? end end + # 添加第二仓库 + if params[:is_secret_repository] + add_secret_repository + else + # 如果有仓库,就要删 + if @shixun.shixun_secret_repository&.repo_name + @shixun.shixun_secret_repository.lock! + GitService.delete_repository(repo_path: @shixun.shixun_secret_repository.repo_path) + @shixun.shixun_secret_repository.destroy + end + end + rescue Exception => e - uid_logger_error(e.message) + uid_logger_error("实训保存失败--------#{e.message}") tip_exception("实训保存失败") raise ActiveRecord::Rollback end @@ -601,7 +674,7 @@ class ShixunsController < ApplicationController challenges.each_with_index do |challenge, index| status = (index == 0 ? 0 : 3) game_identifier = generate_identifier(Game, 12) - worker.add(base_attr.merge(challenge_id: challenge.id, status: status, open_time: Time.now, + worker.add(base_attr.merge(challenge_id: challenge.id, status: status, identifier: game_identifier, modify_time: challenge.modify_time)) end end @@ -779,6 +852,30 @@ class ShixunsController < ApplicationController end end + # 设置私密版本库的在tpm中的目录 + def set_secret_dir + raise("设置路径不能为空") if params[:secret_dir_path].blank? + raise("请先配置私密版本库") if @shixun.shixun_secret_repository.blank? + @shixun.shixun_secret_repository.update_attributes(:secret_dir_path => params[:secret_dir_path]) + normal_status("设置成功") + end + + def secret_repository + begin + @repo_path = @shixun.shixun_secret_repository&.repo_path + @repo_url = repo_url @repo_path + @trees = GitService.file_tree(repo_path: @repo_path, path: params[:path]) + logger.info("#11@@#@#@#@111#@@@@###{@trees}") + if @trees + logger.info("#@@#@#@#@#@@@@###{@trees.try(:count)}") + @latest_commit = [GitService.commits(repo_path: @repo_path).first] + Rails.logger.info("########## #{@latest_commit}") + end + rescue Exception => e + logger.error(e.message) + end + end + include GitCommon def update_file @@ -865,6 +962,7 @@ class ShixunsController < ApplicationController def send_to_course @course = Course.find(params[:course_id]) homework = HomeworksService.new.create_homework @shixun, @course, nil, current_user + CreateStudentWorkJob.perform_later(homework.id) end # 二维码扫描下载 @@ -891,7 +989,7 @@ private raise("实训名称不能为空") if params[:shixun][:name].blank? params.require(:shixun).permit(:name, :trainee, :webssh, :can_copy, :use_scope, :vnc, :test_set_permission, :task_pass, :multi_webssh, :opening_time, :mirror_script_id, :code_hidden, - :hide_code, :forbid_copy) + :hide_code, :forbid_copy, :vnc_evaluate, :code_edit_permission) end def shixun_info_params @@ -914,7 +1012,13 @@ private end def find_repo_name - @repo_path = @shixun.try(:repo_path) + # 有私密版本库的参数时,需要拿私密仓库 + @repo_path = if params[:secret_repository] + @shixun.shixun_secret_repository&.repo_path + else + @shixun.try(:repo_path) + end + logger.info("######{@repo_path}") @path = params[:path] end @@ -949,4 +1053,13 @@ private modify_shixun = ShixunModify.exists?(:myshixun_id => current_myshixun.id, :shixun_id => @shixun.id, :status => 1) games.size != min_challenges.size || modify_shixun end + + # 添加私密仓库 + def add_secret_repository + # 防止跟tpm版本库重名,加了前缀secret + repo_path = repo_namespace(current_user.login, "secret_#{@shixun.identifier}") + GitService.add_repository(repo_path: repo_path) + ShixunSecretRepository.create!(repo_name: repo_path.split(".")[0], shixun_id: @shixun.id) + end + end diff --git a/app/controllers/student_works_controller.rb b/app/controllers/student_works_controller.rb index 99a02106c..2612510c5 100644 --- a/app/controllers/student_works_controller.rb +++ b/app/controllers/student_works_controller.rb @@ -8,12 +8,15 @@ class StudentWorksController < ApplicationController before_action :find_work, only: [:shixun_work_report, :adjust_review_score, :shixun_work, :commit_des, :update_des, :adjust_score, :show, :adjust_score, :supply_attachments, :revise_attachment, :comment_list, :add_score, :add_score_reply, :destroy_score, :appeal_anonymous_score, - :deal_appeal_score, :cancel_appeal, :edit, :update, :export_shixun_work_report] + :deal_appeal_score, :cancel_appeal, :edit, :update, :export_shixun_work_report, + :shixun_work_comment, :destroy_work_comment] before_action :user_course_identity before_action :allow_add_score, only: [:add_score] before_action :homework_publish - before_action :teacher_allowed, only: [:adjust_score, :adjust_review_score, :deal_appeal_score] + before_action :teacher_allowed, only: [:adjust_score, :adjust_review_score, :deal_appeal_score, :shixun_work_comment, + :destroy_work_comment] + before_action :course_student, only: [:new, :commit_des, :update_des, :create, :edit, :update, :search_member_list, :relate_project, :cancel_relate_project, :relate_project, :delete_work] @@ -318,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? @@ -455,6 +459,7 @@ class StudentWorksController < ApplicationController @shixun = @homework.shixuns.take # 提示: 这里如果includes outputs表的话: sum(:evaluate_count)会出现错误 @games = @work.myshixun.games.joins(:challenge).reorder("challenges.position asc") if @work.myshixun + @comment = @work.shixun_work_comments.find_by(challenge_id: 0) # 用户最大评测次数 if @games @@ -468,6 +473,41 @@ class StudentWorksController < ApplicationController @echart_data = student_efficiency(@homework, @work) end + # 实训作品的评阅 + def shixun_work_comment + tip_exception("请至少输入一个评阅") if params[:comment].blank? && params[:hidden_comment].blank? + ActiveRecord::Base.transaction do + challenge = @homework.shixuns.first&.challenges.find_by(id: params[:challenge_id]) unless params[:challenge_id].blank? + if challenge.present? + @comment = @work.shixun_work_comments.find_by(challenge_id: challenge.id) || + ShixunWorkComment.new(student_work_id: @work.id, user_id: current_user.id, challenge_id: challenge.id) + else + @comment = @work.shixun_work_comments.find_by(challenge_id: 0) || + ShixunWorkComment.new(student_work_id: @work.id, user_id: current_user.id, challenge_id: 0) + end + @comment.comment = params[:comment] + @comment.hidden_comment = params[:hidden_comment] + @comment.save! + end + end + + # 删除实训作品评阅 + def destroy_work_comment + ActiveRecord::Base.transaction do + # tip_exception("visible_comment参数有误") if params[:visible_comment].nil? + + comment = @work.shixun_work_comments.find_by!(id: params[:comment_id]) + comment.destroy! + # params[:visible_comment] ? comment.comment = nil : comment.hidden_comment = nil + # if comment.comment.nil? && comment.hidden_comment.nil? + # comment.destroy! + # else + # comment.save! + # end + normal_status("删除成功") + end + end + def export_shixun_work_report @user = @work.user @shixun = @homework.shixuns.take diff --git a/app/controllers/subjects_controller.rb b/app/controllers/subjects_controller.rb index d97b7172c..b7b208842 100644 --- a/app/controllers/subjects_controller.rb +++ b/app/controllers/subjects_controller.rb @@ -203,25 +203,24 @@ class SubjectsController < ApplicationController stages = @subject.stages.where(id: @subject.stage_shixuns.where(shixun_id: params[:shixun_ids]).pluck(:stage_id)) course_module = @course.course_modules.where(module_type: "shixun_homework").first + homework_ids = [] ActiveRecord::Base.transaction do - begin - # 将实训课程下的所有已发布实训按顺序发送到课堂,同时创建与章节同名的实训作业目录 - stages.each do |stage| - category = CourseSecondCategory.where(name: stage.name, course_id: @course.id, category_type: "shixun_homework").first || - CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework", - course_module_id: course_module.id, position: course_module.course_second_categories.count + 1) - - stage.shixuns.where(id: params[:shixun_ids], status: 2).each do |shixun| - homework = HomeworksService.new.create_homework shixun, @course, category, current_user - end + # 将实训课程下的所有已发布实训按顺序发送到课堂,同时创建与章节同名的实训作业目录 + stages.each do |stage| + category = CourseSecondCategory.where(name: stage.name, course_id: @course.id, category_type: "shixun_homework").first || + CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework", + course_module_id: course_module.id, position: course_module.course_second_categories.count + 1) + + stage.shixuns.where(id: params[:shixun_ids], status: 2).each do |shixun| + homework = HomeworksService.new.create_homework shixun, @course, category, current_user + homework_ids << homework.id end - rescue Exception => e - uid_logger(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback end end + homework_ids.each do |homework_id| + CreateStudentWorkJob.perform_later(homework_id) + end end def publish @@ -369,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}) @@ -416,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? @@ -441,8 +454,8 @@ class SubjectsController < ApplicationController # 用户进展和获取的标签 def user_subject_progress challenge_ids pass_games = Game.select(:id, :cost_time, :challenge_id).where(status: 2, user_id: current_user.id, challenge_id: challenge_ids) if current_user.logged? - @all_score = Challenge.where(id: challenge_ids).sum(:score) + @all_score = Challenge.where(id: challenge_ids).size # 如果没有通关的,没必要再继续统计了 if pass_games.blank? @my_score = 0 @@ -451,15 +464,15 @@ class SubjectsController < ApplicationController @user_tags = [] else pass_challenge_ids = pass_games.map(&:challenge_id).uniq # 按道理是不用去重的,但是历史数据与重复 - subject_challenge_count = @subject.shixuns.sum(:challenges_count) + # subject_challenge_count = @subject.shixuns.sum(:challenges_count) # 用户通关获得的标签 @user_tags = ChallengeTag.where(challenge_id: pass_challenge_ids).pluck(:name) # 用户学习进度 @learned = - subject_challenge_count == 0 ? 0 : - ((pass_challenge_ids.size.to_f / subject_challenge_count).round(2) * 100).to_i + @all_score == 0 ? 0 : + ((pass_challenge_ids.size.to_f / @all_score).round(2) * 100).to_i # 用户通关分数 - @my_score = Challenge.where(id: pass_challenge_ids).pluck(:score).sum + @my_score = Challenge.where(id: pass_challenge_ids).size @time = pass_games.map(&:cost_time).sum end diff --git a/app/controllers/task_banks_controller.rb b/app/controllers/task_banks_controller.rb index e2e7f0a1a..2b1a400ef 100644 --- a/app/controllers/task_banks_controller.rb +++ b/app/controllers/task_banks_controller.rb @@ -1,6 +1,7 @@ class TaskBanksController < ApplicationController before_action :require_login - before_action :find_bank + before_action :find_bank, :bank_visit_auth + before_action :bank_visit_auth before_action :bank_admin, only: [:update] def show @@ -25,8 +26,6 @@ class TaskBanksController < ApplicationController def find_bank @bank = GtaskBank.find_by!(id: params[:id]) - tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? || - (current_user.certification_teacher? && @bank.is_public) end def bank_admin @@ -36,14 +35,17 @@ class TaskBanksController < ApplicationController def gtask_bank_params tip_exception("name参数不能为空") if params[:gtask_bank][:name].blank? tip_exception("description参数不能为空") if params[:gtask_bank][:description].blank? - if @bank.homework_type == 3 + if @bank.task_type == 2 tip_exception("base_on_project参数不能为空") if params[:gtask_bank][:base_on_project].nil? tip_exception("min_num参数不能为空") if params[:gtask_bank][:min_num].blank? tip_exception("max_num参数不能为空") if params[:gtask_bank][:max_num].blank? tip_exception("最小人数不能小于1") if params[:gtask_bank][:min_num].to_i < 1 tip_exception("最大人数不能小于最小人数") if params[:gtask_bank][:max_num].to_i < params[:gtask_bank][:min_num].to_i end - params.require(:gtask_bank).permit(:name, :description) if @bank.task_type == 1 - params.require(:gtask_bank).permit(:name, :description, :min_num, :max_num, :base_on_project) if @bank.task_type == 2 + if @bank.task_type == 1 + params.require(:gtask_bank).permit(:name, :description) + else + params.require(:gtask_bank).permit(:name, :description, :min_num, :max_num, :base_on_project) + end end end diff --git a/app/controllers/users/base_controller.rb b/app/controllers/users/base_controller.rb index 3ba6940f5..128dc539b 100644 --- a/app/controllers/users/base_controller.rb +++ b/app/controllers/users/base_controller.rb @@ -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 diff --git a/app/controllers/users/question_banks_controller.rb b/app/controllers/users/question_banks_controller.rb index d2f111973..c5b837d0b 100644 --- a/app/controllers/users/question_banks_controller.rb +++ b/app/controllers/users/question_banks_controller.rb @@ -1,10 +1,12 @@ class Users::QuestionBanksController < Users::BaseController before_action :require_login + skip_before_action :check_observed_user_exists! + # before_action :private_user_resources! before_action :check_query_params! before_action :check_user_permission! def index - service = Users::QuestionBankService.new(observed_user, query_params) + service = Users::QuestionBankService.new(User.current, query_params) question_banks = service.call @count = question_banks.count @@ -29,7 +31,7 @@ class Users::QuestionBanksController < Users::BaseController .where(commit_status: 1, exercises: { exercise_bank_id: question_bank_ids }) .group('exercises.exercise_bank_id').count when 'poll' then - PollUser.joins(:poll).where(polls: { exercise_bank_id: question_bank_ids }) + PollUser.joins(:poll).where(commit_status: 1, polls: { exercise_bank_id: question_bank_ids }) .group('polls.exercise_bank_id').count when 'gtask' then GraduationWork.has_committed.joins(:graduation_task) @@ -64,7 +66,7 @@ class Users::QuestionBanksController < Users::BaseController def check_user_permission! if params[:type] == 'publicly' - render_error("未通过职业认证") unless User.current.admin? || User.current.certification_teacher? + normal_status(-2,"未通过职业认证") unless User.current.admin? || User.current.certification_teacher? else render_forbidden unless User.current.admin? || User.current.is_teacher? end diff --git a/app/controllers/wechats/js_sdk_signatures_controller.rb b/app/controllers/wechats/js_sdk_signatures_controller.rb new file mode 100644 index 000000000..0b66cc263 --- /dev/null +++ b/app/controllers/wechats/js_sdk_signatures_controller.rb @@ -0,0 +1,11 @@ +class Wechats::JsSdkSignaturesController < ApplicationController + def create + timestamp = Time.now.to_i + noncestr = ('A'..'z').to_a.sample(8).join + signature = Util::Wechat.js_sdk_signature(params[:url], noncestr, timestamp) + + render_ok(appid: Util::Wechat.appid, timestamp: timestamp, noncestr: noncestr, signature: signature) + rescue Util::Wechat::Error => ex + render_error(ex.message) + end +end \ No newline at end of file diff --git a/app/decorators/tiding_decorator.rb b/app/decorators/tiding_decorator.rb index 81093dc12..b4f851e5f 100644 --- a/app/decorators/tiding_decorator.rb +++ b/app/decorators/tiding_decorator.rb @@ -81,12 +81,12 @@ module TidingDecorator end def student_join_course_content - I18n.t(locale_format) % Course.find_by(id: container_id)&.name + I18n.t(locale_format) % [trigger_user.show_real_name, Course.find_by(id: container_id)&.name] end def teacher_join_course_content name = Course.find_by(id: container_id)&.name - I18n.t(locale_format extra) % [user.show_real_name, name] + I18n.t(locale_format extra) % [trigger_user&.show_real_name, name] end def apply_add_department_content @@ -258,7 +258,7 @@ module TidingDecorator def manager_join_project_content project = Project.find_by(id: container_id) - I18n.t(locale_format(extra)) % [user&.show_real_name, project.name] + I18n.t(locale_format(extra)) % [trigger_user&.show_real_name, project.name] end def reporter_join_project_content @@ -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 diff --git a/app/helpers/admins/base_helper.rb b/app/helpers/admins/base_helper.rb index c655be2e7..d79456ac8 100644 --- a/app/helpers/admins/base_helper.rb +++ b/app/helpers/admins/base_helper.rb @@ -18,7 +18,7 @@ module Admins::BaseHelper def sidebar_item(url, text, **opts) content = link_to url, 'data-controller': opts[:controller] do - content_tag(:i, '', class: "fa fa-#{opts[:icon]}", 'data-toggle': 'tooltip', 'data-placement': 'right', 'data-boundary': 'window', title: text) + + content_tag(:i, '', class: "fa fa-#{opts[:icon]} fa-fw", 'data-toggle': 'tooltip', 'data-placement': 'right', 'data-boundary': 'window', title: text) + content_tag(:span, text) end @@ -87,16 +87,24 @@ module Admins::BaseHelper raw link_to(name, url, { method: :post, remote: true, class: klass, 'data-confirm': '确认审核通过?'}.merge(opts)) end - def delete_link(name, url, **opts) + def delete_link(name, url, **opts, &block) klass = ['action delete-action', opts.delete(:class)].compact.join(' ') refresh_url_data = "refresh_url=#{CGI::escape(request.fullpath)}" url = url + (url.index('?') ? '&' : '?') + refresh_url_data - raw link_to(name, url, { method: :delete, remote: true, class: klass, 'data-confirm': '确认删除?'}.merge(opts)) + if block_given? + raw link_to(url, { method: :delete, remote: true, class: klass, 'data-confirm': '确认删除?'}.merge(opts), &block) + else + raw link_to(name, url, { method: :delete, remote: true, class: klass, 'data-confirm': '确认删除?'}.merge(opts)) + end end def unsafe_params params.except(:controller, :action).to_unsafe_h end + + def list_index_no(page,index) + (page - 1) * 20 + index + 1 + end end \ No newline at end of file diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 44169dc59..dbdcaea40 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -56,11 +56,6 @@ module ApplicationHelper end - # 相关推荐 - def relation_path(shixun) - shixun.subjects.where(hidden: 0).limit(2) - end - # shixun开启挑战对应的行为名及url def task_operation_url current_myshixun, shixun if current_myshixun.blank? @@ -131,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" diff --git a/app/helpers/course_stages_helper.rb b/app/helpers/course_stages_helper.rb new file mode 100644 index 000000000..7ebb68d9a --- /dev/null +++ b/app/helpers/course_stages_helper.rb @@ -0,0 +1,2 @@ +module CourseStagesHelper +end diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb index c5d376baf..5ca4eb773 100644 --- a/app/helpers/courses_helper.rb +++ b/app/helpers/courses_helper.rb @@ -108,6 +108,10 @@ module CoursesHelper course_board.present? ? course_board.messages.size : 0 when "course_group" course.course_groups_count + when "announcement" + course.informs.count + when "online_learning" + course.shixuns.count end end @@ -265,10 +269,10 @@ module CoursesHelper group_info end - def last_subject_shixun user_id, subject - myshixun = Myshixun.where(user_id: user_id, shixun_id: subject&.shixuns).order("updated_at desc").first + def last_subject_shixun user_id, course + myshixun = Myshixun.where(user_id: user_id, shixun_id: course.shixuns).order("updated_at desc").first return "" unless myshixun - stage_shixun = subject&.stage_shixuns.where(shixun_id: myshixun.shixun_id).take - progress = stage_shixun&.stage&.position.to_s + "-" + stage_shixun&.position.to_s + " " + myshixun.shixun&.name + stage_shixun = course.course_stage_shixuns.where(shixun_id: myshixun.shixun_id).take + progress = stage_shixun&.course_stage&.position.to_s + "-" + stage_shixun&.position.to_s + " " + myshixun.shixun&.name end end diff --git a/app/helpers/ecs/ec_years_helper.rb b/app/helpers/ecs/ec_years_helper.rb new file mode 100644 index 000000000..108abb0e7 --- /dev/null +++ b/app/helpers/ecs/ec_years_helper.rb @@ -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 \ No newline at end of file diff --git a/app/helpers/exercises_helper.rb b/app/helpers/exercises_helper.rb index 2c417ea74..98a580ecc 100644 --- a/app/helpers/exercises_helper.rb +++ b/app/helpers/exercises_helper.rb @@ -16,18 +16,26 @@ module ExercisesHelper end if q_type <= Exercise::JUDGMENT - if answers_content.present? #学生有回答时 - answer_choice_array = [] - answers_content.each do |a| - answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 - end - user_answer_content = answer_choice_array.sort - standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个 - if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 - ques_score = q.question_score - else - ques_score = 0.0 - end + if answers_content.present? #学生有回答时,分数已经全部存到exercise_answer 表,所以可以直接取第一个值 + ques_score = answers_content.first.score + ques_score = ques_score < 0 ? 0.0 : ques_score + # answer_choice_array = [] + # answers_content.each do |a| + # answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 + # end + # user_answer_content = answer_choice_array.sort + # standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个 + # if q_type == Exercise::MULTIPLE && standard_answer.size == 1 # 老数据的问题 + # ques_score = answers_content.first.score + # else + # + # end + + # if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 + # ques_score = q.question_score + # else + # ques_score = 0.0 + # end else ques_score = 0.0 end @@ -58,7 +66,6 @@ module ExercisesHelper exercise_sub_status.each do |s| sub_answer = s.exercise_answers.search_answer_users("user_id",user_id) #主观题只有一个回答 if sub_answer.present? && sub_answer.first.score >= 0.0 - if s.question_score <= sub_answer.first.score stand_status = 1 else @@ -775,22 +782,24 @@ module ExercisesHelper user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : nil elsif ques_type == 5 || ques_type == 3 user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : 0.0 - else - if exercise_answers.present? #判断题和选择题时, - answer_choice_array = [] - exercise_answers.each do |a| - answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 - end - user_answer_content = answer_choice_array.sort - standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个 - if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 - user_score = q.question_score - else - user_score = 0.0 - end - else - user_score = 0.0 - end + else #选择题,判断题根据第一个记录查分 + user_score = user_score_pre.present? ? user_score_pre.first.score : 0.0 + + # if exercise_answers.present? #判断题和选择题时, + # answer_choice_array = [] + # exercise_answers.each do |a| + # answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 + # end + # user_answer_content = answer_choice_array.sort + # standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个 + # if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 + # user_score = q.question_score + # else + # user_score = 0.0 + # end + # else + # user_score = 0.0 + # end end end diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb index f17ede53c..05b1b2f8b 100644 --- a/app/helpers/export_helper.rb +++ b/app/helpers/export_helper.rb @@ -113,7 +113,7 @@ module ExportHelper end else #实训题 shixun = homework.shixuns.first - shixun_head_cells = %w(完成情况 通关时间 总耗时 总评测次数 获得经验值 关卡得分) + shixun_head_cells = %w(完成情况 通关时间 学员在EduCoder做实训花费的时间 总评测次数 获得经验值 关卡得分) eff_boolean = homework.work_efficiency if eff_boolean eff_score_cell = ["效率分"] @@ -123,7 +123,7 @@ module ExportHelper if allow_late_boolean #允许迟交 eff_score_cell.push("迟交扣分") end - shixun_time_cells = %w(最终成绩 更新时间 提交耗时 评语) + shixun_time_cells = %w(最终成绩 更新时间 作业发布到学员完成作业所耗的时间 评语) @work_head_cells = (head_cells_format + shixun_head_cells + eff_score_cell + shixun_time_cells).reject(&:blank?) works.includes(:student_works_scores, user: :user_extension, myshixun: :games).each_with_index do |w, index| myshixun = w.try(:myshixun) @@ -163,7 +163,8 @@ module ExportHelper end w_15 = w.work_score.nil? ? "--" : w.work_score.round(1) w_16 = w.update_time ? format_time(w.update_time) : "--" "更新时间" - w_17 = w.cost_time ? (game_spend_time w.cost_time) : "--" + myshixun_complete = myshixun && myshixun.status == 1 + w_17 = myshixun_complete && w.cost_time ? (game_spend_time w.cost_time) : "未完成" teacher_comments = w.student_works_scores if teacher_comments.present? w_18 = "" diff --git a/app/helpers/homework_commons_helper.rb b/app/helpers/homework_commons_helper.rb index a3ed43405..cc23d05d6 100644 --- a/app/helpers/homework_commons_helper.rb +++ b/app/helpers/homework_commons_helper.rb @@ -237,4 +237,14 @@ module HomeworkCommonsHelper def anon_comments user, work_id StudentWorksScore.where(student_work_id: work_id, reviewer_role: 3, user_id: user.id) end + + def student_redo_work work, homework + status = false + publish_time = homework.homework_group_setting(work.user_id)&.publish_time + if work.myshixun && publish_time && work.myshixun.created_at < publish_time && work.myshixun.games.where("answer_open > 0").count > 0 + min_time = Grade.where(container_type: "Answer", container_id: work.myshixun.games.where("answer_open > 0").pluck(:id)).pluck(:created_at).min + status = min_time && min_time < publish_time + end + status + end end diff --git a/app/jobs/apply_teacher_role_join_course_notify_job.rb b/app/jobs/apply_teacher_role_join_course_notify_job.rb index 3ae5e32db..ab5a9e354 100644 --- a/app/jobs/apply_teacher_role_join_course_notify_job.rb +++ b/app/jobs/apply_teacher_role_join_course_notify_job.rb @@ -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, diff --git a/app/jobs/create_subject_course_student_job.rb b/app/jobs/create_subject_course_student_job.rb new file mode 100644 index 000000000..a7b8cb8af --- /dev/null +++ b/app/jobs/create_subject_course_student_job.rb @@ -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 diff --git a/app/libs/util.rb b/app/libs/util.rb index f39ce2b58..ae2e4b80b 100644 --- a/app/libs/util.rb +++ b/app/libs/util.rb @@ -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]}" diff --git a/app/libs/util/file_manage.rb b/app/libs/util/file_manage.rb index 620fd7f01..b6cd79e57 100644 --- a/app/libs/util/file_manage.rb +++ b/app/libs/util/file_manage.rb @@ -10,10 +10,26 @@ module Util::FileManage File.join(Rails.root, "public", "images", relative_path) end - def disk_filename(source_type,source_id,image_file=nil) + def disk_filename(source_type, source_id,image_file=nil) File.join(storage_path, "#{source_type}", "#{source_id}") end + def exist?(source_type, source_id) + File.exist?(disk_filename(source_type, source_id)) + end + + def exists?(source) + File.exist?(disk_filename(source.class, source.id)) + end + + def disk_file_url(source_type, source_id) + File.join('/images', relative_path, "#{source_type}", "#{source_id}") + end + + def source_disk_file_url(source) + File.join('/images', relative_path, "#{source.class}", "#{source.id}") + end + def disk_auth_filename(source_type, source_id, type) File.join(storage_path, "#{source_type}", "#{source_id}#{type}") end diff --git a/app/libs/util/redis.rb b/app/libs/util/redis.rb new file mode 100644 index 000000000..f240406f5 --- /dev/null +++ b/app/libs/util/redis.rb @@ -0,0 +1,9 @@ +module Util::Redis + class << self + def online_user_count + if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore) + Rails.cache.data.scan(0, match: 'cache:_session_id:*', count: 100000).last.uniq.size + end + end + end +end \ No newline at end of file diff --git a/app/libs/util/wechat.rb b/app/libs/util/wechat.rb new file mode 100644 index 000000000..1b064ba94 --- /dev/null +++ b/app/libs/util/wechat.rb @@ -0,0 +1,75 @@ +module Util::Wechat + BASE_SITE = 'https://api.weixin.qq.com'.freeze + + Error = Class.new(StandardError) + + class << self + attr_accessor :appid, :secret + + def js_sdk_signature(url, noncestr, timestamp) + data = { jsapi_ticket: jsapi_ticket, noncestr: noncestr, timestamp: timestamp, url: url } + str = data.map { |k, v| "#{k}=#{v}" }.join('&') + Digest::SHA1.hexdigest(str) + end + + def access_token + # 7200s 有效时间 + Rails.cache.fetch(access_token_cache_key, expires_in: 100.minutes) do + result = request(:get, '/cgi-bin/token', appid: appid, secret: secret, grant_type: 'client_credential') + result['access_token'] + end + end + + def refresh_access_token + Rails.cache.delete(access_token_cache_key) + access_token + end + + def jsapi_ticket + # 7200s 有效时间 + Rails.cache.fetch(jsapi_ticket_cache_key, expires_in: 100.minutes) do + result = request(:get, '/cgi-bin/ticket/getticket', access_token: access_token, type: 'jsapi') + result['ticket'] + end + end + + def refresh_jsapi_ticket + Rails.cache.delete(jsapi_ticket_cache_key) + jsapi_ticket + end + + def access_token_cache_key + "#{base_cache_key}/access_token" + end + + def jsapi_ticket_cache_key + "#{base_cache_key}/jsapi_ticket" + end + + def base_cache_key + "wechat/#{appid}" + end + + private + + def request(method, url, **params) + Rails.logger.error("[wechat] request: #{method} #{url} #{params.inspect}") + + client = Faraday.new(url: BASE_SITE) + response = client.public_send(method, url, params) + result = JSON.parse(response.body) + + Rails.logger.error("[wechat] response:#{response.status} #{result.inspect}") + + if response.status != 200 + raise Error, result.inspect + end + + if result['errcode'].present? && result['errcode'].to_i.nonzero? + raise Error, result.inspect + end + + result + end + end +end \ No newline at end of file diff --git a/app/models/apply_add_school.rb b/app/models/apply_add_school.rb index c303283ca..ac7c880cd 100644 --- a/app/models/apply_add_school.rb +++ b/app/models/apply_add_school.rb @@ -1,10 +1,12 @@ class ApplyAddSchool < ApplicationRecord belongs_to :school + belongs_to :user has_many :applied_messages, as: :applied has_many :tidings, as: :container, dependent: :destroy after_create :send_notify + # after_destroy :after_delete_apply private @@ -12,4 +14,9 @@ class ApplyAddSchool < ApplicationRecord Tiding.create!(user_id: 1, status: 0, container_id: id, container_type: 'ApplyAddSchools', trigger_user_id: user_id, belong_container: school, tiding_type: 'Apply') end + + # def after_delete_apply + # + # end + end \ No newline at end of file diff --git a/app/models/apply_user_authentication.rb b/app/models/apply_user_authentication.rb index c379fb82e..4f94202f6 100644 --- a/app/models/apply_user_authentication.rb +++ b/app/models/apply_user_authentication.rb @@ -18,6 +18,10 @@ class ApplyUserAuthentication < ApplicationRecord nil end + def revoke! + update!(status: 3) + end + private def send_tiding diff --git a/app/models/attachment.rb b/app/models/attachment.rb index e3c55242f..ae28e7d52 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -4,7 +4,7 @@ class Attachment < ApplicationRecord include Publishable include Lockable - belongs_to :container, polymorphic: true, touch: true, optional: true + belongs_to :container, polymorphic: true, optional: true belongs_to :author, class_name: "User", foreign_key: :author_id belongs_to :course, foreign_key: :container_id, optional: true has_many :attachment_group_settings, :dependent => :destroy diff --git a/app/models/coo_img.rb b/app/models/coo_img.rb new file mode 100644 index 000000000..0766c0727 --- /dev/null +++ b/app/models/coo_img.rb @@ -0,0 +1,5 @@ +class CooImg < ApplicationRecord + extend Enumerize + + enumerize :img_type, in: %i[com_coop edu_coop alliance_coop] +end \ No newline at end of file diff --git a/app/models/cooperation.rb b/app/models/cooperation.rb new file mode 100644 index 000000000..f0eb30cf6 --- /dev/null +++ b/app/models/cooperation.rb @@ -0,0 +1,9 @@ +class Cooperation < ApplicationRecord + def user_type_text + case user_type.to_i + when 1 then '高校合作' + when 2 then '企业合作' + when 3 then '实训投稿' + end + end +end \ No newline at end of file diff --git a/app/models/course.rb b/app/models/course.rb index 5a2a065ba..ba818449e 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -70,6 +70,11 @@ class Course < ApplicationRecord has_many :course_acts, class_name: 'CourseActivity', as: :course_act, dependent: :destroy has_many :tidings, as: :container, dependent: :destroy + # 开放课堂 + has_many :course_stages, -> { order("course_stages.position ASC") }, dependent: :destroy + has_many :course_stage_shixuns, dependent: :destroy + has_many :shixuns, through: :course_stage_shixuns + # 老版的members弃用 现用course_members has_many :members @@ -77,6 +82,7 @@ class Course < ApplicationRecord scope :ended, ->(is_end = true) { where(is_end: is_end) } scope :processing, -> { where(is_end: false) } scope :not_deleted, -> { where(is_delete: 0) } + scope :not_excellent, -> { where(excellent: 0) } scope :deleted, ->(is_delete = 1) { where(is_delete: is_delete) } scope :by_user, ->(user) { joins(:course_members).where('course_members.user_id = ?', user.id).order(updated_at: :desc) } scope :by_keywords, lambda { |keywords| @@ -333,11 +339,33 @@ class Course < ApplicationRecord teacher_power_courses end + def create_stages subject + if subject + subject.stages.each do |stage| + new_stage = CourseStage.create!(course_id: id, name: stage.name, description: stage.description, position: stage.position) + stage.stage_shixuns.each do |stage_shixun| + CourseStageShixun.create!(course_id: id, course_stage_id: new_stage.id, shixun_id: stage_shixun.shixun_id, position: stage_shixun.position) + end + end + end + end + + def learning? user_id + Myshixun.where(user_id: user_id, shixun_id: shixuns).exists? + end + + def my_subject_progress + my_challenge_count = Game.joins(:challenge).where(user_id: User.current.id, status: 2, challenges: {shixun_id: shixuns.published_closed}). + pluck(:challenge_id).uniq.size + course_challeng_count = shixuns.pluck(:challenges_count).sum + count = course_challeng_count == 0 ? 0 : ((my_challenge_count.to_f / course_challeng_count).round(2) * 100).to_i + end + private #创建课程后,给该用户发送消息 def send_tiding - self.tidings << Tiding.new(user_id: tea_id, trigger_user_id: 1, belong_container_id: id, + self.tidings << Tiding.new(user_id: tea_id, trigger_user_id: 0, belong_container_id: id, belong_container_type: 'Course', tiding_type: 'System') end diff --git a/app/models/course_message.rb b/app/models/course_message.rb index 674e92169..a3578d500 100644 --- a/app/models/course_message.rb +++ b/app/models/course_message.rb @@ -28,10 +28,10 @@ class CourseMessage < ApplicationRecord def send_deal_tiding deal_status # 发送申请处理结果消息 Tiding.create!( - user_id: course_message_id, trigger_user_id: 1, container_id: course_id, container_type: 'DealCourse', + user_id: course_message_id, trigger_user_id: 0, container_id: course_id, container_type: 'DealCourse', 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 \ No newline at end of file diff --git a/app/models/course_stage.rb b/app/models/course_stage.rb new file mode 100644 index 000000000..f105e25f6 --- /dev/null +++ b/app/models/course_stage.rb @@ -0,0 +1,9 @@ +class CourseStage < ApplicationRecord + belongs_to :course + + has_many :course_stage_shixuns, -> { order("course_stage_shixuns.position ASC") }, dependent: :destroy + has_many :shixuns, :through => :course_stage_shixuns + + validates :name, length: { maximum: 60 } + validates :description, length: { maximum: 300 } +end diff --git a/app/models/course_stage_shixun.rb b/app/models/course_stage_shixun.rb new file mode 100644 index 000000000..6ab2707a4 --- /dev/null +++ b/app/models/course_stage_shixun.rb @@ -0,0 +1,5 @@ +class CourseStageShixun < ApplicationRecord + belongs_to :course + belongs_to :course_stage, counter_cache: :shixuns_count + belongs_to :shixun +end diff --git a/app/models/department.rb b/app/models/department.rb index 3b0672cce..2c537fd91 100644 --- a/app/models/department.rb +++ b/app/models/department.rb @@ -5,7 +5,7 @@ class Department < ApplicationRecord has_many :member_users, through: :department_members, source: :user has_many :user_extensions, dependent: :nullify - has_many :apply_add_departments + has_many :apply_add_departments, dependent: :destroy scope :without_deleted, -> { where(is_delete: false) } diff --git a/app/models/ec_course_student_score.rb b/app/models/ec_course_student_score.rb index 5b45e34a9..57d524b46 100644 --- a/app/models/ec_course_student_score.rb +++ b/app/models/ec_course_student_score.rb @@ -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 \ No newline at end of file diff --git a/app/models/ec_course_support.rb b/app/models/ec_course_support.rb index a6ca96ea9..518fc1385 100644 --- a/app/models/ec_course_support.rb +++ b/app/models/ec_course_support.rb @@ -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 diff --git a/app/models/ec_course_target.rb b/app/models/ec_course_target.rb index 9b93cb73c..b13c81059 100644 --- a/app/models/ec_course_target.rb +++ b/app/models/ec_course_target.rb @@ -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 } diff --git a/app/models/ec_discipline.rb b/app/models/ec_discipline.rb new file mode 100644 index 000000000..449098ce1 --- /dev/null +++ b/app/models/ec_discipline.rb @@ -0,0 +1,12 @@ +class EcDiscipline < ActiveRecord::Base + validates_presence_of :code, :name + + has_many :ec_discipline_firsts + + # 专业数目 + def major_count + count = 0 + self.ec_discipline_firsts.map{|f| count += f.ec_majors.count} + count + end +end diff --git a/app/models/ec_discipline_first.rb b/app/models/ec_discipline_first.rb new file mode 100644 index 000000000..7c111d2c9 --- /dev/null +++ b/app/models/ec_discipline_first.rb @@ -0,0 +1,6 @@ +class EcDisciplineFirst < ActiveRecord::Base + validates_presence_of :code, :name + + has_many :ec_majors + belongs_to :ec_discipline +end diff --git a/app/models/ec_graduation_requirement.rb b/app/models/ec_graduation_requirement.rb index d0f4195d0..f9c65e28e 100644 --- a/app/models/ec_graduation_requirement.rb +++ b/app/models/ec_graduation_requirement.rb @@ -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 diff --git a/app/models/ec_major.rb b/app/models/ec_major.rb index 4842f7d70..ae854a4c8 100644 --- a/app/models/ec_major.rb +++ b/app/models/ec_major.rb @@ -1,7 +1,10 @@ class EcMajor < ApplicationRecord # 主页对应的学校,不同学校可以选用同样的专业,而每个专业又各具特色 - has_many :schools, through: :ec_major_schools has_many :ec_major_schools, dependent: :destroy + has_many :schools, through: :ec_major_schools + + # 一级专业 + belongs_to :ec_discipline_first scope :search_name_or_code, -> (keyword) { where('name LIKE :keyword OR code LIKE :keyword', keyword: "%#{keyword.strip}%") } end diff --git a/app/models/ec_major_school.rb b/app/models/ec_major_school.rb index 41a835f63..5cfc4df9e 100644 --- a/app/models/ec_major_school.rb +++ b/app/models/ec_major_school.rb @@ -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) diff --git a/app/models/ec_template.rb b/app/models/ec_template.rb new file mode 100644 index 000000000..36f5ae305 --- /dev/null +++ b/app/models/ec_template.rb @@ -0,0 +1,6 @@ +class EcTemplate < ActiveRecord::Base + # attr_accessible :title, :body + # acts_as_attachable + has_many :attachments, as: :container + +end diff --git a/app/models/ec_training_subitem.rb b/app/models/ec_training_subitem.rb index 0c9c61fbc..736e3f0da 100644 --- a/app/models/ec_training_subitem.rb +++ b/app/models/ec_training_subitem.rb @@ -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 diff --git a/app/models/ec_year.rb b/app/models/ec_year.rb index 69ae4c291..6a3d97340 100644 --- a/app/models/ec_year.rb +++ b/app/models/ec_year.rb @@ -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 diff --git a/app/models/exercise_answer_comment.rb b/app/models/exercise_answer_comment.rb index 7da0ec4c7..4279ba445 100644 --- a/app/models/exercise_answer_comment.rb +++ b/app/models/exercise_answer_comment.rb @@ -3,7 +3,7 @@ class ExerciseAnswerComment < ApplicationRecord belongs_to :user belongs_to :exercise_question belongs_to :exercise_shixun_answer, optional: true - belongs_to :exercise_answer,optional: true + belongs_to :exercise_answer, optional: true scope :search_answer_comments, lambda {|name,ids| where("#{name}":ids)} end diff --git a/app/models/graduation_task.rb b/app/models/graduation_task.rb index e247f2b6e..17309101d 100644 --- a/app/models/graduation_task.rb +++ b/app/models/graduation_task.rb @@ -37,7 +37,7 @@ class GraduationTask < ApplicationRecord def user_work user_id - work = self.graduation_works.find_by(user_id: user_id) + work = self.graduation_works.find_by(user_id: user_id) || GraduationWork.create!(graduation_task_id: id, user_id: user_id) end def task_type_name diff --git a/app/models/graduation_work.rb b/app/models/graduation_work.rb index 235bfcac6..c7420ffef 100644 --- a/app/models/graduation_work.rb +++ b/app/models/graduation_work.rb @@ -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 # 分班名 diff --git a/app/models/gtopic_bank.rb b/app/models/gtopic_bank.rb index af5b267a6..609219711 100644 --- a/app/models/gtopic_bank.rb +++ b/app/models/gtopic_bank.rb @@ -1,7 +1,7 @@ class GtopicBank < ApplicationRecord belongs_to :user - belongs_to :graduation_topic - belongs_to :course_list + belongs_to :graduation_topic, optional: true + belongs_to :course_list, optional: true has_many :attachments, as: :container, dependent: :destroy has_many :graduation_topics, dependent: :nullify diff --git a/app/models/help.rb b/app/models/help.rb new file mode 100644 index 000000000..2b8bf5813 --- /dev/null +++ b/app/models/help.rb @@ -0,0 +1,3 @@ +class Help < ApplicationRecord + +end \ No newline at end of file diff --git a/app/models/homework_common.rb b/app/models/homework_common.rb index c33bbca0d..40de5a87c 100644 --- a/app/models/homework_common.rb +++ b/app/models/homework_common.rb @@ -102,7 +102,7 @@ class HomeworkCommon < ApplicationRecord end def user_work user_id - work = self.student_works.find_by_user_id(user_id) + work = self.student_works.find_by_user_id(user_id) || StudentWork.create!(homework_common_id: id, user_id: user_id) 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)). diff --git a/app/models/poll.rb b/app/models/poll.rb index 7f0d2fd94..9cb860f61 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -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 diff --git a/app/models/school.rb b/app/models/school.rb index 1034fd997..387b6b5d8 100644 --- a/app/models/school.rb +++ b/app/models/school.rb @@ -16,6 +16,9 @@ class School < ApplicationRecord has_many :customers, dependent: :destroy has_many :partners, dependent: :destroy + has_many :apply_add_departments, dependent: :destroy + has_many :user_extensions, dependent: :nullify + # 学校管理员 def manager?(user) ec_school_users.exists?(user_id: user.id) diff --git a/app/models/searchable/course.rb b/app/models/searchable/course.rb index 5060d9ddd..794dec0e2 100644 --- a/app/models/searchable/course.rb +++ b/app/models/searchable/course.rb @@ -24,7 +24,7 @@ module Searchable::Course author_name: teacher&.real_name, author_school_name: teacher&.school_name, visits_count: visits, - members_count: members_count, + members_count: course_members_count, is_public: is_public == 1, first_category_url: ApplicationController.helpers.module_url(none_hidden_course_modules.first, self) } diff --git a/app/models/searchable/shixun.rb b/app/models/searchable/shixun.rb index 49e066eac..41bc94b04 100644 --- a/app/models/searchable/shixun.rb +++ b/app/models/searchable/shixun.rb @@ -14,7 +14,9 @@ module Searchable::Shixun def search_data { name: name, - description: Util.extract_content(description)[0..Searchable::MAXIMUM_LENGTH] + description: Util.extract_content(description)[0..Searchable::MAXIMUM_LENGTH], + status: status, + myshixuns_count: myshixuns_count }.merge!(searchable_user_data) .merge!(searchable_challenge_data) end @@ -37,7 +39,7 @@ module Searchable::Shixun end def should_index? - status == 2 # published + [0, 1, 2].include?(status) # published end def to_searchable_json @@ -48,13 +50,13 @@ module Searchable::Shixun author_school_name: user.school_name, visits_count: visits, challenges_count: challenges_count, - study_count: myshixuns_count + study_count: myshixuns_count, } end module ClassMethods def searchable_includes - { user: { user_extension: :school } } + [ :shixun_info, user: { user_extension: :school } ] end end end diff --git a/app/models/shixun.rb b/app/models/shixun.rb index db6bca43e..4912ea15a 100644 --- a/app/models/shixun.rb +++ b/app/models/shixun.rb @@ -5,6 +5,9 @@ class Shixun < ApplicationRecord # hide_code: 隐藏代码窗口 # code_hidden: 隐藏代码目录 # task_pass: 跳关 + # webssh 0:不开启webssh;1:开启练习模式; 2:开启评测模式 + # trainee 实训的难度 + # vnc: VCN实训是否用于评测 has_many :challenges, -> {order("challenges.position asc")}, dependent: :destroy has_many :challenge_tags, through: :challenges has_many :myshixuns, :dependent => :destroy @@ -35,6 +38,9 @@ class Shixun < ApplicationRecord has_one :shixun_info, dependent: :destroy + # 第二版本库 + has_one :shixun_secret_repository, dependent: :destroy + belongs_to :user # 实训服务配置 has_many :shixun_service_configs, :dependent => :destroy @@ -59,6 +65,7 @@ class Shixun < ApplicationRecord scope :visible, -> { where.not(status: -1) } scope :published, lambda{ where(status: 2) } scope :published_closed, lambda{ where(status: [2, 3]) } + scope :none_closed, lambda{ where(status: [0, 1, 2]) } scope :unhidden, lambda{ where(hidden: 0, status: 2) } scope :field_for_recommend, lambda{ select([:id, :name, :identifier, :myshixuns_count]) } scope :find_by_ids,lambda{|k| where(id:k)} @@ -273,6 +280,11 @@ class Shixun < ApplicationRecord self.mirror_name.include?('JavaWeb') || self.mirror_name.include?('PHP') && self.mirror_name.include?('Mysql') || self.mirror_name.include?('Web') end + # 所属实践课程 + def relation_path + subjects.where(hidden: 0).uniq + end + private def send_tiding diff --git a/app/models/shixun_secret_repository.rb b/app/models/shixun_secret_repository.rb new file mode 100644 index 000000000..699c6dd30 --- /dev/null +++ b/app/models/shixun_secret_repository.rb @@ -0,0 +1,11 @@ +class ShixunSecretRepository < ApplicationRecord + # repo_name: 仓库名 + # secret_dir_name: 在tpm仓库的那个目录下 + + belongs_to :shixun + + def repo_path + "#{repo_name}.git" + end + +end diff --git a/app/models/shixun_work_comment.rb b/app/models/shixun_work_comment.rb new file mode 100644 index 000000000..7a67238ab --- /dev/null +++ b/app/models/shixun_work_comment.rb @@ -0,0 +1,5 @@ +class ShixunWorkComment < ApplicationRecord + belongs_to :student_work + belongs_to :user + belongs_to :challenge, optional: true +end diff --git a/app/models/student_graduation_topic.rb b/app/models/student_graduation_topic.rb index 50f150f92..b8f4dfbbb 100644 --- a/app/models/student_graduation_topic.rb +++ b/app/models/student_graduation_topic.rb @@ -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 # 学生名称 diff --git a/app/models/student_work.rb b/app/models/student_work.rb index 168cfeb68..b4ad834de 100644 --- a/app/models/student_work.rb +++ b/app/models/student_work.rb @@ -7,6 +7,7 @@ class StudentWork < ApplicationRecord belongs_to :myshixun, optional: true has_many :student_works_evaluation_distributions, dependent: :destroy has_many :student_works_scores, dependent: :destroy + has_many :shixun_work_comments, dependent: :destroy belongs_to :project, optional: true # attachtype: 1(正常提交的附件), 7(补交的附件) @@ -105,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 # 作品总体评价 diff --git a/app/models/student_works_score.rb b/app/models/student_works_score.rb index 19043f7f8..299b61596 100644 --- a/app/models/student_works_score.rb +++ b/app/models/student_works_score.rb @@ -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 @@ -9,6 +9,9 @@ belongs_to :student_work validates :comment, length: { maximum: 2000 } + scope :shixun_comment, lambda { where(is_ultimate: 0) } + + def show_name identity, user identity < Course::STUDENT || self.user == user || self.reviewer_role != 3 end diff --git a/app/models/subject.rb b/app/models/subject.rb index 4b7f4dbcd..d29a97d0c 100644 --- a/app/models/subject.rb +++ b/app/models/subject.rb @@ -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,10 +46,13 @@ 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).uniq.length > shixuns.pluck(:myshixuns_count).sum ? - CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).uniq.length : shixuns.pluck(:myshixuns_count).sum + excellent ? CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).length : shixuns.pluck(:myshixuns_count).sum end def all_score @@ -110,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 \ No newline at end of file diff --git a/app/models/subject_appointment.rb b/app/models/subject_appointment.rb new file mode 100644 index 000000000..a4bc53b18 --- /dev/null +++ b/app/models/subject_appointment.rb @@ -0,0 +1,4 @@ +class SubjectAppointment < ApplicationRecord + belongs_to :subject + belongs_to :user +end diff --git a/app/models/test_set.rb b/app/models/test_set.rb index 148cb8720..7772a3a00 100644 --- a/app/models/test_set.rb +++ b/app/models/test_set.rb @@ -1,2 +1,3 @@ class TestSet < ApplicationRecord + # match_rule: 匹配规则: full: 完全匹配, last: 末尾匹配 end diff --git a/app/models/tiding.rb b/app/models/tiding.rb index d885f93fd..02692085a 100644 --- a/app/models/tiding.rb +++ b/app/models/tiding.rb @@ -22,4 +22,9 @@ class Tiding < ApplicationRecord value end + + def anonymous? + (container_type == 'StudentWorksScore' && extra.to_i == 3) || + (container_type == 'StudentWorksScoresAppeal' && parent_container_type == 'StudentWork' && tiding_type == 'System') + end end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index 43c5728b5..b9d9e48e6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -26,8 +26,6 @@ class User < ApplicationRecord MIX_PASSWORD_LIMIT = 8 - LOGIN_CHARS = %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).freeze - has_one :user_extension, dependent: :destroy accepts_nested_attributes_for :user_extension, update_only: true @@ -348,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 diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 5a0dc8a37..0a2249308 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -1,6 +1,6 @@ class UserExtension < ApplicationRecord # identity 0: 教师教授 1: 学生, 2: 专业人士, 3: 开发者 - enum identity: { teacher: 0, student: 1, professional: 2, developer: 3 } + enum identity: { teacher: 0, student: 1, professional: 2, developer: 3, enterprise: 4, unselect: -1 } belongs_to :user, touch: true belongs_to :school, optional: true diff --git a/app/queries/admins/department_apply_query.rb b/app/queries/admins/department_apply_query.rb new file mode 100644 index 000000000..500536ddb --- /dev/null +++ b/app/queries/admins/department_apply_query.rb @@ -0,0 +1,25 @@ +class Admins::DepartmentApplyQuery < ApplicationQuery + include CustomSortable + + attr_reader :params + + sort_columns :created_at, default_by: :created_at, default_direction: :desc + + def initialize(params) + @params = params + end + + def call + status = params[:status] + + applies = ApplyAddDepartment.where(status: status) if status.present? + + # 关键字模糊查询 + keyword = params[:keyword].to_s.strip + if keyword.present? + applies = applies.where('name LIKE :keyword', keyword: "%#{keyword}%") + end + + custom_sort(applies, params[:sort_by], params[:sort_direction]) + end +end \ No newline at end of file diff --git a/app/queries/admins/school_query.rb b/app/queries/admins/school_query.rb new file mode 100644 index 000000000..7361588c4 --- /dev/null +++ b/app/queries/admins/school_query.rb @@ -0,0 +1,23 @@ +class Admins::SchoolQuery < ApplicationQuery + include CustomSortable + + attr_reader :params + + sort_columns :users_count, :created_at, default_by: :created_at, default_direction: :desc + + def initialize(params) + @params = params + end + + def call + schools = School.all + + keyword = strip_param(:keyword) + schools = schools.where('schools.name LIKE ?', "%#{keyword}%") if keyword + + schools = schools.joins(:user_extensions).group(:id) + schools = schools.select('schools.*, COUNT(*) AS users_count') + + custom_sort schools, params[:sort_by], params[:sort_direction] + end +end \ No newline at end of file diff --git a/app/queries/admins/unit_apply_query.rb b/app/queries/admins/unit_apply_query.rb new file mode 100644 index 000000000..5df9c8ebb --- /dev/null +++ b/app/queries/admins/unit_apply_query.rb @@ -0,0 +1,24 @@ +class Admins::UnitApplyQuery < ApplicationQuery + include CustomSortable + + attr_reader :params + + sort_columns :created_at, default_by: :created_at, default_direction: :desc + + def initialize(params) + @params = params + end + + def call + unit_applies = ApplyAddSchool.where(status:0) + + # 关键字模糊查询 + keyword = params[:keyword].to_s.strip + if keyword.present? + unit_applies = unit_applies.where("name like ?","%#{keyword}%") + end + + custom_sort(unit_applies, params[:sort_by], params[:sort_direction]) + end +end + diff --git a/app/queries/application_query.rb b/app/queries/application_query.rb index 3a92cc6e8..c66af94c0 100644 --- a/app/queries/application_query.rb +++ b/app/queries/application_query.rb @@ -1,3 +1,9 @@ class ApplicationQuery include Callable + + private + + def strip_param(key) + params[key].to_s.strip.presence + end end \ No newline at end of file diff --git a/app/queries/user_query.rb b/app/queries/user_query.rb new file mode 100644 index 000000000..326665fe9 --- /dev/null +++ b/app/queries/user_query.rb @@ -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 \ No newline at end of file diff --git a/app/services/admins/delete_unit_apply_service.rb b/app/services/admins/delete_unit_apply_service.rb new file mode 100644 index 000000000..a64c8d64d --- /dev/null +++ b/app/services/admins/delete_unit_apply_service.rb @@ -0,0 +1,56 @@ +class Admins::DeleteUnitApplyService < ApplicationService + + attr_reader :department, :params + + def initialize(unit_apply, params) + @unit_apply = unit_apply + @params = params + end + + def call + ActiveRecord::Base.transaction do + @unit_apply.update_attribute("status",3) + @unit_apply&.applied_messages&.update_all(status:3) + @unit_apply&.school&.apply_add_departments&.update_all(status:3) + + applied_departments = ApplyAddDepartment.where(school_id: @unit_apply.school_id) + applied_departments.update_all(status: 3) + + use_extensions = UserExtension&.where(school_id: @unit_apply.school_id) + user_ids = UserExtension&.where(school_id: @unit_apply.school_id)&.pluck(:user_id) + User.where(id: user_ids).update_all(profile_completed: false) + use_extensions.update_all(school_id: nil,department_id: nil) + + @unit_apply&.user&.user_extension&.update_attribute("department_id", nil) + + # 申请了职业认证的用户撤销申请 + apply_user_auth = ApplyUserAuthentication.where(user_id: user_ids, auth_type: 2, status: 0) + apply_user_auth.each do |apply| + apply.tidings.destroy_all + apply.update_attribute('status', 3) + diskfile2 = disk_auth_filename('UserAuthentication', apply.user_id, 'PRO') + diskfilePRO = diskfile2 + 'temp' + File.delete(diskfilePRO) if File.exist?(diskfilePRO) + File.delete(diskfile2) if File.exist?(diskfile2) + end + + # 未审批删除 + if params[:tip] == "unapplied" + Tiding.where(:user_id => 1, :trigger_user_id => @unit_apply.user_id, :container_id => @unit_apply.id, :container_type => 'ApplyAddSchools', :status => 0, :tiding_type => "Apply").update_all(status: 1) + Tiding.create(:user_id => @unit_apply.user_id, :trigger_user_id => 0, :container_id => @unit_apply.id, :container_type =>'ApplyAddSchools', :belong_container_id => @unit_apply.school_id, :belong_container_type=> 'School', :tiding_type => "System", :status => 2, :extra => params[:reason]) + + Tiding.where(:user_id => 1, :container_id => applied_departments.pluck(:id), :container_type => 'ApplyAddDepartment', :status => 0, :tiding_type => "Apply").update_all(status: 1) + if applied_departments&.first.present? + Tiding.create(:user_id => applied_departments.first.user_id, :trigger_user_id => 0, :container_id => applied_departments.first.id, :container_type =>'ApplyAddDepartment', :belong_container_id => @unit_apply.school_id, :belong_container_type=> 'School', :tiding_type => "System", :status => 2) + AppliedMessage.create(:user_id => applied_departments.first.user_id, :status => 3, :viewed => 0, :applied_id => applied_departments.first.id, :applied_type => "ApplyAddDepartment", :name => applied_departments.first.name ) + end + @unit_apply&.school&.destroy + @unit_apply&.school&.departments&.destroy_all + elsif params[:tip] == "applied" + applied_departments.destroy_all + @unit_apply.destroy + end + end + + end +end \ No newline at end of file diff --git a/app/services/admins/drag_cooperative_service.rb b/app/services/admins/drag_cooperative_service.rb new file mode 100644 index 000000000..241b7eb11 --- /dev/null +++ b/app/services/admins/drag_cooperative_service.rb @@ -0,0 +1,35 @@ +class Admins::DragCooperativeService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :move, :after + + def initialize(move, after) + @move = move + @after = after # 移动后下一个位置的元素 + end + + def call + return if move.position + 1 == after&.position # 未移动 + raise Error, '未知错误' if after && move.img_type != after.img_type + + coo_imgs = CooImg.where(img_type: move.img_type) + + ActiveRecord::Base.transaction do + if after.blank? # 移动至末尾 + total = coo_imgs.count + + coo_imgs.where('position > ?', move.position).update_all('position = position - 1') + move.update!(position: total) + return + end + + if move.position > after.position # 前移 + coo_imgs.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1') + move.update!(position: after.position) + else # 后移 + coo_imgs.where('position > ? AND position <= ?', move.position, after.position).update_all('position = position - 1') + move.update!(position: after.position) + end + end + end +end \ No newline at end of file diff --git a/app/services/admins/identity_auths/revoke_apply_service.rb b/app/services/admins/identity_auths/revoke_apply_service.rb new file mode 100644 index 000000000..e76d497a5 --- /dev/null +++ b/app/services/admins/identity_auths/revoke_apply_service.rb @@ -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 \ No newline at end of file diff --git a/app/services/admins/import_user_service.rb b/app/services/admins/import_user_service.rb index e5e7abfe6..f3408051b 100644 --- a/app/services/admins/import_user_service.rb +++ b/app/services/admins/import_user_service.rb @@ -46,6 +46,7 @@ class Admins::ImportUserService < ApplicationService department = school.departments.find_by(name: data.department_name) attr = { + type: 'User', status: User::STATUS_ACTIVE, login: "#{prefix}#{data.student_id}", firstname: '', @@ -54,7 +55,9 @@ class Admins::ImportUserService < ApplicationService professional_certification: 1, certification: 1, password: '12345678', - phone: data.phone + phone: data.phone, + mail: "#{prefix}#{data.student_id}@qq.com", + profile_completed: true } ActiveRecord::Base.transaction do user = User.create!(attr) @@ -66,8 +69,8 @@ class Admins::ImportUserService < ApplicationService extension_attr[:technical_title] = case data.identity.to_i - when 0 then %w(教授 副教授 讲师 助教).include?(data.technical_title) || '讲师' - when 2 then %w(企业管理者 部门管理者 高级工程师 工程师 助理工程师).include?(data.technical_title) || '助理工程师' + when 0 then %w(教授 副教授 讲师 助教).include?(data.technical_title) ? data.technical_title : '讲师' + when 2 then %w(企业管理者 部门管理者 高级工程师 工程师 助理工程师).include?(data.technical_title) ? data.technical_title : '助理工程师' else nil end diff --git a/app/services/admins/professional_auths/revoke_apply_service.rb b/app/services/admins/professional_auths/revoke_apply_service.rb new file mode 100644 index 000000000..1430e7ec8 --- /dev/null +++ b/app/services/admins/professional_auths/revoke_apply_service.rb @@ -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 \ No newline at end of file diff --git a/app/services/admins/update_user_service.rb b/app/services/admins/update_user_service.rb index 9531d3718..c4755a1ae 100644 --- a/app/services/admins/update_user_service.rb +++ b/app/services/admins/update_user_service.rb @@ -11,7 +11,7 @@ class Admins::UpdateUserService < ApplicationService def call user.assign_attributes(user_attributes) user.firstname = '' - user.password = password if params[:password].present? + user.password = params[:password] if params[:password].present? if params[:identity].to_s == 'student' params[:technical_title] = nil diff --git a/app/services/concerns/elasticsearch_able.rb b/app/services/concerns/elasticsearch_able.rb index 80ca5467e..015aac29b 100644 --- a/app/services/concerns/elasticsearch_able.rb +++ b/app/services/concerns/elasticsearch_able.rb @@ -28,9 +28,11 @@ module ElasticsearchAble end def body_options - { - min_score: EduSetting.get('es_min_score') || 10 - } + hash = {} + + hash[:min_score] = (EduSetting.get('es_min_score') || 10) if keyword != '*' + + hash end def per_page diff --git a/app/services/ecs/copy_ec_year_service.rb b/app/services/ecs/copy_ec_year_service.rb index 87cbe0845..462681eba 100644 --- a/app/services/ecs/copy_ec_year_service.rb +++ b/app/services/ecs/copy_ec_year_service.rb @@ -1,4 +1,4 @@ -class CopyEcYearService < ApplicationService +class Ecs::CopyEcYearService < ApplicationService attr_reader :major_school, :to_year def initialize(major_school, year) diff --git a/app/services/ecs/create_course_service.rb b/app/services/ecs/create_course_service.rb index dba162189..3e3828c6f 100644 --- a/app/services/ecs/create_course_service.rb +++ b/app/services/ecs/create_course_service.rb @@ -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 }, diff --git a/app/services/ecs/create_major_manager_service.rb b/app/services/ecs/create_major_manager_service.rb index befe80706..c955bffed 100644 --- a/app/services/ecs/create_major_manager_service.rb +++ b/app/services/ecs/create_major_manager_service.rb @@ -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 \ No newline at end of file diff --git a/app/services/ecs/create_training_objective_service.rb b/app/services/ecs/create_training_objective_service.rb index c3dc3c8a6..effbf5420 100644 --- a/app/services/ecs/create_training_objective_service.rb +++ b/app/services/ecs/create_training_objective_service.rb @@ -11,13 +11,16 @@ class Ecs::CreateTrainingObjectiveService < ApplicationService def call training_objective.content = params[:content].to_s.strip - attributes = build_accepts_nested_attributes( - training_objective, - training_objective.ec_training_subitems, - params[:training_subitems], - &method(:training_subitem_param_handler) - ) - training_objective.assign_attributes(ec_training_subitems_attributes: attributes) + 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 diff --git a/app/services/ecs/import_student_service.rb b/app/services/ecs/import_student_service.rb index 9014e221c..f5cd7c6ac 100644 --- a/app/services/ecs/import_student_service.rb +++ b/app/services/ecs/import_student_service.rb @@ -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) - @ec_year = ec_year - @attachment = Attachment.find_by(id: attachment_id) + def initialize(ec_year, params) + @ec_year = ec_year + @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 diff --git a/app/services/ecs/query_course_evaluation_service.rb b/app/services/ecs/query_course_evaluation_service.rb index 8c76da438..22e0ce1f4 100644 --- a/app/services/ecs/query_course_evaluation_service.rb +++ b/app/services/ecs/query_course_evaluation_service.rb @@ -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 diff --git a/app/services/ecs/save_graduation_course_supports_service.rb b/app/services/ecs/save_graduation_course_supports_service.rb index bfbdb997f..de4ecc71a 100644 --- a/app/services/ecs/save_graduation_course_supports_service.rb +++ b/app/services/ecs/save_graduation_course_supports_service.rb @@ -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 \ No newline at end of file diff --git a/app/services/homeworks_service.rb b/app/services/homeworks_service.rb index f6868afba..0dc814c89 100644 --- a/app/services/homeworks_service.rb +++ b/app/services/homeworks_service.rb @@ -15,7 +15,6 @@ class HomeworksService homework_detail_manual.save! if homework_detail_manual HomeworkCommonsShixun.create!(homework_common_id: homework.id, shixun_id: shixun.id) HomeworksService.new.create_shixun_homework_cha_setting(homework, shixun) - CreateStudentWorkJob.perform_later(homework.id) # HomeworksService.new.create_works_list(homework, course) end homework diff --git a/app/services/libraries/agree_apply_service.rb b/app/services/libraries/agree_apply_service.rb index d452083b3..3367e4585 100644 --- a/app/services/libraries/agree_apply_service.rb +++ b/app/services/libraries/agree_apply_service.rb @@ -25,7 +25,7 @@ class Libraries::AgreeApplyService < ApplicationService private def notify_library_author! - Tiding.create!(user_id: library.user_id, trigger_user_id: 1, + Tiding.create!(user_id: library.user_id, trigger_user_id: 0, container_id: library.id, container_type: 'Library', tiding_type: 'System', status: 1) end diff --git a/app/services/libraries/refuse_apply_service.rb b/app/services/libraries/refuse_apply_service.rb index 9b249b6fa..9868c5989 100644 --- a/app/services/libraries/refuse_apply_service.rb +++ b/app/services/libraries/refuse_apply_service.rb @@ -32,7 +32,7 @@ class Libraries::RefuseApplyService < ApplicationService private def notify_library_author! - Tiding.create!(user_id: library.user_id, trigger_user_id: 1, + Tiding.create!(user_id: library.user_id, trigger_user_id: 0, container_id: library.id, container_type: 'Library', tiding_type: 'System', status: 2, extra: library_apply.reason) end diff --git a/app/services/project_packages/agree_apply_service.rb b/app/services/project_packages/agree_apply_service.rb index 7cef7f70c..3361babad 100644 --- a/app/services/project_packages/agree_apply_service.rb +++ b/app/services/project_packages/agree_apply_service.rb @@ -29,7 +29,7 @@ class ProjectPackages::AgreeApplyService < ApplicationService Tiding.where(container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'Apply', status: 0).update_all(status: 1) - Tiding.create!(user_id: package.creator_id, trigger_user_id: 1, + Tiding.create!(user_id: package.creator_id, trigger_user_id: 0, container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'System', status: 1) end diff --git a/app/services/project_packages/end_bidding_service.rb b/app/services/project_packages/end_bidding_service.rb index 6d43db949..c0d5b76da 100644 --- a/app/services/project_packages/end_bidding_service.rb +++ b/app/services/project_packages/end_bidding_service.rb @@ -16,7 +16,7 @@ class ProjectPackages::EndBiddingService < ApplicationService private def send_bidding_end_notify! - Tiding.create!(user_id: package.creator_id, trigger_user_id: 1, + Tiding.create!(user_id: package.creator_id, trigger_user_id: 0, container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'BiddingEnd') end diff --git a/app/services/project_packages/refuse_apply_service.rb b/app/services/project_packages/refuse_apply_service.rb index 142efe1e0..972a7004f 100644 --- a/app/services/project_packages/refuse_apply_service.rb +++ b/app/services/project_packages/refuse_apply_service.rb @@ -31,7 +31,7 @@ class ProjectPackages::RefuseApplyService < ApplicationService Tiding.where(container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'Apply', status: 0).update_all(status: 1) - Tiding.create!(user_id: package.creator_id, trigger_user_id: 1, + Tiding.create!(user_id: package.creator_id, trigger_user_id: 0, container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'System', status: 2, extra: apply.reason) end diff --git a/app/services/project_packages/save_service.rb b/app/services/project_packages/save_service.rb index 8385ac5dd..40d33c453 100644 --- a/app/services/project_packages/save_service.rb +++ b/app/services/project_packages/save_service.rb @@ -71,7 +71,7 @@ class ProjectPackages::SaveService < ApplicationService end def send_create_notify! - Tiding.create!(user_id: package.creator_id, trigger_user_id: 1, + Tiding.create!(user_id: package.creator_id, trigger_user_id: 0, container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'Created') end diff --git a/app/services/search_service.rb b/app/services/search_service.rb index 7cd1857bd..418021cc0 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -14,10 +14,12 @@ class SearchService < ApplicationService private def search_options - { + model_options = { index_name: index_names, model_includes: model_includes - }.merge(default_options) + } + model_options.merge(where: { status: 2 }) if index_names == [Shixun] + model_options.merge(default_options) end def index_names diff --git a/app/services/shixun_search_service.rb b/app/services/shixun_search_service.rb new file mode 100644 index 000000000..911f341f8 --- /dev/null +++ b/app/services/shixun_search_service.rb @@ -0,0 +1,56 @@ +class ShixunSearchService < ApplicationService + include ElasticsearchAble + + attr_reader :params + + def initialize(params) + @params = params + end + + def call + # 全部实训/我的实训 + type = params[:type] || "all" + # 状态:已发布/未发布 + status = params[:status] || "all" + + # 超级管理员用户显示所有未隐藏的实训、非管理员显示所有已发布的实训(对本单位公开且未隐藏未关闭) + if type == "mine" + @shixuns = User.current.shixuns.none_closed + else + if User.current.admin? || User.current.business? + @shixuns = Shixun.none_closed.where(hidden: 0) + else + none_shixun_ids = ShixunSchool.where("school_id != #{User.current.school_id}").pluck(:shixun_id) + + @shixuns = Shixun.where.not(id: none_shixun_ids).none_closed.where(hidden: 0) + end + end + + unless status == "all" + @shixuns = status == "published" ? @shixuns.where(status: 2) : @shixuns.where(status: [0, 1]) + end + + ## 筛选 难度 + if params[:diff].present? && params[:diff].to_i != 0 + @shixuns = @shixuns.where(trainee: params[:diff]) + end + + Shixun.search(keyword, search_options) + end + + private + + def search_options + model_options = { + includes: [ :shixun_info, :challenges, :subjects, user: { user_extension: :school } ] + } + model_options.merge!(where: { id: @shixuns.pluck(:id) }) + model_options.merge!(order: {"myshixuns_count" => sort_str}) + model_options.merge!(default_options) + model_options + end + + def sort_str + params[:order] || "desc" + end +end \ No newline at end of file diff --git a/app/services/users/apply_professional_auth_service.rb b/app/services/users/apply_professional_auth_service.rb index 07afe18ae..74ee08c85 100644 --- a/app/services/users/apply_professional_auth_service.rb +++ b/app/services/users/apply_professional_auth_service.rb @@ -38,7 +38,11 @@ class Users::ApplyProfessionalAuthService < ApplicationService move_image_file! unless params[:upload_image].to_s == 'false' - sms_notify_admin + # sms_cache = Rails.cache.read("apply_pro_certification") + # if sms_cache.nil? + sms_notify_admin + # Rails.cache.write("apply_pro_certification", 1) + # end end end diff --git a/app/services/users/course_service.rb b/app/services/users/course_service.rb index de70c5b86..db9be69bc 100644 --- a/app/services/users/course_service.rb +++ b/app/services/users/course_service.rb @@ -11,7 +11,7 @@ class Users::CourseService end def call - courses = category_scope_courses.not_deleted + courses = category_scope_courses.not_deleted.not_excellent courses = status_filter(courses) diff --git a/app/services/users/question_bank_service.rb b/app/services/users/question_bank_service.rb index 7e640c6a5..dbaa92e6e 100644 --- a/app/services/users/question_bank_service.rb +++ b/app/services/users/question_bank_service.rb @@ -85,7 +85,7 @@ class Users::QuestionBankService def custom_sort(relations, sort_by, sort_direction) case sort_by when 'updated_at' then - relations.order(updated_at: sort_direction) + relations.order("updated_at #{sort_direction}, id #{sort_direction}") when 'name' then relations.order("CONVERT(name USING gbk) COLLATE gbk_chinese_ci #{sort_direction}") when 'contributor' then diff --git a/app/services/users/update_account_service.rb b/app/services/users/update_account_service.rb index 3f0aa8cc8..fad1210a5 100644 --- a/app/services/users/update_account_service.rb +++ b/app/services/users/update_account_service.rb @@ -53,7 +53,7 @@ class Users::UpdateAccountService < ApplicationService RewardGradeService.call(user, container_id: user.id, container_type: 'Account', score: 500) if user.user_extension.teacher? join_course(user.id,1309, 2) - sms_notify_admin(user.lastname) + # sms_notify_admin(user.lastname) end end diff --git a/app/services/videos/agree_apply_service.rb b/app/services/videos/agree_apply_service.rb index 50791935a..0a95961ab 100644 --- a/app/services/videos/agree_apply_service.rb +++ b/app/services/videos/agree_apply_service.rb @@ -28,7 +28,7 @@ class Videos::AgreeApplyService < ApplicationService private def notify_video_author! - Tiding.create!(user_id: video.user_id, trigger_user_id: 1, + Tiding.create!(user_id: video.user_id, trigger_user_id: 0, container_id: video.id, container_type: 'Video', tiding_type: 'System', status: 1) end diff --git a/app/services/videos/refuse_apply_service.rb b/app/services/videos/refuse_apply_service.rb index 5d796db79..5a2cc4ef9 100644 --- a/app/services/videos/refuse_apply_service.rb +++ b/app/services/videos/refuse_apply_service.rb @@ -31,7 +31,7 @@ class Videos::RefuseApplyService < ApplicationService private def notify_video_author! - Tiding.create!(user_id: video.user_id, trigger_user_id: 1, + Tiding.create!(user_id: video.user_id, trigger_user_id: 0, container_id: video.id, container_type: 'Video', tiding_type: 'System', status: 2, extra: video_apply.reason) end diff --git a/app/tasks/statistic_school_daily_report_task.rb b/app/tasks/statistic_school_daily_report_task.rb index 5cd3fda7c..794a4b573 100644 --- a/app/tasks/statistic_school_daily_report_task.rb +++ b/app/tasks/statistic_school_daily_report_task.rb @@ -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 diff --git a/app/tasks/statistic_school_report_task.rb b/app/tasks/statistic_school_report_task.rb index a55eb7a42..a72c57830 100644 --- a/app/tasks/statistic_school_report_task.rb +++ b/app/tasks/statistic_school_report_task.rb @@ -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) diff --git a/app/templates/shared/main.css b/app/templates/shared/main.css index 884f6fa37..31ebfabac 100644 --- a/app/templates/shared/main.css +++ b/app/templates/shared/main.css @@ -83,6 +83,7 @@ a.edu-txt-w80,.edu-txt-w80{ width:80px; display: inline-block;text-align: center .font-20{ font-size: 20px!important;} .font-22{ font-size: 22px!important;} .font-24{ font-size: 24px!important;} +.font-25{ font-size: 25px!important;} .font-26{ font-size: 26px!important;} .font-28{ font-size: 28px!important;} .font-30{ font-size: 30px!important;} @@ -105,7 +106,7 @@ a.decoration{text-decoration: underline} .mr3{margin-right: 3px}.mr4{margin-right: 4px}.mr5{ margin-right: 5px;}.mr8{ margin-right: 8px;}.mr10{ margin-right: 10px;}.mr12{ margin-right:12px!important;}.mr15{ margin-right: 15px;}.mr18{ margin-right: 18px;}.mr20{ margin-right: 20px;}.mr24{ margin-right: 24px;}.mr25{ margin-right: 25px;}.mr30{ margin-right:30px;}.mr35{margin-right:35px;}.mr40{margin-right:40px;}.mr45{margin-right:45px;}.mr50{ margin-right: 50px;}.mr60{ margin-right:60px;}.mr70{ margin-right: 70px;}.mr75{ margin-right: 75px;}.mr80{ margin-right:80px;}.mr90{ margin-right:90px;}.mr100{ margin-right: 100px;}.mr110{ margin-right:110px;}.mr350{ margin-right:350px;} .pt1{ padding-top:1px;}.pt3{ padding-top:3px!important;}.pt5{ padding-top:5px!important;}.pt10{ padding-top:10px;}.pt15{ padding-top:15px;}.pt17{ padding-top:17px;}.pt20{ padding-top:20px!important;}.pt25{ padding-top:25px;}.pt30{ padding-top:30px;}.pt35{ padding-top:35px;}.pt37{ padding-top:37px;}.pt40{ padding-top:40px;}.pt47{ padding-top:47px;}.pt49{ padding-top:49px;}.pt50{ padding-top:50px;}.pt60{ padding-top:60px;}.pt70{ padding-top:70px;}.pt80{ padding-top:80px;}.pt90{ padding-top:90px;}.pt100{padding-top:100px;}.pt110{ padding-top:110px;}.pt120{ padding-top:120px;}.pt130{padding-top:130px;} -.pb3{ padding-bottom:3px!important;}.pb5{ padding-bottom:5px!important;}.pb10{ padding-bottom:10px;}.pb15{ padding-bottom:15px;}.pb20{ padding-bottom:20px;}.pb25{ padding-bottom:20px;}.pb25{ padding-bottom:20px;}.pb30{ padding-bottom:30px;}.pb35{ padding-bottom:35px;}.pb40{ padding-bottom:40px;}.pb47{ padding-bottom:47px;}.pb50{ padding-bottom:50px;}.pb60{ padding-bottom:60px;}.pb70{ padding-bottom:70px;}.pb80{ padding-bottom:80px;}.pb90{ padding-bottom:90px;}.pb100{ padding-bottom:100px;}.pb110{ padding-bottom:110px;}.pb155{ padding-bottom:155px;} +.pb3{ padding-bottom:3px!important;}.pb5{ padding-bottom:5px!important;}.pb10{ padding-bottom:10px;}.pb15{ padding-bottom:15px;}.pb20{ padding-bottom:20px;}.pb25{ padding-bottom:20px;}.pb25{ padding-bottom:20px;}.pb28{ padding-bottom:28px;}.pb30{ padding-bottom:30px;}.pb35{ padding-bottom:35px;}.pb40{ padding-bottom:40px;}.pb47{ padding-bottom:47px;}.pb50{ padding-bottom:50px;}.pb60{ padding-bottom:60px;}.pb70{ padding-bottom:70px;}.pb80{ padding-bottom:80px;}.pb90{ padding-bottom:90px;}.pb100{ padding-bottom:100px;}.pb110{ padding-bottom:110px;}.pb155{ padding-bottom:155px;} .pr2{ paddding-right:2px;}.pr5{ padding-right:5px;}.pr10{ padding-right:10px;}.pr15{ padding-right:15px;}.pr20{ padding-right:20px!important;}.pr30{ padding-right:30px!important;}.pr35{ padding-right:35px!important;}.pr42{ padding-right:42px;}.pr45{ padding-right:45px;}.pr48{ padding-right:48px;}.pr57{ padding-right:57px;}.pr60{ padding-right:60px;}.pr70{ padding-right:70px;}.pr72{ padding-right:72px;}.pr75{ padding-right:75px;}.pr88{ padding-right:88px;} .pl0{ padding-left:0px!important;}.pl2{ padding-left:2px;}.pl5{ padding-left:5px;}.pl7{ padding-left:7px;}.pl8{ padding-left:8px;}.pl10{ padding-left:10px;}.pl15{ padding-left:15px;}.pl20{ padding-left:20px;}.pl22{ padding-left:22px;}.pl25{ padding-left:25px;}.pl28{ padding-left:28px;}.pl30{ padding-left:30px !important;}.pl33{padding-left: 33px}.pl35{ padding-left:35px;}.pl40{ padding-left:40px;}.pl42{ padding-left:42px;}.pl45{ padding-left:45px;}.pl50{ padding-left:50px;}.pl60{ padding-left:60px;}.pl70{padding-left:70px;}.pl75{padding-left:75px;}.pl80{padding-left:80px;}.pl88{ padding-left:88px;}.pl92{padding-left:92px;}.pl100{ padding-left:100px;} @@ -556,11 +557,6 @@ a.user_greybg_btn{background-color:#747A7F;color: #fff;} .cdefault{cursor: default} -/*md编辑器恢复被覆盖样式*/ -.new_li li{ list-style-type: disc!important; } -.new_li ol li{ list-style-type: decimal!important; } -.new_li li{ margin-bottom: 0!important; } - /*搜索框*/ #pollingPanel{position: relative;width: 248px;height: 32px;} #pollingPanel > input{width: 100%;height: 100%;border:1px solid #eaeaea;border-radius: 4px;padding: 0px 30px 0px 5px;box-sizing: border-box;background-color: #F4F4F4;} diff --git a/app/views/admins/abouts/edit.html.erb b/app/views/admins/abouts/edit.html.erb new file mode 100644 index 000000000..4e75940c2 --- /dev/null +++ b/app/views/admins/abouts/edit.html.erb @@ -0,0 +1,15 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('关于我们') %> +<% end %> + +没有相关的单位
+ <% end %> +没有相关的单位
+ <% end %> +序号 | +学校名称 | +学校管理员 | +操作 | + + + <% if schools.size > 0 %> + <% schools.each_with_index do |school, index| %> +
---|---|---|---|
<%= list_index_no(@params_page.to_i, index) %> | ++ <%= link_to "#{school.name}", "/ecs/department?school_id=#{school.id}", target: "_blank" %> + | +
+
+ <%= link_to "".html_safe, "javascript:void(0)", class: "action", onclick: "show_add_manager('#{school.id}')" %>
+
+
+ <% if school.users.size > 0 %>
+ <%= render partial: "admins/auth_schools/shared/school_user_list", locals: {users: school.users, school_id: school.id} %>
+ <% end %>
+
+ |
+ + <%= link_to "".html_safe, admins_auth_school_path(school), method: :delete, data: {confirm: "确认删除吗?"}, remote: true %> + | +
ID | +部门名称 | +单位名称 | +创建者 | +<%= sort_tag('创建于', name: 'created_at', path: admins_department_applies_path) %> | +操作 | +
---|---|---|---|---|---|
<%= apply.id %> | +<%= apply.name %> | +<%= apply.school.try(:name) %> | +<%= apply&.user&.real_name %> | +<%= format_time apply.created_at %> | ++ <%= agree_link '批准', agree_admins_department_apply_path(apply, element: ".department-apply-#{apply.id}"), 'data-confirm': '确认批准通过?' %> + <%= javascript_void_link('删除', class: 'action refuse-action', + data: { + toggle: 'modal', target: '.admin-common-refuse-modal', id: apply.id, title: "删除原因", type: "delete", + url: admins_department_apply_path(apply,tip:"unapplied", element: ".department-apply-#{apply.id}") + }) %> + <%= javascript_void_link '更改', class: 'action', data: { school_id: apply.school_id, department_id: apply.id, + toggle: 'modal', target: '.admin-merge-department-modal', url: merge_admins_department_applies_path } %> + | +
序号 | +模板名称 | +上传模板 | +操作 | + + + <% if templates.size > 0 %> + <% templates.each_with_index do |t, index| %> + <% attachment = t.attachments.first %> +
---|---|---|---|
<%= list_index_no(@params_page.to_i, index) %> | +<%= t.name %> | ++ <% if attachment.present? %> + <%= link_to "#{attachment.try(:filename)}",attachment_path(attachment), target: "_blank" %> + <% end %> + | ++ <%= link_to "".html_safe, + "javascript:void(0)", data: {"id": "#{t.id}", "template-id": "#{attachment.present? ? attachment.id : "-1"}", + msg: "编辑", name: "#{t.name}", "template_name": "#{attachment.try(:filename)}"}, class: "edit-template-content" %> + + <%= link_to "".html_safe, admins_ec_template_path(t.id), method: :delete, data: {confirm: "确认删除吗?"}, remote: true, title: "删除" %> + | +
序号 | +通用标准 | +操作 | + + + <% if standards.size > 0 %> + <% standards.each_with_index do |standard, index| %> +
---|---|---|
<%= list_index_no(@params_page.to_i, index) %> | +<%= standard.content %> | ++ <%= javascript_void_link "".html_safe, class: 'standard-create-modal', + data: { toggle: 'modal', target: '.graduation-standards-add', id: "#{standard.id}", content: "#{standard.content}", msg: "编辑" }, title: "编辑" %> + + <%= link_to "".html_safe, admins_graduation_standard_path(standard), method: :delete, data: {confirm: "确认删除吗?"}, remote: true, title: "删除" %> + | +