From 3324ca4b52c30525fefd67c9ce7ff6b288f81199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 10 Jan 2020 17:42:40 +0800 Subject: [PATCH 01/55] =?UTF-8?q?=E9=A2=98=E5=BA=93=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../react/src/common/quillForEditor/index.js | 29 ++++++++++--------- .../modules/question/Questionitem_banks.js | 8 ++--- .../question/component/ChoquesEditor.js | 2 +- .../question/component/SingleEditor.js | 8 ++--- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/public/react/src/common/quillForEditor/index.js b/public/react/src/common/quillForEditor/index.js index 525feba09..378111af8 100644 --- a/public/react/src/common/quillForEditor/index.js +++ b/public/react/src/common/quillForEditor/index.js @@ -1,7 +1,7 @@ /* * @Description: quill 编辑器 * @Author: tangjiang - * @Github: + * @Github: * @Date: 2019-12-18 08:49:30 * @LastEditors : tangjiang * @LastEditTime : 2020-01-10 15:05:27 @@ -57,7 +57,7 @@ function QuillForEditor ({ {size: ['12px', '14px', '16px', '18px', '20px']}, {align: []}, {list: 'ordered'}, {list: 'bullet'}, // 列表 {script: 'sub'}, {script: 'super'}, - { 'color': [] }, { 'background': [] }, + { 'color': [] }, { 'background': [] }, {header: [1,2,3,4,5,false]}, 'blockquote', 'code-block', 'link', 'image', 'video', @@ -67,7 +67,7 @@ function QuillForEditor ({ const editorRef = useRef(null); // quill 实例 - const [quill, setQuill] = useState(null); + const [quill, setQuill] = useState(null); const [selection, setSelection] = useState(null); const [fillCount, setFillCount] = useState(0); const [quillCtx, setQuillCtx] = useState({}); @@ -77,7 +77,7 @@ function QuillForEditor ({ // getQuillContent && getQuillContent(quill); onContentChange && onContentChange(content, quill); }; - + const renderOptions = options || defaultConfig; const bindings = { @@ -96,10 +96,10 @@ function QuillForEditor ({ backspace: { key: 'Backspace', /** - * @param {*} range + * @param {*} range * { index, // 删除元素的位置 * length // 删除元素的个数, 当删除一个时, length=0, 其它等于删除的元素的个数 - * } + * } * @param {*} context 上下文 */ handler: function (range, context) { @@ -126,7 +126,7 @@ function QuillForEditor ({ // } else { // return false; // } - return true; + return true; } } }; @@ -190,7 +190,7 @@ function QuillForEditor ({ onClick: showUploadImage, width, height - }); + }); } } }); @@ -208,19 +208,19 @@ function QuillForEditor ({ // 1. 获取编辑器内容 }); - // TODO + // TODO /** * 1.获取键盘删除事件 * 2.点击时获取删除的叶子节点 getLeaf(range.index) */ }, []); - - // 设置值 + + // 设置值 useEffect(() => { if (!quill) return const previous = quill.getContents() - + if (value && value.hasOwnProperty('ops')) { // console.log(value.ops); const ops = value.ops || []; @@ -234,7 +234,8 @@ function QuillForEditor ({ const current = value if (!deepEqual(previous, current)) { setSelection(quill.getSelection()) - if (typeof value === 'string') { + if (typeof value === 'string' && value) { + // debugger quill.clipboard.dangerouslyPasteHTML(value, 'api'); if (autoFocus) { quill.focus(); @@ -268,7 +269,7 @@ function QuillForEditor ({ if (typeof handleOnChange !== 'function') return; let handler; quill.on( - 'text-change', + 'text-change', (handler = (delta, oldDelta, source) => { const _ctx = quill.getContents(); setQuillCtx(_ctx); diff --git a/public/react/src/modules/question/Questionitem_banks.js b/public/react/src/modules/question/Questionitem_banks.js index 129e29d69..0c27dc0fa 100644 --- a/public/react/src/modules/question/Questionitem_banks.js +++ b/public/react/src/modules/question/Questionitem_banks.js @@ -476,7 +476,7 @@ class Questionitem_banks extends Component { this.setState({ item_type: item_type }) - + this.scrollToAnchor("Itembankstopid"); } render() { @@ -515,6 +515,7 @@ class Questionitem_banks extends Component { > +
{ item_type && item_type === "SINGLE" ? @@ -555,9 +556,8 @@ class Questionitem_banks extends Component { : item_type && item_type === "PROGRAM" ? "" : "" - } - - + } +
diff --git a/public/react/src/modules/question/component/ChoquesEditor.js b/public/react/src/modules/question/component/ChoquesEditor.js index 93283c307..16aef2e2d 100644 --- a/public/react/src/modules/question/component/ChoquesEditor.js +++ b/public/react/src/modules/question/component/ChoquesEditor.js @@ -399,7 +399,7 @@ class ChoquesEditor extends Component{ { item===undefined||item===null||item===""? + diff --git a/public/react/src/modules/testpaper/component/Paperlibraryseeid_items.js b/public/react/src/modules/testpaper/component/Paperlibraryseeid_items.js index 7747574dd..d4212c3f1 100644 --- a/public/react/src/modules/testpaper/component/Paperlibraryseeid_items.js +++ b/public/react/src/modules/testpaper/component/Paperlibraryseeid_items.js @@ -95,7 +95,8 @@ class Paperlibraryseeid_items extends Component {
网址克隆
@@ -354,11 +381,15 @@ class VNCContainer extends Component { > - - {/* */} + {/* {this.state.vnc_reseting ? : } 重置桌面系统 + */} + + {this.state.vnc_reseting ? + : } + 重置实训 {/* diff --git a/public/react/src/modules/page/VNCDisplay.js b/public/react/src/modules/page/VNCDisplay.js index b9ec77988..17dbff309 100644 --- a/public/react/src/modules/page/VNCDisplay.js +++ b/public/react/src/modules/page/VNCDisplay.js @@ -166,7 +166,8 @@ class VNCDisplay extends Component { `}
Loading
-
Send CtrlAltDel
+ {/*
Send CtrlAltDel
*/} +
diff --git a/public/react/src/modules/page/header.scss b/public/react/src/modules/page/header.scss new file mode 100644 index 000000000..b8320638f --- /dev/null +++ b/public/react/src/modules/page/header.scss @@ -0,0 +1,6 @@ +.headerRight .exit_btn{ + color: rgba(237,237,237,1); + &:hover{ + // color: #fff; + } +} \ No newline at end of file diff --git a/public/react/src/modules/page/tpiPage.css b/public/react/src/modules/page/tpiPage.css index 0c4faee83..015a66b98 100644 --- a/public/react/src/modules/page/tpiPage.css +++ b/public/react/src/modules/page/tpiPage.css @@ -120,8 +120,10 @@ button.buttonHoverColor:hover a { #myshixun_top { - display: flex; - height: 54px; + display: flex; + position: fixed; + height: 54px; + z-index: 1 !important; } .headerLeft { flex: 0 0 400px; From 1fe5acad9991091b487b9fb4524cc683d944c194 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sat, 11 Jan 2020 16:48:59 +0800 Subject: [PATCH 19/55] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E9=A2=98=E7=9A=84?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/courses_controller.rb | 2 +- .../exercise_answers_controller.rb | 144 ++++++++---------- 2 files changed, 66 insertions(+), 80 deletions(-) diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 753a3d942..b19ad96e8 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -182,7 +182,7 @@ class CoursesController < ApplicationController CreateSubjectCourseStudentJob.perform_later(@course.id) if @course.subject && @course.subject.subject_appointments.count > 0 rescue => e uid_logger_error(e.message) - tip_exception("调用失败") + tip_exception(e.message) raise ActiveRecord::Rollback end end diff --git a/app/controllers/exercise_answers_controller.rb b/app/controllers/exercise_answers_controller.rb index d74e14fe1..dfbe68cb5 100644 --- a/app/controllers/exercise_answers_controller.rb +++ b/app/controllers/exercise_answers_controller.rb @@ -2,94 +2,80 @@ class ExerciseAnswersController < ApplicationController before_action :require_login, :check_auth before_action :get_exercise_question include ExercisesHelper - - # model validation error - rescue_from ActiveRecord::RecordInvalid do |ex| - render_error(ex.record.errors.full_messages.join(',')) - end - # form validation error - rescue_from ActiveModel::ValidationError do |ex| - render_error(ex.model.errors.full_messages.join(',')) - end + include ControllerRescueHandler def create #每一次答案的点击,请求一次,实训题不在这里回答 - begin - q_type = @exercise_question.question_type #试卷的类型 - choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : "" - answer_text = params[:answer_text].present? ? params[:answer_text].strip : "" #为字符串 - if q_type < Exercise::SUBJECTIVE && (q_type != Exercise::MULTIPLE) && choice_id.blank? - normal_status(-1,"请选择序号") - else - ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案 - if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题 - if ea.exists? - ea.first.update!(exercise_choice_id: choice_id ) - else - answer_option = { - :user_id => current_user.id, - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => choice_id, - :answer_text => "" - } - ex_a = ExerciseAnswer.new(answer_option) - ex_a.save! - end - elsif q_type == Exercise::MULTIPLE #多选题的 - choice_ids = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : [] - - ea_ids = ea.pluck(:exercise_choice_id) - common_answer_ids = choice_ids & ea_ids #已经存在的试卷选项id - new_ids = (choice_ids - common_answer_ids).uniq # 新增的id - old_ids = (ea_ids - common_answer_ids).uniq #没有选择的,则删掉 - if new_ids.size > 0 - new_ids.each do |e| - answer_option = { - :user_id => current_user.id, - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => e, - :answer_text => "" - } - ex_a = ExerciseAnswer.new(answer_option) - ex_a.save! - end - end - if old_ids.size > 0 - ea_answer = ea.search_answer_users("exercise_choice_id",old_ids) - ea_answer.destroy_all - end - elsif q_type == Exercise::COMPLETION #填空题 - answer_option = { - :user_id => current_user.id, - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => choice_id, - :answer_text => answer_text - } - ea_answer = ea.search_answer_users("exercise_choice_id",choice_id) - if ea.present? && ea_answer.present? - ea_answer.update!(answer_option) - else - ex_new = ExerciseAnswer.new(answer_option) - ex_new.save! - end - elsif q_type == Exercise::SUBJECTIVE #简答题 + q_type = @exercise_question.question_type #试卷的类型 + choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : "" + answer_text = params[:answer_text].present? ? params[:answer_text].strip : "" #为字符串 + if q_type < Exercise::SUBJECTIVE && (q_type != Exercise::MULTIPLE) && choice_id.blank? + normal_status(-1,"请选择序号") + else + ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案 + if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题 + if ea.exists? + ea.first.update!(exercise_choice_id: choice_id ) + else answer_option = { - :user_id => current_user.id, - :exercise_question_id => @exercise_question.id + :user_id => current_user.id, + :exercise_question_id => @exercise_question.id, + :exercise_choice_id => choice_id, + :answer_text => "" } - if ea.present? #已经回答了的, - ea.first.update!(answer_text: answer_text) - else - answer_option.merge!(answer_text:answer_text) + ex_a = ExerciseAnswer.new(answer_option) + ex_a.save! + end + elsif q_type == Exercise::MULTIPLE #多选题的 + choice_ids = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : [] + + ea_ids = ea.pluck(:exercise_choice_id) + common_answer_ids = choice_ids & ea_ids #已经存在的试卷选项id + new_ids = (choice_ids - common_answer_ids).uniq # 新增的id + old_ids = (ea_ids - common_answer_ids).uniq #没有选择的,则删掉 + if new_ids.size > 0 + new_ids.each do |e| + answer_option = { + :user_id => current_user.id, + :exercise_question_id => @exercise_question.id, + :exercise_choice_id => e, + :answer_text => "" + } ex_a = ExerciseAnswer.new(answer_option) ex_a.save! end end - normal_status(0,"回答成功") + if old_ids.size > 0 + ea_answer = ea.search_answer_users("exercise_choice_id",old_ids) + ea_answer.destroy_all + end + elsif q_type == Exercise::COMPLETION #填空题 + answer_option = { + :user_id => current_user.id, + :exercise_question_id => @exercise_question.id, + :exercise_choice_id => choice_id, + :answer_text => answer_text + } + ea_answer = ea.search_answer_users("exercise_choice_id",choice_id) + if ea.present? && ea_answer.present? + ea_answer.update!(answer_option) + else + ex_new = ExerciseAnswer.new(answer_option) + ex_new.save! + end + elsif q_type == Exercise::SUBJECTIVE #简答题 + answer_option = { + :user_id => current_user.id, + :exercise_question_id => @exercise_question.id + } + if ea.present? #已经回答了的, + ea.first.update!(answer_text: answer_text) + else + answer_option.merge!(answer_text:answer_text) + ex_a = ExerciseAnswer.new(answer_option) + ex_a.save! + end end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("页面调用失败!") - raise ActiveRecord::Rollback + normal_status(0,"回答成功") end end From 4098b420d133fe40378f487249d57da689f2b5ed Mon Sep 17 00:00:00 2001 From: tangjiang <465264938@qq.com> Date: Sat, 11 Jan 2020 16:51:10 +0800 Subject: [PATCH 20/55] update diff --- public/react/src/common/educoder.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/public/react/src/common/educoder.js b/public/react/src/common/educoder.js index b8c735e24..ded33c43a 100644 --- a/public/react/src/common/educoder.js +++ b/public/react/src/common/educoder.js @@ -3,13 +3,9 @@ // export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil'; export { getImageUrl as getImageUrl, getRandomNumber as getRandomNumber,getUrl as getUrl, publicSearchs as publicSearchs,getRandomcode as getRandomcode,getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl -<<<<<<< HEAD , getUploadActionUrl as getUploadActionUrl,getUploadActionUrltwo as getUploadActionUrltwo ,getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth , getTaskUrlById as getTaskUrlById, TEST_HOST ,htmlEncode as htmlEncode ,getupload_git_file as getupload_git_file} from './UrlTool'; -======= - , getUploadActionUrl as getUploadActionUrl,getUploadActionUrltwo as getUploadActionUrltwo ,getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth - , getTaskUrlById as getTaskUrlById, TEST_HOST ,htmlEncode as htmlEncode ,getupload_git_file as getupload_git_file} from './UrlTool'; ->>>>>>> dev_aliyun + export {setmiyah as setmiyah} from './Component'; export { default as queryString } from './UrlTool2'; From a5601a2b2d0460fcb73cf29b9646e09092213a6a Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sat, 11 Jan 2020 16:55:02 +0800 Subject: [PATCH 21/55] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E9=A2=98=E7=9A=84?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/exercise_answers_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/exercise_answers_controller.rb b/app/controllers/exercise_answers_controller.rb index dfbe68cb5..3556ab8d3 100644 --- a/app/controllers/exercise_answers_controller.rb +++ b/app/controllers/exercise_answers_controller.rb @@ -57,7 +57,7 @@ class ExerciseAnswersController < ApplicationController } ea_answer = ea.search_answer_users("exercise_choice_id",choice_id) if ea.present? && ea_answer.present? - ea_answer.update!(answer_option) + ea_answer.first.update!(answer_option) else ex_new = ExerciseAnswer.new(answer_option) ex_new.save! From e26ef0f133c46fb6f4c84f67401645fff697f461 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sat, 11 Jan 2020 16:59:38 +0800 Subject: [PATCH 22/55] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E9=A2=98=E7=9A=84?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/exercise_answers_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/exercise_answers_controller.rb b/app/controllers/exercise_answers_controller.rb index 3556ab8d3..158628475 100644 --- a/app/controllers/exercise_answers_controller.rb +++ b/app/controllers/exercise_answers_controller.rb @@ -2,7 +2,6 @@ class ExerciseAnswersController < ApplicationController before_action :require_login, :check_auth before_action :get_exercise_question include ExercisesHelper - include ControllerRescueHandler def create #每一次答案的点击,请求一次,实训题不在这里回答 q_type = @exercise_question.question_type #试卷的类型 From d5e2446016bf55c4c2cb9a0781b52f29124c1299 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sat, 11 Jan 2020 17:10:39 +0800 Subject: [PATCH 23/55] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E7=9A=84=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/exercises_controller.rb | 3733 ++++++++++++++++------- 1 file changed, 2619 insertions(+), 1114 deletions(-) diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index ea4e38ab9..408f95945 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -1,26 +1,26 @@ class ExercisesController < ApplicationController before_action :require_login, :check_auth, except: [:index] - before_action :find_course,only: [:index,:new,:create,:my_exercises,:public_exercises,:set_public,:destroys, - :join_exercise_banks,:publish_modal,:publish,:end_modal,:end_exercise] #需要有课堂id参数的 - before_action :get_exercise,except: [:index,:new,:create,:my_exercises,:public_exercises,:set_public,:destroys, - :join_exercise_banks,:publish_modal,:publish,:end_modal,:end_exercise] + before_action :find_course, only: [:index, :new, :create, :my_exercises, :public_exercises, :set_public, :destroys, + :join_exercise_banks, :publish_modal, :publish, :end_modal, :end_exercise] #需要有课堂id参数的 + before_action :get_exercise, except: [:index, :new, :create, :my_exercises, :public_exercises, :set_public, :destroys, + :join_exercise_banks, :publish_modal, :publish, :end_modal, :end_exercise] before_action :user_course_identity - before_action :is_course_teacher,except: [:index,:start_answer,:exercise_setting,:commit_exercise,:exercise_lists,:review_exercise, - :exercise_result,:common_header,:cancel_exercise,:begin_commit] - before_action :get_left_banner_id,only:[:common_header,:start_answer,:review_exercise,:index,:new,:edit] - before_action :validates_exercise_params,only: [:create,:update] - before_action :get_exercise_question_counts,only: [:show,:edit,:start_answer,:review_exercise,:blank_exercise,:export_exercise] - before_action :validate_publish_time,only: [:commit_setting] #提交设置时,需判断时间是否符合 - before_action :check_course_public,only: [:set_public] - before_action :check_user_on_answer,only: [:show,:start_answer,:exercise_lists] #判断当前用户在试卷的权限/老师是否属于分班的权限 - before_action :only_student_in,only: [:start_answer] - before_action :check_user_id_start_answer,only: [:start_answer,:review_exercise] + before_action :is_course_teacher, except: [:index, :start_answer, :exercise_setting, :commit_exercise, :exercise_lists, :review_exercise, + :exercise_result, :common_header, :cancel_exercise, :begin_commit] + before_action :get_left_banner_id, only: [:common_header, :start_answer, :review_exercise, :index, :new, :edit] + before_action :validates_exercise_params, only: [:create, :update] + before_action :get_exercise_question_counts, only: [:show, :edit, :start_answer, :review_exercise, :blank_exercise, :export_exercise] + before_action :validate_publish_time, only: [:commit_setting] #提交设置时,需判断时间是否符合 + before_action :check_course_public, only: [:set_public] + before_action :check_user_on_answer, only: [:show, :start_answer, :exercise_lists] #判断当前用户在试卷的权限/老师是否属于分班的权限 + before_action :only_student_in, only: [:start_answer] + before_action :check_user_id_start_answer, only: [:start_answer, :review_exercise] # before_action :commit_user_exercise,only: [:start_answer,:exercise_lists,:review_exercise] #已有定时的任务 - before_action :check_exercise_time,only: [:commit_exercise] #提交试卷时,判断时间是否超过 - before_action :check_exercise_status,only: [:redo_modal,:redo_exercise] + before_action :check_exercise_time, only: [:commit_exercise] #提交试卷时,判断时间是否超过 + before_action :check_exercise_status, only: [:redo_modal, :redo_exercise] before_action :check_exercise_is_end, only: [:review_exercise] - before_action :check_exercise_public,only: [:exercise_result] #试卷是否为公开 - before_action :commit_shixun_present,only: [:commit_shixun] + before_action :check_exercise_public, only: [:exercise_result] #试卷是否为公开 + before_action :commit_shixun_present, only: [:commit_shixun] include ExportHelper include ExercisesHelper @@ -37,28 +37,28 @@ class ExercisesController < ApplicationController begin # 按发布时间或创建时间排序 @exercises_all = @course.exercises - member_show_exercises = @exercises_all.is_exercise_published #已发布的或已截止的试卷 + member_show_exercises = @exercises_all.is_exercise_published #已发布的或已截止的试卷 @current_user_ = current_user # 课堂的学生人数 @course_all_members = @course.students #当前课堂的全部学生 - @current_student = @course_all_members.course_find_by_ids("user_id",current_user.id) #当前用户是否为课堂的学生 + @current_student = @course_all_members.course_find_by_ids("user_id", current_user.id) #当前用户是否为课堂的学生 # exercises的不同用户群体的显示 - if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教 + if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教 @is_teacher_or = 1 - @exercises = @exercises_all #老师能看到全部的试卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同) - elsif @user_course_identity == Course::STUDENT # 2为课堂成员,能看到统一设置的和自己班级的 + @exercises = @exercises_all #老师能看到全部的试卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同) + elsif @user_course_identity == Course::STUDENT # 2为课堂成员,能看到统一设置的和自己班级的 @is_teacher_or = 2 - @member_group_id = @current_student.first.try(:course_group_id).to_i # 成员的分班id,默认为0 - if @member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的) + @member_group_id = @current_student.first.try(:course_group_id).to_i # 成员的分班id,默认为0 + if @member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的) @exercises = member_show_exercises.exists? ? member_show_exercises.unified_setting : [] - else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷 + else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷 # 已发布 当前用户班级分组的 试卷id publish_exercise_ids = @course.exercise_group_settings.exercise_group_published.where("course_group_id = #{@member_group_id}").pluck(:exercise_id) @exercises = member_show_exercises.unified_setting.or(member_show_exercises.where(id: publish_exercise_ids)) end - else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁 + else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁 @is_teacher_or = 0 @exercises = member_show_exercises.unified_setting end @@ -75,7 +75,7 @@ class ExercisesController < ApplicationController ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}").exercise_group_not_published.pluck(:exercise_id) when 2 ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}") - .where("publish_time is not null and publish_time <= ? and end_time > ?",Time.now,Time.now).pluck(:exercise_id) + .where("publish_time is not null and publish_time <= ? and end_time > ?", Time.now, Time.now).pluck(:exercise_id) when 3 ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}").exercise_group_ended.pluck(:exercise_id) end @@ -90,11 +90,11 @@ class ExercisesController < ApplicationController @exercises = @exercises.exercise_search(search_type) end - @exercises_select_count = @exercises.size # 全部页面,需返回 - @exercises = @exercises.distinct.order( "IF(ISNULL(publish_time),0,1), publish_time DESC,created_at DESC") #出现错误 + @exercises_select_count = @exercises.size # 全部页面,需返回 + @exercises = @exercises.distinct.order("IF(ISNULL(publish_time),0,1), publish_time DESC,created_at DESC") #出现错误 # 分页 - @page = params[:page] || 1 + @page = params[:page] || 1 @limit = params[:limit] || 15 @exercises = @exercises.page(@page).per(@limit) @exercises = @exercises&.includes(:published_settings) @@ -102,10 +102,10 @@ class ExercisesController < ApplicationController @exercises = [] end - @course_all_members_count = @course_all_members.size #当前课堂的学生数 - @exercises_count = @exercises_all.size # 全部页面,需返回 + @course_all_members_count = @course_all_members.size #当前课堂的学生数 + @exercises_count = @exercises_all.size # 全部页面,需返回 @exercises_unpublish_counts = @exercises_all.exercise_by_status(1).size #未发布的试卷数 - @exercises_published_counts = @exercises_count - @exercises_unpublish_counts # 已发布的试卷数,包含已截止的 + @exercises_published_counts = @exercises_count - @exercises_unpublish_counts # 已发布的试卷数,包含已截止的 rescue Exception => e uid_logger_error(e.message) @@ -128,108 +128,77 @@ class ExercisesController < ApplicationController def create ActiveRecord::Base.transaction do - begin - ex_name = params[:exercise_name] - ex_desc = params[:exercise_description] - exercise_options = { - :exercise_name => ex_name, - :exercise_description => ex_desc, - :user_id => current_user.id, - :course_id => @course.id, - :time => -1, - :exercise_status => 1 - } - @exercise = Exercise.create!(exercise_options) - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷创建失败!") - raise ActiveRecord::Rollback - end + ex_name = params[:exercise_name] + ex_desc = params[:exercise_description] + exercise_options = { + :exercise_name => ex_name, + :exercise_description => ex_desc, + :user_id => current_user.id, + :course_id => @course.id, + :time => -1, + :exercise_status => 1 + } + @exercise = Exercise.create!(exercise_options) end end #试卷的内容,及试题/答案的内容编辑 def edit ActiveRecord::Base.transaction do - begin - @exercise_questions = @exercise.exercise_questions.order("question_number ASC") - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷创建失败!") - raise ActiveRecord::Rollback - end + @exercise_questions = @exercise.exercise_questions.order("question_number ASC") end end def update ActiveRecord::Base.transaction do - begin - ex_name = params[:exercise_name] - ex_desc = params[:exercise_description] - exercise_options = { - :exercise_name => ex_name, - :exercise_description => ex_desc, - } - @exercise.update!(exercise_options) - normal_status(0,"试卷更新成功!") - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷创建失败!") - raise ActiveRecord::Rollback - end + ex_name = params[:exercise_name] + ex_desc = params[:exercise_description] + exercise_options = { + :exercise_name => ex_name, + :exercise_description => ex_desc, + } + @exercise.update!(exercise_options) + normal_status(0, "试卷更新成功!") end end def show ActiveRecord::Base.transaction do - begin - if @user_course_identity < Course::STUDENT - @is_teacher_or = 1 #为老师/助教/管理员 - else - @is_teacher_or = 0 #为学生 - end - @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_shixun_challenges,:exercise_standard_answers).order("question_number ASC") - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷创建失败!") - raise ActiveRecord::Rollback + if @user_course_identity < Course::STUDENT + @is_teacher_or = 1 #为老师/助教/管理员 + else + @is_teacher_or = 0 #为学生 end + @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices, :exercise_shixun_challenges, :exercise_standard_answers).order("question_number ASC") end end #试卷的公用头部 def common_header ActiveRecord::Base.transaction do - begin - @user_left_time = nil - if @user_course_identity > Course::ASSISTANT_PROFESSOR - @is_teacher_or = 0 - @user_exercise_answer = @exercise.check_user_answer_status(current_user) - @user_commit_counts = 0 - @user_left_time = get_exercise_left_time(@exercise,current_user) - else - @is_teacher_or = 1 - @user_exercise_answer = 3 #教师页面 - @user_commit_counts = @exercise.exercise_users.where(commit_status:1).size #已提交的用户数 - end - @ex_status = @exercise.get_exercise_status(current_user) + @user_left_time = nil + if @user_course_identity > Course::ASSISTANT_PROFESSOR + @is_teacher_or = 0 + @user_exercise_answer = @exercise.check_user_answer_status(current_user) + @user_commit_counts = 0 + @user_left_time = get_exercise_left_time(@exercise, current_user) + else + @is_teacher_or = 1 + @user_exercise_answer = 3 #教师页面 + @user_commit_counts = @exercise.exercise_users.where(commit_status: 1).size #已提交的用户数 + end + @ex_status = @exercise.get_exercise_status(current_user) - exercise_id_array = [@exercise.id] - @exercise_publish_count = get_user_permission_course(exercise_id_array,Exercise::PUBLISHED).size #是否存在已发布的 - @exercise_unpublish_count = get_user_permission_course(exercise_id_array,Exercise::UNPUBLISHED).size #是否存在未发布的 + exercise_id_array = [@exercise.id] + @exercise_publish_count = get_user_permission_course(exercise_id_array, Exercise::PUBLISHED).size #是否存在已发布的 + @exercise_unpublish_count = get_user_permission_course(exercise_id_array, Exercise::UNPUBLISHED).size #是否存在未发布的 - if (@exercise_publish_count == 0) && (@exercise_unpublish_count == 0) #即表示没有分班 - if @ex_status == Exercise::UNPUBLISHED - @exercise_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候 - elsif @ex_status == Exercise::PUBLISHED - @exercise_publish_count = 1 #试卷未发布,且课堂没有分班的时候 - end + if (@exercise_publish_count == 0) && (@exercise_unpublish_count == 0) #即表示没有分班 + if @ex_status == Exercise::UNPUBLISHED + @exercise_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候 + elsif @ex_status == Exercise::PUBLISHED + @exercise_publish_count = 1 #试卷未发布,且课堂没有分班的时候 end - - rescue Exception => e - uid_logger_error(e.message) - tip_exception("没有权限") - raise ActiveRecord::Rollback end end end @@ -237,381 +206,338 @@ class ExercisesController < ApplicationController #实训题目的选用 def choose_shixun ActiveRecord::Base.transaction do - begin - search = params[:search] - if @user_course_identity > Course::ADMIN #当不为管理员的时候 - user_school_id = current_user.school_id #当前用户的学校id - if user_school_id.present? - none_shixun_ids = ShixunSchool.where("school_id != #{user_school_id}").pluck(:shixun_id) - @publish_shixuns = Shixun.where.not(id: none_shixun_ids).unhidden - end - else - @publish_shixuns = Shixun.unhidden - end - if search.present? - @publish_shixuns = @publish_shixuns.search_by_name(search) + search = params[:search] + if @user_course_identity > Course::ADMIN #当不为管理员的时候 + user_school_id = current_user.school_id #当前用户的学校id + if user_school_id.present? + none_shixun_ids = ShixunSchool.where("school_id != #{user_school_id}").pluck(:shixun_id) + @publish_shixuns = Shixun.where.not(id: none_shixun_ids).unhidden end + else + @publish_shixuns = Shixun.unhidden + end + if search.present? + @publish_shixuns = @publish_shixuns.search_by_name(search) + end - @shixuns = @publish_shixuns.joins(:challenges).where("challenges.st != 0").distinct - # 全部页面,需返回 - @shixuns_count = @shixuns.count + @shixuns = @publish_shixuns.joins(:challenges).where("challenges.st != 0").distinct + # 全部页面,需返回 + @shixuns_count = @shixuns.count - # 分页 - @page = params[:page] || 1 - @limit = params[:limit] || 8 + # 分页 + @page = params[:page] || 1 + @limit = params[:limit] || 8 - @shixuns = @shixuns.page(@page).per(@limit) - rescue Exception => e - uid_logger_error(e.message) - tip_exception("实训选择失败!") - end + @shixuns = @shixuns.page(@page).per(@limit) end end #确认实训的选择 def commit_shixun ActiveRecord::Base.transaction do - begin - @shixun_challenges = @shixun.challenges - @shixun_challenges_count = @shixun_challenges.size - rescue Exception => e - uid_logger_error(e.message) - tip_exception("页面调用失败!") - raise ActiveRecord::Rollback - end + @shixun_challenges = @shixun.challenges + @shixun_challenges_count = @shixun_challenges.size end end # 首页批量或单独删除 def destroys ActiveRecord::Base.transaction do - begin - check_ids = Exercise.where(id: params[:check_ids]) - check_ids.destroy_all - normal_status(0, "试卷已删除成功!") - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷删除失败!") - raise ActiveRecord::Rollback - end + check_ids = Exercise.where(id: params[:check_ids]) + check_ids.destroy_all + normal_status(0, "试卷已删除成功!") end end # 设为公开 def set_public ActiveRecord::Base.transaction do - begin - check_ids = Exercise.where(id: params[:check_ids]) - check_ids.each do |exercise| - exercise.update!(is_public: true) - end - normal_status(0, "试卷已设为公开!") - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷设为公开失败!") - raise ActiveRecord::Rollback + check_ids = Exercise.where(id: params[:check_ids]) + check_ids.each do |exercise| + exercise.update!(is_public: true) end + normal_status(0, "试卷已设为公开!") end end ## 加入题库 def join_exercise_banks ActiveRecord::Base.transaction do - begin - check_ids = Exercise.where(id: params[:check_ids]) - check_ids.each do |exercise| - current_ex_bank = current_user.exercise_banks.find_by_container(exercise.id,"Exercise")&.first - if current_ex_bank.present? #当前用户的选择试卷是否已加入习题库,存在则更新习题库和问题库,否则新建习题库和问题库 - ex_params = { - :name => exercise.exercise_name, - :description => exercise.exercise_description, - :course_list_id => exercise.course.try(:course_list_id) - } - current_ex_bank.update!(ex_params) - # question_bank = QuestionBank.ques_by_container(current_ex_bank.id,current_ex_bank.container_type).first #该习题库是否存在于问题库里 - # ques_params = { - # :name => current_ex_bank.name, - # :course_list_id => current_ex_bank.course_list_id - # } - # question_bank.update_attributes(ques_params) if question_bank.present? - current_ex_bank.exercise_bank_questions.destroy_all # 更新后,习题库的问题全部删除,后续重新再建 - else - ex_params = { - :name => exercise.exercise_name, - :description => exercise.exercise_description, - :user_id => current_user.id, - :is_public => 0, - :course_list_id => exercise.course.try(:course_list_id), - :container_id => exercise.id, - :container_type => "Exercise", - :quotes => 1 - } - current_ex_bank= ExerciseBank.new ex_params - current_ex_bank.save! #如果习题库保存成功,则会创建问题库question_bank - # if current_ex_bank.save - # ques_params = { - # :name => current_ex_bank.name, - # :container_id => current_ex_bank.id, - # :container_type => current_ex_bank.container_type, - # :quotes => current_ex_bank.quotes, - # :user_id => current_ex_bank.user_id, - # :is_public => current_ex_bank.is_public, - # :course_list_id => current_ex_bank.course_list_id - # } - # question_bank = QuestionBank.new ques_params - # question_bank.save - # end - exercise.update!(exercise_bank_id: current_ex_bank.id) - end - # 试卷的问题的输入 - exercise.exercise_questions.each do |q| - option = { - :question_title => q.question_title, - :question_type => q.question_type, - :question_number => q.question_number, - :question_score => q.question_score, + check_ids = Exercise.where(id: params[:check_ids]) + check_ids.each do |exercise| + current_ex_bank = current_user.exercise_banks.find_by_container(exercise.id, "Exercise")&.first + if current_ex_bank.present? #当前用户的选择试卷是否已加入习题库,存在则更新习题库和问题库,否则新建习题库和问题库 + ex_params = { + :name => exercise.exercise_name, + :description => exercise.exercise_description, + :course_list_id => exercise.course.try(:course_list_id) + } + current_ex_bank.update!(ex_params) + # question_bank = QuestionBank.ques_by_container(current_ex_bank.id,current_ex_bank.container_type).first #该习题库是否存在于问题库里 + # ques_params = { + # :name => current_ex_bank.name, + # :course_list_id => current_ex_bank.course_list_id + # } + # question_bank.update_attributes(ques_params) if question_bank.present? + current_ex_bank.exercise_bank_questions.destroy_all # 更新后,习题库的问题全部删除,后续重新再建 + else + ex_params = { + :name => exercise.exercise_name, + :description => exercise.exercise_description, + :user_id => current_user.id, + :is_public => 0, + :course_list_id => exercise.course.try(:course_list_id), + :container_id => exercise.id, + :container_type => "Exercise", + :quotes => 1 + } + current_ex_bank = ExerciseBank.new ex_params + current_ex_bank.save! #如果习题库保存成功,则会创建问题库question_bank + # if current_ex_bank.save + # ques_params = { + # :name => current_ex_bank.name, + # :container_id => current_ex_bank.id, + # :container_type => current_ex_bank.container_type, + # :quotes => current_ex_bank.quotes, + # :user_id => current_ex_bank.user_id, + # :is_public => current_ex_bank.is_public, + # :course_list_id => current_ex_bank.course_list_id + # } + # question_bank = QuestionBank.new ques_params + # question_bank.save + # end + exercise.update!(exercise_bank_id: current_ex_bank.id) + end + # 试卷的问题的输入 + exercise.exercise_questions.each do |q| + option = { + :question_title => q.question_title, + :question_type => q.question_type, + :question_number => q.question_number, + :question_score => q.question_score, + :shixun_id => q.shixun_id, + :shixun_name => q.shixun_name + } + exercise_bank_question = current_ex_bank.exercise_bank_questions.new option + exercise_bank_question.save! + ## 试卷选项的输入 + if q.question_type != Exercise::PRACTICAL #不为实训题时,试卷选项加入试题答案库 + ex_choices = q.exercise_choices + ex_standard = q.exercise_standard_answers + ex_choices.each do |c| + choice_option = { + :choice_position => c.choice_position, + :choice_text => c.choice_text + } + ex_bank_choice = exercise_bank_question.exercise_bank_choices.new choice_option + ex_bank_choice.save! + end + ex_standard.each do |s| + ex_stand = { + :exercise_bank_choice_id => s.exercise_choice_id, + :answer_text => s.answer_text + } + ex_stand_bank = exercise_bank_question.exercise_bank_standard_answers.new ex_stand + ex_stand_bank.save! + end + else #当为实训题时 + shixun_challenges = q.exercise_shixun_challenges + shixun_challenges.each do |c| + challenge_option = { + :position => c.position, + :challenge_id => c.challenge_id, :shixun_id => q.shixun_id, - :shixun_name => q.shixun_name - } - exercise_bank_question = current_ex_bank.exercise_bank_questions.new option - exercise_bank_question.save! - ## 试卷选项的输入 - if q.question_type != Exercise::PRACTICAL #不为实训题时,试卷选项加入试题答案库 - ex_choices = q.exercise_choices - ex_standard = q.exercise_standard_answers - ex_choices.each do |c| - choice_option = { - :choice_position => c.choice_position, - :choice_text =>c.choice_text - } - ex_bank_choice = exercise_bank_question.exercise_bank_choices.new choice_option - ex_bank_choice.save! - end - ex_standard.each do |s| - ex_stand = { - :exercise_bank_choice_id => s.exercise_choice_id, - :answer_text => s.answer_text - } - ex_stand_bank = exercise_bank_question.exercise_bank_standard_answers.new ex_stand - ex_stand_bank.save! - end - else #当为实训题时 - shixun_challenges = q.exercise_shixun_challenges - shixun_challenges.each do |c| - challenge_option = { - :position => c.position, - :challenge_id => c.challenge_id, - :shixun_id => q.shixun_id, - :question_score => c.question_score - } - shixun_challenge_bank = exercise_bank_question.exercise_bank_shixun_challenges.new challenge_option - shixun_challenge_bank.save! - end + :question_score => c.question_score + } + shixun_challenge_bank = exercise_bank_question.exercise_bank_shixun_challenges.new challenge_option + shixun_challenge_bank.save! end end - current_ex_bank.save! end - normal_status(0, "题库更新成功!") - rescue Exception => e - uid_logger_error(e.message) - tip_exception("题库更新失败!") - raise ActiveRecord::Rollback + current_ex_bank.save! end + normal_status(0, "题库更新成功!") end end #试卷的设置页面 def exercise_setting ActiveRecord::Base.transaction do - begin - @user_permission = 2 - @user_course_groups = @course.teacher_group(current_user.id) #当前老师的分班 - @being_setting_course_ids = @exercise.common_published_ids(current_user.id) #当前用户已发布的班级的id - @user_published_setting = @exercise.exercise_group_settings - .find_in_exercise_group("course_group_id",@being_setting_course_ids) #当前用户已发布班级的试卷设置 - exercise_ids = [@exercise.id] - @exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).count #判断当前用户是否有试卷已发布的分班,用于显示立即截止/撤销发布 - @exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).count #判断当前用户是否有试卷未发布的分班,用户显示立即发布 - @exercise_users_count = @exercise.exercise_users.commit_exercise_by_status(1).count #判断当前试卷是否有已提交的 - # ## 需添加发送消息的接口,稍后添加 - rescue Exception => e - uid_logger_error(e.message) - tip_exception("页面调用失败!") - raise ActiveRecord::Rollback - end + @user_permission = 2 + @user_course_groups = @course.teacher_group(current_user.id) #当前老师的分班 + @being_setting_course_ids = @exercise.common_published_ids(current_user.id) #当前用户已发布的班级的id + @user_published_setting = @exercise.exercise_group_settings + .find_in_exercise_group("course_group_id", @being_setting_course_ids) #当前用户已发布班级的试卷设置 + exercise_ids = [@exercise.id] + @exercise_publish_count = get_user_permission_course(exercise_ids, Exercise::PUBLISHED).count #判断当前用户是否有试卷已发布的分班,用于显示立即截止/撤销发布 + @exercise_unpublish_count = get_user_permission_course(exercise_ids, Exercise::UNPUBLISHED).count #判断当前用户是否有试卷未发布的分班,用户显示立即发布 + @exercise_users_count = @exercise.exercise_users.commit_exercise_by_status(1).count #判断当前试卷是否有已提交的 + # ## 需添加发送消息的接口,稍后添加 end end #试卷的提交设置 def commit_setting ActiveRecord::Base.transaction do - begin - error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。 - # course_group_ids = @course.teacher_course_group_ids(current_user.id) #当前老师的班级id数组 - course_group_ids = @course.charge_group_ids(current_user) #当前老师的班级id数组 + error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。 + # course_group_ids = @course.teacher_course_group_ids(current_user.id) #当前老师的班级id数组 + course_group_ids = @course.charge_group_ids(current_user) #当前老师的班级id数组 - exercise_status = @exercise.get_exercise_status(current_user) + exercise_status = @exercise.get_exercise_status(current_user) - if exercise_status == Exercise::UNPUBLISHED && course_group_ids.size > 0 # 试卷未发布,且老师的分班大于1 ,才可以修改统一设置,否则按试卷默认的来处理 - unified_setting = params[:unified_setting] + if exercise_status == Exercise::UNPUBLISHED && course_group_ids.size > 0 # 试卷未发布,且老师的分班大于1 ,才可以修改统一设置,否则按试卷默认的来处理 + unified_setting = params[:unified_setting] + else + unified_setting = @exercise.unified_setting + end + + show_statistic = params[:show_statistic] ? true : false + exercise_time = params[:time].blank? ? -1 : params[:time] + question_random = params[:question_random] ? true : false #问题是否随机,0为不随机,1为随机 + choice_random = params[:choice_random] ? true : false + score_open = params[:score_open] ? true : false #分数是否公开 + answer_open = params[:answer_open] ? true : false #答案是否公开 + + # 统一设置或者分班为0,则更新试卷,并删除试卷分组 + if unified_setting || (course_group_ids.size == 0) + tip_exception("发布时间不能为空") if params[:publish_time].blank? + tip_exception("截止时间不能为空") if params[:end_time].blank? + tip_exception("截止时间不能早于发布时间") if params[:publish_time].to_time > params[:end_time].to_time + tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && params[:end_time].to_time > @course.end_date.end_of_day + + params_publish_time = params[:publish_time].to_time + params_end_time = params[:end_time].to_time + + if (exercise_status != Exercise::UNPUBLISHED) && (@exercise.publish_time != params_publish_time) + normal_status(-1, "已发布/已截止,不允许修改发布时间") + elsif params_publish_time.present? && params_end_time.present? && params_end_time < params_publish_time + normal_status(-1, "截止时间不能小于发布时间") else - unified_setting = @exercise.unified_setting - end - - show_statistic = params[:show_statistic] ? true :false - exercise_time = params[:time].blank? ? -1 : params[:time] - question_random = params[:question_random] ? true :false #问题是否随机,0为不随机,1为随机 - choice_random = params[:choice_random] ? true :false - score_open = params[:score_open] ? true : false #分数是否公开 - answer_open = params[:answer_open] ? true : false #答案是否公开 - - # 统一设置或者分班为0,则更新试卷,并删除试卷分组 - if unified_setting || (course_group_ids.size == 0) - tip_exception("发布时间不能为空") if params[:publish_time].blank? - tip_exception("截止时间不能为空") if params[:end_time].blank? - tip_exception("截止时间不能早于发布时间") if params[:publish_time].to_time > params[:end_time].to_time - tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if - @course.end_date.present? && params[:end_time].to_time > @course.end_date.end_of_day - - params_publish_time = params[:publish_time].to_time - params_end_time = params[:end_time].to_time - - if (exercise_status != Exercise::UNPUBLISHED) && (@exercise.publish_time != params_publish_time) - normal_status(-1,"已发布/已截止,不允许修改发布时间") - elsif params_publish_time.present? && params_end_time.present? && params_end_time < params_publish_time - normal_status(-1,"截止时间不能小于发布时间") - else - #发布时间小于当前时间,则试卷显示为未发布,当截止时间大于当前时间,则显示为已截止 - exercise_status_n = set_exercise_status(params_publish_time,params_end_time) - exercise_params = { - :unified_setting => unified_setting, - :show_statistic => show_statistic, - :time => exercise_time, - :question_random => question_random, - :choice_random => choice_random, - :score_open => score_open, - :answer_open => answer_open, - :exercise_status => exercise_status_n, - :publish_time => params_publish_time, - :end_time => params_end_time - } - @exercise.update!(exercise_params) - @exercise.exercise_group_settings.destroy_all - normal_status(0, "试卷设置成功!") + #发布时间小于当前时间,则试卷显示为未发布,当截止时间大于当前时间,则显示为已截止 + exercise_status_n = set_exercise_status(params_publish_time, params_end_time) + exercise_params = { + :unified_setting => unified_setting, + :show_statistic => show_statistic, + :time => exercise_time, + :question_random => question_random, + :choice_random => choice_random, + :score_open => score_open, + :answer_open => answer_open, + :exercise_status => exercise_status_n, + :publish_time => params_publish_time, + :end_time => params_end_time + } + @exercise.update!(exercise_params) + @exercise.exercise_group_settings.destroy_all + normal_status(0, "试卷设置成功!") + end + else + params_times = params[:publish_time_groups] #分班返回的json数组{"publish_time_groups":[{"course_group_id":"1","publish_time":"xx","end_time":"xxx"}]} + exercise_groups = @exercise.exercise_group_settings.find_in_exercise_group("course_id", @course.id) #试卷的全部分班信息 + exercise_groups_ids = exercise_groups.pluck(:course_group_id) #问卷的全部分班id + total_common = params_times.map {|k| k[:course_group_id]}.sum.uniq #传入的所有分组的分班id + total_common_group = exercise_groups_ids & total_common #传入的分班与问卷已存在的分班的交集 + old_exercise_groups = exercise_groups_ids - total_common_group #后来传入的分班里,没有了的班级,即需要删除 + + params_times.each do |t| + tip_exception("发布时间不能为空") if t[:publish_time].blank? + tip_exception("截止时间不能为空") if t[:end_time].blank? + tip_exception("截止时间不能早于发布时间") if t[:publish_time].to_time > t[:end_time].to_time + tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && t[:end_time].to_time > @course.end_date.end_of_day + + course_id = t[:course_group_id] + exercise_publish_time = t[:publish_time].to_time + exercise_end_time = t[:end_time].to_time + + exercise_group = exercise_groups.find_in_exercise_group("course_group_id", course_id) #判断该分班是否存在 + if exercise_group.present? && (exercise_group.first.publish_time < Time.now) && (exercise_publish_time != exercise_group.first.publish_time) + error_count += 1 end - else - params_times = params[:publish_time_groups] #分班返回的json数组{"publish_time_groups":[{"course_group_id":"1","publish_time":"xx","end_time":"xxx"}]} - exercise_groups = @exercise.exercise_group_settings.find_in_exercise_group("course_id",@course.id) #试卷的全部分班信息 - exercise_groups_ids = exercise_groups.pluck(:course_group_id) #问卷的全部分班id - total_common = params_times.map{|k| k[:course_group_id]}.sum.uniq #传入的所有分组的分班id - total_common_group = exercise_groups_ids & total_common #传入的分班与问卷已存在的分班的交集 - old_exercise_groups = exercise_groups_ids - total_common_group #后来传入的分班里,没有了的班级,即需要删除 - - params_times.each do |t| - tip_exception("发布时间不能为空") if t[:publish_time].blank? - tip_exception("截止时间不能为空") if t[:end_time].blank? - tip_exception("截止时间不能早于发布时间") if t[:publish_time].to_time > t[:end_time].to_time - tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if - @course.end_date.present? && t[:end_time].to_time > @course.end_date.end_of_day - - course_id = t[:course_group_id] - exercise_publish_time = t[:publish_time].to_time - exercise_end_time = t[:end_time].to_time - - exercise_group = exercise_groups.find_in_exercise_group("course_group_id",course_id) #判断该分班是否存在 - if exercise_group.present? && (exercise_group.first.publish_time < Time.now) && (exercise_publish_time != exercise_group.first.publish_time) - error_count += 1 - end - if exercise_group.present? && (exercise_group.first.publish_time < Time.now && exercise_group.first.end_time > Time.now) && (exercise_end_time < Time.now) - error_count += 1 - end - if error_count == 0 - common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的 - new_group_ids = course_id - common_group #新传入的班级id - if common_group.count > 0 #判断试卷的分班设置是否存在,存在则更新,负责则新建 - exercise_group_sets = exercise_groups.find_in_exercise_group("course_group_id",common_group) - exercise_group_sets.each do |the_group_setting| + if exercise_group.present? && (exercise_group.first.publish_time < Time.now && exercise_group.first.end_time > Time.now) && (exercise_end_time < Time.now) + error_count += 1 + end + if error_count == 0 + common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的 + new_group_ids = course_id - common_group #新传入的班级id + if common_group.count > 0 #判断试卷的分班设置是否存在,存在则更新,负责则新建 + exercise_group_sets = exercise_groups.find_in_exercise_group("course_group_id", common_group) + exercise_group_sets.each do |the_group_setting| + ex_group_params = { + :publish_time => exercise_publish_time, + :end_time => exercise_end_time + } + + the_group_setting_status = set_exercise_status(the_group_setting.publish_time, the_group_setting.end_time) + if the_group_setting_status == 2 + ex_group_params = { + :publish_time => the_group_setting.publish_time, + :end_time => exercise_end_time < Time.now ? the_group_setting.end_time : exercise_end_time + } + elsif the_group_setting_status == 3 ex_group_params = { - :publish_time => exercise_publish_time, + :publish_time => the_group_setting.publish_time, :end_time => exercise_end_time } - - the_group_setting_status = set_exercise_status(the_group_setting.publish_time,the_group_setting.end_time) - if the_group_setting_status == 2 - ex_group_params = { - :publish_time => the_group_setting.publish_time, - :end_time => exercise_end_time < Time.now ? the_group_setting.end_time : exercise_end_time - } - elsif the_group_setting_status == 3 - ex_group_params = { - :publish_time => the_group_setting.publish_time, - :end_time => exercise_end_time - } - end - the_group_setting.update!(ex_group_params) end + the_group_setting.update!(ex_group_params) end - if new_group_ids.size > 0 - new_group_ids.each do |c| - exercise_group_params = { - :exercise_id => @exercise.id, - :course_group_id => c, - :course_id => @course.id, - :publish_time => exercise_publish_time, - :end_time => exercise_end_time - } - new_exercise_group = ExerciseGroupSetting.new(exercise_group_params) - new_exercise_group.save! - end + end + if new_group_ids.size > 0 + new_group_ids.each do |c| + exercise_group_params = { + :exercise_id => @exercise.id, + :course_group_id => c, + :course_id => @course.id, + :publish_time => exercise_publish_time, + :end_time => exercise_end_time + } + new_exercise_group = ExerciseGroupSetting.new(exercise_group_params) + new_exercise_group.save! end end end + end - if error_count > 0 - error_count == 0 - normal_status(-1,"试卷发布/截止时间不能小于当前时间") - else - # 未发布的分班设置才能删除 - if old_exercise_groups.size > 0 - old_all_ex_groups = exercise_groups.find_in_exercise_group("course_group_id",old_exercise_groups).exercise_group_not_published - old_all_ex_groups.destroy_all - end - #试卷更新为exercise_group_setting的发布时间最小,截止时间最大 - e_time_present = exercise_groups.end_time_no_null.map(&:end_time) - p_time_present = exercise_groups.publish_time_no_null.map(&:publish_time) - e_time = e_time_present.size > 0 ? e_time_present.max : nil - p_time = p_time_present.size > 0 ? p_time_present.min : nil + if error_count > 0 + error_count == 0 + normal_status(-1, "试卷发布/截止时间不能小于当前时间") + else + # 未发布的分班设置才能删除 + if old_exercise_groups.size > 0 + old_all_ex_groups = exercise_groups.find_in_exercise_group("course_group_id", old_exercise_groups).exercise_group_not_published + old_all_ex_groups.destroy_all + end + #试卷更新为exercise_group_setting的发布时间最小,截止时间最大 + e_time_present = exercise_groups.end_time_no_null.map(&:end_time) + p_time_present = exercise_groups.publish_time_no_null.map(&:publish_time) + e_time = e_time_present.size > 0 ? e_time_present.max : nil + p_time = p_time_present.size > 0 ? p_time_present.min : nil + exercise_status = 1 + if p_time.nil? #发布时间为空,则表示问卷未发布 exercise_status = 1 - if p_time.nil? #发布时间为空,则表示问卷未发布 - exercise_status = 1 - elsif p_time.present? && e_time.present? - exercise_status = set_exercise_status(p_time,e_time) - end - exercise_params = { - :unified_setting => unified_setting, - :show_statistic => show_statistic, - :time => exercise_time, - :question_random => question_random, - :choice_random => choice_random, - :score_open => score_open, - :answer_open => answer_open, - :exercise_status => exercise_status, - :publish_time => p_time, - :end_time => e_time - } - @exercise.update!(exercise_params) - if @exercise.exercise_status == Exercise::PUBLISHED - if @exercise.course_acts.size == 0 - @exercise.course_acts << CourseActivity.new(:user_id => @exercise.user_id,:course_id => @exercise.course_id) - end + elsif p_time.present? && e_time.present? + exercise_status = set_exercise_status(p_time, e_time) + end + exercise_params = { + :unified_setting => unified_setting, + :show_statistic => show_statistic, + :time => exercise_time, + :question_random => question_random, + :choice_random => choice_random, + :score_open => score_open, + :answer_open => answer_open, + :exercise_status => exercise_status, + :publish_time => p_time, + :end_time => e_time + } + @exercise.update!(exercise_params) + if @exercise.exercise_status == Exercise::PUBLISHED + if @exercise.course_acts.size == 0 + @exercise.course_acts << CourseActivity.new(:user_id => @exercise.user_id, :course_id => @exercise.course_id) end - normal_status(0, "试卷设置成功!") end + normal_status(0, "试卷设置成功!") end - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback end end end @@ -641,7 +567,7 @@ class ExercisesController < ApplicationController exercise_user.update!(score: score, subjective_score: subjective_score, objective_score: objective_score) else exercise_user.update!(start_at: start_at_time, end_at: Time.now, status: 1, commit_status: 1, score: score, - subjective_score: subjective_score, objective_score: objective_score, commit_method: 5) + subjective_score: subjective_score, objective_score: objective_score, commit_method: 5) end ExerciseUserScore.create!(exercise_id: @exercise.id, exercise_user_id: exercise_user.id, @@ -653,26 +579,20 @@ class ExercisesController < ApplicationController #我的题库 def my_exercises ActiveRecord::Base.transaction do - begin - ## 我的试卷题库 - @current_user_exercises = current_user.exercise_banks.find_by_c_type("Exercise") - if @current_user_exercises.present? + ## 我的试卷题库 + @current_user_exercises = current_user.exercise_banks.find_by_c_type("Exercise") + if @current_user_exercises.present? - if params[:search].present? - search_type = params[:search].to_s.strip - @current_user_exercises = @current_user_exercises.exercise_bank_search(search_type) - end - page = params[:page] || 1 - limit = params[:limit] || 15 - @my_exercises_count = @current_user_exercises.size - @current_user_exercises = @current_user_exercises.page(page).per(limit) - else - @current_user_exercises = [] + if params[:search].present? + search_type = params[:search].to_s.strip + @current_user_exercises = @current_user_exercises.exercise_bank_search(search_type) end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("页面调用失败!") - raise ActiveRecord::Rollback + page = params[:page] || 1 + limit = params[:limit] || 15 + @my_exercises_count = @current_user_exercises.size + @current_user_exercises = @current_user_exercises.page(page).per(limit) + else + @current_user_exercises = [] end end end @@ -680,32 +600,26 @@ class ExercisesController < ApplicationController # 公共题库 def public_exercises ActiveRecord::Base.transaction do - begin - if current_user.is_certification_teacher - @user_certification = 1 #用户已通过认证 - @public_exercises = ExerciseBank.find_by_c_type("Exercise").public_exercises - if @public_exercises.present? - if params[:search].present? - search_type = params[:search].to_s.strip - @public_exercises = @public_exercises.exercise_bank_search(search_type) - end - page = params[:page] || 1 - limit = params[:limit] || 15 - @public_exercises_count = @public_exercises.size - @public_exercises = @public_exercises.page(page).per(limit) - else - @public_exercises_count = 0 - @public_exercises = [] + if current_user.is_certification_teacher + @user_certification = 1 #用户已通过认证 + @public_exercises = ExerciseBank.find_by_c_type("Exercise").public_exercises + if @public_exercises.present? + if params[:search].present? + search_type = params[:search].to_s.strip + @public_exercises = @public_exercises.exercise_bank_search(search_type) end + page = params[:page] || 1 + limit = params[:limit] || 15 + @public_exercises_count = @public_exercises.size + @public_exercises = @public_exercises.page(page).per(limit) else - @user_certification = 0 #用户未通过认证 @public_exercises_count = 0 @public_exercises = [] end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("题库调用失败!") - raise ActiveRecord::Rollback + else + @user_certification = 0 #用户未通过认证 + @public_exercises_count = 0 + @public_exercises = [] end end end @@ -714,17 +628,11 @@ class ExercisesController < ApplicationController def publish_modal ActiveRecord::Base.transaction do - begin - exercise_ids = params[:check_ids] - if exercise_ids.count > 0 - @course_groups = get_user_permission_course(exercise_ids,1) - else - @course_groups = [] - end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("没有权限") - raise ActiveRecord::Rollback + exercise_ids = params[:check_ids] + if exercise_ids.count > 0 + @course_groups = get_user_permission_course(exercise_ids, 1) + else + @course_groups = [] end end end @@ -744,109 +652,95 @@ class ExercisesController < ApplicationController if params[:detail].blank? tip_exception("缺少截止时间参数") if params[:end_time].blank? tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) - tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if - @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) + tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) else - group_end_times = params[:group_end_times].reject(&:blank?).map{|time| time.to_time} + group_end_times = params[:group_end_times].reject(&:blank?).map {|time| time.to_time} tip_exception("缺少截止时间参数") if group_end_times.blank? tip_exception("截止时间和分班参数的个数不一致") if group_end_times.length != group_ids.length group_end_times.each do |time| tip_exception("分班截止时间不能早于当前时间") if time <= Time.now - tip_exception("分班截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if - @course.end_date.present? && time > @course.end_date.end_of_day + tip_exception("分班截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && time > @course.end_date.end_of_day end end ActiveRecord::Base.transaction do - begin - check_ids = Exercise.where(id: params[:check_ids]) - ex_end_time = params[:end_time].blank? ? Time.at(((1.month.since.to_i)/3600.0).ceil * 3600) : params[:end_time].to_time - check_ids.each do |exercise| - if exercise.present? - if exercise.unified_setting - ex_status = exercise.exercise_status #则为试卷的状态 + check_ids = Exercise.where(id: params[:check_ids]) + ex_end_time = params[:end_time].blank? ? Time.at(((1.month.since.to_i) / 3600.0).ceil * 3600) : params[:end_time].to_time + check_ids.each do |exercise| + if exercise.present? + if exercise.unified_setting + ex_status = exercise.exercise_status #则为试卷的状态 + else + ex_status = @course.course_groups.where(id: params[:group_ids]).size != + exercise.exercise_group_settings.where(course_group_id: params[:group_ids]).exercise_group_published.size ? 1 : 0 + end + if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过 + g_course = group_ids #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改 + tiding_group_ids = g_course + if g_course + user_course_groups = @course.course_groups.pluck(:id) + if g_course.map(&:to_i).sort == user_course_groups.sort && + ((params[:detail] && group_end_times.min == group_end_times.max) || params[:detail].blank?) # 如果是设置为全部班级,则试卷不用分组,且试卷设定为统一设置,否则则分组设置 + exercise.exercise_group_settings.destroy_all + ex_unified = true + e_time = params[:detail] ? group_end_times.max : ex_end_time + tiding_group_ids = [] + else + ex_unified = false + g_course.each_with_index do |i, index| + exercise_group_setting = exercise.exercise_group_settings.find_in_exercise_group("course_group_id", i).first #根据课堂分班的id,寻找试卷所在的班级 + group_end_time = params[:detail] ? group_end_times[index] : ex_end_time + if exercise_group_setting.present? #如果该试卷分组存在,则更新,否则新建 + exercise_group_setting.update!(publish_time: Time.now, end_time: group_end_time) + else + p_course_group = { + :exercise_id => exercise.id, + :course_group_id => i, + :course_id => exercise.course.id, + :publish_time => Time.now, + :end_time => group_end_time, + } + new_exercise_group = exercise.exercise_group_settings.new p_course_group + new_exercise_group.save! + end + end + # group_ids = params[:group_ids] + e_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time).max + end else - ex_status = @course.course_groups.where(id: params[:group_ids]).size != - exercise.exercise_group_settings.where(course_group_id: params[:group_ids]).exercise_group_published.size ? 1 : 0 + exercise.exercise_group_settings.destroy_all + ex_unified = true + e_time = ex_end_time end - if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过 - g_course = group_ids #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改 - tiding_group_ids = g_course - if g_course - user_course_groups = @course.course_groups.pluck(:id) - if g_course.map(&:to_i).sort == user_course_groups.sort && - ((params[:detail] && group_end_times.min == group_end_times.max) || params[:detail].blank?) # 如果是设置为全部班级,则试卷不用分组,且试卷设定为统一设置,否则则分组设置 - exercise.exercise_group_settings.destroy_all - ex_unified = true - e_time = params[:detail] ? group_end_times.max : ex_end_time - tiding_group_ids = [] - else - ex_unified = false - g_course.each_with_index do |i, index| - exercise_group_setting = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",i).first #根据课堂分班的id,寻找试卷所在的班级 - group_end_time = params[:detail] ? group_end_times[index] : ex_end_time - if exercise_group_setting.present? #如果该试卷分组存在,则更新,否则新建 - exercise_group_setting.update!(publish_time: Time.now, end_time: group_end_time) - else - p_course_group = { - :exercise_id => exercise.id, - :course_group_id => i, - :course_id => exercise.course.id, - :publish_time => Time.now, - :end_time => group_end_time, - } - new_exercise_group = exercise.exercise_group_settings.new p_course_group - new_exercise_group.save! - end - end - # group_ids = params[:group_ids] - e_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time).max - end - else - exercise.exercise_group_settings.destroy_all - ex_unified = true - e_time = ex_end_time - end - ex_status = set_exercise_status(Time.now,e_time) - exercise_params = { - :publish_time => Time.now, - :end_time => e_time, - :exercise_status => ex_status, - :unified_setting => ex_unified - } - exercise.update!(exercise_params) + ex_status = set_exercise_status(Time.now, e_time) + exercise_params = { + :publish_time => Time.now, + :end_time => e_time, + :exercise_status => ex_status, + :unified_setting => ex_unified + } + exercise.update!(exercise_params) - if exercise.course_acts.size == 0 - exercise.course_acts << CourseActivity.new(:user_id => exercise.user_id,:course_id => exercise.course_id) - end - ExercisePublishNotifyJob.perform_later(exercise.id, tiding_group_ids) + if exercise.course_acts.size == 0 + exercise.course_acts << CourseActivity.new(:user_id => exercise.user_id, :course_id => exercise.course_id) end + ExercisePublishNotifyJob.perform_later(exercise.id, tiding_group_ids) end end - normal_status(0, "试卷发布成功!") - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷发布失败") - raise ActiveRecord::Rollback end + normal_status(0, "试卷发布成功!") end end #立即截止的弹窗内容 def end_modal ActiveRecord::Base.transaction do - begin - exercise_ids = params[:check_ids] - if exercise_ids.count > 0 - @course_groups = get_user_permission_course(exercise_ids,3) - else - @course_groups = [] - end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("没有权限") - raise ActiveRecord::Rollback + exercise_ids = params[:check_ids] + if exercise_ids.count > 0 + @course_groups = get_user_permission_course(exercise_ids, 3) + else + @course_groups = [] end end end @@ -855,128 +749,116 @@ class ExercisesController < ApplicationController def end_exercise ActiveRecord::Base.transaction do - begin - check_ids = Exercise.where(id:params[:check_ids]) - course_students = @course.students #课堂的全部学生数 - check_ids.each do |exercise| - exercise_status= exercise.get_exercise_status(current_user) - if exercise_status == Exercise::PUBLISHED #跳过已截止的或未发布的 - g_course = params[:group_ids] - if g_course.present? - teacher_course_group_ids = @course.charge_group_ids(current_user) - all_course_group_ids = @course.course_groups.pluck(:id) - if exercise.unified_setting && g_course.map(&:to_i).sort == all_course_group_ids.sort #开始为统一设置 - exercise.exercise_group_settings.destroy_all - new_ex_status = set_exercise_status(exercise.publish_time,Time.now) - exercise.update!(:end_time => Time.now,:exercise_status => new_ex_status) - exercise_users = exercise.exercise_users - else - course_members_ids = course_students.course_find_by_ids("course_group_id",g_course).pluck(:user_id).uniq #该班级的全部学生 - exercise_users = exercise.exercise_users.exercise_commit_users(course_members_ids) #参与答题的学生数 - ex_group_setting = exercise.exercise_group_settings - old_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id",g_course) #试卷的分组设置 - left_course_groups = teacher_course_group_ids - g_course - left_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id",left_course_groups) - if left_exercise_groups.blank? && exercise.unified_setting - if left_course_groups.size > 0 #开始为统一设置,但是立即截止为分班。则创建没有立即截止的班级的exercise_group_setting - left_course_groups.each do |g| - ex_group_options = { - :exercise_id => exercise.id, - :course_group_id => g, - :course_id => @course.id, - :publish_time => exercise.publish_time, - :end_time => exercise.end_time - } - ExerciseGroupSetting.create!(ex_group_options) - end - end - end - if old_exercise_groups.present? - old_exercise_groups.update_all(:end_time => Time.now) - else - g_course.each do |g| + check_ids = Exercise.where(id: params[:check_ids]) + course_students = @course.students #课堂的全部学生数 + check_ids.each do |exercise| + exercise_status = exercise.get_exercise_status(current_user) + if exercise_status == Exercise::PUBLISHED #跳过已截止的或未发布的 + g_course = params[:group_ids] + if g_course.present? + teacher_course_group_ids = @course.charge_group_ids(current_user) + all_course_group_ids = @course.course_groups.pluck(:id) + if exercise.unified_setting && g_course.map(&:to_i).sort == all_course_group_ids.sort #开始为统一设置 + exercise.exercise_group_settings.destroy_all + new_ex_status = set_exercise_status(exercise.publish_time, Time.now) + exercise.update!(:end_time => Time.now, :exercise_status => new_ex_status) + exercise_users = exercise.exercise_users + else + course_members_ids = course_students.course_find_by_ids("course_group_id", g_course).pluck(:user_id).uniq #该班级的全部学生 + exercise_users = exercise.exercise_users.exercise_commit_users(course_members_ids) #参与答题的学生数 + ex_group_setting = exercise.exercise_group_settings + old_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", g_course) #试卷的分组设置 + left_course_groups = teacher_course_group_ids - g_course + left_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", left_course_groups) + if left_exercise_groups.blank? && exercise.unified_setting + if left_course_groups.size > 0 #开始为统一设置,但是立即截止为分班。则创建没有立即截止的班级的exercise_group_setting + left_course_groups.each do |g| ex_group_options = { - :exercise_id => exercise.id, - :course_group_id => g, - :course_id => @course.id, - :publish_time => exercise.publish_time, - :end_time => Time.now + :exercise_id => exercise.id, + :course_group_id => g, + :course_id => @course.id, + :publish_time => exercise.publish_time, + :end_time => exercise.end_time } ExerciseGroupSetting.create!(ex_group_options) end end - new_end_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time) # 试卷结束时间不为空的 - new_end_time_s = new_end_time.count > 0 ? new_end_time.max : Time.now - new_ex_status = set_exercise_status(exercise.publish_time,new_end_time_s) - exercise.update!(:end_time => new_end_time_s,:exercise_status => new_ex_status,:unified_setting => false) end - else - exercise_users = exercise.exercise_users - exercise.update!(:exercise_status => 3, :end_time => Time.now,:unified_setting => true) + if old_exercise_groups.present? + old_exercise_groups.update_all(:end_time => Time.now) + else + g_course.each do |g| + ex_group_options = { + :exercise_id => exercise.id, + :course_group_id => g, + :course_id => @course.id, + :publish_time => exercise.publish_time, + :end_time => Time.now + } + ExerciseGroupSetting.create!(ex_group_options) + end + end + new_end_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time) # 试卷结束时间不为空的 + new_end_time_s = new_end_time.count > 0 ? new_end_time.max : Time.now + new_ex_status = set_exercise_status(exercise.publish_time, new_end_time_s) + exercise.update!(:end_time => new_end_time_s, :exercise_status => new_ex_status, :unified_setting => false) end - - ex_user_ids = exercise_users.pluck(:id) - - EndExerciseCalculateJob.perform_later(ex_user_ids,exercise,Time.now.to_s) - # exercise_users.each do |user| - # if user.commit_status == 0 && user.start_at.present? - # objective_score = calculate_student_score(exercise,user.user)[:total_score] - # user_sub_score = user.subjective_score - # subjective_score = user_sub_score < 0.0 ? 0.0 : user_sub_score - # total_score = objective_score + subjective_score - # commit_option = { - # :status => 1, - # :commit_status => 1, - # :end_at => Time.now, - # :objective_score => objective_score, - # :score => total_score, - # :subjective_score => user_sub_score - # } - # user.update_attributes(commit_option) - # end - # end + else + exercise_users = exercise.exercise_users + exercise.update!(:exercise_status => 3, :end_time => Time.now, :unified_setting => true) end + + ex_user_ids = exercise_users.pluck(:id) + + EndExerciseCalculateJob.perform_later(ex_user_ids, exercise, Time.now.to_s) + # exercise_users.each do |user| + # if user.commit_status == 0 && user.start_at.present? + # objective_score = calculate_student_score(exercise,user.user)[:total_score] + # user_sub_score = user.subjective_score + # subjective_score = user_sub_score < 0.0 ? 0.0 : user_sub_score + # total_score = objective_score + subjective_score + # commit_option = { + # :status => 1, + # :commit_status => 1, + # :end_at => Time.now, + # :objective_score => objective_score, + # :score => total_score, + # :subjective_score => user_sub_score + # } + # user.update_attributes(commit_option) + # end + # end end - normal_status(0, "试卷截止成功!") - rescue Exception => e - uid_logger_error(e.message) - tip_exception("立即截止失败!") - raise ActiveRecord::Rollback end + normal_status(0, "试卷截止成功!") end end #学生撤销回答 def cancel_exercise ActiveRecord::Base.transaction do - begin - ex_question_ids = @exercise.exercise_questions.pluck(:id) - exercise_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first - if exercise_user.present? - if exercise_user.commit_status == 1 && @exercise.get_exercise_status(current_user) == Exercise::PUBLISHED #用户已提交且试卷提交中 - if @exercise.time == -1 || ((Time.now.to_i - exercise_user.start_at.to_i) < @exercise.time.to_i * 60) - exercise_user.update!(:score => nil, :end_at => nil, :status => nil, :commit_status => 0, - :objective_score => 0.0, :subjective_score => -1.0) - exercise_user.user.exercise_shixun_answers.search_shixun_answers("exercise_question_id",ex_question_ids).destroy_all - exercise_answers = exercise_user.user.exercise_answers.search_answer_users("exercise_question_id",ex_question_ids) - exercise_answers.update_all(:score => -1.0) - all_answer_comment = ExerciseAnswerComment.search_answer_comments("exercise_question_id",ex_question_ids) - .search_answer_comments("exercise_answer_id",exercise_answers.pluck(:id)) - all_answer_comment.destroy_all - normal_status(0,"撤销回答成功") - else - normal_status(-1,"用户答题时间已到") - end + ex_question_ids = @exercise.exercise_questions.pluck(:id) + exercise_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first + if exercise_user.present? + if exercise_user.commit_status == 1 && @exercise.get_exercise_status(current_user) == Exercise::PUBLISHED #用户已提交且试卷提交中 + if @exercise.time == -1 || ((Time.now.to_i - exercise_user.start_at.to_i) < @exercise.time.to_i * 60) + exercise_user.update!(:score => nil, :end_at => nil, :status => nil, :commit_status => 0, + :objective_score => 0.0, :subjective_score => -1.0) + exercise_user.user.exercise_shixun_answers.search_shixun_answers("exercise_question_id", ex_question_ids).destroy_all + exercise_answers = exercise_user.user.exercise_answers.search_answer_users("exercise_question_id", ex_question_ids) + exercise_answers.update_all(:score => -1.0) + all_answer_comment = ExerciseAnswerComment.search_answer_comments("exercise_question_id", ex_question_ids) + .search_answer_comments("exercise_answer_id", exercise_answers.pluck(:id)) + all_answer_comment.destroy_all + normal_status(0, "撤销回答成功") else - normal_status(-1,"用户未提交/试卷不是提交中") + normal_status(-1, "用户答题时间已到") end else - normal_status(-1,"当前用户未答题") + normal_status(-1, "用户未提交/试卷不是提交中") end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("页面调用失败") - raise ActiveRecord::Rollback + else + normal_status(-1, "当前用户未答题") end end end @@ -984,307 +866,1614 @@ class ExercisesController < ApplicationController #打回重做modal def redo_modal ActiveRecord::Base.transaction do - begin - #搜索 - if params[:realname].present? - search_name = params[:realname] - #搜索用户的nickname,如果存在则返回,否则继续查询用户的真实姓名或学生号 - @exercise_users = @exercise_users.includes(:user).where("LOWER(concat(users.lastname, users.firstname)) like ?", - "%#{search_name}%") - end - if params[:student_id].present? - search_st_id = params[:student_id].to_i - @exercise_users = @exercise_users.includes(user: [:user_extension]) - .where('user_extensions.student_id like ?',"%#{search_st_id}%") - end - sort = params[:sort] ? params[:sort] : "asc" - @exercise_users = @exercise_users.order("score #{sort}") - @exercise_users_size = @exercise_users.size - # 分页 - page = params[:page] || 1 - limit = params[:limit] || 15 - @exercise_users = @exercise_users.page(page).per(limit) - rescue Exception => e - uid_logger_error(e.message) - tip_exception("没有权限") - raise ActiveRecord::Rollback + #搜索 + if params[:realname].present? + search_name = params[:realname] + #搜索用户的nickname,如果存在则返回,否则继续查询用户的真实姓名或学生号 + @exercise_users = @exercise_users.includes(:user).where("LOWER(concat(users.lastname, users.firstname)) like ?", + "%#{search_name}%") end + if params[:student_id].present? + search_st_id = params[:student_id].to_i + @exercise_users = @exercise_users.includes(user: [:user_extension]) + .where('user_extensions.student_id like ?', "%#{search_st_id}%") + end + sort = params[:sort] ? params[:sort] : "asc" + @exercise_users = @exercise_users.order("score #{sort}") + @exercise_users_size = @exercise_users.size + # 分页 + page = params[:page] || 1 + limit = params[:limit] || 15 + @exercise_users = @exercise_users.page(page).per(limit) end end #打回重做确认 def redo_exercise ActiveRecord::Base.transaction do - begin - user_ids = params[:user_ids] - if user_ids.present? - redo_option = { - :score => 0.0, - :start_at => nil, - :end_at => nil, - :status => nil, - :commit_status => 0, - :objective_score => 0.0, - :subjective_score => -1.0, - :commit_method => 0 - } - redo_exercise_users = @exercise_users.exercise_commit_users(user_ids) - redo_exercise_users.update_all(redo_option) - exercise_question_ids = @exercise.exercise_questions.pluck(:id).uniq - ExerciseAnswer.search_answer_users("user_id",user_ids) - .search_answer_users("exercise_question_id",exercise_question_ids).destroy_all - ExerciseShixunAnswer.search_shixun_answers("user_id",user_ids) - .search_shixun_answers("exercise_question_id",exercise_question_ids).destroy_all - - normal_status(0,"已成功打回重做!") - else - normal_status(-1,"请选择学生!") - end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("没有权限") - raise ActiveRecord::Rollback + user_ids = params[:user_ids] + if user_ids.present? + redo_option = { + :score => 0.0, + :start_at => nil, + :end_at => nil, + :status => nil, + :commit_status => 0, + :objective_score => 0.0, + :subjective_score => -1.0, + :commit_method => 0 + } + redo_exercise_users = @exercise_users.exercise_commit_users(user_ids) + redo_exercise_users.update_all(redo_option) + exercise_question_ids = @exercise.exercise_questions.pluck(:id).uniq + ExerciseAnswer.search_answer_users("user_id", user_ids) + .search_answer_users("exercise_question_id", exercise_question_ids).destroy_all + ExerciseShixunAnswer.search_shixun_answers("user_id", user_ids) + .search_shixun_answers("exercise_question_id", exercise_question_ids).destroy_all + + normal_status(0, "已成功打回重做!") + else + normal_status(-1, "请选择学生!") end end end #学生开始答题页面 def start_answer - begin - ex_users_current = ExerciseUser.where(user_id:@exercise_current_user_id,exercise_id:@exercise.id) #不能用@exercise.exercise_users,因为exercise_users删除时,只是状态改变,未删除 - @exercise_user_current = ex_users_current&.first - if ex_users_current.exists? - if @exercise_user_current.start_at.blank? - @exercise_user_current.update!(start_at: Time.now) + ex_users_current = ExerciseUser.where(user_id: @exercise_current_user_id, exercise_id: @exercise.id) #不能用@exercise.exercise_users,因为exercise_users删除时,只是状态改变,未删除 + @exercise_user_current = ex_users_current&.first + if ex_users_current.exists? + if @exercise_user_current.start_at.blank? + @exercise_user_current.update!(start_at: Time.now) + end + else + if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候,不创建exercise_user表,理论上老师是不能进入答题的 + exercise_user_params = { + :user_id => @exercise_current_user_id, + :exercise_id => @exercise.id, + :start_at => Time.now + } + exercise_user_current = ExerciseUser.new(exercise_user_params) + exercise_user_current.save! + end + end + @t_user_exercise_status = @exercise.get_exercise_status(current_user) + + @user_left_time = nil + if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) || + (ex_users_current.exists? && @exercise_user_current.commit_status == 1) + @user_exercise_status = 1 #当前用户为老师/试卷已截止/试卷已提交不可编辑 + else + @user_left_time = get_exercise_left_time(@exercise, current_user) + @user_exercise_status = 0 #可编辑 + end + + @exercise_questions = @exercise.exercise_questions + + if @exercise.question_random + @exercise_questions = @exercise_questions.order("RAND()") + else + @exercise_questions = @exercise_questions.order("question_number ASC") + end + # 判断问题是否已回答还是未回答 + @exercise_questions = @exercise_questions.includes(:exercise_shixun_challenges, + :exercise_shixun_answers, + :exercise_answers, + :exercise_standard_answers) + + if @t_user_exercise_status == Exercise::DEADLINE + get_each_student_exercise(@exercise.id, @exercise_questions, @exercise_current_user_id) + end + get_user_answer_status(@exercise_questions, @exercise_current_user_id, @exercise, @t_user_exercise_status) + + end + + #提交试卷前的弹窗 + def begin_commit + ActiveRecord::Base.transaction do + if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时 + @exercise_questions = @exercise.exercise_questions + @shixun_undo = 0 + @ques_undo = 0 + ex_answer_time = @exercise.time.to_i + if ex_answer_time > 0 #有剩余时间的时候 + user_left_time = get_exercise_left_time(@exercise, current_user) + @ex_end_time = Time.now + user_left_time.to_i.seconds + else + @ex_end_time = @exercise.get_exercise_end_time(current_user.id) end - else - if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候,不创建exercise_user表,理论上老师是不能进入答题的 - exercise_user_params = { - :user_id => @exercise_current_user_id, - :exercise_id => @exercise.id, - :start_at => Time.now - } - exercise_user_current = ExerciseUser.new(exercise_user_params) - exercise_user_current.save! + # @ex_end_time = @exercise.get_exercise_end_time(current_user.id) + # if ex_answer_time > 0 + # left_answer_time = Time.now + ex_answer_time.minutes #判断试卷的倒计时和截止时间哪个先到 + # if left_answer_time < @ex_end_time + # exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id) + # if exercise_end_time.present? + # ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at + # @ex_end_time = ex_end_times + ex_answer_time.minutes + # end + # end + # end + @exercise_questions.each do |q| + if q.question_type == Exercise::PRACTICAL #当为实训题时 + user_myshixun = q.shixun.myshixuns.search_myshixun_user(current_user.id) + if user_myshixun.blank? || user_myshixun.first.status != Exercise::UNPUBLISHED #当前用户的实训是否做完 + @shixun_undo += 1 + end + else + ques_vote = q.exercise_answers.search_exercise_answer("user_id", current_user.id) + if ques_vote.blank? + @ques_undo += 1 + end + end end end - @t_user_exercise_status = @exercise.get_exercise_status(current_user) + end + end - @user_left_time = nil - if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) || - (ex_users_current.exists? && @exercise_user_current.commit_status == 1) - @user_exercise_status = 1 #当前用户为老师/试卷已截止/试卷已提交不可编辑 + # 学生提交试卷 + def commit_exercise + tip_exception(0, "试卷截止时间已到,系统已自动提交") if @answer_committed_user.commit_status == 1 + ActiveRecord::Base.transaction do + can_commit_exercise = false + user_left_time = nil + if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时 + if params[:commit_method].to_i == 2 #自动提交时 + user_left_time = get_exercise_left_time(@exercise, current_user) + Rails.logger.info("######__________auto_commit_user_left_time_________################{user_left_time}") + if user_left_time.to_i <= 0 + can_commit_exercise = true + end + else + can_commit_exercise = true + end + if can_commit_exercise + objective_score = calculate_student_score(@exercise, current_user, Time.now)[:total_score] + subjective_score = @answer_committed_user.subjective_score + total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score + total_score = objective_score + total_score_subjective_score + commit_option = { + :status => 1, + :commit_status => 1, + :end_at => Time.now, + :objective_score => objective_score, + :score => total_score, + :subjective_score => subjective_score, + :commit_method => @answer_committed_user&.commit_method.to_i > 0 ? @answer_committed_user&.commit_method.to_i : params[:commit_method].to_i + } + @answer_committed_user.update!(commit_option) + CommitExercsieNotifyJobJob.perform_later(@exercise.id, current_user.id) + normal_status(0, "试卷提交成功!") + else + normal_status(-2, "#{user_left_time.to_i}") + end else - @user_left_time = get_exercise_left_time(@exercise,current_user) - @user_exercise_status = 0 #可编辑 + normal_status(-1, "提交失败,当前用户不为课堂学生!") + end + end + end + + #教师评阅试卷 及学生查看试卷 + def review_exercise + ActiveRecord::Base.transaction do + # 1 老师权限,0 学生权限 + @is_teacher_or = (@user_course_identity < Course::STUDENT) ? 1 : 0 + @student_status = 2 + @exercise_questions = @exercise.exercise_questions.includes(:exercise_shixun_challenges, :exercise_standard_answers, :exercise_answers, :exercise_shixun_answers, :exercise_answer_comments).order("question_number ASC") + @question_status = [] + get_exercise_status = @exercise.get_exercise_status(current_user) #当前用户的试卷状态 + @ex_answer_status = @exercise.get_exercise_status(@ex_user&.user) #当前试卷用户的试卷状态 + if @ex_user.present? && @is_teacher_or == 0 + if get_exercise_status == Exercise::PUBLISHED #当前用户已提交,且试卷未截止 + if @ex_user.commit_status == 0 #学生未提交,且当前为学生 + @student_status = 0 + else + @student_status = 1 + get_user_answer_status(@exercise_questions, @exercise_current_user_id, @exercise, get_exercise_status) + end + end + end + if @student_status == 2 + get_each_student_exercise(@exercise.id, @exercise_questions, @exercise_current_user_id) + end + end + end + + #答题列表 + def exercise_lists + @current_user_id = current_user.id + exercise_ids = [@exercise.id] + @exercise_status = @exercise.get_exercise_status(current_user) + @course_all_members = @course.students + @c_group_counts = @course.course_groups_count + question_types = @exercise.exercise_questions.pluck(:question_type).uniq + @exercise_publish_count = get_user_permission_course(exercise_ids, Exercise::PUBLISHED).count #判断是否有已发布的分班 + @exercise_unpublish_count = get_user_permission_course(exercise_ids, Exercise::UNPUBLISHED).count #判断是否有未发布的分班 + + if (question_types.size > 1) && question_types.include?(Exercise::SUBJECTIVE) #是否包含主观题,或者是否大于1 + @subjective_type = 1 + else + @subjective_type = 0 + end + + #初始化值 + @exercise_users_list = [] #答题用户列表 + @exercise_course_groups = [] #当前用户有权限的班级 + @exercise_unanswers = 0 # 未答用户数 + @exercise_answers = 0 #已答用户数 + @exercise_users_count = 0 #全部用户数 + @teacher_review_count = 0 #已评数 + @teacher_unreview_count = 0 #未评数 + + #试卷的答题列表页的显示用户 + if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的试卷 + @exercise_current_user_status = 0 + unless @exercise_status == Exercise::UNPUBLISHED + ex_common_ids = @exercise.common_published_ids(current_user.id) + @exercise_course_groups = @course.get_ex_published_course(ex_common_ids) + @exercise_users_list = @exercise.all_exercise_users(current_user.id) #当前老师所在班级的全部学生 + get_exercise_answers(@exercise_users_list, @exercise_status) + end + else #当前为学生或者有过答题的 + @ex_user_end_time = @exercise.get_exercise_end_time(current_user.id) #当前用户所看到的剩余时间 + @exercise_all_users = @exercise.get_stu_exercise_users + get_exercise_answers(@exercise_all_users, @exercise_status) # 未答和已答的 + exercise_current_user = @exercise_all_users.exercise_commit_users(current_user.id) + if exercise_current_user.exists? #表示为课堂学生或已回答的 + @exercise_current_user_status = 1 + if @exercise.score_open && @exercise_status == Exercise::DEADLINE #勾选了成绩公开且试卷已截止的 + all_user_ids = @exercise_all_users.pluck(:user_id) + all_user_ids.delete(current_user.id) #删除了当前用户的ID + @exercise_users_list = @exercise_all_users.exercise_commit_users(all_user_ids).distinct + @current_user_ex_answers = exercise_current_user #当前用户的回答 + else + @exercise_users_list = exercise_current_user + end + else #表示为未回答的,或未非课堂成员的 + @exercise_current_user_status = 2 #当前用户非课堂成员 + end + end + + if @exercise_unanswers < 0 + @exercise_unanswers = 0 + end + + #筛选/分类,排序 + order = params[:order] + order_type = params[:order_type] || "desc" + + if @exercise_users_list.present? && @exercise_users_list.size > 0 + @exercise_users_count = @exercise_users_list.size #当前显示的全部成员数量 + teacher_reviews = @exercise_users_list.exercise_review + teacher_unreviews = @exercise_users_list.exercise_unreview + @teacher_review_count = teacher_reviews.size #已评阅 + @teacher_unreview_count = teacher_unreviews.size #未评阅 + + #是否评阅 + if params[:review].present? + review_type = params[:review].first.to_i #已评,则数据为1,未评,则数据为0,前端传过来的为数组 + if review_type == 1 + @exercise_users_list = teacher_reviews + else + @exercise_users_list = teacher_unreviews + end + end + + #答题状态的选择 + if params[:commit_status].present? + choose_type = params[:commit_status] + @exercise_users_list = @exercise_users_list.commit_exercise_by_status(choose_type) + end + + #班级的选择 + if params[:exercise_group_id].present? + group_id = params[:exercise_group_id] + exercise_students = @course_all_members.course_find_by_ids("course_group_id", group_id) #试卷所分班的全部人数 + user_ids = exercise_students.pluck(:user_id).reject(&:blank?) + @exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids) + end + + #搜索 + if params[:search].present? + @exercise_users_list = @exercise_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") end - @exercise_questions = @exercise.exercise_questions + exercise_user_joins = @exercise_users_list.joins(user: :user_extension) - if @exercise.question_random - @exercise_questions = @exercise_questions.order("RAND()") + if order == "student_id" + @exercise_users_list = exercise_user_joins.order("user_extensions.student_id #{order_type}") + elsif order == "score" + @exercise_users_list = exercise_user_joins.order("#{order} #{order_type}") else - @exercise_questions = @exercise_questions.order("question_number ASC") + @exercise_users_list = exercise_user_joins.order("end_at #{order_type}, start_at #{order_type}") end - # 判断问题是否已回答还是未回答 - @exercise_questions = @exercise_questions.includes(:exercise_shixun_challenges, - :exercise_shixun_answers, - :exercise_answers, - :exercise_standard_answers) - if @t_user_exercise_status == Exercise::DEADLINE - get_each_student_exercise(@exercise.id,@exercise_questions,@exercise_current_user_id) + @export_ex_users = @exercise_users_list + + @exercise_users_size = @exercise_users_list.size + + # 分页 + @page = params[:page] || 1 + @limit = params[:limit] || 20 + @exercise_users_list = @exercise_users_list.page(@page).per(@limit) + else + @exercise_users_list = [] + @export_ex_users = @exercise_users_list + @exercise_users_size = 0 + end + + if params[:format] == "xlsx" + if @user_course_identity > Course::ASSISTANT_PROFESSOR + tip_exception(403, "无权限操作") + elsif @exercise_status == Exercise::UNPUBLISHED + normal_status(-1, "试卷未发布") + elsif (@exercise_users_size == 0) || (@export_ex_users&.exercise_user_committed.size == 0) + normal_status(-1, "暂无用户提交") + elsif params[:export].present? && params[:export] + normal_status(0, "正在下载中") + else + respond_to do |format| + format.xlsx { + set_export_cookies + get_export_users(@exercise, @course, @export_ex_users) + exercise_export_name_ = + "#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" + render xlsx: "#{exercise_export_name_.strip}", template: "exercises/exercise_lists.xlsx.axlsx", locals: {table_columns: @table_columns, exercise_users: @user_columns} + } + end end - get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,@t_user_exercise_status) + end + end - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback + #导出空白试卷 + def export_exercise + @request_url = request.base_url + @exercise_questions = @exercise.exercise_questions.includes(:exercise_choices).order("question_number ASC") + filename_ = "#{@exercise.user.real_name}_#{@course.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.pdf" + stylesheets = "#{Rails.root}/app/templates/exercise_export/exercise_export.css" + if params[:export].present? && params[:export] + normal_status(0, "正在下载中") + else + set_export_cookies + render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets, disposition: 'inline', type: "pdf_attachment.content_type", stream: false end end - #提交试卷前的弹窗 - def begin_commit - ActiveRecord::Base.transaction do - begin - if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时 - @exercise_questions = @exercise.exercise_questions - @shixun_undo = 0 - @ques_undo = 0 - ex_answer_time = @exercise.time.to_i - if ex_answer_time > 0 #有剩余时间的时候 - user_left_time = get_exercise_left_time(@exercise,current_user) - @ex_end_time = Time.now + user_left_time.to_i.seconds - else - @ex_end_time = @exercise.get_exercise_end_time(current_user.id) - end - # @ex_end_time = @exercise.get_exercise_end_time(current_user.id) - # if ex_answer_time > 0 - # left_answer_time = Time.now + ex_answer_time.minutes #判断试卷的倒计时和截止时间哪个先到 - # if left_answer_time < @ex_end_time - # exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id) - # if exercise_end_time.present? - # ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at - # @ex_end_time = ex_end_times + ex_answer_time.minutes - # end - # end - # end - @exercise_questions.each do |q| - if q.question_type == Exercise::PRACTICAL #当为实训题时 - user_myshixun = q.shixun.myshixuns.search_myshixun_user(current_user.id) - if user_myshixun.blank? || user_myshixun.first.status != Exercise::UNPUBLISHED #当前用户的实训是否做完 - @shixun_undo += 1 + #空白试卷预览页面,仅供测试使用,无其他任何用途 + # def blank_exercise + # ActiveRecord::Base.transaction do + # begin + # @exercise_questions = @exercise.exercise_questions.order("question_number ASC") + # challenge_ids = @exercise_questions.joins(:exercise_shixun_challenges).pluck("exercise_shixun_challenges.challenge_id") + # get_each_student_exercise(@exercise.id,@exercise_questions,31798) + # @games = @exercise_user.user.games.ch_games(challenge_ids) + # respond_to do |format| + # format.html + # end + # rescue Exception => e + # uid_logger_error(e.message) + # tip_exception("没有权限") + # raise ActiveRecord::Rollback + # end + # end + # end + + #学生的统计结果 + def exercise_result + exercise_ids = [@exercise.id] + @exercise_publish_count = get_user_permission_course(exercise_ids, Exercise::PUBLISHED).size #判断是否有已发布的分班 + @exercise_unpublish_count = get_user_permission_course(exercise_ids, Exercise::UNPUBLISHED).size #判断是否有未发布的分班 + @course_all_members = @course.students #课堂的全部学生 + @exercise_all_users = @exercise.exercise_users + ex_common_ids = @exercise.common_published_ids(current_user.id) + @exercise_course_groups = @course.get_ex_published_course(ex_common_ids) + + #班级的选择 + if params[:exercise_group_id].present? + group_id = params[:exercise_group_id] + exercise_students = @course_all_members.course_find_by_ids("course_group_id", group_id) # 试卷所分班的全部人数 + user_ids = exercise_students.pluck(:user_id).reject(&:blank?) + @exercise_all_users = @exercise.exercise_users.exercise_commit_users(user_ids) + @course_all_members_count = @exercise_all_users.size + else + @exercise_users_list = @exercise.all_exercise_users(current_user.id) + @course_all_members_count = @exercise_users_list.size + end + @exercise_commit_users = @exercise_all_users.commit_exercise_by_status(1) #试卷的已提交用户 + @exercise_commit_user_ids = @exercise_commit_users.pluck(:user_id).uniq #已提交试卷的全部用户id + @exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数 + @exercise_status = @exercise.get_exercise_status(current_user) + + #提交率 + if @course_all_members_count == 0 + commit_percent = 0.00 + min_score = 0.0 + max_score = 0.0 + average_score = 0.0 + fail_counts = 0 + pass_counts = 0 + good_counts = 0 + best_counts = 0 + else + commit_percent = (@exercise_commit_user_counts / @course_all_members_count.to_f).round(3) + exercise_scores = @exercise_commit_users.pluck(:score).reject(&:blank?) + min_score = exercise_scores.min.present? ? exercise_scores.min : 0.0 + max_score = exercise_scores.max.present? ? exercise_scores.max : 0.0 + total_score = exercise_scores.sum.present? ? exercise_scores.sum : 0.0 + average_score = @exercise_commit_user_counts > 0 ? (total_score.round(1) / @exercise_commit_user_counts).round(1) : 0.0 + question_scores = @exercise.question_scores + fail_score = question_scores * 0.6.round(2) + pass_score = question_scores * 0.7.round(2) + good_score = question_scores * 0.9.round(2) + + fail_counts = exercise_scores.count {|a| a < fail_score} + pass_counts = exercise_scores.count {|a| a < pass_score && a >= fail_score} + good_counts = exercise_scores.count {|a| a < good_score && a >= pass_score} + best_counts = exercise_scores.count {|a| a >= good_score && a <= question_scores} + end + @counts_array = { + :commit_percent => commit_percent, + :min_score => min_score.to_s, + :max_score => max_score.to_s, + :average_score => average_score.to_s, + :fail_counts => fail_counts, + :pass_counts => pass_counts, + :good_counts => good_counts, + :best_counts => best_counts, + } + + @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices, :exercise_answers, :exercise_standard_answers, :exercise_shixun_challenges, :exercise_shixun_answers) + + percent_sort = "desc" + + if params[:sort].present? + percent_sort = params[:sort] + end + # @paging_type = "percent" + # # 按题型排序 + # if params[:sort].present? + # @paging_type = params[:sort].to_s + # end + + ques_result_all = exercise_commit_result(@exercise_questions, @exercise_commit_user_ids) + + #默认降序排列 + if percent_sort == "desc" + @question_result_hash = ques_result_all.sort_by {|s| s[:percent]}.reverse + else + @question_result_hash = ques_result_all.sort_by {|s| s[:percent]} + end + class ExercisesController < ApplicationController + before_action :require_login, :check_auth, except: [:index] + before_action :find_course, only: [:index, :new, :create, :my_exercises, :public_exercises, :set_public, :destroys, + :join_exercise_banks, :publish_modal, :publish, :end_modal, :end_exercise] #需要有课堂id参数的 + before_action :get_exercise, except: [:index, :new, :create, :my_exercises, :public_exercises, :set_public, :destroys, + :join_exercise_banks, :publish_modal, :publish, :end_modal, :end_exercise] + before_action :user_course_identity + before_action :is_course_teacher, except: [:index, :start_answer, :exercise_setting, :commit_exercise, :exercise_lists, :review_exercise, + :exercise_result, :common_header, :cancel_exercise, :begin_commit] + before_action :get_left_banner_id, only: [:common_header, :start_answer, :review_exercise, :index, :new, :edit] + before_action :validates_exercise_params, only: [:create, :update] + before_action :get_exercise_question_counts, only: [:show, :edit, :start_answer, :review_exercise, :blank_exercise, :export_exercise] + before_action :validate_publish_time, only: [:commit_setting] #提交设置时,需判断时间是否符合 + before_action :check_course_public, only: [:set_public] + before_action :check_user_on_answer, only: [:show, :start_answer, :exercise_lists] #判断当前用户在试卷的权限/老师是否属于分班的权限 + before_action :only_student_in, only: [:start_answer] + before_action :check_user_id_start_answer, only: [:start_answer, :review_exercise] + # before_action :commit_user_exercise,only: [:start_answer,:exercise_lists,:review_exercise] #已有定时的任务 + before_action :check_exercise_time, only: [:commit_exercise] #提交试卷时,判断时间是否超过 + before_action :check_exercise_status, only: [:redo_modal, :redo_exercise] + before_action :check_exercise_is_end, only: [:review_exercise] + before_action :check_exercise_public, only: [:exercise_result] #试卷是否为公开 + before_action :commit_shixun_present, only: [:commit_shixun] + include ExportHelper + include ExercisesHelper + + # model validation error + rescue_from ActiveRecord::RecordInvalid do |ex| + render_error(ex.record.errors.full_messages.join(',')) + end + # form validation error + rescue_from ActiveModel::ValidationError do |ex| + render_error(ex.model.errors.full_messages.join(',')) + end + + def index + begin + # 按发布时间或创建时间排序 + @exercises_all = @course.exercises + member_show_exercises = @exercises_all.is_exercise_published #已发布的或已截止的试卷 + @current_user_ = current_user + + # 课堂的学生人数 + @course_all_members = @course.students #当前课堂的全部学生 + @current_student = @course_all_members.course_find_by_ids("user_id", current_user.id) #当前用户是否为课堂的学生 + + # exercises的不同用户群体的显示 + if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教 + @is_teacher_or = 1 + @exercises = @exercises_all #老师能看到全部的试卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同) + elsif @user_course_identity == Course::STUDENT # 2为课堂成员,能看到统一设置的和自己班级的 + @is_teacher_or = 2 + @member_group_id = @current_student.first.try(:course_group_id).to_i # 成员的分班id,默认为0 + if @member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的) + @exercises = member_show_exercises.exists? ? member_show_exercises.unified_setting : [] + else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷 + # 已发布 当前用户班级分组的 试卷id + publish_exercise_ids = @course.exercise_group_settings.exercise_group_published.where("course_group_id = #{@member_group_id}").pluck(:exercise_id) + @exercises = member_show_exercises.unified_setting.or(member_show_exercises.where(id: publish_exercise_ids)) + end + else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁 + @is_teacher_or = 0 + @exercises = member_show_exercises.unified_setting + end + + if @exercises.size > 0 + if params[:type].present? + choose_type = params[:type].to_i + ex_setting_ids = [] + if @is_teacher_or != 2 + @exercises = @exercises.where("exercise_status = #{choose_type}") + else + case choose_type + when 1 + ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}").exercise_group_not_published.pluck(:exercise_id) + when 2 + ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}") + .where("publish_time is not null and publish_time <= ? and end_time > ?", Time.now, Time.now).pluck(:exercise_id) + when 3 + ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}").exercise_group_ended.pluck(:exercise_id) + end + unified_setting_ids = @exercises.unified_setting.where("exercise_status = #{choose_type}").pluck(:id) + ex_ids = (ex_setting_ids + unified_setting_ids).uniq + @exercises = @exercises.where(id: ex_ids) end + end + + if params[:search].present? + search_type = params[:search].to_s.strip + @exercises = @exercises.exercise_search(search_type) + end + + @exercises_select_count = @exercises.size # 全部页面,需返回 + @exercises = @exercises.distinct.order("IF(ISNULL(publish_time),0,1), publish_time DESC,created_at DESC") #出现错误 + + # 分页 + @page = params[:page] || 1 + @limit = params[:limit] || 15 + @exercises = @exercises.page(@page).per(@limit) + @exercises = @exercises&.includes(:published_settings) + else + @exercises = [] + end + + @course_all_members_count = @course_all_members.size #当前课堂的学生数 + @exercises_count = @exercises_all.size # 全部页面,需返回 + @exercises_unpublish_counts = @exercises_all.exercise_by_status(1).size #未发布的试卷数 + @exercises_published_counts = @exercises_count - @exercises_unpublish_counts # 已发布的试卷数,包含已截止的 + + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + raise ActiveRecord::Rollback + end + end + + def new + ActiveRecord::Base.transaction do + begin + @exercise = Exercise.new + rescue Exception => e + uid_logger_error(e.message) + tip_exception("试卷创建失败!") + raise ActiveRecord::Rollback + end + end + end + + def create + ActiveRecord::Base.transaction do + ex_name = params[:exercise_name] + ex_desc = params[:exercise_description] + exercise_options = { + :exercise_name => ex_name, + :exercise_description => ex_desc, + :user_id => current_user.id, + :course_id => @course.id, + :time => -1, + :exercise_status => 1 + } + @exercise = Exercise.create!(exercise_options) + end + end + + #试卷的内容,及试题/答案的内容编辑 + def edit + ActiveRecord::Base.transaction do + @exercise_questions = @exercise.exercise_questions.order("question_number ASC") + end + end + + def update + ActiveRecord::Base.transaction do + ex_name = params[:exercise_name] + ex_desc = params[:exercise_description] + exercise_options = { + :exercise_name => ex_name, + :exercise_description => ex_desc, + } + @exercise.update!(exercise_options) + normal_status(0, "试卷更新成功!") + end + end + + def show + ActiveRecord::Base.transaction do + if @user_course_identity < Course::STUDENT + @is_teacher_or = 1 #为老师/助教/管理员 + else + @is_teacher_or = 0 #为学生 + end + @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices, :exercise_shixun_challenges, :exercise_standard_answers).order("question_number ASC") + end + end + + #试卷的公用头部 + def common_header + ActiveRecord::Base.transaction do + @user_left_time = nil + if @user_course_identity > Course::ASSISTANT_PROFESSOR + @is_teacher_or = 0 + @user_exercise_answer = @exercise.check_user_answer_status(current_user) + @user_commit_counts = 0 + @user_left_time = get_exercise_left_time(@exercise, current_user) + else + @is_teacher_or = 1 + @user_exercise_answer = 3 #教师页面 + @user_commit_counts = @exercise.exercise_users.where(commit_status: 1).size #已提交的用户数 + end + @ex_status = @exercise.get_exercise_status(current_user) + + exercise_id_array = [@exercise.id] + @exercise_publish_count = get_user_permission_course(exercise_id_array, Exercise::PUBLISHED).size #是否存在已发布的 + @exercise_unpublish_count = get_user_permission_course(exercise_id_array, Exercise::UNPUBLISHED).size #是否存在未发布的 + + if (@exercise_publish_count == 0) && (@exercise_unpublish_count == 0) #即表示没有分班 + if @ex_status == Exercise::UNPUBLISHED + @exercise_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候 + elsif @ex_status == Exercise::PUBLISHED + @exercise_publish_count = 1 #试卷未发布,且课堂没有分班的时候 + end + end + end + end + + #实训题目的选用 + def choose_shixun + ActiveRecord::Base.transaction do + search = params[:search] + if @user_course_identity > Course::ADMIN #当不为管理员的时候 + user_school_id = current_user.school_id #当前用户的学校id + if user_school_id.present? + none_shixun_ids = ShixunSchool.where("school_id != #{user_school_id}").pluck(:shixun_id) + @publish_shixuns = Shixun.where.not(id: none_shixun_ids).unhidden + end + else + @publish_shixuns = Shixun.unhidden + end + if search.present? + @publish_shixuns = @publish_shixuns.search_by_name(search) + end + + @shixuns = @publish_shixuns.joins(:challenges).where("challenges.st != 0").distinct + # 全部页面,需返回 + @shixuns_count = @shixuns.count + + # 分页 + @page = params[:page] || 1 + @limit = params[:limit] || 8 + + @shixuns = @shixuns.page(@page).per(@limit) + end + end + + #确认实训的选择 + def commit_shixun + ActiveRecord::Base.transaction do + @shixun_challenges = @shixun.challenges + @shixun_challenges_count = @shixun_challenges.size + end + end + + # 首页批量或单独删除 + def destroys + ActiveRecord::Base.transaction do + check_ids = Exercise.where(id: params[:check_ids]) + check_ids.destroy_all + normal_status(0, "试卷已删除成功!") + end + end + + # 设为公开 + def set_public + ActiveRecord::Base.transaction do + check_ids = Exercise.where(id: params[:check_ids]) + check_ids.each do |exercise| + exercise.update!(is_public: true) + end + normal_status(0, "试卷已设为公开!") + end + end + + ## 加入题库 + def join_exercise_banks + ActiveRecord::Base.transaction do + check_ids = Exercise.where(id: params[:check_ids]) + check_ids.each do |exercise| + current_ex_bank = current_user.exercise_banks.find_by_container(exercise.id, "Exercise")&.first + if current_ex_bank.present? #当前用户的选择试卷是否已加入习题库,存在则更新习题库和问题库,否则新建习题库和问题库 + ex_params = { + :name => exercise.exercise_name, + :description => exercise.exercise_description, + :course_list_id => exercise.course.try(:course_list_id) + } + current_ex_bank.update!(ex_params) + # question_bank = QuestionBank.ques_by_container(current_ex_bank.id,current_ex_bank.container_type).first #该习题库是否存在于问题库里 + # ques_params = { + # :name => current_ex_bank.name, + # :course_list_id => current_ex_bank.course_list_id + # } + # question_bank.update_attributes(ques_params) if question_bank.present? + current_ex_bank.exercise_bank_questions.destroy_all # 更新后,习题库的问题全部删除,后续重新再建 + else + ex_params = { + :name => exercise.exercise_name, + :description => exercise.exercise_description, + :user_id => current_user.id, + :is_public => 0, + :course_list_id => exercise.course.try(:course_list_id), + :container_id => exercise.id, + :container_type => "Exercise", + :quotes => 1 + } + current_ex_bank = ExerciseBank.new ex_params + current_ex_bank.save! #如果习题库保存成功,则会创建问题库question_bank + # if current_ex_bank.save + # ques_params = { + # :name => current_ex_bank.name, + # :container_id => current_ex_bank.id, + # :container_type => current_ex_bank.container_type, + # :quotes => current_ex_bank.quotes, + # :user_id => current_ex_bank.user_id, + # :is_public => current_ex_bank.is_public, + # :course_list_id => current_ex_bank.course_list_id + # } + # question_bank = QuestionBank.new ques_params + # question_bank.save + # end + exercise.update!(exercise_bank_id: current_ex_bank.id) + end + # 试卷的问题的输入 + exercise.exercise_questions.each do |q| + option = { + :question_title => q.question_title, + :question_type => q.question_type, + :question_number => q.question_number, + :question_score => q.question_score, + :shixun_id => q.shixun_id, + :shixun_name => q.shixun_name + } + exercise_bank_question = current_ex_bank.exercise_bank_questions.new option + exercise_bank_question.save! + ## 试卷选项的输入 + if q.question_type != Exercise::PRACTICAL #不为实训题时,试卷选项加入试题答案库 + ex_choices = q.exercise_choices + ex_standard = q.exercise_standard_answers + ex_choices.each do |c| + choice_option = { + :choice_position => c.choice_position, + :choice_text => c.choice_text + } + ex_bank_choice = exercise_bank_question.exercise_bank_choices.new choice_option + ex_bank_choice.save! + end + ex_standard.each do |s| + ex_stand = { + :exercise_bank_choice_id => s.exercise_choice_id, + :answer_text => s.answer_text + } + ex_stand_bank = exercise_bank_question.exercise_bank_standard_answers.new ex_stand + ex_stand_bank.save! + end + else #当为实训题时 + shixun_challenges = q.exercise_shixun_challenges + shixun_challenges.each do |c| + challenge_option = { + :position => c.position, + :challenge_id => c.challenge_id, + :shixun_id => q.shixun_id, + :question_score => c.question_score + } + shixun_challenge_bank = exercise_bank_question.exercise_bank_shixun_challenges.new challenge_option + shixun_challenge_bank.save! + end + end + end + current_ex_bank.save! + end + normal_status(0, "题库更新成功!") + end + end + + #试卷的设置页面 + def exercise_setting + ActiveRecord::Base.transaction do + @user_permission = 2 + @user_course_groups = @course.teacher_group(current_user.id) #当前老师的分班 + @being_setting_course_ids = @exercise.common_published_ids(current_user.id) #当前用户已发布的班级的id + @user_published_setting = @exercise.exercise_group_settings + .find_in_exercise_group("course_group_id", @being_setting_course_ids) #当前用户已发布班级的试卷设置 + exercise_ids = [@exercise.id] + @exercise_publish_count = get_user_permission_course(exercise_ids, Exercise::PUBLISHED).count #判断当前用户是否有试卷已发布的分班,用于显示立即截止/撤销发布 + @exercise_unpublish_count = get_user_permission_course(exercise_ids, Exercise::UNPUBLISHED).count #判断当前用户是否有试卷未发布的分班,用户显示立即发布 + @exercise_users_count = @exercise.exercise_users.commit_exercise_by_status(1).count #判断当前试卷是否有已提交的 + # ## 需添加发送消息的接口,稍后添加 + end + end + + #试卷的提交设置 + def commit_setting + ActiveRecord::Base.transaction do + error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。 + # course_group_ids = @course.teacher_course_group_ids(current_user.id) #当前老师的班级id数组 + course_group_ids = @course.charge_group_ids(current_user) #当前老师的班级id数组 + + exercise_status = @exercise.get_exercise_status(current_user) + + if exercise_status == Exercise::UNPUBLISHED && course_group_ids.size > 0 # 试卷未发布,且老师的分班大于1 ,才可以修改统一设置,否则按试卷默认的来处理 + unified_setting = params[:unified_setting] + else + unified_setting = @exercise.unified_setting + end + + show_statistic = params[:show_statistic] ? true : false + exercise_time = params[:time].blank? ? -1 : params[:time] + question_random = params[:question_random] ? true : false #问题是否随机,0为不随机,1为随机 + choice_random = params[:choice_random] ? true : false + score_open = params[:score_open] ? true : false #分数是否公开 + answer_open = params[:answer_open] ? true : false #答案是否公开 + + # 统一设置或者分班为0,则更新试卷,并删除试卷分组 + if unified_setting || (course_group_ids.size == 0) + tip_exception("发布时间不能为空") if params[:publish_time].blank? + tip_exception("截止时间不能为空") if params[:end_time].blank? + tip_exception("截止时间不能早于发布时间") if params[:publish_time].to_time > params[:end_time].to_time + tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && params[:end_time].to_time > @course.end_date.end_of_day + + params_publish_time = params[:publish_time].to_time + params_end_time = params[:end_time].to_time + + if (exercise_status != Exercise::UNPUBLISHED) && (@exercise.publish_time != params_publish_time) + normal_status(-1, "已发布/已截止,不允许修改发布时间") + elsif params_publish_time.present? && params_end_time.present? && params_end_time < params_publish_time + normal_status(-1, "截止时间不能小于发布时间") + else + #发布时间小于当前时间,则试卷显示为未发布,当截止时间大于当前时间,则显示为已截止 + exercise_status_n = set_exercise_status(params_publish_time, params_end_time) + exercise_params = { + :unified_setting => unified_setting, + :show_statistic => show_statistic, + :time => exercise_time, + :question_random => question_random, + :choice_random => choice_random, + :score_open => score_open, + :answer_open => answer_open, + :exercise_status => exercise_status_n, + :publish_time => params_publish_time, + :end_time => params_end_time + } + @exercise.update!(exercise_params) + @exercise.exercise_group_settings.destroy_all + normal_status(0, "试卷设置成功!") + end + else + params_times = params[:publish_time_groups] #分班返回的json数组{"publish_time_groups":[{"course_group_id":"1","publish_time":"xx","end_time":"xxx"}]} + exercise_groups = @exercise.exercise_group_settings.find_in_exercise_group("course_id", @course.id) #试卷的全部分班信息 + exercise_groups_ids = exercise_groups.pluck(:course_group_id) #问卷的全部分班id + total_common = params_times.map {|k| k[:course_group_id]}.sum.uniq #传入的所有分组的分班id + total_common_group = exercise_groups_ids & total_common #传入的分班与问卷已存在的分班的交集 + old_exercise_groups = exercise_groups_ids - total_common_group #后来传入的分班里,没有了的班级,即需要删除 + + params_times.each do |t| + tip_exception("发布时间不能为空") if t[:publish_time].blank? + tip_exception("截止时间不能为空") if t[:end_time].blank? + tip_exception("截止时间不能早于发布时间") if t[:publish_time].to_time > t[:end_time].to_time + tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && t[:end_time].to_time > @course.end_date.end_of_day + + course_id = t[:course_group_id] + exercise_publish_time = t[:publish_time].to_time + exercise_end_time = t[:end_time].to_time + + exercise_group = exercise_groups.find_in_exercise_group("course_group_id", course_id) #判断该分班是否存在 + if exercise_group.present? && (exercise_group.first.publish_time < Time.now) && (exercise_publish_time != exercise_group.first.publish_time) + error_count += 1 + end + if exercise_group.present? && (exercise_group.first.publish_time < Time.now && exercise_group.first.end_time > Time.now) && (exercise_end_time < Time.now) + error_count += 1 + end + if error_count == 0 + common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的 + new_group_ids = course_id - common_group #新传入的班级id + if common_group.count > 0 #判断试卷的分班设置是否存在,存在则更新,负责则新建 + exercise_group_sets = exercise_groups.find_in_exercise_group("course_group_id", common_group) + exercise_group_sets.each do |the_group_setting| + ex_group_params = { + :publish_time => exercise_publish_time, + :end_time => exercise_end_time + } + + the_group_setting_status = set_exercise_status(the_group_setting.publish_time, the_group_setting.end_time) + if the_group_setting_status == 2 + ex_group_params = { + :publish_time => the_group_setting.publish_time, + :end_time => exercise_end_time < Time.now ? the_group_setting.end_time : exercise_end_time + } + elsif the_group_setting_status == 3 + ex_group_params = { + :publish_time => the_group_setting.publish_time, + :end_time => exercise_end_time + } + end + the_group_setting.update!(ex_group_params) + end + end + if new_group_ids.size > 0 + new_group_ids.each do |c| + exercise_group_params = { + :exercise_id => @exercise.id, + :course_group_id => c, + :course_id => @course.id, + :publish_time => exercise_publish_time, + :end_time => exercise_end_time + } + new_exercise_group = ExerciseGroupSetting.new(exercise_group_params) + new_exercise_group.save! + end + end + end + end + + if error_count > 0 + error_count == 0 + normal_status(-1, "试卷发布/截止时间不能小于当前时间") + else + # 未发布的分班设置才能删除 + if old_exercise_groups.size > 0 + old_all_ex_groups = exercise_groups.find_in_exercise_group("course_group_id", old_exercise_groups).exercise_group_not_published + old_all_ex_groups.destroy_all + end + #试卷更新为exercise_group_setting的发布时间最小,截止时间最大 + e_time_present = exercise_groups.end_time_no_null.map(&:end_time) + p_time_present = exercise_groups.publish_time_no_null.map(&:publish_time) + e_time = e_time_present.size > 0 ? e_time_present.max : nil + p_time = p_time_present.size > 0 ? p_time_present.min : nil + exercise_status = 1 + if p_time.nil? #发布时间为空,则表示问卷未发布 + exercise_status = 1 + elsif p_time.present? && e_time.present? + exercise_status = set_exercise_status(p_time, e_time) + end + exercise_params = { + :unified_setting => unified_setting, + :show_statistic => show_statistic, + :time => exercise_time, + :question_random => question_random, + :choice_random => choice_random, + :score_open => score_open, + :answer_open => answer_open, + :exercise_status => exercise_status, + :publish_time => p_time, + :end_time => e_time + } + @exercise.update!(exercise_params) + if @exercise.exercise_status == Exercise::PUBLISHED + if @exercise.course_acts.size == 0 + @exercise.course_acts << CourseActivity.new(:user_id => @exercise.user_id, :course_id => @exercise.course_id) + end + end + normal_status(0, "试卷设置成功!") + end + end + end + end + + # 对未提交的用户进行调分 + def adjust_score + exercise_user = @exercise.exercise_users.find_by!(user_id: params[:user_id]) + tip_exception("已提交的作品请去评阅页进行调分") if exercise_user.commit_status == 1 && exercise_user.commit_method != 5 + if @exercise.subjective_score > 0 + tip_exception("主观题成绩不能为空") if params[:subjective_score].blank? + tip_exception("主观题成绩不能小于零") if params[:subjective_score].to_f < 0 + tip_exception("主观题成绩不能大于总分值:#{@exercise.subjective_score}分") if params[:subjective_score].to_f.round(1) > @exercise.subjective_score.round(1) + end + + if @exercise.objective_score > 0 + tip_exception("客观题成绩不能为空") if params[:objective_score].blank? + tip_exception("客观题成绩不能小于零") if params[:objective_score].to_f < 0 + tip_exception("客观题成绩不能大于总分值:#{@exercise.objective_score}分") if params[:objective_score].to_f.round(1) > @exercise.objective_score.round(1) + end + + ActiveRecord::Base.transaction do + start_at_time = exercise_user.start_at || Time.now + subjective_score = @exercise.subjective_score > 0 ? params[:subjective_score].to_f.round(2) : 0 + objective_score = @exercise.objective_score > 0 ? params[:objective_score].to_f.round(2) : 0 + score = subjective_score + objective_score + if exercise_user.commit_status == 1 + exercise_user.update!(score: score, subjective_score: subjective_score, objective_score: objective_score) + else + exercise_user.update!(start_at: start_at_time, end_at: Time.now, status: 1, commit_status: 1, score: score, + subjective_score: subjective_score, objective_score: objective_score, commit_method: 5) + end + + ExerciseUserScore.create!(exercise_id: @exercise.id, exercise_user_id: exercise_user.id, + subjective_score: subjective_score, objective_score: objective_score) + normal_status("操作成功") + end + end + + #我的题库 + def my_exercises + ActiveRecord::Base.transaction do + ## 我的试卷题库 + @current_user_exercises = current_user.exercise_banks.find_by_c_type("Exercise") + if @current_user_exercises.present? + + if params[:search].present? + search_type = params[:search].to_s.strip + @current_user_exercises = @current_user_exercises.exercise_bank_search(search_type) + end + page = params[:page] || 1 + limit = params[:limit] || 15 + @my_exercises_count = @current_user_exercises.size + @current_user_exercises = @current_user_exercises.page(page).per(limit) + else + @current_user_exercises = [] + end + end + end + + # 公共题库 + def public_exercises + ActiveRecord::Base.transaction do + if current_user.is_certification_teacher + @user_certification = 1 #用户已通过认证 + @public_exercises = ExerciseBank.find_by_c_type("Exercise").public_exercises + if @public_exercises.present? + if params[:search].present? + search_type = params[:search].to_s.strip + @public_exercises = @public_exercises.exercise_bank_search(search_type) + end + page = params[:page] || 1 + limit = params[:limit] || 15 + @public_exercises_count = @public_exercises.size + @public_exercises = @public_exercises.page(page).per(limit) + else + @public_exercises_count = 0 + @public_exercises = [] + end + else + @user_certification = 0 #用户未通过认证 + @public_exercises_count = 0 + @public_exercises = [] + end + end + end + + #立即发布的弹窗内容 + def publish_modal + + ActiveRecord::Base.transaction do + exercise_ids = params[:check_ids] + if exercise_ids.count > 0 + @course_groups = get_user_permission_course(exercise_ids, 1) + else + @course_groups = [] + end + end + end + + # 详情页的立即发布弹框 + def publish_groups + @current_user = current_user + # 可立即发布的分班:当前用户管理的分班去除已发布的分班 + group_ids = @course.charge_group_ids(@current_user) - @exercise.exercise_group_settings.exercise_group_published.pluck(:course_group_id) + @course_groups = @course.course_groups.where(id: group_ids) + @group_settings = @exercise.exercise_group_settings.where(course_group_id: group_ids) + end + + #首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。 + def publish + group_ids = params[:group_ids]&.reject(&:blank?) + if params[:detail].blank? + tip_exception("缺少截止时间参数") if params[:end_time].blank? + tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) + tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) + else + group_end_times = params[:group_end_times].reject(&:blank?).map {|time| time.to_time} + tip_exception("缺少截止时间参数") if group_end_times.blank? + tip_exception("截止时间和分班参数的个数不一致") if group_end_times.length != group_ids.length + group_end_times.each do |time| + tip_exception("分班截止时间不能早于当前时间") if time <= Time.now + tip_exception("分班截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && time > @course.end_date.end_of_day + end + end + + ActiveRecord::Base.transaction do + check_ids = Exercise.where(id: params[:check_ids]) + ex_end_time = params[:end_time].blank? ? Time.at(((1.month.since.to_i) / 3600.0).ceil * 3600) : params[:end_time].to_time + check_ids.each do |exercise| + if exercise.present? + if exercise.unified_setting + ex_status = exercise.exercise_status #则为试卷的状态 + else + ex_status = @course.course_groups.where(id: params[:group_ids]).size != + exercise.exercise_group_settings.where(course_group_id: params[:group_ids]).exercise_group_published.size ? 1 : 0 + end + if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过 + g_course = group_ids #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改 + tiding_group_ids = g_course + if g_course + user_course_groups = @course.course_groups.pluck(:id) + if g_course.map(&:to_i).sort == user_course_groups.sort && + ((params[:detail] && group_end_times.min == group_end_times.max) || params[:detail].blank?) # 如果是设置为全部班级,则试卷不用分组,且试卷设定为统一设置,否则则分组设置 + exercise.exercise_group_settings.destroy_all + ex_unified = true + e_time = params[:detail] ? group_end_times.max : ex_end_time + tiding_group_ids = [] + else + ex_unified = false + g_course.each_with_index do |i, index| + exercise_group_setting = exercise.exercise_group_settings.find_in_exercise_group("course_group_id", i).first #根据课堂分班的id,寻找试卷所在的班级 + group_end_time = params[:detail] ? group_end_times[index] : ex_end_time + if exercise_group_setting.present? #如果该试卷分组存在,则更新,否则新建 + exercise_group_setting.update!(publish_time: Time.now, end_time: group_end_time) + else + p_course_group = { + :exercise_id => exercise.id, + :course_group_id => i, + :course_id => exercise.course.id, + :publish_time => Time.now, + :end_time => group_end_time, + } + new_exercise_group = exercise.exercise_group_settings.new p_course_group + new_exercise_group.save! + end + end + # group_ids = params[:group_ids] + e_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time).max + end + else + exercise.exercise_group_settings.destroy_all + ex_unified = true + e_time = ex_end_time + end + + ex_status = set_exercise_status(Time.now, e_time) + exercise_params = { + :publish_time => Time.now, + :end_time => e_time, + :exercise_status => ex_status, + :unified_setting => ex_unified + } + exercise.update!(exercise_params) + + if exercise.course_acts.size == 0 + exercise.course_acts << CourseActivity.new(:user_id => exercise.user_id, :course_id => exercise.course_id) + end + ExercisePublishNotifyJob.perform_later(exercise.id, tiding_group_ids) + end + end + end + normal_status(0, "试卷发布成功!") + end + end + + #立即截止的弹窗内容 + def end_modal + ActiveRecord::Base.transaction do + exercise_ids = params[:check_ids] + if exercise_ids.count > 0 + @course_groups = get_user_permission_course(exercise_ids, 3) + else + @course_groups = [] + end + end + end + + # 首页批量或单独 立即截止,截止时间为当前时间 + def end_exercise + + ActiveRecord::Base.transaction do + check_ids = Exercise.where(id: params[:check_ids]) + course_students = @course.students #课堂的全部学生数 + check_ids.each do |exercise| + exercise_status = exercise.get_exercise_status(current_user) + if exercise_status == Exercise::PUBLISHED #跳过已截止的或未发布的 + g_course = params[:group_ids] + if g_course.present? + teacher_course_group_ids = @course.charge_group_ids(current_user) + all_course_group_ids = @course.course_groups.pluck(:id) + if exercise.unified_setting && g_course.map(&:to_i).sort == all_course_group_ids.sort #开始为统一设置 + exercise.exercise_group_settings.destroy_all + new_ex_status = set_exercise_status(exercise.publish_time, Time.now) + exercise.update!(:end_time => Time.now, :exercise_status => new_ex_status) + exercise_users = exercise.exercise_users + else + course_members_ids = course_students.course_find_by_ids("course_group_id", g_course).pluck(:user_id).uniq #该班级的全部学生 + exercise_users = exercise.exercise_users.exercise_commit_users(course_members_ids) #参与答题的学生数 + ex_group_setting = exercise.exercise_group_settings + old_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", g_course) #试卷的分组设置 + left_course_groups = teacher_course_group_ids - g_course + left_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", left_course_groups) + if left_exercise_groups.blank? && exercise.unified_setting + if left_course_groups.size > 0 #开始为统一设置,但是立即截止为分班。则创建没有立即截止的班级的exercise_group_setting + left_course_groups.each do |g| + ex_group_options = { + :exercise_id => exercise.id, + :course_group_id => g, + :course_id => @course.id, + :publish_time => exercise.publish_time, + :end_time => exercise.end_time + } + ExerciseGroupSetting.create!(ex_group_options) + end + end + end + if old_exercise_groups.present? + old_exercise_groups.update_all(:end_time => Time.now) + else + g_course.each do |g| + ex_group_options = { + :exercise_id => exercise.id, + :course_group_id => g, + :course_id => @course.id, + :publish_time => exercise.publish_time, + :end_time => Time.now + } + ExerciseGroupSetting.create!(ex_group_options) + end + end + new_end_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time) # 试卷结束时间不为空的 + new_end_time_s = new_end_time.count > 0 ? new_end_time.max : Time.now + new_ex_status = set_exercise_status(exercise.publish_time, new_end_time_s) + exercise.update!(:end_time => new_end_time_s, :exercise_status => new_ex_status, :unified_setting => false) + end + else + exercise_users = exercise.exercise_users + exercise.update!(:exercise_status => 3, :end_time => Time.now, :unified_setting => true) + end + + ex_user_ids = exercise_users.pluck(:id) + + EndExerciseCalculateJob.perform_later(ex_user_ids, exercise, Time.now.to_s) + # exercise_users.each do |user| + # if user.commit_status == 0 && user.start_at.present? + # objective_score = calculate_student_score(exercise,user.user)[:total_score] + # user_sub_score = user.subjective_score + # subjective_score = user_sub_score < 0.0 ? 0.0 : user_sub_score + # total_score = objective_score + subjective_score + # commit_option = { + # :status => 1, + # :commit_status => 1, + # :end_at => Time.now, + # :objective_score => objective_score, + # :score => total_score, + # :subjective_score => user_sub_score + # } + # user.update_attributes(commit_option) + # end + # end + end + end + normal_status(0, "试卷截止成功!") + end + end + + #学生撤销回答 + def cancel_exercise + ActiveRecord::Base.transaction do + ex_question_ids = @exercise.exercise_questions.pluck(:id) + exercise_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first + if exercise_user.present? + if exercise_user.commit_status == 1 && @exercise.get_exercise_status(current_user) == Exercise::PUBLISHED #用户已提交且试卷提交中 + if @exercise.time == -1 || ((Time.now.to_i - exercise_user.start_at.to_i) < @exercise.time.to_i * 60) + exercise_user.update!(:score => nil, :end_at => nil, :status => nil, :commit_status => 0, + :objective_score => 0.0, :subjective_score => -1.0) + exercise_user.user.exercise_shixun_answers.search_shixun_answers("exercise_question_id", ex_question_ids).destroy_all + exercise_answers = exercise_user.user.exercise_answers.search_answer_users("exercise_question_id", ex_question_ids) + exercise_answers.update_all(:score => -1.0) + all_answer_comment = ExerciseAnswerComment.search_answer_comments("exercise_question_id", ex_question_ids) + .search_answer_comments("exercise_answer_id", exercise_answers.pluck(:id)) + all_answer_comment.destroy_all + normal_status(0, "撤销回答成功") + else + normal_status(-1, "用户答题时间已到") + end + else + normal_status(-1, "用户未提交/试卷不是提交中") + end + else + normal_status(-1, "当前用户未答题") + end + end + end + + #打回重做modal + def redo_modal + ActiveRecord::Base.transaction do + #搜索 + if params[:realname].present? + search_name = params[:realname] + #搜索用户的nickname,如果存在则返回,否则继续查询用户的真实姓名或学生号 + @exercise_users = @exercise_users.includes(:user).where("LOWER(concat(users.lastname, users.firstname)) like ?", + "%#{search_name}%") + end + if params[:student_id].present? + search_st_id = params[:student_id].to_i + @exercise_users = @exercise_users.includes(user: [:user_extension]) + .where('user_extensions.student_id like ?', "%#{search_st_id}%") + end + sort = params[:sort] ? params[:sort] : "asc" + @exercise_users = @exercise_users.order("score #{sort}") + @exercise_users_size = @exercise_users.size + # 分页 + page = params[:page] || 1 + limit = params[:limit] || 15 + @exercise_users = @exercise_users.page(page).per(limit) + end + end + + #打回重做确认 + def redo_exercise + ActiveRecord::Base.transaction do + user_ids = params[:user_ids] + if user_ids.present? + redo_option = { + :score => 0.0, + :start_at => nil, + :end_at => nil, + :status => nil, + :commit_status => 0, + :objective_score => 0.0, + :subjective_score => -1.0, + :commit_method => 0 + } + redo_exercise_users = @exercise_users.exercise_commit_users(user_ids) + redo_exercise_users.update_all(redo_option) + exercise_question_ids = @exercise.exercise_questions.pluck(:id).uniq + ExerciseAnswer.search_answer_users("user_id", user_ids) + .search_answer_users("exercise_question_id", exercise_question_ids).destroy_all + ExerciseShixunAnswer.search_shixun_answers("user_id", user_ids) + .search_shixun_answers("exercise_question_id", exercise_question_ids).destroy_all + + normal_status(0, "已成功打回重做!") + else + normal_status(-1, "请选择学生!") + end + end + end + + #学生开始答题页面 + def start_answer + ex_users_current = ExerciseUser.where(user_id: @exercise_current_user_id, exercise_id: @exercise.id) #不能用@exercise.exercise_users,因为exercise_users删除时,只是状态改变,未删除 + @exercise_user_current = ex_users_current&.first + if ex_users_current.exists? + if @exercise_user_current.start_at.blank? + @exercise_user_current.update!(start_at: Time.now) + end + else + if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候,不创建exercise_user表,理论上老师是不能进入答题的 + exercise_user_params = { + :user_id => @exercise_current_user_id, + :exercise_id => @exercise.id, + :start_at => Time.now + } + exercise_user_current = ExerciseUser.new(exercise_user_params) + exercise_user_current.save! + end + end + @t_user_exercise_status = @exercise.get_exercise_status(current_user) + + @user_left_time = nil + if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) || + (ex_users_current.exists? && @exercise_user_current.commit_status == 1) + @user_exercise_status = 1 #当前用户为老师/试卷已截止/试卷已提交不可编辑 + else + @user_left_time = get_exercise_left_time(@exercise, current_user) + @user_exercise_status = 0 #可编辑 + end + + @exercise_questions = @exercise.exercise_questions + + if @exercise.question_random + @exercise_questions = @exercise_questions.order("RAND()") + else + @exercise_questions = @exercise_questions.order("question_number ASC") + end + # 判断问题是否已回答还是未回答 + @exercise_questions = @exercise_questions.includes(:exercise_shixun_challenges, + :exercise_shixun_answers, + :exercise_answers, + :exercise_standard_answers) + + if @t_user_exercise_status == Exercise::DEADLINE + get_each_student_exercise(@exercise.id, @exercise_questions, @exercise_current_user_id) + end + get_user_answer_status(@exercise_questions, @exercise_current_user_id, @exercise, @t_user_exercise_status) + + end + + #提交试卷前的弹窗 + def begin_commit + ActiveRecord::Base.transaction do + if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时 + @exercise_questions = @exercise.exercise_questions + @shixun_undo = 0 + @ques_undo = 0 + ex_answer_time = @exercise.time.to_i + if ex_answer_time > 0 #有剩余时间的时候 + user_left_time = get_exercise_left_time(@exercise, current_user) + @ex_end_time = Time.now + user_left_time.to_i.seconds else - ques_vote = q.exercise_answers.search_exercise_answer("user_id",current_user.id) - if ques_vote.blank? - @ques_undo += 1 + @ex_end_time = @exercise.get_exercise_end_time(current_user.id) + end + # @ex_end_time = @exercise.get_exercise_end_time(current_user.id) + # if ex_answer_time > 0 + # left_answer_time = Time.now + ex_answer_time.minutes #判断试卷的倒计时和截止时间哪个先到 + # if left_answer_time < @ex_end_time + # exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id) + # if exercise_end_time.present? + # ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at + # @ex_end_time = ex_end_times + ex_answer_time.minutes + # end + # end + # end + @exercise_questions.each do |q| + if q.question_type == Exercise::PRACTICAL #当为实训题时 + user_myshixun = q.shixun.myshixuns.search_myshixun_user(current_user.id) + if user_myshixun.blank? || user_myshixun.first.status != Exercise::UNPUBLISHED #当前用户的实训是否做完 + @shixun_undo += 1 + end + else + ques_vote = q.exercise_answers.search_exercise_answer("user_id", current_user.id) + if ques_vote.blank? + @ques_undo += 1 + end end end end end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷提交失败!") - raise ActiveRecord::Rollback end - end - end - # 学生提交试卷 - def commit_exercise - tip_exception(0, "试卷截止时间已到,系统已自动提交") if @answer_committed_user.commit_status == 1 - ActiveRecord::Base.transaction do - begin - can_commit_exercise = false - user_left_time = nil - if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时 - if params[:commit_method].to_i == 2 #自动提交时 - user_left_time = get_exercise_left_time(@exercise,current_user) - Rails.logger.info("######__________auto_commit_user_left_time_________################{user_left_time}") - if user_left_time.to_i <= 0 + # 学生提交试卷 + def commit_exercise + tip_exception(0, "试卷截止时间已到,系统已自动提交") if @answer_committed_user.commit_status == 1 + ActiveRecord::Base.transaction do + can_commit_exercise = false + user_left_time = nil + if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时 + if params[:commit_method].to_i == 2 #自动提交时 + user_left_time = get_exercise_left_time(@exercise, current_user) + Rails.logger.info("######__________auto_commit_user_left_time_________################{user_left_time}") + if user_left_time.to_i <= 0 + can_commit_exercise = true + end + else can_commit_exercise = true end + if can_commit_exercise + objective_score = calculate_student_score(@exercise, current_user, Time.now)[:total_score] + subjective_score = @answer_committed_user.subjective_score + total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score + total_score = objective_score + total_score_subjective_score + commit_option = { + :status => 1, + :commit_status => 1, + :end_at => Time.now, + :objective_score => objective_score, + :score => total_score, + :subjective_score => subjective_score, + :commit_method => @answer_committed_user&.commit_method.to_i > 0 ? @answer_committed_user&.commit_method.to_i : params[:commit_method].to_i + } + @answer_committed_user.update!(commit_option) + CommitExercsieNotifyJobJob.perform_later(@exercise.id, current_user.id) + normal_status(0, "试卷提交成功!") + else + normal_status(-2, "#{user_left_time.to_i}") + end else - can_commit_exercise = true - end - if can_commit_exercise - objective_score = calculate_student_score(@exercise,current_user,Time.now)[:total_score] - subjective_score = @answer_committed_user.subjective_score - total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score - total_score = objective_score + total_score_subjective_score - commit_option = { - :status => 1, - :commit_status => 1, - :end_at => Time.now, - :objective_score => objective_score, - :score => total_score, - :subjective_score => subjective_score, - :commit_method => @answer_committed_user&.commit_method.to_i > 0 ? @answer_committed_user&.commit_method.to_i : params[:commit_method].to_i - } - @answer_committed_user.update!(commit_option) - CommitExercsieNotifyJobJob.perform_later(@exercise.id, current_user.id) - normal_status(0,"试卷提交成功!") - else - normal_status(-2,"#{user_left_time.to_i}") + normal_status(-1, "提交失败,当前用户不为课堂学生!") end - else - normal_status(-1,"提交失败,当前用户不为课堂学生!") end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷提交失败!") - raise ActiveRecord::Rollback end - end - end - #教师评阅试卷 及学生查看试卷 - def review_exercise - ActiveRecord::Base.transaction do - begin - # 1 老师权限,0 学生权限 - @is_teacher_or = (@user_course_identity < Course::STUDENT) ? 1 : 0 - @student_status = 2 - @exercise_questions = @exercise.exercise_questions.includes(:exercise_shixun_challenges,:exercise_standard_answers,:exercise_answers,:exercise_shixun_answers,:exercise_answer_comments).order("question_number ASC") - @question_status = [] - get_exercise_status = @exercise.get_exercise_status(current_user) #当前用户的试卷状态 - @ex_answer_status = @exercise.get_exercise_status(@ex_user&.user) #当前试卷用户的试卷状态 - if @ex_user.present? && @is_teacher_or == 0 - if get_exercise_status == Exercise::PUBLISHED #当前用户已提交,且试卷未截止 - if @ex_user.commit_status == 0 #学生未提交,且当前为学生 - @student_status = 0 - else - @student_status = 1 - get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,get_exercise_status) + #教师评阅试卷 及学生查看试卷 + def review_exercise + ActiveRecord::Base.transaction do + # 1 老师权限,0 学生权限 + @is_teacher_or = (@user_course_identity < Course::STUDENT) ? 1 : 0 + @student_status = 2 + @exercise_questions = @exercise.exercise_questions.includes(:exercise_shixun_challenges, :exercise_standard_answers, :exercise_answers, :exercise_shixun_answers, :exercise_answer_comments).order("question_number ASC") + @question_status = [] + get_exercise_status = @exercise.get_exercise_status(current_user) #当前用户的试卷状态 + @ex_answer_status = @exercise.get_exercise_status(@ex_user&.user) #当前试卷用户的试卷状态 + if @ex_user.present? && @is_teacher_or == 0 + if get_exercise_status == Exercise::PUBLISHED #当前用户已提交,且试卷未截止 + if @ex_user.commit_status == 0 #学生未提交,且当前为学生 + @student_status = 0 + else + @student_status = 1 + get_user_answer_status(@exercise_questions, @exercise_current_user_id, @exercise, get_exercise_status) + end end end + if @student_status == 2 + get_each_student_exercise(@exercise.id, @exercise_questions, @exercise_current_user_id) + end end - if @student_status == 2 - get_each_student_exercise(@exercise.id,@exercise_questions,@exercise_current_user_id) - end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("没有权限") - raise ActiveRecord::Rollback end - end - end - #答题列表 - def exercise_lists - begin + #答题列表 + def exercise_lists @current_user_id = current_user.id exercise_ids = [@exercise.id] @exercise_status = @exercise.get_exercise_status(current_user) @course_all_members = @course.students @c_group_counts = @course.course_groups_count question_types = @exercise.exercise_questions.pluck(:question_type).uniq - @exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).count #判断是否有已发布的分班 - @exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).count #判断是否有未发布的分班 + @exercise_publish_count = get_user_permission_course(exercise_ids, Exercise::PUBLISHED).count #判断是否有已发布的分班 + @exercise_unpublish_count = get_user_permission_course(exercise_ids, Exercise::UNPUBLISHED).count #判断是否有未发布的分班 - if (question_types.size > 1) && question_types.include?(Exercise::SUBJECTIVE) #是否包含主观题,或者是否大于1 + if (question_types.size > 1) && question_types.include?(Exercise::SUBJECTIVE) #是否包含主观题,或者是否大于1 @subjective_type = 1 else @subjective_type = 0 end #初始化值 - @exercise_users_list = [] #答题用户列表 - @exercise_course_groups = [] #当前用户有权限的班级 - @exercise_unanswers = 0 # 未答用户数 - @exercise_answers = 0 #已答用户数 - @exercise_users_count = 0 #全部用户数 - @teacher_review_count = 0 #已评数 - @teacher_unreview_count = 0 #未评数 + @exercise_users_list = [] #答题用户列表 + @exercise_course_groups = [] #当前用户有权限的班级 + @exercise_unanswers = 0 # 未答用户数 + @exercise_answers = 0 #已答用户数 + @exercise_users_count = 0 #全部用户数 + @teacher_review_count = 0 #已评数 + @teacher_unreview_count = 0 #未评数 #试卷的答题列表页的显示用户 - if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的试卷 + if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的试卷 @exercise_current_user_status = 0 unless @exercise_status == Exercise::UNPUBLISHED ex_common_ids = @exercise.common_published_ids(current_user.id) @exercise_course_groups = @course.get_ex_published_course(ex_common_ids) - @exercise_users_list = @exercise.all_exercise_users(current_user.id) #当前老师所在班级的全部学生 + @exercise_users_list = @exercise.all_exercise_users(current_user.id) #当前老师所在班级的全部学生 get_exercise_answers(@exercise_users_list, @exercise_status) end - else #当前为学生或者有过答题的 - @ex_user_end_time = @exercise.get_exercise_end_time(current_user.id) #当前用户所看到的剩余时间 + else #当前为学生或者有过答题的 + @ex_user_end_time = @exercise.get_exercise_end_time(current_user.id) #当前用户所看到的剩余时间 @exercise_all_users = @exercise.get_stu_exercise_users - get_exercise_answers(@exercise_all_users, @exercise_status) # 未答和已答的 + get_exercise_answers(@exercise_all_users, @exercise_status) # 未答和已答的 exercise_current_user = @exercise_all_users.exercise_commit_users(current_user.id) - if exercise_current_user.exists? #表示为课堂学生或已回答的 + if exercise_current_user.exists? #表示为课堂学生或已回答的 @exercise_current_user_status = 1 - if @exercise.score_open && @exercise_status == Exercise::DEADLINE #勾选了成绩公开且试卷已截止的 + if @exercise.score_open && @exercise_status == Exercise::DEADLINE #勾选了成绩公开且试卷已截止的 all_user_ids = @exercise_all_users.pluck(:user_id) - all_user_ids.delete(current_user.id) #删除了当前用户的ID + all_user_ids.delete(current_user.id) #删除了当前用户的ID @exercise_users_list = @exercise_all_users.exercise_commit_users(all_user_ids).distinct - @current_user_ex_answers = exercise_current_user #当前用户的回答 + @current_user_ex_answers = exercise_current_user #当前用户的回答 else @exercise_users_list = exercise_current_user end - else #表示为未回答的,或未非课堂成员的 - @exercise_current_user_status = 2 #当前用户非课堂成员 + else #表示为未回答的,或未非课堂成员的 + @exercise_current_user_status = 2 #当前用户非课堂成员 end end @@ -1297,230 +2486,545 @@ class ExercisesController < ApplicationController order_type = params[:order_type] || "desc" if @exercise_users_list.present? && @exercise_users_list.size > 0 - @exercise_users_count = @exercise_users_list.size #当前显示的全部成员数量 + @exercise_users_count = @exercise_users_list.size #当前显示的全部成员数量 teacher_reviews = @exercise_users_list.exercise_review teacher_unreviews = @exercise_users_list.exercise_unreview - @teacher_review_count = teacher_reviews.size #已评阅 - @teacher_unreview_count = teacher_unreviews.size #未评阅 + @teacher_review_count = teacher_reviews.size #已评阅 + @teacher_unreview_count = teacher_unreviews.size #未评阅 #是否评阅 if params[:review].present? - review_type = params[:review].first.to_i #已评,则数据为1,未评,则数据为0,前端传过来的为数组 + review_type = params[:review].first.to_i #已评,则数据为1,未评,则数据为0,前端传过来的为数组 if review_type == 1 - @exercise_users_list = teacher_reviews + @exercise_users_list = teacher_reviews + else + @exercise_users_list = teacher_unreviews + end + end + + #答题状态的选择 + if params[:commit_status].present? + choose_type = params[:commit_status] + @exercise_users_list = @exercise_users_list.commit_exercise_by_status(choose_type) + end + + #班级的选择 + if params[:exercise_group_id].present? + group_id = params[:exercise_group_id] + exercise_students = @course_all_members.course_find_by_ids("course_group_id", group_id) #试卷所分班的全部人数 + user_ids = exercise_students.pluck(:user_id).reject(&:blank?) + @exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids) + end + + #搜索 + if params[:search].present? + @exercise_users_list = @exercise_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") + end + + exercise_user_joins = @exercise_users_list.joins(user: :user_extension) + + if order == "student_id" + @exercise_users_list = exercise_user_joins.order("user_extensions.student_id #{order_type}") + elsif order == "score" + @exercise_users_list = exercise_user_joins.order("#{order} #{order_type}") + else + @exercise_users_list = exercise_user_joins.order("end_at #{order_type}, start_at #{order_type}") + end + + @export_ex_users = @exercise_users_list + + @exercise_users_size = @exercise_users_list.size + + # 分页 + @page = params[:page] || 1 + @limit = params[:limit] || 20 + @exercise_users_list = @exercise_users_list.page(@page).per(@limit) + else + @exercise_users_list = [] + @export_ex_users = @exercise_users_list + @exercise_users_size = 0 + end + + if params[:format] == "xlsx" + if @user_course_identity > Course::ASSISTANT_PROFESSOR + tip_exception(403, "无权限操作") + elsif @exercise_status == Exercise::UNPUBLISHED + normal_status(-1, "试卷未发布") + elsif (@exercise_users_size == 0) || (@export_ex_users&.exercise_user_committed.size == 0) + normal_status(-1, "暂无用户提交") + elsif params[:export].present? && params[:export] + normal_status(0, "正在下载中") else - @exercise_users_list = teacher_unreviews + respond_to do |format| + format.xlsx { + set_export_cookies + get_export_users(@exercise, @course, @export_ex_users) + exercise_export_name_ = + "#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" + render xlsx: "#{exercise_export_name_.strip}", template: "exercises/exercise_lists.xlsx.axlsx", locals: {table_columns: @table_columns, exercise_users: @user_columns} + } + end end end + end - #答题状态的选择 - if params[:commit_status].present? - choose_type = params[:commit_status] - @exercise_users_list = @exercise_users_list.commit_exercise_by_status(choose_type) + #导出空白试卷 + def export_exercise + @request_url = request.base_url + @exercise_questions = @exercise.exercise_questions.includes(:exercise_choices).order("question_number ASC") + filename_ = "#{@exercise.user.real_name}_#{@course.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.pdf" + stylesheets = "#{Rails.root}/app/templates/exercise_export/exercise_export.css" + if params[:export].present? && params[:export] + normal_status(0, "正在下载中") + else + set_export_cookies + render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets, disposition: 'inline', type: "pdf_attachment.content_type", stream: false end + end + + #空白试卷预览页面,仅供测试使用,无其他任何用途 + # def blank_exercise + # ActiveRecord::Base.transaction do + # begin + # @exercise_questions = @exercise.exercise_questions.order("question_number ASC") + # challenge_ids = @exercise_questions.joins(:exercise_shixun_challenges).pluck("exercise_shixun_challenges.challenge_id") + # get_each_student_exercise(@exercise.id,@exercise_questions,31798) + # @games = @exercise_user.user.games.ch_games(challenge_ids) + # respond_to do |format| + # format.html + # end + # rescue Exception => e + # uid_logger_error(e.message) + # tip_exception("没有权限") + # raise ActiveRecord::Rollback + # end + # end + # end + + #学生的统计结果 + def exercise_result + exercise_ids = [@exercise.id] + @exercise_publish_count = get_user_permission_course(exercise_ids, Exercise::PUBLISHED).size #判断是否有已发布的分班 + @exercise_unpublish_count = get_user_permission_course(exercise_ids, Exercise::UNPUBLISHED).size #判断是否有未发布的分班 + @course_all_members = @course.students #课堂的全部学生 + @exercise_all_users = @exercise.exercise_users + ex_common_ids = @exercise.common_published_ids(current_user.id) + @exercise_course_groups = @course.get_ex_published_course(ex_common_ids) #班级的选择 if params[:exercise_group_id].present? group_id = params[:exercise_group_id] - exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) #试卷所分班的全部人数 + exercise_students = @course_all_members.course_find_by_ids("course_group_id", group_id) # 试卷所分班的全部人数 user_ids = exercise_students.pluck(:user_id).reject(&:blank?) - @exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids) + @exercise_all_users = @exercise.exercise_users.exercise_commit_users(user_ids) + @course_all_members_count = @exercise_all_users.size + else + @exercise_users_list = @exercise.all_exercise_users(current_user.id) + @course_all_members_count = @exercise_users_list.size end + @exercise_commit_users = @exercise_all_users.commit_exercise_by_status(1) #试卷的已提交用户 + @exercise_commit_user_ids = @exercise_commit_users.pluck(:user_id).uniq #已提交试卷的全部用户id + @exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数 + @exercise_status = @exercise.get_exercise_status(current_user) - #搜索 - if params[:search].present? - @exercise_users_list = @exercise_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") + #提交率 + if @course_all_members_count == 0 + commit_percent = 0.00 + min_score = 0.0 + max_score = 0.0 + average_score = 0.0 + fail_counts = 0 + pass_counts = 0 + good_counts = 0 + best_counts = 0 + else + commit_percent = (@exercise_commit_user_counts / @course_all_members_count.to_f).round(3) + exercise_scores = @exercise_commit_users.pluck(:score).reject(&:blank?) + min_score = exercise_scores.min.present? ? exercise_scores.min : 0.0 + max_score = exercise_scores.max.present? ? exercise_scores.max : 0.0 + total_score = exercise_scores.sum.present? ? exercise_scores.sum : 0.0 + average_score = @exercise_commit_user_counts > 0 ? (total_score.round(1) / @exercise_commit_user_counts).round(1) : 0.0 + question_scores = @exercise.question_scores + fail_score = question_scores * 0.6.round(2) + pass_score = question_scores * 0.7.round(2) + good_score = question_scores * 0.9.round(2) + + fail_counts = exercise_scores.count {|a| a < fail_score} + pass_counts = exercise_scores.count {|a| a < pass_score && a >= fail_score} + good_counts = exercise_scores.count {|a| a < good_score && a >= pass_score} + best_counts = exercise_scores.count {|a| a >= good_score && a <= question_scores} + end + @counts_array = { + :commit_percent => commit_percent, + :min_score => min_score.to_s, + :max_score => max_score.to_s, + :average_score => average_score.to_s, + :fail_counts => fail_counts, + :pass_counts => pass_counts, + :good_counts => good_counts, + :best_counts => best_counts, + } + + @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices, :exercise_answers, :exercise_standard_answers, :exercise_shixun_challenges, :exercise_shixun_answers) + + percent_sort = "desc" + + if params[:sort].present? + percent_sort = params[:sort] end + # @paging_type = "percent" + # # 按题型排序 + # if params[:sort].present? + # @paging_type = params[:sort].to_s + # end - exercise_user_joins = @exercise_users_list.joins(user: :user_extension) + ques_result_all = exercise_commit_result(@exercise_questions, @exercise_commit_user_ids) - if order == "student_id" - @exercise_users_list = exercise_user_joins.order("user_extensions.student_id #{order_type}") - elsif order == "score" - @exercise_users_list = exercise_user_joins.order("#{order} #{order_type}") + #默认降序排列 + if percent_sort == "desc" + @question_result_hash = ques_result_all.sort_by {|s| s[:percent]}.reverse else - @exercise_users_list = exercise_user_joins.order("end_at #{order_type}, start_at #{order_type}") + @question_result_hash = ques_result_all.sort_by {|s| s[:percent]} end - @export_ex_users = @exercise_users_list + @exercise_questions_count = @exercise_questions.size + @page = params[:page] || 1 + @limit = params[:limit] || 10 + @question_result_hash = Kaminari.paginate_array(@question_result_hash).page(@page).per(@limit) + end - @exercise_users_size = @exercise_users_list.size + private - # 分页 - @page = params[:page] || 1 - @limit = params[:limit] || 20 - @exercise_users_list = @exercise_users_list.page(@page).per(@limit) - else - @exercise_users_list = [] - @export_ex_users = @exercise_users_list - @exercise_users_size = 0 + def exercise_params + params.require(:exercise).permit(:exercise_name, :exercise_description, :course_id, :exercise_status, :user_id, :time, + :publish_time, :end_time, :show_result, :question_random, :choice_random, :is_public, + :score_open, :answer_open, :exercise_bank_id, :unified_setting, :show_statistic) end - if params[:format] == "xlsx" - if @user_course_identity > Course::ASSISTANT_PROFESSOR - tip_exception(403,"无权限操作") - elsif @exercise_status == Exercise::UNPUBLISHED - normal_status(-1,"试卷未发布") - elsif (@exercise_users_size == 0) || ( @export_ex_users&.exercise_user_committed.size == 0) - normal_status(-1,"暂无用户提交") - elsif params[:export].present? && params[:export] - normal_status(0,"正在下载中") + def is_course_teacher + unless @user_course_identity < Course::STUDENT #为老师/助教/管理员 + normal_status(403, "...") + end + end + + #检查传入的参数内容是否符合 + def validates_exercise_params + normal_status(-1, "试卷标题不能为空!") if params[:exercise_name].blank? + normal_status(-1, "试卷标题不能超过60个字符") if (params[:exercise_name].length > 60) + normal_status(-1, "试卷须知不能超过100个字符") if (params[:exercise_description].present? && + params[:exercise_description].length > 100) + end + + #判断设置的时间是否合理 + def validate_publish_time + # 截止时间存在,且截止时间必须大于当前时间或发布时间 + unified_setting = params[:unified_setting] + publish_course = params[:publish_time_groups] + if @course.is_end + normal_status(-1, "课堂已结束不能再修改") + elsif unified_setting + ex_group_settings = @exercise.exercise_group_settings + if ex_group_settings.present? + p_time_present = ex_group_settings.publish_time_no_null.map(&:publish_time).min + if p_time_present && p_time_present < Time.now + normal_status(-1, "设置失败,存在已发布的分班") + end + elsif params[:publish_time].blank? + normal_status(-1, "发布时间不允许为空") + end + elsif unified_setting.present? && !unified_setting #非统一设置,分班不能为空 + if publish_course.present? + course_ids = publish_course.map {|a| a[:course_group_id]}.sum + publish_t = publish_course.map {|a| a[:publish_time]} + if course_ids.include?(nil) || course_ids.count == 0 + normal_status(-1, "请选择分班") + elsif publish_t.include?(nil) || publish_t.count == 0 + normal_status(-1, "发布时间不允许为空") + end + else + normal_status(-1, "请选择分班") + end + end + end + + def get_exercise + @exercise = Exercise.find_by(id: params[:id]) + if @exercise.blank? + normal_status(404, "试卷不存在") else - respond_to do |format| - format.xlsx{ - set_export_cookies - get_export_users(@exercise,@course,@export_ex_users) - exercise_export_name_ = - "#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" - render xlsx: "#{exercise_export_name_.strip}",template: "exercises/exercise_lists.xlsx.axlsx",locals: {table_columns:@table_columns,exercise_users:@user_columns} - } + @course = @exercise.course + normal_status(404, "课堂不存在") if @course.blank? + end + end + + def get_exercise_question_counts #获取试卷的问题数及总分数 + exercise_questions = @exercise.exercise_questions + @exercise_ques_count = exercise_questions.size # 全部的题目数 + @exercise_ques_scores = exercise_questions.pluck(:question_score).sum + + #单选题的数量及分数 + exercise_single_ques = exercise_questions.find_by_custom("question_type", Exercise::SINGLE) + @exercise_single_ques_count = exercise_single_ques.size + @exercise_single_ques_scores = exercise_single_ques.pluck(:question_score).sum + + #多选题的数量及分数 + exercise_double_ques = exercise_questions.find_by_custom("question_type", Exercise::MULTIPLE) + @exercise_double_ques_count = exercise_double_ques.size + @exercise_double_ques_scores = exercise_double_ques.pluck(:question_score).sum + + # 判断题数量及分数 + exercise_ques_judge = exercise_questions.find_by_custom("question_type", Exercise::JUDGMENT) + @exercise_ques_judge_count = exercise_ques_judge.size + @exercise_ques_judge_scores = exercise_ques_judge.pluck(:question_score).sum + + #填空题数量及分数 + exercise_ques_null = exercise_questions.find_by_custom("question_type", Exercise::COMPLETION) + @exercise_ques_null_count = exercise_ques_null.size + @exercise_ques_null_scores = exercise_ques_null.pluck(:question_score).sum + + #简答题数量及分数 + exercise_ques_main = exercise_questions.find_by_custom("question_type", Exercise::SUBJECTIVE) + @exercise_ques_main_count = exercise_ques_main.size + @exercise_ques_main_scores = exercise_ques_main.pluck(:question_score).sum + + #实训题数量及分数 + exercise_ques_shixun = exercise_questions.find_by_custom("question_type", Exercise::PRACTICAL) + @exercise_ques_shixun_count = exercise_ques_shixun.size + @exercise_ques_shixun_scores = exercise_ques_shixun.pluck(:question_score).sum + + @exercise_questions = @exercise_questions&.includes(:exercise_choices, :exercise_shixun_challenges, :exercise_answers, :exercise_shixun_answers, :exercise_answer_comments, :exercise_standard_answers) + + end + + #获取用户有权限的分班 + def get_user_permission_course(exercise_ids, status) + exercise_status = status.to_i #传入的试卷发布状态 + unpublish_group = [] + course_groups = [] + user_groups_id = @course.charge_group_ids(current_user) + exercises_all = Exercise.includes(:exercise_group_settings).where(id: exercise_ids) + exercises_all.each do |exercise| + if exercise.present? + if exercise.unified_setting #统一设置只有两种情况,全部发布,全部截止 + exercise_user_status = exercise.get_exercise_status(current_user) #当前用户的能看到的试卷 + if (exercise_user_status == exercise_status) || exercise_status == Exercise::DEADLINE #未发布的情况 + unpublish_group = unpublish_group + user_groups_id + end + else + ex_all_group_settings = exercise.exercise_group_settings + ex_group_settings = ex_all_group_settings.exercise_group_published.pluck(:course_group_id).uniq #问卷设置的班级 + if exercise_status == Exercise::UNPUBLISHED + unpublish_group = user_groups_id - ex_group_settings + elsif exercise_status == Exercise::DEADLINE + ex_ended_groups = ex_all_group_settings.exercise_group_ended.pluck(:course_group_id).uniq + ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班 + unpublish_group = unpublish_group + ex_and_user - ex_ended_groups #已发布的全部班级减去截止的全部班级 + else + ex_ended_groups = ex_all_group_settings.exercise_group_ended.pluck(:course_group_id).uniq + ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班 + unpublish_group = unpublish_group + ex_and_user - ex_ended_groups + end + end end end + Rails.logger.info("#####____________unpublish_group_______#######{unpublish_group}") + unpublish_group = unpublish_group.uniq + if unpublish_group.count > 0 + course_groups = CourseGroup.by_group_ids(unpublish_group) + end + course_groups end - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback - end - end - #导出空白试卷 - def export_exercise - @request_url = request.base_url - @exercise_questions = @exercise.exercise_questions.includes(:exercise_choices).order("question_number ASC") - filename_ = "#{@exercise.user.real_name}_#{@course.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.pdf" - stylesheets = "#{Rails.root}/app/templates/exercise_export/exercise_export.css" - if params[:export].present? && params[:export] - normal_status(0,"正在下载中") - else - set_export_cookies - render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false - end - end + def set_exercise_status(publish_time, end_time) + time_now_i = Time.now + if publish_time.present? && (publish_time <= time_now_i) && (end_time > time_now_i) + 2 + elsif publish_time.nil? || (publish_time.present? && publish_time > time_now_i) + 1 + elsif end_time.present? && (end_time <= time_now_i) + 3 + elsif end_time.present? && publish_time.present? && (end_time < publish_time) + normal_status(-1, "时间设置错误!") + else + 1 + end + end - #空白试卷预览页面,仅供测试使用,无其他任何用途 - # def blank_exercise - # ActiveRecord::Base.transaction do - # begin - # @exercise_questions = @exercise.exercise_questions.order("question_number ASC") - # challenge_ids = @exercise_questions.joins(:exercise_shixun_challenges).pluck("exercise_shixun_challenges.challenge_id") - # get_each_student_exercise(@exercise.id,@exercise_questions,31798) - # @games = @exercise_user.user.games.ch_games(challenge_ids) - # respond_to do |format| - # format.html - # end - # rescue Exception => e - # uid_logger_error(e.message) - # tip_exception("没有权限") - # raise ActiveRecord::Rollback - # end - # end - # end + def check_course_public + unless @course.is_public == 1 # 0为私有,1为公开 + normal_status(403, "...") + end + end - #学生的统计结果 - def exercise_result - begin - exercise_ids = [@exercise.id] - @exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).size #判断是否有已发布的分班 - @exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).size #判断是否有未发布的分班 - @course_all_members = @course.students #课堂的全部学生 - @exercise_all_users = @exercise.exercise_users - ex_common_ids = @exercise.common_published_ids(current_user.id) - @exercise_course_groups = @course.get_ex_published_course(ex_common_ids) + def check_user_id_start_answer #判断用户在开始答题时,是否有用户id传入,如果为老师,则id必需,否则为当前用户的id + user_login = params[:login] + if user_login.blank? && @user_course_identity < Course::STUDENT #id不存在,且当前为老师/管理员等 + normal_status(-1, "请输入学生登陆名!") + else + if @user_course_identity < Course::STUDENT || @exercise.score_open + @ex_answerer = user_login.blank? ? current_user : User.find_by(login: user_login) + else + @ex_answerer = current_user + end - #班级的选择 - if params[:exercise_group_id].present? - group_id = params[:exercise_group_id] - exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数 - user_ids = exercise_students.pluck(:user_id).reject(&:blank?) - @exercise_all_users = @exercise.exercise_users.exercise_commit_users(user_ids) - @course_all_members_count = @exercise_all_users.size - else - @exercise_users_list = @exercise.all_exercise_users(current_user.id) - @course_all_members_count = @exercise_users_list.size - end - @exercise_commit_users = @exercise_all_users.commit_exercise_by_status(1) #试卷的已提交用户 - @exercise_commit_user_ids = @exercise_commit_users.pluck(:user_id).uniq #已提交试卷的全部用户id - @exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数 - @exercise_status = @exercise.get_exercise_status(current_user) - - #提交率 - if @course_all_members_count == 0 - commit_percent = 0.00 - min_score = 0.0 - max_score = 0.0 - average_score = 0.0 - fail_counts = 0 - pass_counts = 0 - good_counts = 0 - best_counts = 0 - else - commit_percent = (@exercise_commit_user_counts / @course_all_members_count.to_f).round(3) - exercise_scores = @exercise_commit_users.pluck(:score).reject(&:blank?) - min_score = exercise_scores.min.present? ? exercise_scores.min : 0.0 - max_score = exercise_scores.max.present? ? exercise_scores.max : 0.0 - total_score = exercise_scores.sum.present? ? exercise_scores.sum : 0.0 - average_score = @exercise_commit_user_counts > 0 ? (total_score.round(1) / @exercise_commit_user_counts).round(1) : 0.0 - question_scores = @exercise.question_scores - fail_score = question_scores * 0.6.round(2) - pass_score = question_scores * 0.7.round(2) - good_score = question_scores * 0.9.round(2) - - fail_counts = exercise_scores.count{|a| a < fail_score} - pass_counts = exercise_scores.count{|a| a < pass_score && a >= fail_score} - good_counts = exercise_scores.count{|a| a < good_score && a >= pass_score} - best_counts = exercise_scores.count{|a| a >= good_score && a <= question_scores} - end - @counts_array = { - :commit_percent => commit_percent, - :min_score => min_score.to_s, - :max_score => max_score.to_s, - :average_score => average_score.to_s, - :fail_counts => fail_counts, - :pass_counts => pass_counts, - :good_counts => good_counts, - :best_counts => best_counts, - } + if @ex_answerer.blank? + normal_status(404, "答题用户不存在") + elsif @user_course_identity > Course::STUDENT && !@exercise.is_public + normal_status(403, "非公开试卷") + else + # @exercise_current_user_id = @ex_answerer.id || current_user.id + @exercise_current_user_id = @ex_answerer.id + end + end + end - @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_answers,:exercise_standard_answers,:exercise_shixun_challenges,:exercise_shixun_answers) + ## 判断开始答题页面的用户权限 + def check_user_on_answer + if @user_course_identity == Course::STUDENT && @exercise.get_exercise_status(current_user) == Exercise::UNPUBLISHED #试卷未发布,且当前用户不为老师/管理员 + normal_status(-1, "未发布试卷!") + elsif @user_course_identity > Course::STUDENT && (!@exercise.is_public || (@exercise.is_public && !@exercise.unified_setting)) ##不为课堂成员,且试卷不为公开的,或试卷公开,但不是统一设置的 + normal_status(-1, "试卷暂未公开!") + end + end - percent_sort = "desc" + def check_exercise_time + @answer_committed_user = @exercise.exercise_users.exercise_commit_users(current_user.id)&.first + if @answer_committed_user.blank? + normal_status(404, "答题用户不存在") + end + end - if params[:sort].present? - percent_sort = params[:sort] + #打回重做时的初步判断 + def check_exercise_status + @exercise_users = @exercise.all_exercise_users(current_user.id).commit_exercise_by_status(1) #当前教师所在分班的全部已提交的学生数 + if @exercise.get_exercise_status(current_user) != Exercise::PUBLISHED + normal_status(-1, "非提交中的试卷不允许打回重做!") + elsif @exercise_users.count < 1 + normal_status(-1, "暂无人提交试卷!") + end end - # @paging_type = "percent" - # # 按题型排序 - # if params[:sort].present? - # @paging_type = params[:sort].to_s - # end - ques_result_all = exercise_commit_result(@exercise_questions,@exercise_commit_user_ids) - #默认降序排列 - if percent_sort == "desc" - @question_result_hash = ques_result_all.sort_by{|s| s[:percent]}.reverse - else - @question_result_hash = ques_result_all.sort_by{|s| s[:percent]} + #查看试题页面,当为学生时,除非试卷已截止,或已提交才可以查看 + def check_exercise_is_end + ex_status = @exercise.get_exercise_status(current_user) + @ex_user = @exercise.exercise_users.find_by(user_id: @exercise_current_user_id) #该试卷的回答者 + if @user_course_identity > Course::ASSISTANT_PROFESSOR + if ex_status == Exercise::UNPUBLISHED + normal_status(-1, "试卷未发布") + elsif @ex_user.present? && @ex_user.commit_status == 0 + normal_status(-1, "试卷未提交") + elsif params[:user_id].present? && current_user.id != params[:user_id] + normal_status(-1, "不能查看他人的试卷") + end + end + end + + #查看试卷是否选择为公开统计 + def check_exercise_public + if @user_course_identity > Course::ASSISTANT_PROFESSOR #当前为学生,试卷公开统计,且已截止,且已提交 + ex_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first + unless @exercise.get_exercise_status(current_user) == Exercise::DEADLINE && ex_user.present? && ex_user.commit_status == 1 && + @exercise.show_statistic + normal_status(-1, "学生暂不能查看") + end + end + end + + def get_left_banner_id + left_banner_content = @course.course_modules.search_by_module_type("exercise") + if left_banner_content.present? + @left_banner_id = left_banner_content.first.id + @left_banner_name = left_banner_content.first.module_name + else + normal_status(404, "左侧导航不存在") + end + end + + def get_user_answer_status(exercise_questions, user_id, exercise, exercise_user_status) + @question_status = [] + @exercise_all_questions = [] + ex_question_random = exercise.question_random + question_answered = 0 + exercise_questions.each_with_index do |q, index| + if ex_question_random && exercise_user_status != Exercise::DEADLINE + ques_number = index + 1 + else + ques_number = q.question_number + end + ques_status = 0 + if q.question_type != Exercise::PRACTICAL + ques_vote = q.exercise_answers.select {|answer| answer.user_id == user_id} + + if ques_vote.present? + #其他题目,需回答的有内容,才会为已答,否则如内容为空,视为未答 + vote_answer_id = ques_vote.pluck(:exercise_choice_id).reject(&:blank?) + vote_text_count = ques_vote.pluck(:answer_text).reject(&:blank?).size + if q.question_type <= Exercise::JUDGMENT #选择题和判断题的时候,需要有选项,才算回答 + if vote_answer_id.size > 0 + ques_status = 1 + question_answered += 1 + end + else + if vote_text_count > 0 #主观题,必选有内容,才算回答 + ques_status = 1 + question_answered += 1 + end + end + end + else + if Myshixun.exists?(user_id: user_id, shixun_id: q.shixun_id) + ques_status = 1 + question_answered += 1 + end + end + question_status = { + :ques_id => q.id, + :ques_number => ques_number, #仅问题的显示位置变化,但是问题的question_number 不会变化,与之相关的choice/standard_answer/answer不会变化 + :ques_status => ques_status, + } + question_options = { + :question => q, + :ques_number => ques_number, + } + @question_status = @question_status.push(question_status).sort_by {|k| k[:ques_number]} + @exercise_all_questions = @exercise_all_questions.push(question_options).sort_by {|k| k[:ques_number]} + end + end + + #下一步也有check_on_users再进行判断 + def only_student_in + if @user_course_identity < Course::STUDENT + normal_status(-1, "老师身份不允许进入") + end + end + + #判断实训是否已选择 + def commit_shixun_present + question_shixun_ids = @exercise.exercise_questions.pluck(:shixun_id).reject(&:blank?) + shixun_id = params[:shixun_id] + @shixun = Shixun.find_by(id: shixun_id) + if shixun_id.present? && question_shixun_ids.include?(shixun_id) + normal_status(-1, "该实训已选择!") + elsif @shixun.blank? + normal_status(-1, "该实训不存在!") + end end - @exercise_questions_count = @exercise_questions.size - @page = params[:page] || 1 - @limit = params[:limit] || 10 - @question_result_hash = Kaminari.paginate_array(@question_result_hash).page(@page).per(@limit) - rescue Exception => e - uid_logger_error(e.message) - tip_exception("没有权限") - raise ActiveRecord::Rollback end + + @exercise_questions_count = @exercise_questions.size + @page = params[:page] || 1 + @limit = params[:limit] || 10 + @question_result_hash = Kaminari.paginate_array(@question_result_hash).page(@page).per(@limit) end private def exercise_params params.require(:exercise).permit(:exercise_name, :exercise_description, :course_id, :exercise_status, :user_id, :time, - :publish_time, :end_time, :show_result, :question_random, :choice_random, :is_public, - :score_open, :answer_open, :exercise_bank_id, :unified_setting, :show_statistic) + :publish_time, :end_time, :show_result, :question_random, :choice_random, :is_public, + :score_open, :answer_open, :exercise_bank_id, :unified_setting, :show_statistic) end def is_course_teacher @@ -1534,7 +3038,7 @@ class ExercisesController < ApplicationController normal_status(-1, "试卷标题不能为空!") if params[:exercise_name].blank? normal_status(-1, "试卷标题不能超过60个字符") if (params[:exercise_name].length > 60) normal_status(-1, "试卷须知不能超过100个字符") if (params[:exercise_description].present? && - params[:exercise_description].length > 100) + params[:exercise_description].length > 100) end #判断设置的时间是否合理 @@ -1543,39 +3047,39 @@ class ExercisesController < ApplicationController unified_setting = params[:unified_setting] publish_course = params[:publish_time_groups] if @course.is_end - normal_status(-1,"课堂已结束不能再修改") + normal_status(-1, "课堂已结束不能再修改") elsif unified_setting ex_group_settings = @exercise.exercise_group_settings if ex_group_settings.present? p_time_present = ex_group_settings.publish_time_no_null.map(&:publish_time).min if p_time_present && p_time_present < Time.now - normal_status(-1,"设置失败,存在已发布的分班") + normal_status(-1, "设置失败,存在已发布的分班") end elsif params[:publish_time].blank? - normal_status(-1,"发布时间不允许为空") + normal_status(-1, "发布时间不允许为空") end - elsif unified_setting.present? && !unified_setting #非统一设置,分班不能为空 + elsif unified_setting.present? && !unified_setting #非统一设置,分班不能为空 if publish_course.present? - course_ids = publish_course.map{|a| a[:course_group_id]}.sum - publish_t = publish_course.map{|a| a[:publish_time]} + course_ids = publish_course.map {|a| a[:course_group_id]}.sum + publish_t = publish_course.map {|a| a[:publish_time]} if course_ids.include?(nil) || course_ids.count == 0 - normal_status(-1,"请选择分班") + normal_status(-1, "请选择分班") elsif publish_t.include?(nil) || publish_t.count == 0 - normal_status(-1,"发布时间不允许为空") + normal_status(-1, "发布时间不允许为空") end else - normal_status(-1,"请选择分班") + normal_status(-1, "请选择分班") end end end def get_exercise - @exercise = Exercise.find_by(id:params[:id]) + @exercise = Exercise.find_by(id: params[:id]) if @exercise.blank? - normal_status(404,"试卷不存在") + normal_status(404, "试卷不存在") else @course = @exercise.course - normal_status(404,"课堂不存在") if @course.blank? + normal_status(404, "课堂不存在") if @course.blank? end end @@ -1585,65 +3089,65 @@ class ExercisesController < ApplicationController @exercise_ques_scores = exercise_questions.pluck(:question_score).sum #单选题的数量及分数 - exercise_single_ques = exercise_questions.find_by_custom("question_type",Exercise::SINGLE) + exercise_single_ques = exercise_questions.find_by_custom("question_type", Exercise::SINGLE) @exercise_single_ques_count = exercise_single_ques.size @exercise_single_ques_scores = exercise_single_ques.pluck(:question_score).sum #多选题的数量及分数 - exercise_double_ques = exercise_questions.find_by_custom("question_type",Exercise::MULTIPLE) + exercise_double_ques = exercise_questions.find_by_custom("question_type", Exercise::MULTIPLE) @exercise_double_ques_count = exercise_double_ques.size @exercise_double_ques_scores = exercise_double_ques.pluck(:question_score).sum # 判断题数量及分数 - exercise_ques_judge = exercise_questions.find_by_custom("question_type",Exercise::JUDGMENT) + exercise_ques_judge = exercise_questions.find_by_custom("question_type", Exercise::JUDGMENT) @exercise_ques_judge_count = exercise_ques_judge.size @exercise_ques_judge_scores = exercise_ques_judge.pluck(:question_score).sum #填空题数量及分数 - exercise_ques_null = exercise_questions.find_by_custom("question_type",Exercise::COMPLETION) + exercise_ques_null = exercise_questions.find_by_custom("question_type", Exercise::COMPLETION) @exercise_ques_null_count = exercise_ques_null.size @exercise_ques_null_scores = exercise_ques_null.pluck(:question_score).sum #简答题数量及分数 - exercise_ques_main = exercise_questions.find_by_custom("question_type",Exercise::SUBJECTIVE) + exercise_ques_main = exercise_questions.find_by_custom("question_type", Exercise::SUBJECTIVE) @exercise_ques_main_count = exercise_ques_main.size @exercise_ques_main_scores = exercise_ques_main.pluck(:question_score).sum #实训题数量及分数 - exercise_ques_shixun = exercise_questions.find_by_custom("question_type",Exercise::PRACTICAL) + exercise_ques_shixun = exercise_questions.find_by_custom("question_type", Exercise::PRACTICAL) @exercise_ques_shixun_count = exercise_ques_shixun.size @exercise_ques_shixun_scores = exercise_ques_shixun.pluck(:question_score).sum - @exercise_questions = @exercise_questions&.includes(:exercise_choices,:exercise_shixun_challenges,:exercise_answers,:exercise_shixun_answers,:exercise_answer_comments,:exercise_standard_answers) + @exercise_questions = @exercise_questions&.includes(:exercise_choices, :exercise_shixun_challenges, :exercise_answers, :exercise_shixun_answers, :exercise_answer_comments, :exercise_standard_answers) end #获取用户有权限的分班 - def get_user_permission_course(exercise_ids,status) + def get_user_permission_course(exercise_ids, status) exercise_status = status.to_i #传入的试卷发布状态 unpublish_group = [] course_groups = [] user_groups_id = @course.charge_group_ids(current_user) - exercises_all = Exercise.includes(:exercise_group_settings).where(id:exercise_ids) + exercises_all = Exercise.includes(:exercise_group_settings).where(id: exercise_ids) exercises_all.each do |exercise| if exercise.present? - if exercise.unified_setting #统一设置只有两种情况,全部发布,全部截止 - exercise_user_status = exercise.get_exercise_status(current_user) #当前用户的能看到的试卷 + if exercise.unified_setting #统一设置只有两种情况,全部发布,全部截止 + exercise_user_status = exercise.get_exercise_status(current_user) #当前用户的能看到的试卷 if (exercise_user_status == exercise_status) || exercise_status == Exercise::DEADLINE #未发布的情况 unpublish_group = unpublish_group + user_groups_id end else ex_all_group_settings = exercise.exercise_group_settings - ex_group_settings = ex_all_group_settings.exercise_group_published.pluck(:course_group_id).uniq #问卷设置的班级 + ex_group_settings = ex_all_group_settings.exercise_group_published.pluck(:course_group_id).uniq #问卷设置的班级 if exercise_status == Exercise::UNPUBLISHED - unpublish_group = user_groups_id - ex_group_settings + unpublish_group = user_groups_id - ex_group_settings elsif exercise_status == Exercise::DEADLINE ex_ended_groups = ex_all_group_settings.exercise_group_ended.pluck(:course_group_id).uniq - ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班 - unpublish_group = unpublish_group + ex_and_user - ex_ended_groups #已发布的全部班级减去截止的全部班级 + ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班 + unpublish_group = unpublish_group + ex_and_user - ex_ended_groups #已发布的全部班级减去截止的全部班级 else ex_ended_groups = ex_all_group_settings.exercise_group_ended.pluck(:course_group_id).uniq - ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班 + ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班 unpublish_group = unpublish_group + ex_and_user - ex_ended_groups end end @@ -1657,7 +3161,7 @@ class ExercisesController < ApplicationController course_groups end - def set_exercise_status(publish_time,end_time) + def set_exercise_status(publish_time, end_time) time_now_i = Time.now if publish_time.present? && (publish_time <= time_now_i) && (end_time > time_now_i) 2 @@ -1666,22 +3170,22 @@ class ExercisesController < ApplicationController elsif end_time.present? && (end_time <= time_now_i) 3 elsif end_time.present? && publish_time.present? && (end_time < publish_time) - normal_status(-1,"时间设置错误!") + normal_status(-1, "时间设置错误!") else 1 end end def check_course_public - unless @course.is_public == 1 # 0为私有,1为公开 - normal_status(403,"...") + unless @course.is_public == 1 # 0为私有,1为公开 + normal_status(403, "...") end end def check_user_id_start_answer #判断用户在开始答题时,是否有用户id传入,如果为老师,则id必需,否则为当前用户的id user_login = params[:login] - if user_login.blank? && @user_course_identity < Course::STUDENT #id不存在,且当前为老师/管理员等 - normal_status(-1,"请输入学生登陆名!") + if user_login.blank? && @user_course_identity < Course::STUDENT #id不存在,且当前为老师/管理员等 + normal_status(-1, "请输入学生登陆名!") else if @user_course_identity < Course::STUDENT || @exercise.score_open @ex_answerer = user_login.blank? ? current_user : User.find_by(login: user_login) @@ -1690,9 +3194,9 @@ class ExercisesController < ApplicationController end if @ex_answerer.blank? - normal_status(404,"答题用户不存在") + normal_status(404, "答题用户不存在") elsif @user_course_identity > Course::STUDENT && !@exercise.is_public - normal_status(403,"非公开试卷") + normal_status(403, "非公开试卷") else # @exercise_current_user_id = @ex_answerer.id || current_user.id @exercise_current_user_id = @ex_answerer.id @@ -1702,9 +3206,9 @@ class ExercisesController < ApplicationController ## 判断开始答题页面的用户权限 def check_user_on_answer - if @user_course_identity == Course::STUDENT && @exercise.get_exercise_status(current_user) == Exercise::UNPUBLISHED #试卷未发布,且当前用户不为老师/管理员 + if @user_course_identity == Course::STUDENT && @exercise.get_exercise_status(current_user) == Exercise::UNPUBLISHED #试卷未发布,且当前用户不为老师/管理员 normal_status(-1, "未发布试卷!") - elsif @user_course_identity > Course::STUDENT && (!@exercise.is_public || (@exercise.is_public && !@exercise.unified_setting)) ##不为课堂成员,且试卷不为公开的,或试卷公开,但不是统一设置的 + elsif @user_course_identity > Course::STUDENT && (!@exercise.is_public || (@exercise.is_public && !@exercise.unified_setting)) ##不为课堂成员,且试卷不为公开的,或试卷公开,但不是统一设置的 normal_status(-1, "试卷暂未公开!") end end @@ -1712,7 +3216,7 @@ class ExercisesController < ApplicationController def check_exercise_time @answer_committed_user = @exercise.exercise_users.exercise_commit_users(current_user.id)&.first if @answer_committed_user.blank? - normal_status(404,"答题用户不存在") + normal_status(404, "答题用户不存在") end end @@ -1720,9 +3224,9 @@ class ExercisesController < ApplicationController def check_exercise_status @exercise_users = @exercise.all_exercise_users(current_user.id).commit_exercise_by_status(1) #当前教师所在分班的全部已提交的学生数 if @exercise.get_exercise_status(current_user) != Exercise::PUBLISHED - normal_status(-1,"非提交中的试卷不允许打回重做!") + normal_status(-1, "非提交中的试卷不允许打回重做!") elsif @exercise_users.count < 1 - normal_status(-1,"暂无人提交试卷!") + normal_status(-1, "暂无人提交试卷!") end end @@ -1730,25 +3234,25 @@ class ExercisesController < ApplicationController #查看试题页面,当为学生时,除非试卷已截止,或已提交才可以查看 def check_exercise_is_end ex_status = @exercise.get_exercise_status(current_user) - @ex_user = @exercise.exercise_users.find_by(user_id:@exercise_current_user_id) #该试卷的回答者 + @ex_user = @exercise.exercise_users.find_by(user_id: @exercise_current_user_id) #该试卷的回答者 if @user_course_identity > Course::ASSISTANT_PROFESSOR if ex_status == Exercise::UNPUBLISHED - normal_status(-1,"试卷未发布") + normal_status(-1, "试卷未发布") elsif @ex_user.present? && @ex_user.commit_status == 0 - normal_status(-1,"试卷未提交") + normal_status(-1, "试卷未提交") elsif params[:user_id].present? && current_user.id != params[:user_id] - normal_status(-1,"不能查看他人的试卷") + normal_status(-1, "不能查看他人的试卷") end end end #查看试卷是否选择为公开统计 def check_exercise_public - if @user_course_identity > Course::ASSISTANT_PROFESSOR #当前为学生,试卷公开统计,且已截止,且已提交 + if @user_course_identity > Course::ASSISTANT_PROFESSOR #当前为学生,试卷公开统计,且已截止,且已提交 ex_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first unless @exercise.get_exercise_status(current_user) == Exercise::DEADLINE && ex_user.present? && ex_user.commit_status == 1 && - @exercise.show_statistic - normal_status(-1,"学生暂不能查看") + @exercise.show_statistic + normal_status(-1, "学生暂不能查看") end end end @@ -1759,16 +3263,16 @@ class ExercisesController < ApplicationController @left_banner_id = left_banner_content.first.id @left_banner_name = left_banner_content.first.module_name else - normal_status(404,"左侧导航不存在") + normal_status(404, "左侧导航不存在") end end - def get_user_answer_status(exercise_questions,user_id,exercise,exercise_user_status) + def get_user_answer_status(exercise_questions, user_id, exercise, exercise_user_status) @question_status = [] @exercise_all_questions = [] ex_question_random = exercise.question_random question_answered = 0 - exercise_questions.each_with_index do |q,index| + exercise_questions.each_with_index do |q, index| if ex_question_random && exercise_user_status != Exercise::DEADLINE ques_number = index + 1 else @@ -1776,19 +3280,19 @@ class ExercisesController < ApplicationController end ques_status = 0 if q.question_type != Exercise::PRACTICAL - ques_vote = q.exercise_answers.select{|answer| answer.user_id == user_id} + ques_vote = q.exercise_answers.select {|answer| answer.user_id == user_id} if ques_vote.present? #其他题目,需回答的有内容,才会为已答,否则如内容为空,视为未答 vote_answer_id = ques_vote.pluck(:exercise_choice_id).reject(&:blank?) vote_text_count = ques_vote.pluck(:answer_text).reject(&:blank?).size - if q.question_type <= Exercise::JUDGMENT #选择题和判断题的时候,需要有选项,才算回答 + if q.question_type <= Exercise::JUDGMENT #选择题和判断题的时候,需要有选项,才算回答 if vote_answer_id.size > 0 ques_status = 1 question_answered += 1 end else - if vote_text_count > 0 #主观题,必选有内容,才算回答 + if vote_text_count > 0 #主观题,必选有内容,才算回答 ques_status = 1 question_answered += 1 end @@ -1801,22 +3305,23 @@ class ExercisesController < ApplicationController end end question_status = { - :ques_id => q.id, - :ques_number => ques_number, #仅问题的显示位置变化,但是问题的question_number 不会变化,与之相关的choice/standard_answer/answer不会变化 - :ques_status => ques_status, + :ques_id => q.id, + :ques_number => ques_number, #仅问题的显示位置变化,但是问题的question_number 不会变化,与之相关的choice/standard_answer/answer不会变化 + :ques_status => ques_status, } question_options = { - :question => q, - :ques_number => ques_number, + :question => q, + :ques_number => ques_number, } @question_status = @question_status.push(question_status).sort_by {|k| k[:ques_number]} @exercise_all_questions = @exercise_all_questions.push(question_options).sort_by {|k| k[:ques_number]} end end + #下一步也有check_on_users再进行判断 def only_student_in if @user_course_identity < Course::STUDENT - normal_status(-1,"老师身份不允许进入") + normal_status(-1, "老师身份不允许进入") end end @@ -1826,9 +3331,9 @@ class ExercisesController < ApplicationController shixun_id = params[:shixun_id] @shixun = Shixun.find_by(id: shixun_id) if shixun_id.present? && question_shixun_ids.include?(shixun_id) - normal_status(-1,"该实训已选择!") + normal_status(-1, "该实训已选择!") elsif @shixun.blank? - normal_status(-1,"该实训不存在!") + normal_status(-1, "该实训不存在!") end end From ba2249767258fb254e32e1cbb2dd69a266d577a6 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Sat, 11 Jan 2020 17:25:53 +0800 Subject: [PATCH 24/55] 1 --- app/controllers/subjects_controller.rb | 2 +- app/helpers/subjects_helper.rb | 4 ++-- app/views/subjects/show.json.jbuilder | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/subjects_controller.rb b/app/controllers/subjects_controller.rb index 1ceece56f..d58c4a9c3 100644 --- a/app/controllers/subjects_controller.rb +++ b/app/controllers/subjects_controller.rb @@ -92,7 +92,7 @@ class SubjectsController < ApplicationController @is_creator = current_user.creator_of_subject?(@subject) @is_manager = @user.manager_of_subject?(@subject) # 合作团队 - @shixuns = @subject.shixuns.published.pluck(:id) + # @shixuns = @subject.shixuns.published.pluck(:id) @courses = @subject.courses if @subject.excellent @members = @subject.subject_members.includes(:user) diff --git a/app/helpers/subjects_helper.rb b/app/helpers/subjects_helper.rb index 75ae9f041..72154b0a8 100644 --- a/app/helpers/subjects_helper.rb +++ b/app/helpers/subjects_helper.rb @@ -1,10 +1,10 @@ module SubjectsHelper # 实训路径的发布状态 - def publish_status subject, is_manager, user, shixuns + def publish_status subject, is_manager, user status = -1 if is_manager - status = 0 if subject.status == 0 && shixuns.count > 0 + status = 0 if subject.status == 0 status = 1 if subject.status == 1 status = 2 if subject.status == 2 && user.admin? end diff --git a/app/views/subjects/show.json.jbuilder b/app/views/subjects/show.json.jbuilder index 870d33d40..49ad55517 100644 --- a/app/views/subjects/show.json.jbuilder +++ b/app/views/subjects/show.json.jbuilder @@ -6,7 +6,7 @@ json.subject_score @subject.all_score json.member_count @subject.member_count json.allow_delete (@subject.status != 2 && @is_creator) || @user.admin? -json.publish_status publish_status(@subject, @is_manager, @user, @shixuns) +json.publish_status publish_status(@subject, @is_manager, @user) json.allow_statistics @is_manager json.allow_send @user.logged? json.allow_visit @subject.status > 1 || @is_manager From 5058b7973611f847afb17c46c0e38d7cba8b5a40 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sat, 11 Jan 2020 17:26:22 +0800 Subject: [PATCH 25/55] =?UTF-8?q?=E8=AF=84=E9=98=85=E5=92=8C=E5=9B=9E?= =?UTF-8?q?=E5=A4=8D=E7=9A=84=E5=AD=97=E7=AC=A6=E9=99=90=E5=88=B6=E6=94=B9?= =?UTF-8?q?=E4=B8=BA2000?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/memos_controller.rb | 2 +- app/controllers/messages_controller.rb | 2 +- app/models/discuss.rb | 2 +- app/models/graduation_work_score.rb | 2 +- app/models/hack_set.rb | 4 ++-- app/models/journals_for_message.rb | 2 +- app/models/student_works_score.rb | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/memos_controller.rb b/app/controllers/memos_controller.rb index a4d72371c..b80bfed32 100644 --- a/app/controllers/memos_controller.rb +++ b/app/controllers/memos_controller.rb @@ -144,7 +144,7 @@ class MemosController < ApplicationController def reply tip_exception("parent_id不能为空") if params[:parent_id].blank? tip_exception("content不能为空") if params[:content].blank? - tip_exception("内容不能超过1000字符") if params[:content].length > 1000 + tip_exception("内容不能超过2000字符") if params[:content].length > 2000 ActiveRecord::Base.transaction do begin diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 7b096f1ec..2b9d9d69f 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -63,7 +63,7 @@ class MessagesController < ApplicationController def reply return normal_status(2, "回复内容不能为空") if params[:content].blank? - return normal_status(2, "回复内容不能超过1000字符") if params[:content].length > 1000 + return normal_status(2, "回复内容不能超过2000字符") if params[:content].length > 2000 @reply = Message.create!(board: @message.board, root_id: @message.root_id || @message.id, author: current_user, parent: @message, message_detail_attributes: { diff --git a/app/models/discuss.rb b/app/models/discuss.rb index b563a6295..a4c833b55 100644 --- a/app/models/discuss.rb +++ b/app/models/discuss.rb @@ -13,7 +13,7 @@ class Discuss < ApplicationRecord belongs_to :challenge, optional: true validate :validate_sensitive_string - validates :content, length: { maximum: 1000, too_long: "不能超过1000个字符" } + validates :content, length: { maximum: 2000, too_long: "不能超过2000个字符" } after_create :send_tiding diff --git a/app/models/graduation_work_score.rb b/app/models/graduation_work_score.rb index 5c2627c88..78c2727fc 100644 --- a/app/models/graduation_work_score.rb +++ b/app/models/graduation_work_score.rb @@ -5,5 +5,5 @@ class GraduationWorkScore < ApplicationRecord belongs_to :graduation_task has_many :attachments, as: :container, dependent: :destroy - validates :comment, length: { maximum: 1000, too_long: "不能超过1000个字符" } + validates :comment, length: { maximum: 2000, too_long: "不能超过2000个字符" } end diff --git a/app/models/hack_set.rb b/app/models/hack_set.rb index e2ca60549..2c21c3c22 100644 --- a/app/models/hack_set.rb +++ b/app/models/hack_set.rb @@ -1,6 +1,6 @@ class HackSet < ApplicationRecord - validates_length_of :input, maximum: 1000, message: "不能超过5000个字符" - validates_length_of :output, maximum: 1000, message: "不能超过5000个字符" + validates_length_of :input, maximum: 1000, message: "不能超过1000个字符" + validates_length_of :output, maximum: 1000, message: "不能超过1000个字符" validates :input, presence: { message: "测试集输入不能为空" } validates :output, presence: { message: "测试集输出不能为空" } validates_uniqueness_of :input, scope: [:hack_id, :input], message: "多个测试集的输入不能相同" diff --git a/app/models/journals_for_message.rb b/app/models/journals_for_message.rb index 190fa4351..3d0189c91 100644 --- a/app/models/journals_for_message.rb +++ b/app/models/journals_for_message.rb @@ -26,7 +26,7 @@ class JournalsForMessage < ApplicationRecord # "is_comprehensive_evaluation", # 1 教师评论、2 匿评、3 留言 # "hidden", 隐藏、 - validates :notes, length: { maximum: 1000, too_long: "不能超过1000个字符" } + validates :notes, length: { maximum: 2000, too_long: "不能超过2000个字符" } after_create :send_tiding diff --git a/app/models/student_works_score.rb b/app/models/student_works_score.rb index dec4512a8..a193d4e77 100644 --- a/app/models/student_works_score.rb +++ b/app/models/student_works_score.rb @@ -7,7 +7,7 @@ class StudentWorksScore < ApplicationRecord has_many :tidings, as: :container, dependent: :destroy has_many :attachments, as: :container, dependent: :destroy - validates :comment, length: { maximum: 1000, too_long: "不能超过1000个字符" } + validates :comment, length: { maximum: 2000, too_long: "不能超过2000个字符" } scope :shixun_comment, lambda { where(is_ultimate: 0) } From 12746914e1b853d9bae67c34e6f8949d00a50475 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sat, 11 Jan 2020 17:31:15 +0800 Subject: [PATCH 26/55] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E7=9A=84=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/exercises_controller.rb | 1670 ----------------------- 1 file changed, 1670 deletions(-) diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 408f95945..5b555cf4c 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -1342,1676 +1342,6 @@ class ExercisesController < ApplicationController else @question_result_hash = ques_result_all.sort_by {|s| s[:percent]} end - class ExercisesController < ApplicationController - before_action :require_login, :check_auth, except: [:index] - before_action :find_course, only: [:index, :new, :create, :my_exercises, :public_exercises, :set_public, :destroys, - :join_exercise_banks, :publish_modal, :publish, :end_modal, :end_exercise] #需要有课堂id参数的 - before_action :get_exercise, except: [:index, :new, :create, :my_exercises, :public_exercises, :set_public, :destroys, - :join_exercise_banks, :publish_modal, :publish, :end_modal, :end_exercise] - before_action :user_course_identity - before_action :is_course_teacher, except: [:index, :start_answer, :exercise_setting, :commit_exercise, :exercise_lists, :review_exercise, - :exercise_result, :common_header, :cancel_exercise, :begin_commit] - before_action :get_left_banner_id, only: [:common_header, :start_answer, :review_exercise, :index, :new, :edit] - before_action :validates_exercise_params, only: [:create, :update] - before_action :get_exercise_question_counts, only: [:show, :edit, :start_answer, :review_exercise, :blank_exercise, :export_exercise] - before_action :validate_publish_time, only: [:commit_setting] #提交设置时,需判断时间是否符合 - before_action :check_course_public, only: [:set_public] - before_action :check_user_on_answer, only: [:show, :start_answer, :exercise_lists] #判断当前用户在试卷的权限/老师是否属于分班的权限 - before_action :only_student_in, only: [:start_answer] - before_action :check_user_id_start_answer, only: [:start_answer, :review_exercise] - # before_action :commit_user_exercise,only: [:start_answer,:exercise_lists,:review_exercise] #已有定时的任务 - before_action :check_exercise_time, only: [:commit_exercise] #提交试卷时,判断时间是否超过 - before_action :check_exercise_status, only: [:redo_modal, :redo_exercise] - before_action :check_exercise_is_end, only: [:review_exercise] - before_action :check_exercise_public, only: [:exercise_result] #试卷是否为公开 - before_action :commit_shixun_present, only: [:commit_shixun] - include ExportHelper - include ExercisesHelper - - # model validation error - rescue_from ActiveRecord::RecordInvalid do |ex| - render_error(ex.record.errors.full_messages.join(',')) - end - # form validation error - rescue_from ActiveModel::ValidationError do |ex| - render_error(ex.model.errors.full_messages.join(',')) - end - - def index - begin - # 按发布时间或创建时间排序 - @exercises_all = @course.exercises - member_show_exercises = @exercises_all.is_exercise_published #已发布的或已截止的试卷 - @current_user_ = current_user - - # 课堂的学生人数 - @course_all_members = @course.students #当前课堂的全部学生 - @current_student = @course_all_members.course_find_by_ids("user_id", current_user.id) #当前用户是否为课堂的学生 - - # exercises的不同用户群体的显示 - if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教 - @is_teacher_or = 1 - @exercises = @exercises_all #老师能看到全部的试卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同) - elsif @user_course_identity == Course::STUDENT # 2为课堂成员,能看到统一设置的和自己班级的 - @is_teacher_or = 2 - @member_group_id = @current_student.first.try(:course_group_id).to_i # 成员的分班id,默认为0 - if @member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的) - @exercises = member_show_exercises.exists? ? member_show_exercises.unified_setting : [] - else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷 - # 已发布 当前用户班级分组的 试卷id - publish_exercise_ids = @course.exercise_group_settings.exercise_group_published.where("course_group_id = #{@member_group_id}").pluck(:exercise_id) - @exercises = member_show_exercises.unified_setting.or(member_show_exercises.where(id: publish_exercise_ids)) - end - else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁 - @is_teacher_or = 0 - @exercises = member_show_exercises.unified_setting - end - - if @exercises.size > 0 - if params[:type].present? - choose_type = params[:type].to_i - ex_setting_ids = [] - if @is_teacher_or != 2 - @exercises = @exercises.where("exercise_status = #{choose_type}") - else - case choose_type - when 1 - ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}").exercise_group_not_published.pluck(:exercise_id) - when 2 - ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}") - .where("publish_time is not null and publish_time <= ? and end_time > ?", Time.now, Time.now).pluck(:exercise_id) - when 3 - ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}").exercise_group_ended.pluck(:exercise_id) - end - unified_setting_ids = @exercises.unified_setting.where("exercise_status = #{choose_type}").pluck(:id) - ex_ids = (ex_setting_ids + unified_setting_ids).uniq - @exercises = @exercises.where(id: ex_ids) - end - end - - if params[:search].present? - search_type = params[:search].to_s.strip - @exercises = @exercises.exercise_search(search_type) - end - - @exercises_select_count = @exercises.size # 全部页面,需返回 - @exercises = @exercises.distinct.order("IF(ISNULL(publish_time),0,1), publish_time DESC,created_at DESC") #出现错误 - - # 分页 - @page = params[:page] || 1 - @limit = params[:limit] || 15 - @exercises = @exercises.page(@page).per(@limit) - @exercises = @exercises&.includes(:published_settings) - else - @exercises = [] - end - - @course_all_members_count = @course_all_members.size #当前课堂的学生数 - @exercises_count = @exercises_all.size # 全部页面,需返回 - @exercises_unpublish_counts = @exercises_all.exercise_by_status(1).size #未发布的试卷数 - @exercises_published_counts = @exercises_count - @exercises_unpublish_counts # 已发布的试卷数,包含已截止的 - - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback - end - end - - def new - ActiveRecord::Base.transaction do - begin - @exercise = Exercise.new - rescue Exception => e - uid_logger_error(e.message) - tip_exception("试卷创建失败!") - raise ActiveRecord::Rollback - end - end - end - - def create - ActiveRecord::Base.transaction do - ex_name = params[:exercise_name] - ex_desc = params[:exercise_description] - exercise_options = { - :exercise_name => ex_name, - :exercise_description => ex_desc, - :user_id => current_user.id, - :course_id => @course.id, - :time => -1, - :exercise_status => 1 - } - @exercise = Exercise.create!(exercise_options) - end - end - - #试卷的内容,及试题/答案的内容编辑 - def edit - ActiveRecord::Base.transaction do - @exercise_questions = @exercise.exercise_questions.order("question_number ASC") - end - end - - def update - ActiveRecord::Base.transaction do - ex_name = params[:exercise_name] - ex_desc = params[:exercise_description] - exercise_options = { - :exercise_name => ex_name, - :exercise_description => ex_desc, - } - @exercise.update!(exercise_options) - normal_status(0, "试卷更新成功!") - end - end - - def show - ActiveRecord::Base.transaction do - if @user_course_identity < Course::STUDENT - @is_teacher_or = 1 #为老师/助教/管理员 - else - @is_teacher_or = 0 #为学生 - end - @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices, :exercise_shixun_challenges, :exercise_standard_answers).order("question_number ASC") - end - end - - #试卷的公用头部 - def common_header - ActiveRecord::Base.transaction do - @user_left_time = nil - if @user_course_identity > Course::ASSISTANT_PROFESSOR - @is_teacher_or = 0 - @user_exercise_answer = @exercise.check_user_answer_status(current_user) - @user_commit_counts = 0 - @user_left_time = get_exercise_left_time(@exercise, current_user) - else - @is_teacher_or = 1 - @user_exercise_answer = 3 #教师页面 - @user_commit_counts = @exercise.exercise_users.where(commit_status: 1).size #已提交的用户数 - end - @ex_status = @exercise.get_exercise_status(current_user) - - exercise_id_array = [@exercise.id] - @exercise_publish_count = get_user_permission_course(exercise_id_array, Exercise::PUBLISHED).size #是否存在已发布的 - @exercise_unpublish_count = get_user_permission_course(exercise_id_array, Exercise::UNPUBLISHED).size #是否存在未发布的 - - if (@exercise_publish_count == 0) && (@exercise_unpublish_count == 0) #即表示没有分班 - if @ex_status == Exercise::UNPUBLISHED - @exercise_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候 - elsif @ex_status == Exercise::PUBLISHED - @exercise_publish_count = 1 #试卷未发布,且课堂没有分班的时候 - end - end - end - end - - #实训题目的选用 - def choose_shixun - ActiveRecord::Base.transaction do - search = params[:search] - if @user_course_identity > Course::ADMIN #当不为管理员的时候 - user_school_id = current_user.school_id #当前用户的学校id - if user_school_id.present? - none_shixun_ids = ShixunSchool.where("school_id != #{user_school_id}").pluck(:shixun_id) - @publish_shixuns = Shixun.where.not(id: none_shixun_ids).unhidden - end - else - @publish_shixuns = Shixun.unhidden - end - if search.present? - @publish_shixuns = @publish_shixuns.search_by_name(search) - end - - @shixuns = @publish_shixuns.joins(:challenges).where("challenges.st != 0").distinct - # 全部页面,需返回 - @shixuns_count = @shixuns.count - - # 分页 - @page = params[:page] || 1 - @limit = params[:limit] || 8 - - @shixuns = @shixuns.page(@page).per(@limit) - end - end - - #确认实训的选择 - def commit_shixun - ActiveRecord::Base.transaction do - @shixun_challenges = @shixun.challenges - @shixun_challenges_count = @shixun_challenges.size - end - end - - # 首页批量或单独删除 - def destroys - ActiveRecord::Base.transaction do - check_ids = Exercise.where(id: params[:check_ids]) - check_ids.destroy_all - normal_status(0, "试卷已删除成功!") - end - end - - # 设为公开 - def set_public - ActiveRecord::Base.transaction do - check_ids = Exercise.where(id: params[:check_ids]) - check_ids.each do |exercise| - exercise.update!(is_public: true) - end - normal_status(0, "试卷已设为公开!") - end - end - - ## 加入题库 - def join_exercise_banks - ActiveRecord::Base.transaction do - check_ids = Exercise.where(id: params[:check_ids]) - check_ids.each do |exercise| - current_ex_bank = current_user.exercise_banks.find_by_container(exercise.id, "Exercise")&.first - if current_ex_bank.present? #当前用户的选择试卷是否已加入习题库,存在则更新习题库和问题库,否则新建习题库和问题库 - ex_params = { - :name => exercise.exercise_name, - :description => exercise.exercise_description, - :course_list_id => exercise.course.try(:course_list_id) - } - current_ex_bank.update!(ex_params) - # question_bank = QuestionBank.ques_by_container(current_ex_bank.id,current_ex_bank.container_type).first #该习题库是否存在于问题库里 - # ques_params = { - # :name => current_ex_bank.name, - # :course_list_id => current_ex_bank.course_list_id - # } - # question_bank.update_attributes(ques_params) if question_bank.present? - current_ex_bank.exercise_bank_questions.destroy_all # 更新后,习题库的问题全部删除,后续重新再建 - else - ex_params = { - :name => exercise.exercise_name, - :description => exercise.exercise_description, - :user_id => current_user.id, - :is_public => 0, - :course_list_id => exercise.course.try(:course_list_id), - :container_id => exercise.id, - :container_type => "Exercise", - :quotes => 1 - } - current_ex_bank = ExerciseBank.new ex_params - current_ex_bank.save! #如果习题库保存成功,则会创建问题库question_bank - # if current_ex_bank.save - # ques_params = { - # :name => current_ex_bank.name, - # :container_id => current_ex_bank.id, - # :container_type => current_ex_bank.container_type, - # :quotes => current_ex_bank.quotes, - # :user_id => current_ex_bank.user_id, - # :is_public => current_ex_bank.is_public, - # :course_list_id => current_ex_bank.course_list_id - # } - # question_bank = QuestionBank.new ques_params - # question_bank.save - # end - exercise.update!(exercise_bank_id: current_ex_bank.id) - end - # 试卷的问题的输入 - exercise.exercise_questions.each do |q| - option = { - :question_title => q.question_title, - :question_type => q.question_type, - :question_number => q.question_number, - :question_score => q.question_score, - :shixun_id => q.shixun_id, - :shixun_name => q.shixun_name - } - exercise_bank_question = current_ex_bank.exercise_bank_questions.new option - exercise_bank_question.save! - ## 试卷选项的输入 - if q.question_type != Exercise::PRACTICAL #不为实训题时,试卷选项加入试题答案库 - ex_choices = q.exercise_choices - ex_standard = q.exercise_standard_answers - ex_choices.each do |c| - choice_option = { - :choice_position => c.choice_position, - :choice_text => c.choice_text - } - ex_bank_choice = exercise_bank_question.exercise_bank_choices.new choice_option - ex_bank_choice.save! - end - ex_standard.each do |s| - ex_stand = { - :exercise_bank_choice_id => s.exercise_choice_id, - :answer_text => s.answer_text - } - ex_stand_bank = exercise_bank_question.exercise_bank_standard_answers.new ex_stand - ex_stand_bank.save! - end - else #当为实训题时 - shixun_challenges = q.exercise_shixun_challenges - shixun_challenges.each do |c| - challenge_option = { - :position => c.position, - :challenge_id => c.challenge_id, - :shixun_id => q.shixun_id, - :question_score => c.question_score - } - shixun_challenge_bank = exercise_bank_question.exercise_bank_shixun_challenges.new challenge_option - shixun_challenge_bank.save! - end - end - end - current_ex_bank.save! - end - normal_status(0, "题库更新成功!") - end - end - - #试卷的设置页面 - def exercise_setting - ActiveRecord::Base.transaction do - @user_permission = 2 - @user_course_groups = @course.teacher_group(current_user.id) #当前老师的分班 - @being_setting_course_ids = @exercise.common_published_ids(current_user.id) #当前用户已发布的班级的id - @user_published_setting = @exercise.exercise_group_settings - .find_in_exercise_group("course_group_id", @being_setting_course_ids) #当前用户已发布班级的试卷设置 - exercise_ids = [@exercise.id] - @exercise_publish_count = get_user_permission_course(exercise_ids, Exercise::PUBLISHED).count #判断当前用户是否有试卷已发布的分班,用于显示立即截止/撤销发布 - @exercise_unpublish_count = get_user_permission_course(exercise_ids, Exercise::UNPUBLISHED).count #判断当前用户是否有试卷未发布的分班,用户显示立即发布 - @exercise_users_count = @exercise.exercise_users.commit_exercise_by_status(1).count #判断当前试卷是否有已提交的 - # ## 需添加发送消息的接口,稍后添加 - end - end - - #试卷的提交设置 - def commit_setting - ActiveRecord::Base.transaction do - error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。 - # course_group_ids = @course.teacher_course_group_ids(current_user.id) #当前老师的班级id数组 - course_group_ids = @course.charge_group_ids(current_user) #当前老师的班级id数组 - - exercise_status = @exercise.get_exercise_status(current_user) - - if exercise_status == Exercise::UNPUBLISHED && course_group_ids.size > 0 # 试卷未发布,且老师的分班大于1 ,才可以修改统一设置,否则按试卷默认的来处理 - unified_setting = params[:unified_setting] - else - unified_setting = @exercise.unified_setting - end - - show_statistic = params[:show_statistic] ? true : false - exercise_time = params[:time].blank? ? -1 : params[:time] - question_random = params[:question_random] ? true : false #问题是否随机,0为不随机,1为随机 - choice_random = params[:choice_random] ? true : false - score_open = params[:score_open] ? true : false #分数是否公开 - answer_open = params[:answer_open] ? true : false #答案是否公开 - - # 统一设置或者分班为0,则更新试卷,并删除试卷分组 - if unified_setting || (course_group_ids.size == 0) - tip_exception("发布时间不能为空") if params[:publish_time].blank? - tip_exception("截止时间不能为空") if params[:end_time].blank? - tip_exception("截止时间不能早于发布时间") if params[:publish_time].to_time > params[:end_time].to_time - tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && params[:end_time].to_time > @course.end_date.end_of_day - - params_publish_time = params[:publish_time].to_time - params_end_time = params[:end_time].to_time - - if (exercise_status != Exercise::UNPUBLISHED) && (@exercise.publish_time != params_publish_time) - normal_status(-1, "已发布/已截止,不允许修改发布时间") - elsif params_publish_time.present? && params_end_time.present? && params_end_time < params_publish_time - normal_status(-1, "截止时间不能小于发布时间") - else - #发布时间小于当前时间,则试卷显示为未发布,当截止时间大于当前时间,则显示为已截止 - exercise_status_n = set_exercise_status(params_publish_time, params_end_time) - exercise_params = { - :unified_setting => unified_setting, - :show_statistic => show_statistic, - :time => exercise_time, - :question_random => question_random, - :choice_random => choice_random, - :score_open => score_open, - :answer_open => answer_open, - :exercise_status => exercise_status_n, - :publish_time => params_publish_time, - :end_time => params_end_time - } - @exercise.update!(exercise_params) - @exercise.exercise_group_settings.destroy_all - normal_status(0, "试卷设置成功!") - end - else - params_times = params[:publish_time_groups] #分班返回的json数组{"publish_time_groups":[{"course_group_id":"1","publish_time":"xx","end_time":"xxx"}]} - exercise_groups = @exercise.exercise_group_settings.find_in_exercise_group("course_id", @course.id) #试卷的全部分班信息 - exercise_groups_ids = exercise_groups.pluck(:course_group_id) #问卷的全部分班id - total_common = params_times.map {|k| k[:course_group_id]}.sum.uniq #传入的所有分组的分班id - total_common_group = exercise_groups_ids & total_common #传入的分班与问卷已存在的分班的交集 - old_exercise_groups = exercise_groups_ids - total_common_group #后来传入的分班里,没有了的班级,即需要删除 - - params_times.each do |t| - tip_exception("发布时间不能为空") if t[:publish_time].blank? - tip_exception("截止时间不能为空") if t[:end_time].blank? - tip_exception("截止时间不能早于发布时间") if t[:publish_time].to_time > t[:end_time].to_time - tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && t[:end_time].to_time > @course.end_date.end_of_day - - course_id = t[:course_group_id] - exercise_publish_time = t[:publish_time].to_time - exercise_end_time = t[:end_time].to_time - - exercise_group = exercise_groups.find_in_exercise_group("course_group_id", course_id) #判断该分班是否存在 - if exercise_group.present? && (exercise_group.first.publish_time < Time.now) && (exercise_publish_time != exercise_group.first.publish_time) - error_count += 1 - end - if exercise_group.present? && (exercise_group.first.publish_time < Time.now && exercise_group.first.end_time > Time.now) && (exercise_end_time < Time.now) - error_count += 1 - end - if error_count == 0 - common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的 - new_group_ids = course_id - common_group #新传入的班级id - if common_group.count > 0 #判断试卷的分班设置是否存在,存在则更新,负责则新建 - exercise_group_sets = exercise_groups.find_in_exercise_group("course_group_id", common_group) - exercise_group_sets.each do |the_group_setting| - ex_group_params = { - :publish_time => exercise_publish_time, - :end_time => exercise_end_time - } - - the_group_setting_status = set_exercise_status(the_group_setting.publish_time, the_group_setting.end_time) - if the_group_setting_status == 2 - ex_group_params = { - :publish_time => the_group_setting.publish_time, - :end_time => exercise_end_time < Time.now ? the_group_setting.end_time : exercise_end_time - } - elsif the_group_setting_status == 3 - ex_group_params = { - :publish_time => the_group_setting.publish_time, - :end_time => exercise_end_time - } - end - the_group_setting.update!(ex_group_params) - end - end - if new_group_ids.size > 0 - new_group_ids.each do |c| - exercise_group_params = { - :exercise_id => @exercise.id, - :course_group_id => c, - :course_id => @course.id, - :publish_time => exercise_publish_time, - :end_time => exercise_end_time - } - new_exercise_group = ExerciseGroupSetting.new(exercise_group_params) - new_exercise_group.save! - end - end - end - end - - if error_count > 0 - error_count == 0 - normal_status(-1, "试卷发布/截止时间不能小于当前时间") - else - # 未发布的分班设置才能删除 - if old_exercise_groups.size > 0 - old_all_ex_groups = exercise_groups.find_in_exercise_group("course_group_id", old_exercise_groups).exercise_group_not_published - old_all_ex_groups.destroy_all - end - #试卷更新为exercise_group_setting的发布时间最小,截止时间最大 - e_time_present = exercise_groups.end_time_no_null.map(&:end_time) - p_time_present = exercise_groups.publish_time_no_null.map(&:publish_time) - e_time = e_time_present.size > 0 ? e_time_present.max : nil - p_time = p_time_present.size > 0 ? p_time_present.min : nil - exercise_status = 1 - if p_time.nil? #发布时间为空,则表示问卷未发布 - exercise_status = 1 - elsif p_time.present? && e_time.present? - exercise_status = set_exercise_status(p_time, e_time) - end - exercise_params = { - :unified_setting => unified_setting, - :show_statistic => show_statistic, - :time => exercise_time, - :question_random => question_random, - :choice_random => choice_random, - :score_open => score_open, - :answer_open => answer_open, - :exercise_status => exercise_status, - :publish_time => p_time, - :end_time => e_time - } - @exercise.update!(exercise_params) - if @exercise.exercise_status == Exercise::PUBLISHED - if @exercise.course_acts.size == 0 - @exercise.course_acts << CourseActivity.new(:user_id => @exercise.user_id, :course_id => @exercise.course_id) - end - end - normal_status(0, "试卷设置成功!") - end - end - end - end - - # 对未提交的用户进行调分 - def adjust_score - exercise_user = @exercise.exercise_users.find_by!(user_id: params[:user_id]) - tip_exception("已提交的作品请去评阅页进行调分") if exercise_user.commit_status == 1 && exercise_user.commit_method != 5 - if @exercise.subjective_score > 0 - tip_exception("主观题成绩不能为空") if params[:subjective_score].blank? - tip_exception("主观题成绩不能小于零") if params[:subjective_score].to_f < 0 - tip_exception("主观题成绩不能大于总分值:#{@exercise.subjective_score}分") if params[:subjective_score].to_f.round(1) > @exercise.subjective_score.round(1) - end - - if @exercise.objective_score > 0 - tip_exception("客观题成绩不能为空") if params[:objective_score].blank? - tip_exception("客观题成绩不能小于零") if params[:objective_score].to_f < 0 - tip_exception("客观题成绩不能大于总分值:#{@exercise.objective_score}分") if params[:objective_score].to_f.round(1) > @exercise.objective_score.round(1) - end - - ActiveRecord::Base.transaction do - start_at_time = exercise_user.start_at || Time.now - subjective_score = @exercise.subjective_score > 0 ? params[:subjective_score].to_f.round(2) : 0 - objective_score = @exercise.objective_score > 0 ? params[:objective_score].to_f.round(2) : 0 - score = subjective_score + objective_score - if exercise_user.commit_status == 1 - exercise_user.update!(score: score, subjective_score: subjective_score, objective_score: objective_score) - else - exercise_user.update!(start_at: start_at_time, end_at: Time.now, status: 1, commit_status: 1, score: score, - subjective_score: subjective_score, objective_score: objective_score, commit_method: 5) - end - - ExerciseUserScore.create!(exercise_id: @exercise.id, exercise_user_id: exercise_user.id, - subjective_score: subjective_score, objective_score: objective_score) - normal_status("操作成功") - end - end - - #我的题库 - def my_exercises - ActiveRecord::Base.transaction do - ## 我的试卷题库 - @current_user_exercises = current_user.exercise_banks.find_by_c_type("Exercise") - if @current_user_exercises.present? - - if params[:search].present? - search_type = params[:search].to_s.strip - @current_user_exercises = @current_user_exercises.exercise_bank_search(search_type) - end - page = params[:page] || 1 - limit = params[:limit] || 15 - @my_exercises_count = @current_user_exercises.size - @current_user_exercises = @current_user_exercises.page(page).per(limit) - else - @current_user_exercises = [] - end - end - end - - # 公共题库 - def public_exercises - ActiveRecord::Base.transaction do - if current_user.is_certification_teacher - @user_certification = 1 #用户已通过认证 - @public_exercises = ExerciseBank.find_by_c_type("Exercise").public_exercises - if @public_exercises.present? - if params[:search].present? - search_type = params[:search].to_s.strip - @public_exercises = @public_exercises.exercise_bank_search(search_type) - end - page = params[:page] || 1 - limit = params[:limit] || 15 - @public_exercises_count = @public_exercises.size - @public_exercises = @public_exercises.page(page).per(limit) - else - @public_exercises_count = 0 - @public_exercises = [] - end - else - @user_certification = 0 #用户未通过认证 - @public_exercises_count = 0 - @public_exercises = [] - end - end - end - - #立即发布的弹窗内容 - def publish_modal - - ActiveRecord::Base.transaction do - exercise_ids = params[:check_ids] - if exercise_ids.count > 0 - @course_groups = get_user_permission_course(exercise_ids, 1) - else - @course_groups = [] - end - end - end - - # 详情页的立即发布弹框 - def publish_groups - @current_user = current_user - # 可立即发布的分班:当前用户管理的分班去除已发布的分班 - group_ids = @course.charge_group_ids(@current_user) - @exercise.exercise_group_settings.exercise_group_published.pluck(:course_group_id) - @course_groups = @course.course_groups.where(id: group_ids) - @group_settings = @exercise.exercise_group_settings.where(course_group_id: group_ids) - end - - #首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。 - def publish - group_ids = params[:group_ids]&.reject(&:blank?) - if params[:detail].blank? - tip_exception("缺少截止时间参数") if params[:end_time].blank? - tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) - tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) - else - group_end_times = params[:group_end_times].reject(&:blank?).map {|time| time.to_time} - tip_exception("缺少截止时间参数") if group_end_times.blank? - tip_exception("截止时间和分班参数的个数不一致") if group_end_times.length != group_ids.length - group_end_times.each do |time| - tip_exception("分班截止时间不能早于当前时间") if time <= Time.now - tip_exception("分班截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if @course.end_date.present? && time > @course.end_date.end_of_day - end - end - - ActiveRecord::Base.transaction do - check_ids = Exercise.where(id: params[:check_ids]) - ex_end_time = params[:end_time].blank? ? Time.at(((1.month.since.to_i) / 3600.0).ceil * 3600) : params[:end_time].to_time - check_ids.each do |exercise| - if exercise.present? - if exercise.unified_setting - ex_status = exercise.exercise_status #则为试卷的状态 - else - ex_status = @course.course_groups.where(id: params[:group_ids]).size != - exercise.exercise_group_settings.where(course_group_id: params[:group_ids]).exercise_group_published.size ? 1 : 0 - end - if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过 - g_course = group_ids #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改 - tiding_group_ids = g_course - if g_course - user_course_groups = @course.course_groups.pluck(:id) - if g_course.map(&:to_i).sort == user_course_groups.sort && - ((params[:detail] && group_end_times.min == group_end_times.max) || params[:detail].blank?) # 如果是设置为全部班级,则试卷不用分组,且试卷设定为统一设置,否则则分组设置 - exercise.exercise_group_settings.destroy_all - ex_unified = true - e_time = params[:detail] ? group_end_times.max : ex_end_time - tiding_group_ids = [] - else - ex_unified = false - g_course.each_with_index do |i, index| - exercise_group_setting = exercise.exercise_group_settings.find_in_exercise_group("course_group_id", i).first #根据课堂分班的id,寻找试卷所在的班级 - group_end_time = params[:detail] ? group_end_times[index] : ex_end_time - if exercise_group_setting.present? #如果该试卷分组存在,则更新,否则新建 - exercise_group_setting.update!(publish_time: Time.now, end_time: group_end_time) - else - p_course_group = { - :exercise_id => exercise.id, - :course_group_id => i, - :course_id => exercise.course.id, - :publish_time => Time.now, - :end_time => group_end_time, - } - new_exercise_group = exercise.exercise_group_settings.new p_course_group - new_exercise_group.save! - end - end - # group_ids = params[:group_ids] - e_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time).max - end - else - exercise.exercise_group_settings.destroy_all - ex_unified = true - e_time = ex_end_time - end - - ex_status = set_exercise_status(Time.now, e_time) - exercise_params = { - :publish_time => Time.now, - :end_time => e_time, - :exercise_status => ex_status, - :unified_setting => ex_unified - } - exercise.update!(exercise_params) - - if exercise.course_acts.size == 0 - exercise.course_acts << CourseActivity.new(:user_id => exercise.user_id, :course_id => exercise.course_id) - end - ExercisePublishNotifyJob.perform_later(exercise.id, tiding_group_ids) - end - end - end - normal_status(0, "试卷发布成功!") - end - end - - #立即截止的弹窗内容 - def end_modal - ActiveRecord::Base.transaction do - exercise_ids = params[:check_ids] - if exercise_ids.count > 0 - @course_groups = get_user_permission_course(exercise_ids, 3) - else - @course_groups = [] - end - end - end - - # 首页批量或单独 立即截止,截止时间为当前时间 - def end_exercise - - ActiveRecord::Base.transaction do - check_ids = Exercise.where(id: params[:check_ids]) - course_students = @course.students #课堂的全部学生数 - check_ids.each do |exercise| - exercise_status = exercise.get_exercise_status(current_user) - if exercise_status == Exercise::PUBLISHED #跳过已截止的或未发布的 - g_course = params[:group_ids] - if g_course.present? - teacher_course_group_ids = @course.charge_group_ids(current_user) - all_course_group_ids = @course.course_groups.pluck(:id) - if exercise.unified_setting && g_course.map(&:to_i).sort == all_course_group_ids.sort #开始为统一设置 - exercise.exercise_group_settings.destroy_all - new_ex_status = set_exercise_status(exercise.publish_time, Time.now) - exercise.update!(:end_time => Time.now, :exercise_status => new_ex_status) - exercise_users = exercise.exercise_users - else - course_members_ids = course_students.course_find_by_ids("course_group_id", g_course).pluck(:user_id).uniq #该班级的全部学生 - exercise_users = exercise.exercise_users.exercise_commit_users(course_members_ids) #参与答题的学生数 - ex_group_setting = exercise.exercise_group_settings - old_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", g_course) #试卷的分组设置 - left_course_groups = teacher_course_group_ids - g_course - left_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", left_course_groups) - if left_exercise_groups.blank? && exercise.unified_setting - if left_course_groups.size > 0 #开始为统一设置,但是立即截止为分班。则创建没有立即截止的班级的exercise_group_setting - left_course_groups.each do |g| - ex_group_options = { - :exercise_id => exercise.id, - :course_group_id => g, - :course_id => @course.id, - :publish_time => exercise.publish_time, - :end_time => exercise.end_time - } - ExerciseGroupSetting.create!(ex_group_options) - end - end - end - if old_exercise_groups.present? - old_exercise_groups.update_all(:end_time => Time.now) - else - g_course.each do |g| - ex_group_options = { - :exercise_id => exercise.id, - :course_group_id => g, - :course_id => @course.id, - :publish_time => exercise.publish_time, - :end_time => Time.now - } - ExerciseGroupSetting.create!(ex_group_options) - end - end - new_end_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time) # 试卷结束时间不为空的 - new_end_time_s = new_end_time.count > 0 ? new_end_time.max : Time.now - new_ex_status = set_exercise_status(exercise.publish_time, new_end_time_s) - exercise.update!(:end_time => new_end_time_s, :exercise_status => new_ex_status, :unified_setting => false) - end - else - exercise_users = exercise.exercise_users - exercise.update!(:exercise_status => 3, :end_time => Time.now, :unified_setting => true) - end - - ex_user_ids = exercise_users.pluck(:id) - - EndExerciseCalculateJob.perform_later(ex_user_ids, exercise, Time.now.to_s) - # exercise_users.each do |user| - # if user.commit_status == 0 && user.start_at.present? - # objective_score = calculate_student_score(exercise,user.user)[:total_score] - # user_sub_score = user.subjective_score - # subjective_score = user_sub_score < 0.0 ? 0.0 : user_sub_score - # total_score = objective_score + subjective_score - # commit_option = { - # :status => 1, - # :commit_status => 1, - # :end_at => Time.now, - # :objective_score => objective_score, - # :score => total_score, - # :subjective_score => user_sub_score - # } - # user.update_attributes(commit_option) - # end - # end - end - end - normal_status(0, "试卷截止成功!") - end - end - - #学生撤销回答 - def cancel_exercise - ActiveRecord::Base.transaction do - ex_question_ids = @exercise.exercise_questions.pluck(:id) - exercise_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first - if exercise_user.present? - if exercise_user.commit_status == 1 && @exercise.get_exercise_status(current_user) == Exercise::PUBLISHED #用户已提交且试卷提交中 - if @exercise.time == -1 || ((Time.now.to_i - exercise_user.start_at.to_i) < @exercise.time.to_i * 60) - exercise_user.update!(:score => nil, :end_at => nil, :status => nil, :commit_status => 0, - :objective_score => 0.0, :subjective_score => -1.0) - exercise_user.user.exercise_shixun_answers.search_shixun_answers("exercise_question_id", ex_question_ids).destroy_all - exercise_answers = exercise_user.user.exercise_answers.search_answer_users("exercise_question_id", ex_question_ids) - exercise_answers.update_all(:score => -1.0) - all_answer_comment = ExerciseAnswerComment.search_answer_comments("exercise_question_id", ex_question_ids) - .search_answer_comments("exercise_answer_id", exercise_answers.pluck(:id)) - all_answer_comment.destroy_all - normal_status(0, "撤销回答成功") - else - normal_status(-1, "用户答题时间已到") - end - else - normal_status(-1, "用户未提交/试卷不是提交中") - end - else - normal_status(-1, "当前用户未答题") - end - end - end - - #打回重做modal - def redo_modal - ActiveRecord::Base.transaction do - #搜索 - if params[:realname].present? - search_name = params[:realname] - #搜索用户的nickname,如果存在则返回,否则继续查询用户的真实姓名或学生号 - @exercise_users = @exercise_users.includes(:user).where("LOWER(concat(users.lastname, users.firstname)) like ?", - "%#{search_name}%") - end - if params[:student_id].present? - search_st_id = params[:student_id].to_i - @exercise_users = @exercise_users.includes(user: [:user_extension]) - .where('user_extensions.student_id like ?', "%#{search_st_id}%") - end - sort = params[:sort] ? params[:sort] : "asc" - @exercise_users = @exercise_users.order("score #{sort}") - @exercise_users_size = @exercise_users.size - # 分页 - page = params[:page] || 1 - limit = params[:limit] || 15 - @exercise_users = @exercise_users.page(page).per(limit) - end - end - - #打回重做确认 - def redo_exercise - ActiveRecord::Base.transaction do - user_ids = params[:user_ids] - if user_ids.present? - redo_option = { - :score => 0.0, - :start_at => nil, - :end_at => nil, - :status => nil, - :commit_status => 0, - :objective_score => 0.0, - :subjective_score => -1.0, - :commit_method => 0 - } - redo_exercise_users = @exercise_users.exercise_commit_users(user_ids) - redo_exercise_users.update_all(redo_option) - exercise_question_ids = @exercise.exercise_questions.pluck(:id).uniq - ExerciseAnswer.search_answer_users("user_id", user_ids) - .search_answer_users("exercise_question_id", exercise_question_ids).destroy_all - ExerciseShixunAnswer.search_shixun_answers("user_id", user_ids) - .search_shixun_answers("exercise_question_id", exercise_question_ids).destroy_all - - normal_status(0, "已成功打回重做!") - else - normal_status(-1, "请选择学生!") - end - end - end - - #学生开始答题页面 - def start_answer - ex_users_current = ExerciseUser.where(user_id: @exercise_current_user_id, exercise_id: @exercise.id) #不能用@exercise.exercise_users,因为exercise_users删除时,只是状态改变,未删除 - @exercise_user_current = ex_users_current&.first - if ex_users_current.exists? - if @exercise_user_current.start_at.blank? - @exercise_user_current.update!(start_at: Time.now) - end - else - if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候,不创建exercise_user表,理论上老师是不能进入答题的 - exercise_user_params = { - :user_id => @exercise_current_user_id, - :exercise_id => @exercise.id, - :start_at => Time.now - } - exercise_user_current = ExerciseUser.new(exercise_user_params) - exercise_user_current.save! - end - end - @t_user_exercise_status = @exercise.get_exercise_status(current_user) - - @user_left_time = nil - if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) || - (ex_users_current.exists? && @exercise_user_current.commit_status == 1) - @user_exercise_status = 1 #当前用户为老师/试卷已截止/试卷已提交不可编辑 - else - @user_left_time = get_exercise_left_time(@exercise, current_user) - @user_exercise_status = 0 #可编辑 - end - - @exercise_questions = @exercise.exercise_questions - - if @exercise.question_random - @exercise_questions = @exercise_questions.order("RAND()") - else - @exercise_questions = @exercise_questions.order("question_number ASC") - end - # 判断问题是否已回答还是未回答 - @exercise_questions = @exercise_questions.includes(:exercise_shixun_challenges, - :exercise_shixun_answers, - :exercise_answers, - :exercise_standard_answers) - - if @t_user_exercise_status == Exercise::DEADLINE - get_each_student_exercise(@exercise.id, @exercise_questions, @exercise_current_user_id) - end - get_user_answer_status(@exercise_questions, @exercise_current_user_id, @exercise, @t_user_exercise_status) - - end - - #提交试卷前的弹窗 - def begin_commit - ActiveRecord::Base.transaction do - if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时 - @exercise_questions = @exercise.exercise_questions - @shixun_undo = 0 - @ques_undo = 0 - ex_answer_time = @exercise.time.to_i - if ex_answer_time > 0 #有剩余时间的时候 - user_left_time = get_exercise_left_time(@exercise, current_user) - @ex_end_time = Time.now + user_left_time.to_i.seconds - else - @ex_end_time = @exercise.get_exercise_end_time(current_user.id) - end - # @ex_end_time = @exercise.get_exercise_end_time(current_user.id) - # if ex_answer_time > 0 - # left_answer_time = Time.now + ex_answer_time.minutes #判断试卷的倒计时和截止时间哪个先到 - # if left_answer_time < @ex_end_time - # exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id) - # if exercise_end_time.present? - # ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at - # @ex_end_time = ex_end_times + ex_answer_time.minutes - # end - # end - # end - @exercise_questions.each do |q| - if q.question_type == Exercise::PRACTICAL #当为实训题时 - user_myshixun = q.shixun.myshixuns.search_myshixun_user(current_user.id) - if user_myshixun.blank? || user_myshixun.first.status != Exercise::UNPUBLISHED #当前用户的实训是否做完 - @shixun_undo += 1 - end - else - ques_vote = q.exercise_answers.search_exercise_answer("user_id", current_user.id) - if ques_vote.blank? - @ques_undo += 1 - end - end - end - end - end - end - - # 学生提交试卷 - def commit_exercise - tip_exception(0, "试卷截止时间已到,系统已自动提交") if @answer_committed_user.commit_status == 1 - ActiveRecord::Base.transaction do - can_commit_exercise = false - user_left_time = nil - if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时 - if params[:commit_method].to_i == 2 #自动提交时 - user_left_time = get_exercise_left_time(@exercise, current_user) - Rails.logger.info("######__________auto_commit_user_left_time_________################{user_left_time}") - if user_left_time.to_i <= 0 - can_commit_exercise = true - end - else - can_commit_exercise = true - end - if can_commit_exercise - objective_score = calculate_student_score(@exercise, current_user, Time.now)[:total_score] - subjective_score = @answer_committed_user.subjective_score - total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score - total_score = objective_score + total_score_subjective_score - commit_option = { - :status => 1, - :commit_status => 1, - :end_at => Time.now, - :objective_score => objective_score, - :score => total_score, - :subjective_score => subjective_score, - :commit_method => @answer_committed_user&.commit_method.to_i > 0 ? @answer_committed_user&.commit_method.to_i : params[:commit_method].to_i - } - @answer_committed_user.update!(commit_option) - CommitExercsieNotifyJobJob.perform_later(@exercise.id, current_user.id) - normal_status(0, "试卷提交成功!") - else - normal_status(-2, "#{user_left_time.to_i}") - end - else - normal_status(-1, "提交失败,当前用户不为课堂学生!") - end - end - end - - #教师评阅试卷 及学生查看试卷 - def review_exercise - ActiveRecord::Base.transaction do - # 1 老师权限,0 学生权限 - @is_teacher_or = (@user_course_identity < Course::STUDENT) ? 1 : 0 - @student_status = 2 - @exercise_questions = @exercise.exercise_questions.includes(:exercise_shixun_challenges, :exercise_standard_answers, :exercise_answers, :exercise_shixun_answers, :exercise_answer_comments).order("question_number ASC") - @question_status = [] - get_exercise_status = @exercise.get_exercise_status(current_user) #当前用户的试卷状态 - @ex_answer_status = @exercise.get_exercise_status(@ex_user&.user) #当前试卷用户的试卷状态 - if @ex_user.present? && @is_teacher_or == 0 - if get_exercise_status == Exercise::PUBLISHED #当前用户已提交,且试卷未截止 - if @ex_user.commit_status == 0 #学生未提交,且当前为学生 - @student_status = 0 - else - @student_status = 1 - get_user_answer_status(@exercise_questions, @exercise_current_user_id, @exercise, get_exercise_status) - end - end - end - if @student_status == 2 - get_each_student_exercise(@exercise.id, @exercise_questions, @exercise_current_user_id) - end - end - end - - #答题列表 - def exercise_lists - @current_user_id = current_user.id - exercise_ids = [@exercise.id] - @exercise_status = @exercise.get_exercise_status(current_user) - @course_all_members = @course.students - @c_group_counts = @course.course_groups_count - question_types = @exercise.exercise_questions.pluck(:question_type).uniq - @exercise_publish_count = get_user_permission_course(exercise_ids, Exercise::PUBLISHED).count #判断是否有已发布的分班 - @exercise_unpublish_count = get_user_permission_course(exercise_ids, Exercise::UNPUBLISHED).count #判断是否有未发布的分班 - - if (question_types.size > 1) && question_types.include?(Exercise::SUBJECTIVE) #是否包含主观题,或者是否大于1 - @subjective_type = 1 - else - @subjective_type = 0 - end - - #初始化值 - @exercise_users_list = [] #答题用户列表 - @exercise_course_groups = [] #当前用户有权限的班级 - @exercise_unanswers = 0 # 未答用户数 - @exercise_answers = 0 #已答用户数 - @exercise_users_count = 0 #全部用户数 - @teacher_review_count = 0 #已评数 - @teacher_unreview_count = 0 #未评数 - - #试卷的答题列表页的显示用户 - if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的试卷 - @exercise_current_user_status = 0 - unless @exercise_status == Exercise::UNPUBLISHED - ex_common_ids = @exercise.common_published_ids(current_user.id) - @exercise_course_groups = @course.get_ex_published_course(ex_common_ids) - @exercise_users_list = @exercise.all_exercise_users(current_user.id) #当前老师所在班级的全部学生 - get_exercise_answers(@exercise_users_list, @exercise_status) - end - else #当前为学生或者有过答题的 - @ex_user_end_time = @exercise.get_exercise_end_time(current_user.id) #当前用户所看到的剩余时间 - @exercise_all_users = @exercise.get_stu_exercise_users - get_exercise_answers(@exercise_all_users, @exercise_status) # 未答和已答的 - exercise_current_user = @exercise_all_users.exercise_commit_users(current_user.id) - if exercise_current_user.exists? #表示为课堂学生或已回答的 - @exercise_current_user_status = 1 - if @exercise.score_open && @exercise_status == Exercise::DEADLINE #勾选了成绩公开且试卷已截止的 - all_user_ids = @exercise_all_users.pluck(:user_id) - all_user_ids.delete(current_user.id) #删除了当前用户的ID - @exercise_users_list = @exercise_all_users.exercise_commit_users(all_user_ids).distinct - @current_user_ex_answers = exercise_current_user #当前用户的回答 - else - @exercise_users_list = exercise_current_user - end - else #表示为未回答的,或未非课堂成员的 - @exercise_current_user_status = 2 #当前用户非课堂成员 - end - end - - if @exercise_unanswers < 0 - @exercise_unanswers = 0 - end - - #筛选/分类,排序 - order = params[:order] - order_type = params[:order_type] || "desc" - - if @exercise_users_list.present? && @exercise_users_list.size > 0 - @exercise_users_count = @exercise_users_list.size #当前显示的全部成员数量 - teacher_reviews = @exercise_users_list.exercise_review - teacher_unreviews = @exercise_users_list.exercise_unreview - @teacher_review_count = teacher_reviews.size #已评阅 - @teacher_unreview_count = teacher_unreviews.size #未评阅 - - #是否评阅 - if params[:review].present? - review_type = params[:review].first.to_i #已评,则数据为1,未评,则数据为0,前端传过来的为数组 - if review_type == 1 - @exercise_users_list = teacher_reviews - else - @exercise_users_list = teacher_unreviews - end - end - - #答题状态的选择 - if params[:commit_status].present? - choose_type = params[:commit_status] - @exercise_users_list = @exercise_users_list.commit_exercise_by_status(choose_type) - end - - #班级的选择 - if params[:exercise_group_id].present? - group_id = params[:exercise_group_id] - exercise_students = @course_all_members.course_find_by_ids("course_group_id", group_id) #试卷所分班的全部人数 - user_ids = exercise_students.pluck(:user_id).reject(&:blank?) - @exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids) - end - - #搜索 - if params[:search].present? - @exercise_users_list = @exercise_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") - end - - exercise_user_joins = @exercise_users_list.joins(user: :user_extension) - - if order == "student_id" - @exercise_users_list = exercise_user_joins.order("user_extensions.student_id #{order_type}") - elsif order == "score" - @exercise_users_list = exercise_user_joins.order("#{order} #{order_type}") - else - @exercise_users_list = exercise_user_joins.order("end_at #{order_type}, start_at #{order_type}") - end - - @export_ex_users = @exercise_users_list - - @exercise_users_size = @exercise_users_list.size - - # 分页 - @page = params[:page] || 1 - @limit = params[:limit] || 20 - @exercise_users_list = @exercise_users_list.page(@page).per(@limit) - else - @exercise_users_list = [] - @export_ex_users = @exercise_users_list - @exercise_users_size = 0 - end - - if params[:format] == "xlsx" - if @user_course_identity > Course::ASSISTANT_PROFESSOR - tip_exception(403, "无权限操作") - elsif @exercise_status == Exercise::UNPUBLISHED - normal_status(-1, "试卷未发布") - elsif (@exercise_users_size == 0) || (@export_ex_users&.exercise_user_committed.size == 0) - normal_status(-1, "暂无用户提交") - elsif params[:export].present? && params[:export] - normal_status(0, "正在下载中") - else - respond_to do |format| - format.xlsx { - set_export_cookies - get_export_users(@exercise, @course, @export_ex_users) - exercise_export_name_ = - "#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" - render xlsx: "#{exercise_export_name_.strip}", template: "exercises/exercise_lists.xlsx.axlsx", locals: {table_columns: @table_columns, exercise_users: @user_columns} - } - end - end - end - end - - #导出空白试卷 - def export_exercise - @request_url = request.base_url - @exercise_questions = @exercise.exercise_questions.includes(:exercise_choices).order("question_number ASC") - filename_ = "#{@exercise.user.real_name}_#{@course.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.pdf" - stylesheets = "#{Rails.root}/app/templates/exercise_export/exercise_export.css" - if params[:export].present? && params[:export] - normal_status(0, "正在下载中") - else - set_export_cookies - render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets, disposition: 'inline', type: "pdf_attachment.content_type", stream: false - end - end - - #空白试卷预览页面,仅供测试使用,无其他任何用途 - # def blank_exercise - # ActiveRecord::Base.transaction do - # begin - # @exercise_questions = @exercise.exercise_questions.order("question_number ASC") - # challenge_ids = @exercise_questions.joins(:exercise_shixun_challenges).pluck("exercise_shixun_challenges.challenge_id") - # get_each_student_exercise(@exercise.id,@exercise_questions,31798) - # @games = @exercise_user.user.games.ch_games(challenge_ids) - # respond_to do |format| - # format.html - # end - # rescue Exception => e - # uid_logger_error(e.message) - # tip_exception("没有权限") - # raise ActiveRecord::Rollback - # end - # end - # end - - #学生的统计结果 - def exercise_result - exercise_ids = [@exercise.id] - @exercise_publish_count = get_user_permission_course(exercise_ids, Exercise::PUBLISHED).size #判断是否有已发布的分班 - @exercise_unpublish_count = get_user_permission_course(exercise_ids, Exercise::UNPUBLISHED).size #判断是否有未发布的分班 - @course_all_members = @course.students #课堂的全部学生 - @exercise_all_users = @exercise.exercise_users - ex_common_ids = @exercise.common_published_ids(current_user.id) - @exercise_course_groups = @course.get_ex_published_course(ex_common_ids) - - #班级的选择 - if params[:exercise_group_id].present? - group_id = params[:exercise_group_id] - exercise_students = @course_all_members.course_find_by_ids("course_group_id", group_id) # 试卷所分班的全部人数 - user_ids = exercise_students.pluck(:user_id).reject(&:blank?) - @exercise_all_users = @exercise.exercise_users.exercise_commit_users(user_ids) - @course_all_members_count = @exercise_all_users.size - else - @exercise_users_list = @exercise.all_exercise_users(current_user.id) - @course_all_members_count = @exercise_users_list.size - end - @exercise_commit_users = @exercise_all_users.commit_exercise_by_status(1) #试卷的已提交用户 - @exercise_commit_user_ids = @exercise_commit_users.pluck(:user_id).uniq #已提交试卷的全部用户id - @exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数 - @exercise_status = @exercise.get_exercise_status(current_user) - - #提交率 - if @course_all_members_count == 0 - commit_percent = 0.00 - min_score = 0.0 - max_score = 0.0 - average_score = 0.0 - fail_counts = 0 - pass_counts = 0 - good_counts = 0 - best_counts = 0 - else - commit_percent = (@exercise_commit_user_counts / @course_all_members_count.to_f).round(3) - exercise_scores = @exercise_commit_users.pluck(:score).reject(&:blank?) - min_score = exercise_scores.min.present? ? exercise_scores.min : 0.0 - max_score = exercise_scores.max.present? ? exercise_scores.max : 0.0 - total_score = exercise_scores.sum.present? ? exercise_scores.sum : 0.0 - average_score = @exercise_commit_user_counts > 0 ? (total_score.round(1) / @exercise_commit_user_counts).round(1) : 0.0 - question_scores = @exercise.question_scores - fail_score = question_scores * 0.6.round(2) - pass_score = question_scores * 0.7.round(2) - good_score = question_scores * 0.9.round(2) - - fail_counts = exercise_scores.count {|a| a < fail_score} - pass_counts = exercise_scores.count {|a| a < pass_score && a >= fail_score} - good_counts = exercise_scores.count {|a| a < good_score && a >= pass_score} - best_counts = exercise_scores.count {|a| a >= good_score && a <= question_scores} - end - @counts_array = { - :commit_percent => commit_percent, - :min_score => min_score.to_s, - :max_score => max_score.to_s, - :average_score => average_score.to_s, - :fail_counts => fail_counts, - :pass_counts => pass_counts, - :good_counts => good_counts, - :best_counts => best_counts, - } - - @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices, :exercise_answers, :exercise_standard_answers, :exercise_shixun_challenges, :exercise_shixun_answers) - - percent_sort = "desc" - - if params[:sort].present? - percent_sort = params[:sort] - end - # @paging_type = "percent" - # # 按题型排序 - # if params[:sort].present? - # @paging_type = params[:sort].to_s - # end - - ques_result_all = exercise_commit_result(@exercise_questions, @exercise_commit_user_ids) - - #默认降序排列 - if percent_sort == "desc" - @question_result_hash = ques_result_all.sort_by {|s| s[:percent]}.reverse - else - @question_result_hash = ques_result_all.sort_by {|s| s[:percent]} - end - - @exercise_questions_count = @exercise_questions.size - @page = params[:page] || 1 - @limit = params[:limit] || 10 - @question_result_hash = Kaminari.paginate_array(@question_result_hash).page(@page).per(@limit) - end - - private - - def exercise_params - params.require(:exercise).permit(:exercise_name, :exercise_description, :course_id, :exercise_status, :user_id, :time, - :publish_time, :end_time, :show_result, :question_random, :choice_random, :is_public, - :score_open, :answer_open, :exercise_bank_id, :unified_setting, :show_statistic) - end - - def is_course_teacher - unless @user_course_identity < Course::STUDENT #为老师/助教/管理员 - normal_status(403, "...") - end - end - - #检查传入的参数内容是否符合 - def validates_exercise_params - normal_status(-1, "试卷标题不能为空!") if params[:exercise_name].blank? - normal_status(-1, "试卷标题不能超过60个字符") if (params[:exercise_name].length > 60) - normal_status(-1, "试卷须知不能超过100个字符") if (params[:exercise_description].present? && - params[:exercise_description].length > 100) - end - - #判断设置的时间是否合理 - def validate_publish_time - # 截止时间存在,且截止时间必须大于当前时间或发布时间 - unified_setting = params[:unified_setting] - publish_course = params[:publish_time_groups] - if @course.is_end - normal_status(-1, "课堂已结束不能再修改") - elsif unified_setting - ex_group_settings = @exercise.exercise_group_settings - if ex_group_settings.present? - p_time_present = ex_group_settings.publish_time_no_null.map(&:publish_time).min - if p_time_present && p_time_present < Time.now - normal_status(-1, "设置失败,存在已发布的分班") - end - elsif params[:publish_time].blank? - normal_status(-1, "发布时间不允许为空") - end - elsif unified_setting.present? && !unified_setting #非统一设置,分班不能为空 - if publish_course.present? - course_ids = publish_course.map {|a| a[:course_group_id]}.sum - publish_t = publish_course.map {|a| a[:publish_time]} - if course_ids.include?(nil) || course_ids.count == 0 - normal_status(-1, "请选择分班") - elsif publish_t.include?(nil) || publish_t.count == 0 - normal_status(-1, "发布时间不允许为空") - end - else - normal_status(-1, "请选择分班") - end - end - end - - def get_exercise - @exercise = Exercise.find_by(id: params[:id]) - if @exercise.blank? - normal_status(404, "试卷不存在") - else - @course = @exercise.course - normal_status(404, "课堂不存在") if @course.blank? - end - end - - def get_exercise_question_counts #获取试卷的问题数及总分数 - exercise_questions = @exercise.exercise_questions - @exercise_ques_count = exercise_questions.size # 全部的题目数 - @exercise_ques_scores = exercise_questions.pluck(:question_score).sum - - #单选题的数量及分数 - exercise_single_ques = exercise_questions.find_by_custom("question_type", Exercise::SINGLE) - @exercise_single_ques_count = exercise_single_ques.size - @exercise_single_ques_scores = exercise_single_ques.pluck(:question_score).sum - - #多选题的数量及分数 - exercise_double_ques = exercise_questions.find_by_custom("question_type", Exercise::MULTIPLE) - @exercise_double_ques_count = exercise_double_ques.size - @exercise_double_ques_scores = exercise_double_ques.pluck(:question_score).sum - - # 判断题数量及分数 - exercise_ques_judge = exercise_questions.find_by_custom("question_type", Exercise::JUDGMENT) - @exercise_ques_judge_count = exercise_ques_judge.size - @exercise_ques_judge_scores = exercise_ques_judge.pluck(:question_score).sum - - #填空题数量及分数 - exercise_ques_null = exercise_questions.find_by_custom("question_type", Exercise::COMPLETION) - @exercise_ques_null_count = exercise_ques_null.size - @exercise_ques_null_scores = exercise_ques_null.pluck(:question_score).sum - - #简答题数量及分数 - exercise_ques_main = exercise_questions.find_by_custom("question_type", Exercise::SUBJECTIVE) - @exercise_ques_main_count = exercise_ques_main.size - @exercise_ques_main_scores = exercise_ques_main.pluck(:question_score).sum - - #实训题数量及分数 - exercise_ques_shixun = exercise_questions.find_by_custom("question_type", Exercise::PRACTICAL) - @exercise_ques_shixun_count = exercise_ques_shixun.size - @exercise_ques_shixun_scores = exercise_ques_shixun.pluck(:question_score).sum - - @exercise_questions = @exercise_questions&.includes(:exercise_choices, :exercise_shixun_challenges, :exercise_answers, :exercise_shixun_answers, :exercise_answer_comments, :exercise_standard_answers) - - end - - #获取用户有权限的分班 - def get_user_permission_course(exercise_ids, status) - exercise_status = status.to_i #传入的试卷发布状态 - unpublish_group = [] - course_groups = [] - user_groups_id = @course.charge_group_ids(current_user) - exercises_all = Exercise.includes(:exercise_group_settings).where(id: exercise_ids) - exercises_all.each do |exercise| - if exercise.present? - if exercise.unified_setting #统一设置只有两种情况,全部发布,全部截止 - exercise_user_status = exercise.get_exercise_status(current_user) #当前用户的能看到的试卷 - if (exercise_user_status == exercise_status) || exercise_status == Exercise::DEADLINE #未发布的情况 - unpublish_group = unpublish_group + user_groups_id - end - else - ex_all_group_settings = exercise.exercise_group_settings - ex_group_settings = ex_all_group_settings.exercise_group_published.pluck(:course_group_id).uniq #问卷设置的班级 - if exercise_status == Exercise::UNPUBLISHED - unpublish_group = user_groups_id - ex_group_settings - elsif exercise_status == Exercise::DEADLINE - ex_ended_groups = ex_all_group_settings.exercise_group_ended.pluck(:course_group_id).uniq - ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班 - unpublish_group = unpublish_group + ex_and_user - ex_ended_groups #已发布的全部班级减去截止的全部班级 - else - ex_ended_groups = ex_all_group_settings.exercise_group_ended.pluck(:course_group_id).uniq - ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班 - unpublish_group = unpublish_group + ex_and_user - ex_ended_groups - end - end - end - end - Rails.logger.info("#####____________unpublish_group_______#######{unpublish_group}") - unpublish_group = unpublish_group.uniq - if unpublish_group.count > 0 - course_groups = CourseGroup.by_group_ids(unpublish_group) - end - course_groups - end - - def set_exercise_status(publish_time, end_time) - time_now_i = Time.now - if publish_time.present? && (publish_time <= time_now_i) && (end_time > time_now_i) - 2 - elsif publish_time.nil? || (publish_time.present? && publish_time > time_now_i) - 1 - elsif end_time.present? && (end_time <= time_now_i) - 3 - elsif end_time.present? && publish_time.present? && (end_time < publish_time) - normal_status(-1, "时间设置错误!") - else - 1 - end - end - - def check_course_public - unless @course.is_public == 1 # 0为私有,1为公开 - normal_status(403, "...") - end - end - - def check_user_id_start_answer #判断用户在开始答题时,是否有用户id传入,如果为老师,则id必需,否则为当前用户的id - user_login = params[:login] - if user_login.blank? && @user_course_identity < Course::STUDENT #id不存在,且当前为老师/管理员等 - normal_status(-1, "请输入学生登陆名!") - else - if @user_course_identity < Course::STUDENT || @exercise.score_open - @ex_answerer = user_login.blank? ? current_user : User.find_by(login: user_login) - else - @ex_answerer = current_user - end - - if @ex_answerer.blank? - normal_status(404, "答题用户不存在") - elsif @user_course_identity > Course::STUDENT && !@exercise.is_public - normal_status(403, "非公开试卷") - else - # @exercise_current_user_id = @ex_answerer.id || current_user.id - @exercise_current_user_id = @ex_answerer.id - end - end - end - - ## 判断开始答题页面的用户权限 - def check_user_on_answer - if @user_course_identity == Course::STUDENT && @exercise.get_exercise_status(current_user) == Exercise::UNPUBLISHED #试卷未发布,且当前用户不为老师/管理员 - normal_status(-1, "未发布试卷!") - elsif @user_course_identity > Course::STUDENT && (!@exercise.is_public || (@exercise.is_public && !@exercise.unified_setting)) ##不为课堂成员,且试卷不为公开的,或试卷公开,但不是统一设置的 - normal_status(-1, "试卷暂未公开!") - end - end - - def check_exercise_time - @answer_committed_user = @exercise.exercise_users.exercise_commit_users(current_user.id)&.first - if @answer_committed_user.blank? - normal_status(404, "答题用户不存在") - end - end - - #打回重做时的初步判断 - def check_exercise_status - @exercise_users = @exercise.all_exercise_users(current_user.id).commit_exercise_by_status(1) #当前教师所在分班的全部已提交的学生数 - if @exercise.get_exercise_status(current_user) != Exercise::PUBLISHED - normal_status(-1, "非提交中的试卷不允许打回重做!") - elsif @exercise_users.count < 1 - normal_status(-1, "暂无人提交试卷!") - end - end - - - #查看试题页面,当为学生时,除非试卷已截止,或已提交才可以查看 - def check_exercise_is_end - ex_status = @exercise.get_exercise_status(current_user) - @ex_user = @exercise.exercise_users.find_by(user_id: @exercise_current_user_id) #该试卷的回答者 - if @user_course_identity > Course::ASSISTANT_PROFESSOR - if ex_status == Exercise::UNPUBLISHED - normal_status(-1, "试卷未发布") - elsif @ex_user.present? && @ex_user.commit_status == 0 - normal_status(-1, "试卷未提交") - elsif params[:user_id].present? && current_user.id != params[:user_id] - normal_status(-1, "不能查看他人的试卷") - end - end - end - - #查看试卷是否选择为公开统计 - def check_exercise_public - if @user_course_identity > Course::ASSISTANT_PROFESSOR #当前为学生,试卷公开统计,且已截止,且已提交 - ex_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first - unless @exercise.get_exercise_status(current_user) == Exercise::DEADLINE && ex_user.present? && ex_user.commit_status == 1 && - @exercise.show_statistic - normal_status(-1, "学生暂不能查看") - end - end - end - - def get_left_banner_id - left_banner_content = @course.course_modules.search_by_module_type("exercise") - if left_banner_content.present? - @left_banner_id = left_banner_content.first.id - @left_banner_name = left_banner_content.first.module_name - else - normal_status(404, "左侧导航不存在") - end - end - - def get_user_answer_status(exercise_questions, user_id, exercise, exercise_user_status) - @question_status = [] - @exercise_all_questions = [] - ex_question_random = exercise.question_random - question_answered = 0 - exercise_questions.each_with_index do |q, index| - if ex_question_random && exercise_user_status != Exercise::DEADLINE - ques_number = index + 1 - else - ques_number = q.question_number - end - ques_status = 0 - if q.question_type != Exercise::PRACTICAL - ques_vote = q.exercise_answers.select {|answer| answer.user_id == user_id} - - if ques_vote.present? - #其他题目,需回答的有内容,才会为已答,否则如内容为空,视为未答 - vote_answer_id = ques_vote.pluck(:exercise_choice_id).reject(&:blank?) - vote_text_count = ques_vote.pluck(:answer_text).reject(&:blank?).size - if q.question_type <= Exercise::JUDGMENT #选择题和判断题的时候,需要有选项,才算回答 - if vote_answer_id.size > 0 - ques_status = 1 - question_answered += 1 - end - else - if vote_text_count > 0 #主观题,必选有内容,才算回答 - ques_status = 1 - question_answered += 1 - end - end - end - else - if Myshixun.exists?(user_id: user_id, shixun_id: q.shixun_id) - ques_status = 1 - question_answered += 1 - end - end - question_status = { - :ques_id => q.id, - :ques_number => ques_number, #仅问题的显示位置变化,但是问题的question_number 不会变化,与之相关的choice/standard_answer/answer不会变化 - :ques_status => ques_status, - } - question_options = { - :question => q, - :ques_number => ques_number, - } - @question_status = @question_status.push(question_status).sort_by {|k| k[:ques_number]} - @exercise_all_questions = @exercise_all_questions.push(question_options).sort_by {|k| k[:ques_number]} - end - end - - #下一步也有check_on_users再进行判断 - def only_student_in - if @user_course_identity < Course::STUDENT - normal_status(-1, "老师身份不允许进入") - end - end - - #判断实训是否已选择 - def commit_shixun_present - question_shixun_ids = @exercise.exercise_questions.pluck(:shixun_id).reject(&:blank?) - shixun_id = params[:shixun_id] - @shixun = Shixun.find_by(id: shixun_id) - if shixun_id.present? && question_shixun_ids.include?(shixun_id) - normal_status(-1, "该实训已选择!") - elsif @shixun.blank? - normal_status(-1, "该实训不存在!") - end - end - - end @exercise_questions_count = @exercise_questions.size @page = params[:page] || 1 From e581771ec14286db7fbf3469cf761e27feafad4a Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sat, 11 Jan 2020 17:33:04 +0800 Subject: [PATCH 27/55] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E7=9A=84=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/message_detail.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/message_detail.rb b/app/models/message_detail.rb index 9f5269bc5..d589ada3e 100644 --- a/app/models/message_detail.rb +++ b/app/models/message_detail.rb @@ -1,5 +1,5 @@ class MessageDetail < ApplicationRecord belongs_to :message, :touch => true - validates :content, length: { maximum: 5000, too_long: "内容不能超过5000个字符" } + validates :content, length: { maximum: 10000, too_long: "内容不能超过10000个字符" } end From 7ecac799d550d10bf5073187efad636e821a4006 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sat, 11 Jan 2020 17:50:47 +0800 Subject: [PATCH 28/55] =?UTF-8?q?=E7=BF=BB=E8=BD=AC=E8=AF=BE=E5=A0=82?= =?UTF-8?q?=EF=BC=9A=E5=85=AC=E5=BC=80=E8=AF=BE=EF=BC=8C=E5=AF=B9=E4=BA=8E?= =?UTF-8?q?=E9=9D=9E=E8=AF=BE=E5=A0=82=E6=88=90=E5=91=98=E4=B8=8D=E5=85=81?= =?UTF-8?q?=E8=AE=B8=E6=9F=A5=E7=9C=8B=E6=95=99=E5=B8=88=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E3=80=81=E5=AD=A6=E7=94=9F=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/courses_controller.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 753a3d942..0a6e95470 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -394,6 +394,7 @@ class CoursesController < ApplicationController # 教师列表以及教师搜索 def teachers + tip_exception(403, "无权限访问") if @course.excellent && @user_course_identity > Course::ASSISTANT_PROFESSOR @search_str = params[:search].present? ? params[:search].strip : "" if @course.try(:id) != 1309 || current_user.admin_or_business? || current_user.try(:id) == 15582 @@ -850,6 +851,8 @@ class CoursesController < ApplicationController # 学生列表(包括各个子分班的学生列表)及搜索 def students + tip_exception(403, "无权限访问") if @course.excellent && @user_course_identity > Course::ASSISTANT_PROFESSOR + search = params[:search].present? ? params[:search].strip : nil order = params[:order].present? ? params[:order].to_i : 1 sort = params[:sort].present? ? params[:sort] : "asc" From be4a2102fcf720e62c83d228c03b4c916bbc9a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Sat, 11 Jan 2020 19:19:23 +0800 Subject: [PATCH 29/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/AppConfig.js | 2 +- .../tasks/GraduationTasksappraiseMainEditor.js | 18 ++++++++++++++---- .../Challenges/Challengesjupyter.js | 14 ++++++++------ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index 12e0043d5..02d554806 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -42,7 +42,7 @@ if (isDev) { // 老师 //debugType="teacher"; // 学生 -//debugType="student"; +debugType="student"; function railsgettimes(proxy) { diff --git a/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js b/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js index ec6979c19..376a45eb8 100644 --- a/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js +++ b/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js @@ -20,7 +20,8 @@ class GraduationTasksappraiseMainEditor extends Component{ score: undefined, same_score: false, errorMessage: '', - numberErrorMessage: '' + numberErrorMessage: '', + errorMessagetype:false } } onSubmit = () => { @@ -37,7 +38,10 @@ class GraduationTasksappraiseMainEditor extends Component{ return; } if (!score && this.props.isAdmin()===false) { - this.setState( {errorMessage : '分数不能同时为空' }) + this.setState( { + errorMessage : '分数不能同时为空', + errorMessagetype:true + }) // this.props.showNotification('请先输入评阅说明') return; } @@ -142,6 +146,12 @@ class GraduationTasksappraiseMainEditor extends Component{ }); } onScoreChange = (val) => { + if(val){ + this.setState( { + errorMessage: '', + errorMessagetype:false + }) + } if (val > 100 ) { this.props.showNotification('不能大于100') this.setState({ score: 100 }) @@ -163,7 +173,7 @@ class GraduationTasksappraiseMainEditor extends Component{ this.setState({ same_score: e.target.checked }) //!this.state.same_score } render(){ - let { total_count, comments, pageCount, fileList, score, same_score, errorMessage, numberErrorMessage } = this.state + let { total_count, comments, errorMessagetype, fileList, score, same_score, errorMessage, numberErrorMessage } = this.state const { current_user, memo, showSameScore, placeholder } = this.props const isAdmin = this.props.isAdmin() const commentUploadProp = { @@ -215,7 +225,7 @@ class GraduationTasksappraiseMainEditor extends Component{ `} {this.props.title && {this.props.title}} + watch={false} height={160} className={errorMessage&&errorMessagetype!=true ? 'editorInputError' : ''} imageExpand={true}> { showSameScore == true &&
整组同评 (选中,则本次评阅对象指小组全部成员,否则仅评阅此成员1人 ) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index 61782d69f..9e50e44d5 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -87,7 +87,7 @@ class Challengesjupyter extends Component { // // } this.setState({ - opentitletype:true, + opentitletype:false, isopentitletype:"greater", boxoffsetHeigh:boxoffsetHeigh }) @@ -646,11 +646,13 @@ class Challengesjupyter extends Component { } {/*this.state.enlarge===false?"":*/} - {this.state.isopentitletype==="Less"?"":this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> - 阅读全文 - :this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> - 收起全文 - } + {/*{this.state.isopentitletype==="Less"?"":this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}>*/} + {/* 阅读全文 */} + {/*:this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}>*/} + {/* 收起全文 */} + {/*}*/} + +

From c9bc9fbe1e5299b8ae2625b49e2a7efa283931b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Sat, 11 Jan 2020 19:19:45 +0800 Subject: [PATCH 30/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../graduation/tasks/GraduationTasksappraiseMainEditor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js b/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js index 376a45eb8..1415414e4 100644 --- a/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js +++ b/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js @@ -39,7 +39,7 @@ class GraduationTasksappraiseMainEditor extends Component{ } if (!score && this.props.isAdmin()===false) { this.setState( { - errorMessage : '分数不能同时为空', + errorMessage : '分数不能为空', errorMessagetype:true }) // this.props.showNotification('请先输入评阅说明') From 2ec0ffc1dbd95d6f9678414276d264be6ab93009 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sat, 11 Jan 2020 19:34:40 +0800 Subject: [PATCH 31/55] =?UTF-8?q?=E5=B8=96=E5=AD=90=E6=8A=9B=E5=BC=82?= =?UTF-8?q?=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/messages_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 2b9d9d69f..0e28ccb4f 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -62,8 +62,8 @@ class MessagesController < ApplicationController end def reply - return normal_status(2, "回复内容不能为空") if params[:content].blank? - return normal_status(2, "回复内容不能超过2000字符") if params[:content].length > 2000 + return normal_status(-1, "回复内容不能为空") if params[:content].blank? + return normal_status(-1, "回复内容不能超过2000字符") if params[:content].length > 2000 @reply = Message.create!(board: @message.board, root_id: @message.root_id || @message.id, author: current_user, parent: @message, message_detail_attributes: { From 0b76c5d64892577e421f36f300369c04cecc51e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Sat, 11 Jan 2020 19:34:49 +0800 Subject: [PATCH 32/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/forums/MemoDetail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/react/src/modules/forums/MemoDetail.js b/public/react/src/modules/forums/MemoDetail.js index 9f3885906..792b24aa9 100644 --- a/public/react/src/modules/forums/MemoDetail.js +++ b/public/react/src/modules/forums/MemoDetail.js @@ -845,7 +845,7 @@ class MemoDetail extends Component {
:
-
写评论1
+
写评论
}
From 079b5bb967bcf8a6e5795983a1554a30ebb8a07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Sat, 11 Jan 2020 19:39:14 +0800 Subject: [PATCH 33/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/tpm/NewHeader.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/public/react/src/modules/tpm/NewHeader.js b/public/react/src/modules/tpm/NewHeader.js index 572389b8a..5ca8e986b 100644 --- a/public/react/src/modules/tpm/NewHeader.js +++ b/public/react/src/modules/tpm/NewHeader.js @@ -1047,17 +1047,17 @@ submittojoinclass=(value)=>{ ` } -
  • - -
    -
    - 题库 -
    -
    -
    -
  • + {/*
  • */} + {/* */} + {/*
    */} + {/*
    */} + {/* 题库*/} + {/*
    */} + {/*
    */} + {/*
    */} + {/*
  • */}
  • Date: Sat, 11 Jan 2020 20:18:52 +0800 Subject: [PATCH 34/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/AppConfig.js | 2 +- public/react/src/context/TPIContextProvider.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index 02d554806..12e0043d5 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -42,7 +42,7 @@ if (isDev) { // 老师 //debugType="teacher"; // 学生 -debugType="student"; +//debugType="student"; function railsgettimes(proxy) { diff --git a/public/react/src/context/TPIContextProvider.js b/public/react/src/context/TPIContextProvider.js index ed7eb2210..bb1e0bef4 100644 --- a/public/react/src/context/TPIContextProvider.js +++ b/public/react/src/context/TPIContextProvider.js @@ -32,7 +32,7 @@ import _ from 'lodash' import TPIContext from './TPIContext' import { EDU_ADMIN, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CERTIFICATION_TEACHER - , EDU_GAME_MANAGER, EDU_TEACHER, EDU_NORMAL, EDU_BUSINESS, CNotificationHOC } from 'educoder' + , EDU_GAME_MANAGER, EDU_TEACHER, EDU_NORMAL, EDU_BUSINESS, CNotificationHOC ,getRandomNumber} from 'educoder' import { MuiThemeProvider, createMuiTheme, withStyles } from 'material-ui/styles'; import MUIDialogStyleUtil from '../modules/page/component/MUIDialogStyleUtil' @@ -176,7 +176,7 @@ class TPIContextProvider extends Component { testPath = 'http://test-newweb.educoder.net' } // var url = `${testPath}/api/v1/games/${ game.identifier }/cost_time` - var url = `${testPath}/api/tasks/${ game.identifier }/cost_time` + var url = `${testPath}/api/tasks/${ game.identifier }/cost_time${getRandomNumber()}` window.$.ajax({ type: 'get', url: url, From 06bae0facf6ef87cabb1232deccd26c8d545b730 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Sat, 11 Jan 2020 20:31:16 +0800 Subject: [PATCH 35/55] =?UTF-8?q?=E6=97=B6=E9=97=B4=E8=AF=BE=E7=A8=8B?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/subjects_controller.rb | 1 + app/views/subjects/statistics_info.json.jbuilder | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 app/views/subjects/statistics_info.json.jbuilder diff --git a/app/controllers/subjects_controller.rb b/app/controllers/subjects_controller.rb index d58c4a9c3..47863a3a0 100644 --- a/app/controllers/subjects_controller.rb +++ b/app/controllers/subjects_controller.rb @@ -13,6 +13,7 @@ class SubjectsController < ApplicationController include ApplicationHelper include SubjectsHelper include GitCommon + include CustomSortable def index @tech_system = current_laboratory.subject_repertoires diff --git a/app/views/subjects/statistics_info.json.jbuilder b/app/views/subjects/statistics_info.json.jbuilder new file mode 100644 index 000000000..b31e41b31 --- /dev/null +++ b/app/views/subjects/statistics_info.json.jbuilder @@ -0,0 +1,6 @@ +json.status 0 +json.message "success" +json.data do + json.subject_info @subject.subject_record + json.other_info @data +end \ No newline at end of file From 72cea0893900ceceddc6703c1c2dfbe2eb61bddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Sat, 11 Jan 2020 20:33:44 +0800 Subject: [PATCH 36/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../react/src/modules/courses/coursesDetail/CoursesLeftNav.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js b/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js index c37b45c84..ba8fe27b0 100644 --- a/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js +++ b/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js @@ -549,6 +549,10 @@ class Coursesleftnav extends Component{ window.location.href=`/courses/${coursesId}/boards/${result.data.category_id}`; } + if(positiontype!="course_groups"){ + this.updasaveNavmoda() + } + if(positiontype==="course_groups"){ window.location.href=`/courses/${coursesId}/course_groups/${result.data.group_id}`; } From 6f610eebd26e9c93ffef348d9e6ea864ccbbe95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Sat, 11 Jan 2020 20:50:34 +0800 Subject: [PATCH 37/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/page/layers/TaskResultLayer.js | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/public/react/src/modules/page/layers/TaskResultLayer.js b/public/react/src/modules/page/layers/TaskResultLayer.js index 9e096b7b3..f4ccea8f7 100644 --- a/public/react/src/modules/page/layers/TaskResultLayer.js +++ b/public/react/src/modules/page/layers/TaskResultLayer.js @@ -14,6 +14,7 @@ import passpartImg from '../../../images/tpi/passpart.png' import empiricgreenImg from '../../../images/tpi/empiricgreen.png' import { trigger } from 'educoder'; +import SecondTab from "../../paths/SchoolStatistics/SecondTab"; class TaskResultLayer extends Component { @@ -29,7 +30,7 @@ class TaskResultLayer extends Component { } componentWillReceiveProps(newProps, newContext) { - if (newProps.currentGamePassed && (!this.props.currentGamePassed + if (newProps.currentGamePassed && (!this.props.currentGamePassed || (newProps.currentGamePassed !== this.props.currentGamePassed ))) { // this.fakeRanking = this._fakeRanking() const $ = window.$; @@ -51,10 +52,10 @@ class TaskResultLayer extends Component { } } } - + onStarChange(challenge, index, value) { this.props.onStarChange(challenge, index, value); - + this.setState({ stared: value ? true : false, }) @@ -87,11 +88,11 @@ class TaskResultLayer extends Component { // this.context.router.push('/sample'); if (goNext === true) { if (next_game) { // https://www.trustie.net/issues/18573 - this.goNext = true; + this.goNext = true; } // 隐藏掉效果查看页面 window.$('#picture_display').hide() - } + } this.props.onGamePassed(); this.setState({ stared: false @@ -110,9 +111,9 @@ class TaskResultLayer extends Component { // return; // } // const { showLanguagePictrue } = this.props.challenge; - // if ( prevProps.challenge.showLanguagePictrue != showLanguagePictrue && + // if ( prevProps.challenge.showLanguagePictrue != showLanguagePictrue && // showLanguagePictrue == true ) { - + // } // } initEffectDisplayServerTimer = () => { @@ -128,7 +129,7 @@ class TaskResultLayer extends Component { this.setState({ timeRemain }) }, 1000) }) - + } componentWillUnmount() { this.intervalHandler && clearInterval(this.intervalHandler); @@ -162,7 +163,7 @@ class TaskResultLayer extends Component { // const fakeRanking = this.fakeRanking; return (
    - {currentGamePassed ? + {currentGamePassed ?
    @@ -174,52 +175,60 @@ class TaskResultLayer extends Component {

    {currentPassedGameGainExperience >= 0 ? `+${currentPassedGameGainExperience}` : '+0'} -

    +

    - +
    - { !game.star ? + { !game.star ?

    您的评价决定老师的江湖地位~

    this.onStarChange(this.props.game, this.props.challenge.position, value)} - /> + />
    : ''} -

    +

    {/*下一关*/} this.onFinish(true)}>{ next_game ? '下一关' : '完成'} - { challenge.showLanguagePictrue && + { challenge.showLanguagePictrue && this.onFinish()}> { `查看效果` } {/* ${ moment(this.state.timeRemain * 1000).format('mm:ss') } */} - + } - {/* - - (this.state.timeRemain ? + {/* + + (this.state.timeRemain ? - - + + : {}} style={{ backgroundColor: 'gray'}}> { `查看效果` } - + ) */} - {/* + {/* 注意:效果查看服务只会保留5分钟 效果查看服务已被终止运行,需要重新评测后才能查看 */} From 21c6e3ba7bcc6edb83b1257cc51c291588150c11 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sun, 12 Jan 2020 10:58:24 +0800 Subject: [PATCH 38/55] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E7=9A=84=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E9=9B=86=E5=BE=97=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/exercises_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/exercises_helper.rb b/app/helpers/exercises_helper.rb index cf9aec815..4b18ccba2 100644 --- a/app/helpers/exercises_helper.rb +++ b/app/helpers/exercises_helper.rb @@ -530,7 +530,7 @@ module ExercisesHelper exercise_cha_score = 0.0 answer_status = 0 # if game.status == 2 && game.final_score >= 0 - if game.final_score > 0 && game.end_time && game.end_time < exercise_end_time + if game.final_score > 0 && (game.end_time.nil? && game.end_time < exercise_end_time) exercise_cha_score = game.real_score(exercise_cha.question_score) # exercise_cha_score = exercise_cha.question_score #每一关卡的得分 answer_status = 1 From 5a6c58a0f61aad60dcaf0434e22b50f1bbc6c7cc Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sun, 12 Jan 2020 10:59:10 +0800 Subject: [PATCH 39/55] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E6=8C=89=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E9=9B=86=E7=BB=99=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/exercises_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/exercises_helper.rb b/app/helpers/exercises_helper.rb index 4b18ccba2..eaeb458a3 100644 --- a/app/helpers/exercises_helper.rb +++ b/app/helpers/exercises_helper.rb @@ -530,7 +530,7 @@ module ExercisesHelper exercise_cha_score = 0.0 answer_status = 0 # if game.status == 2 && game.final_score >= 0 - if game.final_score > 0 && (game.end_time.nil? && game.end_time < exercise_end_time) + if game.final_score > 0 && (game.end_time.nil? || game.end_time < exercise_end_time) exercise_cha_score = game.real_score(exercise_cha.question_score) # exercise_cha_score = exercise_cha.question_score #每一关卡的得分 answer_status = 1 From ee3444394572d84ad834a67b2a1f6eb1fbc92d81 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sun, 12 Jan 2020 11:14:37 +0800 Subject: [PATCH 40/55] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...00112030419_migrate_3176_exercise_score.rb | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 db/migrate/20200112030419_migrate_3176_exercise_score.rb diff --git a/db/migrate/20200112030419_migrate_3176_exercise_score.rb b/db/migrate/20200112030419_migrate_3176_exercise_score.rb new file mode 100644 index 000000000..449a87578 --- /dev/null +++ b/db/migrate/20200112030419_migrate_3176_exercise_score.rb @@ -0,0 +1,50 @@ +class Migrate3176ExerciseScore < ActiveRecord::Migration[5.2] + + def calculate_student_score(exercise,user) + score5 = 0.0 #实训题 + exercise_end_time = exercise.end_time + exercise_questions = exercise.exercise_questions.includes(:exercise_standard_answers,:exercise_shixun_challenges) + exercise_questions.each do |q| + if q.question_type == 5 + q.exercise_shixun_challenges.each do |exercise_cha| + game = Game.user_games(user.id,exercise_cha.challenge_id)&.first #当前用户的关卡 + if game.present? + exercise_cha_score = 0.0 + answer_status = 0 + # if game.status == 2 && game.final_score >= 0 + if game.final_score > 0 && (game.end_time.nil? || game.end_time < exercise_end_time) + exercise_cha_score = game.real_score(exercise_cha.question_score) + # exercise_cha_score = exercise_cha.question_score #每一关卡的得分 + answer_status = 1 + end + ex_shixun_answer_content = exercise_cha.exercise_shixun_answers.find_by(user_id:user.id,exercise_question_id:q.id) + if ex_shixun_answer_content.present? && !ex_shixun_answer_content.score >0 #把关卡的答案存入试卷的实训里 + ex_shixun_answer_content.update_attributes!(score:exercise_cha_score.round(1),status:answer_status) + end + score5 += exercise_cha_score + else + score5 += 0.0 + end + end + end + end + score5 + end + + def change + exercise = Exercise.find_by(id: 3176) + if exercise + exercise_users = exercise.exercise_users.where("start_at is not null") + exercise_users.each do |exercise_user| + calculate_score = calculate_student_score(exercise, exercise_user.user) + subjective_score = exercise_user.subjective_score + total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score + total_score = calculate_score + total_score_subjective_score + if exercise_user.end_at.present? + exercise_user.update_attributes!(score:total_score,objective_score:calculate_score) + end + puts exercise_user.id + end + end + end +end From b4d6c003821d6ba05a80194ce67ce1ebe124db83 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sun, 12 Jan 2020 11:21:18 +0800 Subject: [PATCH 41/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/migrate/20200111024736_add_index_for_subject_records.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20200111024736_add_index_for_subject_records.rb b/db/migrate/20200111024736_add_index_for_subject_records.rb index c27c9b9ae..e196c407f 100644 --- a/db/migrate/20200111024736_add_index_for_subject_records.rb +++ b/db/migrate/20200111024736_add_index_for_subject_records.rb @@ -1,6 +1,6 @@ class AddIndexForSubjectRecords < ActiveRecord::Migration[5.2] def change - remove_index :subject_records, :subject_id + # remove_index :subject_records, :subject_id add_index :subject_records, :subject_id, unique: true end end From f4a95fa206514fb5c950c39db69ac3dbdaaf7df9 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sun, 12 Jan 2020 11:50:16 +0800 Subject: [PATCH 42/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/migrate/20200112030419_migrate_3176_exercise_score.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20200112030419_migrate_3176_exercise_score.rb b/db/migrate/20200112030419_migrate_3176_exercise_score.rb index 449a87578..e96931f79 100644 --- a/db/migrate/20200112030419_migrate_3176_exercise_score.rb +++ b/db/migrate/20200112030419_migrate_3176_exercise_score.rb @@ -18,7 +18,7 @@ class Migrate3176ExerciseScore < ActiveRecord::Migration[5.2] answer_status = 1 end ex_shixun_answer_content = exercise_cha.exercise_shixun_answers.find_by(user_id:user.id,exercise_question_id:q.id) - if ex_shixun_answer_content.present? && !ex_shixun_answer_content.score >0 #把关卡的答案存入试卷的实训里 + if ex_shixun_answer_content.present? && !(ex_shixun_answer_content.score >0) #把关卡的答案存入试卷的实训里 ex_shixun_answer_content.update_attributes!(score:exercise_cha_score.round(1),status:answer_status) end score5 += exercise_cha_score From ab089c2cc5ef9a943c13e5c88814faf829765bf3 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Sun, 12 Jan 2020 11:53:27 +0800 Subject: [PATCH 43/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...00112035304_migrate_3517_exercise_score.rb | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 db/migrate/20200112035304_migrate_3517_exercise_score.rb diff --git a/db/migrate/20200112035304_migrate_3517_exercise_score.rb b/db/migrate/20200112035304_migrate_3517_exercise_score.rb new file mode 100644 index 000000000..821b2bbd8 --- /dev/null +++ b/db/migrate/20200112035304_migrate_3517_exercise_score.rb @@ -0,0 +1,49 @@ +class Migrate3517ExerciseScore < ActiveRecord::Migration[5.2] + def calculate_student_score(exercise,user) + score5 = 0.0 #实训题 + exercise_end_time = exercise.end_time + exercise_questions = exercise.exercise_questions.includes(:exercise_standard_answers,:exercise_shixun_challenges) + exercise_questions.each do |q| + if q.question_type == 5 + q.exercise_shixun_challenges.each do |exercise_cha| + game = Game.user_games(user.id,exercise_cha.challenge_id)&.first #当前用户的关卡 + if game.present? + exercise_cha_score = 0.0 + answer_status = 0 + # if game.status == 2 && game.final_score >= 0 + if game.final_score > 0 && (game.end_time.nil? || game.end_time < exercise_end_time) + exercise_cha_score = game.real_score(exercise_cha.question_score) + # exercise_cha_score = exercise_cha.question_score #每一关卡的得分 + answer_status = 1 + end + ex_shixun_answer_content = exercise_cha.exercise_shixun_answers.find_by(user_id:user.id,exercise_question_id:q.id) + if ex_shixun_answer_content.present? && !(ex_shixun_answer_content.score >0) #把关卡的答案存入试卷的实训里 + ex_shixun_answer_content.update_attributes!(score:exercise_cha_score.round(1),status:answer_status) + end + score5 += exercise_cha_score + else + score5 += 0.0 + end + end + end + end + score5 + end + + def change + exercise = Exercise.find_by(id: 3517) + if exercise + exercise_users = exercise.exercise_users.where("start_at is not null") + exercise_users.each do |exercise_user| + calculate_score = calculate_student_score(exercise, exercise_user.user) + subjective_score = exercise_user.subjective_score + total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score + total_score = calculate_score + total_score_subjective_score + if exercise_user.end_at.present? + exercise_user.update_attributes!(score:total_score,objective_score:calculate_score) + end + puts exercise_user.id + end + end + end +end From 185a64dce29145a5eba64b78c86bc19ca52ef86f Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Mon, 13 Jan 2020 10:02:45 +0800 Subject: [PATCH 44/55] =?UTF-8?q?=E4=BA=A4=E6=B5=81=E9=97=AE=E7=AD=94?= =?UTF-8?q?=EF=BC=9A=E5=8F=91=E9=80=81=E8=AF=84=E8=AE=BA=EF=BC=8C=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E5=9C=A8=E7=8E=B0=E6=9C=89=E6=B5=81=E7=A8=8B=E7=9A=84?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E4=B8=8A=E5=A2=9E=E5=8A=A0=E2=80=9C=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E8=B5=84=E6=96=99=E2=80=9D=E7=9A=84check=E5=92=8C?= =?UTF-8?q?=E5=BC=95=E5=AF=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/memos_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/memos_controller.rb b/app/controllers/memos_controller.rb index b80bfed32..c0ea8d601 100644 --- a/app/controllers/memos_controller.rb +++ b/app/controllers/memos_controller.rb @@ -1,6 +1,6 @@ class MemosController < ApplicationController before_action :require_login, except: [:show, :index] - before_action :check_account, only: [:new, :create] + before_action :check_account, only: [:new, :create, :reply] before_action :set_memo, only: [:show, :edit, :update, :destroy, :sticky_or_cancel, :hidden, :more_reply] before_action :validate_memo_params, only: [:create, :update] before_action :owner_or_admin, only: [:edit, :update, :destroy] From b6cdd2ed1aaf3311d38da10393f21589d4ddd5cc Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Mon, 13 Jan 2020 10:08:25 +0800 Subject: [PATCH 45/55] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=89=88=E8=B7=B3?= =?UTF-8?q?=E8=BF=87=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/application_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index fdb41c114..e0639de3f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -23,7 +23,7 @@ class ApplicationController < ActionController::Base # 所有请求必须合法签名 def check_sign - if !Rails.env.development? + if !Rails.env.development? && EduSetting.get("host_name") != "https://test-newweb.educoder.net" Rails.logger.info("66666 #{params}") # suffix = request.url.split(".").last.split("?").first # suffix_arr = ["xls", "xlsx", "pdf", "zip"] # excel文件先注释 From 457c629b9ea59034bc663789b5bbfbc245deb6f8 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Mon, 13 Jan 2020 10:30:03 +0800 Subject: [PATCH 46/55] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/application_controller.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e0639de3f..ed839eccf 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -23,6 +23,8 @@ class ApplicationController < ActionController::Base # 所有请求必须合法签名 def check_sign + Rails.logger.info("#####################request: #{request.headers}") + Rails.logger.info("#####################type: #{request.type}") if !Rails.env.development? && EduSetting.get("host_name") != "https://test-newweb.educoder.net" Rails.logger.info("66666 #{params}") # suffix = request.url.split(".").last.split("?").first From ec8e92c5f616bdb7ae8f5e8bd0a8349e28f5b8ff Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Mon, 13 Jan 2020 10:31:09 +0800 Subject: [PATCH 47/55] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/application_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ed839eccf..9faa14593 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -24,7 +24,7 @@ class ApplicationController < ActionController::Base # 所有请求必须合法签名 def check_sign Rails.logger.info("#####################request: #{request.headers}") - Rails.logger.info("#####################type: #{request.type}") + #Rails.logger.info("#####################type: #{request.type}") if !Rails.env.development? && EduSetting.get("host_name") != "https://test-newweb.educoder.net" Rails.logger.info("66666 #{params}") # suffix = request.url.split(".").last.split("?").first From b2ad28591b418980713992e0c5480dacd982e69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Mon, 13 Jan 2020 10:40:09 +0800 Subject: [PATCH 48/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/courses/graduation/tasks/GraduationTaskDetail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/react/src/modules/courses/graduation/tasks/GraduationTaskDetail.js b/public/react/src/modules/courses/graduation/tasks/GraduationTaskDetail.js index 44bcf5777..3330f9389 100644 --- a/public/react/src/modules/courses/graduation/tasks/GraduationTaskDetail.js +++ b/public/react/src/modules/courses/graduation/tasks/GraduationTaskDetail.js @@ -523,7 +523,7 @@ class GraduationTaskDetail extends Component{ 导出

  • :""} {questionslist.work_status===undefined||questionslist.work_status===null||questionslist.work_status.length===0?"":questionslist.work_status.map((item,key)=>{ From b4f6f5be639b4adf08c38d4e3b60cd67f90f31ec Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Mon, 13 Jan 2020 10:59:20 +0800 Subject: [PATCH 49/55] =?UTF-8?q?=E6=AF=95=E8=AE=BE=E4=BD=9C=E5=93=81?= =?UTF-8?q?=E9=99=84=E4=BB=B6=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/export_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb index 8b61ca2b6..a5268a789 100644 --- a/app/helpers/export_helper.rb +++ b/app/helpers/export_helper.rb @@ -851,7 +851,8 @@ module ExportHelper def make_zip_name(work, file_name="") Rails.logger.info("######################file_name: #{file_name}") # name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_") - "#{work&.homework_common.course&.user_group_name(work.user_id)}_#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" + course = work&.homework_common.course || work&.graduation_task.course + "#{course&.user_group_name(work.user_id)}_#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" end def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[]) From 39fa3c8096d94a6493557d02a56c137fb3317c40 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Mon, 13 Jan 2020 11:04:03 +0800 Subject: [PATCH 50/55] =?UTF-8?q?=E6=AF=95=E8=AE=BE=E4=BD=9C=E5=93=81?= =?UTF-8?q?=E9=99=84=E4=BB=B6=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/export_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb index a5268a789..b7a4d4def 100644 --- a/app/helpers/export_helper.rb +++ b/app/helpers/export_helper.rb @@ -851,7 +851,7 @@ module ExportHelper def make_zip_name(work, file_name="") Rails.logger.info("######################file_name: #{file_name}") # name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_") - course = work&.homework_common.course || work&.graduation_task.course + course = work&.homework_common&.course || work&.graduation_task&.course "#{course&.user_group_name(work.user_id)}_#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" end From 1c7db6bef9f2b87ca5f321d98d0af153eb9351a0 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Mon, 13 Jan 2020 11:06:56 +0800 Subject: [PATCH 51/55] =?UTF-8?q?=E6=AF=95=E8=AE=BE=E4=BD=9C=E5=93=81?= =?UTF-8?q?=E9=99=84=E4=BB=B6=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/export_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb index b7a4d4def..64ad114bd 100644 --- a/app/helpers/export_helper.rb +++ b/app/helpers/export_helper.rb @@ -851,7 +851,7 @@ module ExportHelper def make_zip_name(work, file_name="") Rails.logger.info("######################file_name: #{file_name}") # name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_") - course = work&.homework_common&.course || work&.graduation_task&.course + course = work.is_a?(StudentWork) ? work&.homework_common&.course : work&.graduation_task&.course "#{course&.user_group_name(work.user_id)}_#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" end From 573cf053445c8756cdc8107648693463c541806c Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Mon, 13 Jan 2020 11:14:30 +0800 Subject: [PATCH 52/55] =?UTF-8?q?=E9=99=84=E4=BB=B6=E7=9A=84=E5=AF=BC?= =?UTF-8?q?=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/export_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb index a5268a789..64ad114bd 100644 --- a/app/helpers/export_helper.rb +++ b/app/helpers/export_helper.rb @@ -851,7 +851,7 @@ module ExportHelper def make_zip_name(work, file_name="") Rails.logger.info("######################file_name: #{file_name}") # name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_") - course = work&.homework_common.course || work&.graduation_task.course + course = work.is_a?(StudentWork) ? work&.homework_common&.course : work&.graduation_task&.course "#{course&.user_group_name(work.user_id)}_#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" end From 1ecf433fc5cc084eef5b1babc563ade9bd251d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Mon, 13 Jan 2020 11:48:49 +0800 Subject: [PATCH 53/55] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/images/educoder/xcx/weixinhome.png | Bin 0 -> 54273 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/images/educoder/xcx/weixinhome.png diff --git a/public/images/educoder/xcx/weixinhome.png b/public/images/educoder/xcx/weixinhome.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba56d1b6a64d80ecbada157231fabb19fbfb96d GIT binary patch literal 54273 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 E0eq`7f&c&j literal 0 HcmV?d00001 From 1fa2fe4ad3b6ffc0d2adee088eb2e4980f118ae1 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Mon, 13 Jan 2020 14:37:53 +0800 Subject: [PATCH 54/55] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E8=BA=AB=E4=BB=BD=E7=9A=84api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/users/interests_controller.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/controllers/users/interests_controller.rb b/app/controllers/users/interests_controller.rb index 93f2345f1..06470f553 100644 --- a/app/controllers/users/interests_controller.rb +++ b/app/controllers/users/interests_controller.rb @@ -9,18 +9,18 @@ class Users::InterestsController < Users::BaseController extension = current_user.user_extension || current_user.build_user_extension return render_error('请选择职业') unless %w(teacher student professional).include?(identity) - interest_ids = Array.wrap(params[:interest_ids]).map(&:to_i) - return render_error('请选择兴趣') if interest_ids.blank? + # interest_ids = Array.wrap(params[:interest_ids]).map(&:to_i) + # return render_error('请选择兴趣') if interest_ids.blank? ActiveRecord::Base.transaction do extension.update_column(:identity, identity) # 兴趣 - UserInterest.bulk_insert(:user_id, :repertoire_id) do |worker| - (Repertoire.pluck(:id) & interest_ids).each do |repertoire_id| - worker.add(user_id: current_user.id, repertoire_id: repertoire_id) - end - end + # UserInterest.bulk_insert(:user_id, :repertoire_id) do |worker| + # (Repertoire.pluck(:id) & interest_ids).each do |repertoire_id| + # worker.add(user_id: current_user.id, repertoire_id: repertoire_id) + # end + # end end render_ok From 2e6222bca279fbfc70dd83d25d6607a18d1b70f2 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Mon, 13 Jan 2020 15:23:36 +0800 Subject: [PATCH 55/55] =?UTF-8?q?=E9=A2=98=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/hacks_controller.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/hacks_controller.rb b/app/controllers/hacks_controller.rb index 0e98e771b..6eb454feb 100644 --- a/app/controllers/hacks_controller.rb +++ b/app/controllers/hacks_controller.rb @@ -232,7 +232,11 @@ class HacksController < ApplicationController hacks = Hack.select(select_sql).mine(current_user.id) else # 全部包括已经发布的,和我的未发布的 - hacks = Hack.select(select_sql).published.opening.or(Hack.select(select_sql).unpublish.mine(current_user.id)) + if current_user.admin_or_business? + hacks = Hack.select(select_sql) + else + hacks = Hack.select(select_sql).published.opening.or(Hack.select(select_sql).unpublish.mine(current_user.id)) + end end # 搜索 if params[:search]