diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index e6ada3098..ee2b061ba 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -146,7 +146,7 @@ class PollsController < ApplicationController def edit ActiveRecord::Base.transaction do begin - @poll_questions = @poll.poll_questions.order("question_number ASC") + rescue Exception => e uid_logger_error(e.message) tip_exception("页面请求失败!") @@ -183,7 +183,7 @@ class PollsController < ApplicationController else @is_teacher_or = 0 end - @poll_questions = @poll.poll_questions&.includes(:poll_answers).order("question_number ASC") + rescue Exception => e uid_logger_error(e.message) tip_exception("没有权限") @@ -868,7 +868,6 @@ class PollsController < ApplicationController @user_poll_status = 0 #可编辑 end - # @answer_user = User.find_by(id:@poll_current_user_id) @answer_status = [] question_answered = 0 @@ -925,7 +924,6 @@ class PollsController < ApplicationController @page = params[:page] || 1 @limit = params[:limit] || 10 @poll_export_questions = @poll_questions - @poll_questions = @poll_questions.page(@page).per(@limit) if params[:format] == "xlsx" if @user_course_identity > Course::ASSISTANT_PROFESSOR @@ -1151,7 +1149,7 @@ class PollsController < ApplicationController def get_questions_count @poll_questions = @poll.poll_questions.order("question_number ASC") - @poll_questions_count = @poll_questions.size # 全部的题目数 + @poll_questions_count = @poll_questions&.size # 全部的题目数 @poll_question_singles = @poll_questions.ques_count(1).size # 单选题 @poll_question_doubles = @poll_questions.ques_count(2).size # 多选题 @poll_question_mains = @poll_questions.ques_count(3).size #主观题 @@ -1301,7 +1299,6 @@ class PollsController < ApplicationController #问卷的统计结果的导出 def poll_commit_result(poll,poll_questions,poll_users,poll_commit_ids) - obj_commit = [] sub_commit = [] user_commit = [] poll_users_info = %w(序号) @@ -1315,30 +1312,28 @@ class PollsController < ApplicationController poll_users_info = poll_users_info + user_info + poll_ques_titles poll_questions.each do |q| if q.question_type != 3 #问题不为主观题 - question_vote_user = q.poll_votes.find_current_vote("user_id",poll_commit_ids).size #该问题的有效填写量 + question_vote_user = q.poll_votes.find_current_vote("user_id",poll_commit_ids)&.size #该问题的有效填写量 sheet_row = ["第#{q.question_number}题"] #选择题答案选项的数组 sheet_answer_row = ["小计"] #选择题回答的答案人数,数组 sheet_answer_percent = ["比例"] - sheet_answer_useful = ["有效填写人次",question_vote_user] + sheet_answer_useful = ["本题有效填写人次",question_vote_user] q.poll_answers.each do |a| #问卷的答案选项 - answer_users_count = a.poll_votes.find_current_vote("user_id",poll_commit_ids).size + answer_users_count = a.poll_votes.find_current_vote("user_id",poll_commit_ids)&.size answer_percent = (question_vote_user == 0) ? "0.0%" : "#{((answer_users_count / question_vote_user.to_f)*100).round(1).to_s}%" sheet_row.push(a.answer_text) sheet_answer_row.push(answer_users_count) sheet_answer_percent.push(answer_percent) end - sheet_obj_commit = { - sheet_row:sheet_row, - sheet_answer_row:sheet_answer_row, - sheet_answer_percent:sheet_answer_percent, - sheet_answer_useful:sheet_answer_useful + sheet_sub_commit = { + sub_title: sheet_row, + sub_user_votes:[sheet_answer_row,sheet_answer_percent,sheet_answer_useful] } - obj_commit.push(sheet_obj_commit) + sub_commit.push(sheet_sub_commit) else #主观题答案 user_votes= [] - main_show_row = ["第#{q.question_number}题", q.question_title] + main_show_row = ["第#{q.question_number}题", q.question_title ] q.poll_votes.each_with_index do |v,index| #主观题的答案 - q_poll_vote = [(index+1),v.vote_text.present? ? v.vote_text : "--"] + q_poll_vote = [(index+1), v.vote_text.present? ? v.vote_text : "--"] user_votes.push(q_poll_vote) end sheet_sub_commit = { @@ -1347,9 +1342,10 @@ class PollsController < ApplicationController } sub_commit.push(sheet_sub_commit) end + end #each_with_index - poll_users.includes(user: :user_extension).each_with_index do |u,index| + poll_users.includes(user: [:user_extension,:poll_votes]).each_with_index do |u,index| u_user = u.user user_answer_array = [] poll_questions.each do |q| @@ -1390,7 +1386,6 @@ class PollsController < ApplicationController end { - obj_commit:obj_commit, poll_users_info:poll_users_info, sub_commit:sub_commit, user_commit:user_commit diff --git a/app/controllers/users/auth_attachments_controller.rb b/app/controllers/users/auth_attachments_controller.rb new file mode 100644 index 000000000..86c3e70ef --- /dev/null +++ b/app/controllers/users/auth_attachments_controller.rb @@ -0,0 +1,39 @@ +class Users::AuthAttachmentsController < Users::BaseAccountController + before_action :private_user_resources! + before_action :convert_image!, only: [:update] + + def update + image_temp_path = auth_image_path + 'temp' # 上传文件保存至临时文件,提交申请时再移到正常目录 + + File.delete(image_temp_path) if File.exist?(image_temp_path) # 删除之前的临时文件 + + Util.write_file(@image, image_temp_path) + + render_ok + rescue StandardError => ex + logger_error(ex) + render_error('上传失败') + end + + private + + def convert_image! + max_size = EduSetting.get('upload_avatar_max_size') || 10 * 1024 * 1024 # 10M + if params[:image].class == ActionDispatch::Http::UploadedFile + @image = params[:image] + render_error('请上传文件') if @image.size.zero? + render_error('文件大小超过限制') if @image.size > max_size + else + image = params[:image].to_s.strip + return render_error('请上传正确的图片') if image.blank? + @image = Util.convert_base64_image(image, max_size: max_size) + end + rescue Base64ImageConverter::Error => ex + render_error(ex.message) + end + + def auth_image_path + url_method = params[:type] == 'professional' ? :disk_professional_auth_filename : :disk_real_name_auth_filename + ApplicationController.helpers.send(url_method, observed_user.id) + end +end \ No newline at end of file diff --git a/app/controllers/users/authentication_applies_controller.rb b/app/controllers/users/authentication_applies_controller.rb new file mode 100644 index 000000000..d406b33d3 --- /dev/null +++ b/app/controllers/users/authentication_applies_controller.rb @@ -0,0 +1,16 @@ +class Users::AuthenticationAppliesController < Users::BaseAccountController + before_action :private_user_resources! + + def create + Users::ApplyAuthenticationService.call(observed_user, create_params) + render_ok + rescue Users::ApplyAuthenticationService::Error => ex + render_error(ex.message) + end + + private + + def create_params + params.permit(:name, :id_number, :upload_image) + end +end \ No newline at end of file diff --git a/app/controllers/users/professional_auth_applies_controller.rb b/app/controllers/users/professional_auth_applies_controller.rb new file mode 100644 index 000000000..b2603f642 --- /dev/null +++ b/app/controllers/users/professional_auth_applies_controller.rb @@ -0,0 +1,16 @@ +class Users::ProfessionalAuthAppliesController < Users::BaseAccountController + before_action :private_user_resources! + + def create + Users::ApplyProfessionalAuthService.call(observed_user, create_params) + render_ok + rescue Users::ApplyProfessionalAuthService::Error => ex + render_error(ex.message) + end + + private + + def create_params + params.permit(:school_id, :department_id, :identity, :extra, :upload_image) + end +end \ No newline at end of file diff --git a/app/forms/users/apply_authentication_form.rb b/app/forms/users/apply_authentication_form.rb new file mode 100644 index 000000000..986ba6223 --- /dev/null +++ b/app/forms/users/apply_authentication_form.rb @@ -0,0 +1,8 @@ +class Users::ApplyAuthenticationForm + include ActiveModel::Model + + attr_accessor :name, :id_number, :upload_image + + validates :name, presence: true + validates :id_number, presence: true +end \ No newline at end of file diff --git a/app/forms/users/apply_professional_auth_form.rb b/app/forms/users/apply_professional_auth_form.rb new file mode 100644 index 000000000..c5de9700c --- /dev/null +++ b/app/forms/users/apply_professional_auth_form.rb @@ -0,0 +1,10 @@ +class Users::ApplyProfessionalAuthForm + include ActiveModel::Model + + attr_accessor :school_id, :department_id, :identity, :extra, :upload_image + + validates :school_id, presence: true, numericality: { only_integer: true, greater_than: 0 } + validates :department_id, numericality: { only_integer: true, greater_than: 0 }, allow_blank: true + validates :identity, presence: true, inclusion: { in: %w(student teacher professional) } + validates :extra, presence: true +end \ No newline at end of file diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index fd72b5651..cdd647ebd 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -145,6 +145,18 @@ module ApplicationHelper File.join(storage_path, "#{source_type}", "#{source_id}") end + def disk_auth_filename(source_type, source_id, type) + File.join(storage_path, "#{source_type}", "#{source_id}#{type}") + end + + def disk_real_name_auth_filename(source_id) + disk_auth_filename('UserAuthentication', source_id, 'ID') + end + + def disk_professional_auth_filename(source_id) + disk_auth_filename('UserAuthentication', source_id, 'PRO') + end + def shixun_url_to_avatar(shixun) if File.exist?(disk_filename(shixun.class, shixun.id)) File.join("images/#{relative_path}", "#{shixun.class}", "#{shixun.id}") diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 3d8457ce3..49fca7c71 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -4,7 +4,7 @@ class UserExtension < ApplicationRecord belongs_to :user belongs_to :school - belongs_to :department + belongs_to :department, optional: true def identity_text I18n.t("user.identity.#{identity}") diff --git a/app/services/users/apply_authentication_service.rb b/app/services/users/apply_authentication_service.rb new file mode 100644 index 000000000..f31bb335c --- /dev/null +++ b/app/services/users/apply_authentication_service.rb @@ -0,0 +1,52 @@ +class Users::ApplyAuthenticationService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :user, :params + + def initialize(user, params) + @user = user + @params = params + end + + def call + Users::ApplyAuthenticationForm.new(params).validate! + raise Error, '您已经申请过实名认证了' if ApplyUserAuthentication.real_name_auth.processing.exists?(user_id: user.id) + + user.lastname = params[:name].to_s.strip + user.firstname = '' + user.ID_number = params[:id_number].to_s.strip.presence + + ActiveRecord::Base.transaction do + user.authentication = false + user.save! + + user.apply_user_authentication.create!(auth_type: 1, status: 0) + + move_image_file! unless params[:upload_image].to_s == 'false' + + sms_notify_admin + end + + user + end + + private + + def move_image_file! + image_url = ApplicationController.helpers.disk_real_name_auth_filename(user.id) + temp_image_url = image_url + 'temp' + + FileUtils.mv(temp_image_url, image_url, force: true) if File.exist?(temp_image_url) + rescue RuntimeError => ex + Util.logger_error(ex) + raise Error, '申请失败' + ensure + File.delete(temp_image_url) if File.exist?(temp_image_url) + end + + def sms_notify_admin + Educoder::Sms.notify_admin(send_type: 'apply_auth') + rescue => ex + Util.logger_error(ex) + end +end \ No newline at end of file diff --git a/app/services/users/apply_professional_auth_service.rb b/app/services/users/apply_professional_auth_service.rb new file mode 100644 index 000000000..2d8279317 --- /dev/null +++ b/app/services/users/apply_professional_auth_service.rb @@ -0,0 +1,62 @@ +class Users::ApplyProfessionalAuthService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :user, :params + + def initialize(user, params) + @user = user + @params = params + end + + def call + Users::ApplyProfessionalAuthForm.new(params).validate! + raise Error, '您已经申请过职业认证了' if ApplyUserAuthentication.professional_auth.processing.exists?(user_id: user.id) + + user.professional_certification = false + + extension = user.user_extension + extension.school_id = params[:school_id] + extension.department_id = params[:department_id] + extension.identity = params[:identity] + + extra = params[:extra].to_s.strip.presence + if extension.identity.to_s == 'student' + extension.technical_title = nil + extension.student_id = extra + else + extension.technical_title = extra + extension.student_id = nil + end + + ActiveRecord::Base.transaction do + user.save! + extension.save! + + user.apply_user_authentication.create!(auth_type: 2, status: 0) + + move_image_file! unless params[:upload_image].to_s == 'false' + + sms_notify_admin + end + end + + private + + def move_image_file! + image_url = ApplicationController.helpers.disk_professional_auth_filename(user.id) + temp_image_url = image_url + 'temp' + + FileUtils.mv(temp_image_url, image_url, force: true) if File.exist?(temp_image_url) + rescue RuntimeError => ex + Util.logger_error(ex) + raise Error, '申请失败' + ensure + File.delete(temp_image_url) if File.exist?(temp_image_url) + end + + def sms_notify_admin + Educoder::Sms.notify_admin(send_type: 'apply_pro_certification') + rescue => ex + Util.logger_error(ex) + end +end \ No newline at end of file diff --git a/app/views/homework_commons/works_list.json.jbuilder b/app/views/homework_commons/works_list.json.jbuilder index a7dc292b8..458db9621 100644 --- a/app/views/homework_commons/works_list.json.jbuilder +++ b/app/views/homework_commons/works_list.json.jbuilder @@ -13,6 +13,7 @@ json.ta_mode @homework_detail_manual.ta_mode json.is_evaluation @is_evaluation ? @is_evaluation : false json.work_public @homework.work_public +json.allow_late @homework.allow_late if @user_course_identity < Course::STUDENT diff --git a/app/views/polls/commit_result.xlsx.axlsx b/app/views/polls/commit_result.xlsx.axlsx index 016c6e34c..4391e0e8f 100644 --- a/app/views/polls/commit_result.xlsx.axlsx +++ b/app/views/polls/commit_result.xlsx.axlsx @@ -7,30 +7,19 @@ wb.styles do |s| wb.add_worksheet(:name => "统计结果") do |sheet| sheet.sheet_view.show_grid_lines = false - obj_commit = polls_user_commit[:obj_commit] || [] - sub_commit = polls_user_commit[:sub_commit] || [] - poll_user_info = polls_user_commit[:poll_users_info] || [] - user_commit = polls_user_commit[:user_commit] || [] + sub_commit = polls_user_commit[:sub_commit] + poll_user_info = polls_user_commit[:poll_users_info] + user_commit = polls_user_commit[:user_commit] - #客观题的导出 - if obj_commit&.size > 0 - obj_commit.each do |obj| - sheet.add_row obj[:sheet_row], :height =>15,:style => blue_cell - sheet.add_row obj[:sheet_answer_row], :height =>15, :style => sz_all - sheet.add_row obj[:sheet_answer_percent], :height =>15, :style => sz_all - sheet.add_row obj[:sheet_answer_useful], :height =>15, :style => sz_all - sheet.add_row [] - end - end - - #主观题的导出 if sub_commit&.size > 0 sub_commit.each do |sub| - main_sub_title = sub[:sub_tile] + main_sub_title = sub[:sub_title] main_sub_content = sub[:sub_user_votes] sheet.add_row main_sub_title,:height =>15, :style => blue_cell - main_sub_content.each do |con| - sheet.add_row con,:height =>15, :style => sz_all + if main_sub_content.present? + main_sub_content.each do |con| + sheet.add_row con,:height =>15, :style => sz_all + end end sheet.add_row [] end @@ -44,93 +33,7 @@ wb.styles do |s| end end sheet.column_widths *([25]*sheet.column_info.count) - sheet.column_info.first.width = 10 - - #答题用户的导出 + sheet.column_info.first.width = 15 - # sheet.sheet_view.show_grid_lines = false - # poll_users_info = %w(序号) - # poll_ques_titles = poll_questions.pluck(:question_title).map {|k| strip_export_title(k) if k.present?} - # poll_un_anony = poll.un_anonymous - # if poll_un_anony #是否匿名,默认为false - # user_info = %w(登陆名 真实姓名 邮箱 学号) - # else - # user_info = [] - # end - # poll_users_info = poll_users_info + user_info + poll_ques_titles - # poll_questions.each do |q| - # if q.question_type != 3 #问题不为主观题 - # question_vote_user = q.poll_votes.find_current_vote("user_id",poll_commit_ids).size #该问题的有效填写量 - # sheet_row = ["第#{q.question_number}题"] #选择题答案选项的数组 - # sheet_answer_row = ["小计"] #选择题回答的答案人数,数组 - # sheet_answer_percent = ["比例"] - # sheet_answer_useful = ["有效填写人次",question_vote_user] - # q.poll_answers.each do |a| #问卷的答案选项 - # answer_users_count = a.poll_votes.find_current_vote("user_id",poll_commit_ids).size - # answer_percent = number_to_percentage((answer_users_count.to_f / question_vote_user.to_f)*100,precision:1) - # sheet_row.push(a.answer_text) - # sheet_answer_row.push(answer_users_count) - # sheet_answer_percent.push(answer_percent.to_s) - # end - # sheet.add_row sheet_row, :height =>15,:style => blue_cell - # sheet.add_row sheet_answer_row, :height =>15, :style => sz_all - # sheet.add_row sheet_answer_percent, :height =>15, :style => sz_all - # sheet.add_row sheet_answer_useful, :height =>15, :style => sz_all - # #合并单元格,但无法填充style - # # sheet.merge_cells (Axlsx::cell_r(1,sheet.rows.last.row_index) + ':' + Axlsx::cell_r(sheet_row.count-1,sheet.rows.last.row_index)) - # # sheet.rows[sheet.rows.last.row_index].style = sz_all - # sheet.add_row [] - # else #主观题答案 - # main_show_row = ["第#{q.question_number}题",q.question_title] - # sheet.add_row main_show_row,:height =>15, :style => blue_cell - # q.poll_votes.each_with_index do |v,index| #主观题的答案 - # sheet.add_row [(index+1),v.vote_text.present? ? v.vote_text : "--"],:height =>15, :style => sz_all - # end - # sheet.add_row [], :style => sz_all - # end - # end #each_with_index - # - # sheet.add_row poll_users_info, :height =>15, :style => blue_cell - # poll_users.includes(user: :user_extension).each_with_index do |u,index| - # u_user = u.user - # user_answer_array = [] - # poll_questions.each do |q| - # user_poll_votes = u_user.poll_votes.find_current_vote("poll_question_id",q.id) - # if user_poll_votes.present? - # user_poll_answer_ids = user_poll_votes.pluck(:poll_answer_id).reject(&:blank?) - # user_poll_vote_texts = user_poll_votes.pluck(:vote_text).reject(&:blank?) - # if user_poll_answer_ids.count > 0 - # answer_content = q.poll_answers.find_answer_by_custom("id",user_poll_answer_ids) - # if user_poll_answer_ids.count >1 - # u_answer = answer_content.pluck(:answer_text).join(";") - # else - # u_answer = answer_content.first.answer_text - # end - # elsif user_poll_vote_texts.count > 0 - # if user_poll_vote_texts.count > 1 - # u_answer = user_poll_vote_texts.join(";") - # else - # u_answer = user_poll_vote_texts.first - # end - # else - # u_answer = "--" - # end - # else - # u_answer = "--" - # end - # user_answer_array.push(u_answer) - # end - # user_cell = [index+1] - # if poll_un_anony - # user_login = u_user.login - # user_name = u_user.real_name.present? ? u_user.real_name : "--" - # user_student_id = u_user.student_id.present? ? u_user.student_id : "--" - # user_cell += [user_login,user_name, u_user.mail, user_student_id] - # end - # all_user_cell = user_cell + user_answer_array - # sheet.add_row all_user_cell, :height =>15,:style => sz_all - # end - # sheet.column_widths *([25]*sheet.column_info.count) - # sheet.column_info.first.width = 10 end #add_worksheet -end \ No newline at end of file +end diff --git a/config/locales/forms/apply_authentication_form.zh-CN.yml b/config/locales/forms/apply_authentication_form.zh-CN.yml new file mode 100644 index 000000000..cfc2e5b39 --- /dev/null +++ b/config/locales/forms/apply_authentication_form.zh-CN.yml @@ -0,0 +1,7 @@ +'zh-CN': + activemodel: + attributes: + users/apply_authentication_form: + name: 姓名 + id_number: 身份证号 + diff --git a/config/locales/forms/apply_professional_auth_form.zh-CN.yml b/config/locales/forms/apply_professional_auth_form.zh-CN.yml new file mode 100644 index 000000000..bbba03238 --- /dev/null +++ b/config/locales/forms/apply_professional_auth_form.zh-CN.yml @@ -0,0 +1,9 @@ +'zh-CN': + activemodel: + attributes: + users/apply_professional_auth_form: + school_id: 学校/单位 + department_id: 学院/部门 + identity: 职业 + extra: 职称/学号 + diff --git a/config/routes.rb b/config/routes.rb index 1a81f1175..e09808f6c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -74,6 +74,9 @@ Rails.application.routes.draw do resource :email_bind, only: [:create] resource :password, only: [:update] resource :avatar, only: [:update] + resource :auth_attachment, only: [:update] + resource :authentication_apply, only: [:create] + resource :professional_auth_apply, only: [:create] end end end diff --git a/lib/educoder/sms.rb b/lib/educoder/sms.rb index e79678ad3..237b270d5 100644 --- a/lib/educoder/sms.rb +++ b/lib/educoder/sms.rb @@ -21,7 +21,7 @@ module Educoder def self.notify_admin(opt) opt[:name] = '管理员' - opt[:mobile] = ENV['NOTIDY_ADMIN_PHONE'] || '17680641960' + opt[:mobile] = ENV['NOTIFY_ADMIN_PHONE'] || EduSetting.get('notify_admin_phone') || '17680641960' send(opt) end