diff --git a/.gitignore b/.gitignore index 18e26e891..c6841909b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,57 +1,63 @@ -# See https://help.github.com/articles/ignoring-files for more about ignoring files. -# -# If you find yourself ignoring temporary files generated by your text editor -# or operating system, you probably want to add a global ignore instead: -# git config --global core.excludesfile '~/.gitignore_global' - -# Ignore bundler config. -/.bundle - -# mac -*.DS_Store - -# Ignore all logfiles and tempfiles. -/log/* -/tmp/* -!/log/.keep -!/tmp/.keep - -# Ignore uploaded files in development -/storage/* - -/node_modules -/yarn-error.log - -# /public/assets -.byebug_history - -# Ignore master key for decrypting credentials and more. -/config/master.key -/config/database.yml -/.idea/* - -# Ignore react node_modules -/public/react/build -/public/react/build/ -/public/react/.cache -/public/react/node_modules/ -/public/react/config/stats.json -/public/react/stats.json - -/public/npm-debug.log - -# avatars -/public/images/avatars - -/config/secrets.yml -/files/archiveZip/* -/files/cache_store/* -public/upload.html -/config/configuration.yml -/config/initializers/gitlab_config.rb -/db/schema.rb -.vscode/ -vendor/bundle/ -.ruby-version -.ruby-gemset - +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# mac +*.DS_Store + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +# Ignore uploaded files in development +/storage/* + +/node_modules +/yarn-error.log + +# /public/assets +.byebug_history + +# Ignore master key for decrypting credentials and more. +/config/master.key +/config/database.yml +/.idea/* + +# Ignore react node_modules +/public/react/build +/public/react/build/ +/public/react/node_modules/ +/public/react/config/stats.json +/public/react/stats.json + +/public/npm-debug.log + +# avatars +/public/images/avatars + +/config/secrets.yml +/config/redis.yml +/config/elasticsearch.yml + +public/upload.html +/config/configuration.yml +/config/environments/production.rb +/config/initializers/gitlab_config.rb +/db/schema.rb +.vscode/ +vendor/bundle/ +.ruby-version +.ruby-gemset + +/files +/public/images/avatars +/public/files +/workspace +/log \ No newline at end of file diff --git a/Gemfile b/Gemfile index dfc9d41fd..4cabd09b9 100644 --- a/Gemfile +++ b/Gemfile @@ -39,6 +39,8 @@ gem 'pdfkit' gem 'wkhtmltopdf-binary' #gem 'iconv' +# markdown 转html +gem 'redcarpet', '~> 3.4' gem 'rqrcode', '~> 0.10.1' gem 'rqrcode_png' @@ -46,11 +48,13 @@ gem 'rqrcode_png' gem 'acts-as-taggable-on', '~> 6.0' group :development, :test do +#group :'development.rb.example', :test do gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rspec-rails', '~> 3.8' end group :development do +#group :'development.rb.example' do gem 'awesome_print' gem 'web-console', '>= 3.3.0' gem 'listen', '>= 3.0.5', '< 3.2' @@ -80,7 +84,10 @@ gem 'rails-i18n', '~> 5.1' # job gem 'sidekiq' +gem 'sinatra' # batch insert gem 'bulk_insert' +# elasticsearch +gem 'searchkick' diff --git a/Gemfile.lock b/Gemfile.lock index 83bd79628..94893687b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -90,6 +90,14 @@ GEM connection_pool (2.2.2) crass (1.0.4) diff-lcs (1.3) + elasticsearch (7.2.0) + elasticsearch-api (= 7.2.0) + elasticsearch-transport (= 7.2.0) + elasticsearch-api (7.2.0) + multi_json + elasticsearch-transport (7.2.0) + faraday + multi_json erubi (1.7.1) execjs (2.7.0) faraday (0.15.4) @@ -100,6 +108,7 @@ GEM grape-entity (0.7.1) activesupport (>= 4.0) multi_json (>= 1.3.2) + hashie (3.6.0) htmlentities (4.3.4) httparty (0.16.2) multi_xml (>= 0.5.2) @@ -142,6 +151,7 @@ GEM multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) + mustermann (1.0.3) mysql2 (0.5.2) nio4r (2.3.1) nokogiri (1.8.4) @@ -193,6 +203,7 @@ GEM rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) rchardet (1.8.0) + redcarpet (3.4.0) redis (4.1.0) redis-actionpack (5.0.2) actionpack (>= 4.0, < 6) @@ -253,6 +264,10 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) + searchkick (3.1.3) + activemodel (>= 4.2) + elasticsearch (>= 5) + hashie selenium-webdriver (3.14.0) childprocess (~> 0.5) rubyzip (~> 1.2) @@ -264,6 +279,11 @@ GEM simple_xlsx_reader (1.0.4) nokogiri rubyzip + sinatra (2.0.5) + mustermann (~> 1.0) + rack (~> 2.0) + rack-protection (= 2.0.5) + tilt (~> 2.0) spreadsheet (1.2.3) ruby-ole (>= 1.0) spring (2.0.2) @@ -328,6 +348,7 @@ DEPENDENCIES rails (~> 5.2.0) rails-i18n (~> 5.1) rchardet (~> 1.8) + redcarpet (~> 3.4) redis-rails roo-xls rqrcode (~> 0.10.1) @@ -336,9 +357,11 @@ DEPENDENCIES ruby-ole rubyzip sass-rails (~> 5.0) + searchkick selenium-webdriver sidekiq simple_xlsx_reader + sinatra spreadsheet spring spring-watcher-listen (~> 2.0.0) diff --git a/README.md b/README.md index 1aa92e1f5..8dcb6d131 100644 --- a/README.md +++ b/README.md @@ -62,3 +62,8 @@ testeduplus2.educoder.net/games/* # 文件上传:ActiveStorage # 新能:bootsnap + +# 注意事项: +# 第一次部署需要执行一些rake任务 +# 配置redis地址 +# 配置gitlab/intializers/gitlab_config.yml \ No newline at end of file diff --git a/app/constraint/admin_constraint.rb b/app/constraint/admin_constraint.rb new file mode 100644 index 000000000..3ddf9a11e --- /dev/null +++ b/app/constraint/admin_constraint.rb @@ -0,0 +1,7 @@ +class AdminConstraint + def matches?(request) + return false unless request.session[:user_id] + user = User.find request.session[:user_id] + user && user.admin? + end +end \ No newline at end of file diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index c3333c912..47349e219 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -1,6 +1,5 @@ class AccountsController < ApplicationController - include ErrorCommon #skip_before_action :check_account, :only => [:logout] def index @@ -31,20 +30,21 @@ class AccountsController < ApplicationController phone = nil verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last end - uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.created_at.to_i}") - check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60) - unless check_code - tip_exception("验证码无效") - end + uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}") + # check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60) + return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip + return normal_status(-2, "验证码已失效") if !verifi_code&.effective? code = generate_identifier User, 8 login = pre + code - @user = User.new(admin: false, login: login, mail: email, phone: phone) + @user = User.new(admin: false, login: login, mail: email, phone: phone, type: "User") @user.password = params[:password] # 现在因为是验证码,所以在注册的时候就可以激活 @user.activate # 必须要用save操作,密码的保存是在users中 if @user.save! + # todo user_extension + UserExtension.create!(user_id: @user.id) # 注册完成,手机号或邮箱想可以奖励500金币 RewardGradeService.call( @user, @@ -52,6 +52,13 @@ class AccountsController < ApplicationController container_type: pre == 'p' ? 'Phone' : 'Mail', score: 500 ) + # 注册时,记录是否是引流用户 + ip = request.remote_ip + ua = UserAgent.find_by_ip(ip) + ua.update_column(:agent_type, UserAgent::USER_REGISTER) if ua + successful_authentication(@user) + session[:user_id] = @user.id + normal_status("注册成功") end rescue Exception => e uid_logger_error(e.message) @@ -62,6 +69,15 @@ class AccountsController < ApplicationController # 用户登录 def login @user = User.try_to_login(params[:login], params[:password]) + + if @user + # user is already in local database + return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked? + return normal_status(-2, "错误的账号或密码") unless @user.check_password?(params[:password].to_s) + else + return normal_status(-2, "错误的账号或密码") + end + @user.update_column(:last_login_on, Time.now) successful_authentication(@user) @@ -83,20 +99,17 @@ class AccountsController < ApplicationController email = params[:login] verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last user = User.find_by_mail(email) #这里有问题,应该是为email,而不是mail 6.13-hs - - end - check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60) - unless check_code - tip_exception("验证码无效") end + return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip + return normal_status(-2, "验证码已失效") if !verifi_code&.effective? user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation] if user.save! sucess_status end - # rescue Exception => e - # uid_logger_error(e.message) - # tip_exception("密码重置失败,请稍后再试") + rescue Exception => e + uid_logger_error(e.message) + tip_exception("密码重置失败") end end @@ -107,7 +120,10 @@ class AccountsController < ApplicationController # generate a key and set cookie if autologin set_autologin_cookie(user) - UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id)) + UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip) + + # 注册完成后有一天的试用申请 + UserDayCertification.create(user_id: user.id, status: 1) end def set_autologin_cookie(user) @@ -127,7 +143,7 @@ class AccountsController < ApplicationController end def logout - UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id) + UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip) session[:user_id] = nil logout_user render :json => {status: 1, message: "退出成功!"} @@ -143,7 +159,7 @@ class AccountsController < ApplicationController # params[:login] 手机号或者邮箱号 # params[:type]为事件通知类型 1:用户注册注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱 # 如果有新的继续后面加 # 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱 - # 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 + # 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效 def get_verification_code code = %W(0 1 2 3 4 5 6 7 8 9) value = params[:login] @@ -152,6 +168,8 @@ class AccountsController < ApplicationController send_type = verify_type(login_type, type) verification_code = code.sample(6).join + logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ") + # 记录验证码 check_verification_code(verification_code, send_type, value) sucess_status diff --git a/app/controllers/add_department_applies_controller.rb b/app/controllers/add_department_applies_controller.rb new file mode 100644 index 000000000..644ebd87e --- /dev/null +++ b/app/controllers/add_department_applies_controller.rb @@ -0,0 +1,15 @@ +class AddDepartmentAppliesController < ApplicationController + before_action :require_login, :check_auth + + def create + CreateAddDepartmentApplyService.call(current_user, create_params) + render_ok + rescue CreateAddDepartmentApplyService::Error => ex + render_error(ex.message) + end + + private + def create_params + params.permit(:name, :school_id, :remarks) + end +end \ No newline at end of file diff --git a/app/controllers/add_school_applies_controller.rb b/app/controllers/add_school_applies_controller.rb new file mode 100644 index 000000000..c868d79c9 --- /dev/null +++ b/app/controllers/add_school_applies_controller.rb @@ -0,0 +1,16 @@ +class AddSchoolAppliesController < ApplicationController + before_action :require_login, :check_auth + + def create + CreateAddSchoolApplyService.call(current_user, create_params) + render_ok + rescue CreateAddSchoolApplyService::Error => ex + render_error(ex.message) + end + + private + + def create_params + params.permit(:name, :province, :city, :address, :remarks) + end +end \ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index cffe2df15..b0183574d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,6 +5,8 @@ class ApplicationController < ActionController::Base include RenderExpand include RenderHelper include ControllerRescueHandler + include GitHelper + include LoggerHelper protect_from_forgery prepend: true, unless: -> { request.format.json? } @@ -17,8 +19,19 @@ class ApplicationController < ActionController::Base # 全局配置参数 # 返回name对应的value - def edu_setting name - EduSetting.find_by_name(name).try(:value) + def edu_setting(name) + EduSetting.get(name) + end + + # 实训的访问权限 + def shixun_access_allowed + if !current_user.shixun_permission(@shixun) + tip_exception(403, "..") + end + end + + def admin_or_business? + User.current.admin? || User.current.business? end def user_course_identity @@ -33,15 +46,16 @@ class ApplicationController < ActionController::Base # 判断用户的邮箱或者手机是否可用 # params[:type] 1: 注册;2:忘记密码 def check_mail_and_phone_valid login, type - unless login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ || login =~ /^1\d{10}$/ - tip_exception("请输入正确的手机号或邮箱") + unless login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ || login =~ /^1\d{10}$/ || + login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/ + tip_exception(-2, "请输入正确的手机号或邮箱") end # 考虑到安全参数问题,多一次查询,去掉Union user = User.where(phone: login).first || User.where(mail: login).first if type.to_i == 1 && !user.nil? - tip_exception("该手机号码或邮箱已被注册") + tip_exception(-2, "该手机号码或邮箱已被注册") elsif type.to_i == 2 && user.nil? - tip_exception("该手机号码或邮箱未注册") + tip_exception(-2, "该手机号码或邮箱未注册") end sucess_status end @@ -55,7 +69,7 @@ class ApplicationController < ActionController::Base # 手机类型的发送 sigle_para = {phone: value} status = Educoder::Sms.send(mobile: value, code: code) - tip_exception(code_msg(status)) if status != 0 + tip_exception(-2, code_msg(status)) if status != 0 when 8, 3, 5 # 邮箱类型的发送 sigle_para = {email: value} @@ -63,8 +77,8 @@ class ApplicationController < ActionController::Base UserMailer.register_email(value, code).deliver_now # Mailer.run.email_register(code, value) rescue Exception => e - uid_logger_error(e.message) - tip_exception("邮件发送失败,请稍后重试") + logger_error(e) + tip_exception(-2,"邮件发送失败,请稍后重试") end end ver_params = {code_type: send_type, code: code}.merge(sigle_para) @@ -124,27 +138,26 @@ class ApplicationController < ActionController::Base end end + # 课堂教师、课堂管理员、超级管理员的权限(不包含助教) + def teacher_or_admin_allowed + unless current_user.course_identity(@course) < Course::ASSISTANT_PROFESSOR + normal_status(403, "") + end + end + def require_admin normal_status(403, "") unless User.current.admin? end + def require_business + normal_status(403, "") unless admin_or_business? + end + # 前端会捕捉401,弹登录弹框 # 未授权的捕捉407,弹试用申请弹框 def require_login #6.13 -hs - if User.current.logged? - if !current_user.profile_completed? - info_url = "#{edu_setting('old_edu_host')}/account/user_info" - tip_exception(402, info_url) - # render :json => { status: 402, url: info_url } - elsif current_user.certification != 1 - day_cer = UserDayCertification.where(user_id: current_user.id).last - tip_exception(407, "系统未授权") unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400 - end - else - tip_exception(401, "..") - end - + tip_exception(401, "..") unless User.current.logged? end # 异常提醒 @@ -172,85 +185,18 @@ class ApplicationController < ActionController::Base end # 系统全局认证 - # def check_auth - old_edu_host = edu_setting('old_edu_host') - ue = current_user.user_extension - - if current_user.lastname.blank? || ue.school_id.blank? || ue.identity.blank? || current_user.mail.blank? - info_url = old_edu_host + '/account/user_info' - render :json => { status: 402, url: info_url } + if current_user.certification != 1 && current_user.apply_actions.exists?(container_type: 'TrialAuthorization', status: 0) + tip_exception(408, "您的试用申请正在审核中,请耐心等待") elsif current_user.certification != 1 - day_cer = UserDayCertification.where(user_id: current_user.id).last - unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400 - account_url = old_edu_host + "/my/account" - render :json => { status: 402, url: account_url } - end + day_cer = UserDayCertification.find_by(user_id: current_user.id) + tip_exception(407, "系统未授权") unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400 + elsif !current_user.profile_completed? + info_url = '/account/profile' + tip_exception(402, info_url) end end - # 身份资料的认证: - # 如果试用过期则弹框提示认证,先跳入个人资料页面完善资料,资料完成后,弹框提醒用户试用申请 - def check_account - # # todo user_extension - # if User.current.logged? - # ue = current_user.user_extension - # if current_user.lastname.blank? || ue.school_id.blank? || ue.identity.blank? || current_user.mail.blank? - # info_url = "#{edu_setting('old_edu_host')}/account/user_info" - # render :json => { status: 402, url: info_url } - # end - # end - end - - # 版本库目录空间 - def repo_namespace(user_login, shixun_identifier) - "#{user_login}/#{shixun_identifier}.git" - end - - # 版本库文件内容,带转码 - def git_fle_content(repo_path, path) - begin - content = GitService.file_content(repo_path: repo_path, path: path)["content"] - logger.info("@@@@@@@@@@@@@@@@@@#{content}") - - decode_content = nil - if content.present? - content = Base64.decode64(content) - cd = CharDet.detect(content) - logger.info "encoding: #{cd['encoding']} confidence: #{cd['confidence']}" - - decode_content = - if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8 - content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '}) - else - content.force_encoding('UTF-8') - end - end - - decode_content - rescue Exception => e - uid_logger_error(e.message) - raise Educoder::TipException.new("文档内容获取异常") - end - end - - # 更新文件代码 - # content: 文件内容;message:提交描述 - def update_file_content(content, repo_path, path, mail, username, message) - GitService.update_file(repo_path: repo_path, file_path: path, message: message, - content: content, author_name: username, author_email: mail) - end - - # 版本库Fork功能 - def project_fork(container, original_rep_path, username) - raise Educoder::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank? - # 将要生成的仓库名字 - new_repo_name = "#{username}/#{container.try(:identifier)}#{ Time.now.strftime("%Y%m%d%H%M%S")}" - uid_logger("start fork container: repo_name is #{new_repo_name}") - GitService.fork_repository(repo_path: original_rep_path, fork_repository_path: (new_repo_name + ".git")) - container.update_attributes!(:repo_name => new_repo_name) - end - def start_user_session(user) session[:user_id] = user.id session[:ctime] = Time.now.utc.to_i @@ -258,20 +204,26 @@ class ApplicationController < ActionController::Base end def user_setup + # reacct静态资源加载不需要走这一步 + return if params[:controller] == "main" # Find the current user User.current = find_current_user - uid_logger("user_step: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous")) + uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous")) if !User.current.logged? && Rails.env.development? User.current = User.find 12 end + # User.current = User.find 81403 + if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除 - User.current = User.find 49610 + User.current = User.find 81403 elsif params[:debug] == 'student' User.current = User.find 8686 elsif params[:debug] == 'admin' User.current = User.find 1 + elsif params[:debug] + User.current = User.find_by_login params[:debug] end end @@ -289,6 +241,7 @@ class ApplicationController < ActionController::Base # Returns the current user or nil if no user is logged in # and starts a session if needed def find_current_user + uid_logger("user setup start: session[:user_id] is #{session[:user_id]}") if session[:user_id] # existing session (User.active.find(session[:user_id]) rescue nil) @@ -330,16 +283,6 @@ class ApplicationController < ActionController::Base end end - # 以用户id开始的日志定义 - def uid_logger(message) - Rails.logger.info("##:#{current_user.try(:id)} --#{message}") - end - - # 以用户id开始的日志定义 - def uid_logger_error(message) - Rails.logger.error("##:#{current_user.try(:id)} --#{message}") - end - ## 输出错误信息 def error_status(message = nil) @status = -1 @@ -403,12 +346,6 @@ class ApplicationController < ActionController::Base end end - #实训题的关卡url初始化 - def challenge_path(path) - cha_path = path.present? ? path.split(";") : [] - cha_path.reject(&:blank?)[0].try(:strip) - end - # 适用与已经用url_safe编码后,回调字符串形式 def tran_base64_decode64(str) s_size = str.size % 4 @@ -472,6 +409,24 @@ class ApplicationController < ActionController::Base container.to_json end + # 实训中间层pod配置 + def shixun_container_limit shixun + container = [] + shixun.shixun_service_configs.each do |config| + mirror = config.mirror_repository + if mirror.name.present? + container << {:image => mirror.name, + :cpuLimit => config.cpu_limit, + :cpuRequest => config.lower_cpu_limit, + :memoryLimit => "#{config.memory_limit}M", + :memoryRequest => "#{config.request_limit}M", + :resourceLimit => "#{config.resource_limit}K", + :type => mirror.try(:main_type) == "1" ? "main" : "sub"} + end + end + container.to_json + end + # 毕设任务列表的赛选 def course_work(task, **option) logger.info("#############{option}") diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index 0a89bb3f9..2efe1df09 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -2,10 +2,9 @@ # # 文件上传 class AttachmentsController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :find_file, only: %i[show destroy] - include ErrorCommon include ApplicationHelper def show @@ -15,7 +14,7 @@ class AttachmentsController < ApplicationController update_downloads(@file) redirect_to @file.cloud_url and return end - send_file absolute_path(local_path(@file)), type: @file.content_type + send_file absolute_path(local_path(@file)), type: @file.content_type.presence || 'application/octet-stream' update_downloads(@file) end @@ -25,51 +24,50 @@ class AttachmentsController < ApplicationController # 2. 上传到云 upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称 uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}") - if upload_file - folder = edu_setting('attachment_folder') - raise "存储目录未定义" unless folder.present? + raise "未上传文件" unless upload_file - month_folder = current_month_folder - save_path = File.join(folder, month_folder) + folder = edu_setting('attachment_folder') + raise "存储目录未定义" unless folder.present? - ext = file_ext(upload_file.original_filename) + month_folder = current_month_folder + save_path = File.join(folder, month_folder) - local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext) + ext = file_ext(upload_file.original_filename) - content_type = upload_file.content_type.presence || 'application/octet-stream' + local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext) - remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type) + content_type = upload_file.content_type.presence || 'application/octet-stream' - logger.info "local_path: #{local_path}" - logger.info "remote_path: #{remote_path}" + # remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type) + remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端 + logger.info "local_path: #{local_path}" + logger.info "remote_path: #{remote_path}" - disk_filename = local_path[save_path.size + 1, local_path.size] - #存数据库 - # - @attachment = Attachment.where(disk_filename: disk_filename, - author_id: current_user.id, - cloud_url: remote_path).first - unless @attachment.present? - @attachment = Attachment.new - @attachment.filename = upload_file.original_filename - @attachment.disk_filename = local_path[save_path.size + 1, local_path.size] - @attachment.filesize = upload_file.tempfile.size - @attachment.content_type = content_type - @attachment.digest = digest - @attachment.author_id = current_user.id - @attachment.disk_directory = month_folder - @attachment.cloud_url = remote_path - @attachment.save! - else - logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}" - end + disk_filename = local_path[save_path.size + 1, local_path.size] + #存数据库 + # + @attachment = Attachment.where(disk_filename: disk_filename, + author_id: current_user.id, + cloud_url: remote_path).first - render_json + if @attachment.blank? + @attachment = Attachment.new + @attachment.filename = upload_file.original_filename + @attachment.disk_filename = local_path[save_path.size + 1, local_path.size] + @attachment.filesize = upload_file.tempfile.size + @attachment.content_type = content_type + @attachment.digest = digest + @attachment.author_id = current_user.id + @attachment.disk_directory = month_folder + @attachment.cloud_url = remote_path + @attachment.save! else - raise "未上传文件" + logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}" end + + render_json end def destroy diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb index 51c8397b1..1081a82ce 100644 --- a/app/controllers/boards_controller.rb +++ b/app/controllers/boards_controller.rb @@ -1,54 +1,47 @@ class BoardsController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :find_course, only: [:create] before_action :set_board, except: [:create] - before_action :teacher_allowed + before_action :teacher_or_admin_allowed def index - @boards = @course.boards.includes(messages: [:last_reply, :author]); + @boards = @course.boards.includes(messages: [:last_reply, :author]) end def show - - end - - def new end def create ActiveRecord::Base.transaction do - begin - board = @course.course_board - new_board = Board.new(board_params) - new_board.course_id = @course.id - new_board.project_id = -1 - new_board.parent_id = board.try(:id) - new_board.position = board.children.count + 1 - new_board.save! - normal_status(0, "添加成功") - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback - end + board = @course.course_board + new_board = Board.new(board_params) + new_board.course_id = @course.id + new_board.project_id = -1 + new_board.parent_id = board.try(:id) + new_board.position = board.children.count + 1 + new_board.save! end + + normal_status(0, "添加成功") end # 子目录的拖动 def move_category tip_exception("移动失败") if params[:position].blank? - unless params[:position].to_i == @board.position - course_board = @course.course_board + return normal_status(-1, "位置没有变化") if params[:position].to_i == @board.position + + course_board = @course.course_board + ActiveRecord::Base.transaction do if params[:position].to_i < @board.position - course_board.children.where("position < #{@board.position} and position >= ?", params[:position]).update_all("position = position + 1") + course_board.children.where("position < ? and position >= ?", @board.position, params[:position]) + .update_all("position = position + 1") else - course_board.children.where("position > #{@board.position} and position <= ?", params[:position]).update_all("position = position - 1") + course_board.children.where("position > ? and position <= ?", @board.position, params[:position]) + .update_all("position = position - 1") end @board.update_attributes(position: params[:position]) - normal_status(0, "移动成功") - else - normal_status(-1, "位置没有变化") end + normal_status(0, "移动成功") end def destroy diff --git a/app/controllers/challenges_controller.rb b/app/controllers/challenges_controller.rb index d603904c4..9b5f0b869 100644 --- a/app/controllers/challenges_controller.rb +++ b/app/controllers/challenges_controller.rb @@ -1,12 +1,14 @@ class ChallengesController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :find_shixun, only: [:new, :create, :index] skip_before_action :verify_authenticity_token, only: [:create, :update, :create_choose_question, :crud_answer] before_action :find_challenge, only: [:edit, :show, :update, :create_choose_question, :index_down, :index_up, :edit_choose_question, :show_choose_question, :destroy_challenge_choose, :update_choose_question, :destroy, :crud_answer, :answer] - # before_action :allowed, except: [:index, :show, :edit_choose_question, :edit] - + # 关卡更新和操作的权限控制 + before_action :update_allowed, except: [:index] + # 关卡访问的权限控制 + before_action :shixun_access_allowed, only: [:index] include ShixunsHelper include ChallengesHelper @@ -136,7 +138,7 @@ class ChallengesController < ApplicationController # tab 0,nil 过关任务, 1 评测设置, 2 参考答案 def edit @tab = params[:tab].to_i - @power = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0 + @power = @shixun.status == 0 challenge_num = Challenge.where(:shixun_id => @shixun).count @position = @challenge.position @chooses = @challenge.challenge_chooses @@ -148,16 +150,17 @@ class ChallengesController < ApplicationController def index uid_logger("identifier: #{params}") - # 通过调试发现 这里includes(:games)性能会慢10倍 - @challenges = @shixun.challenges.fields_for_list - @editable = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0 + + @challenges = Challenge.fields_for_list.where(shixun_id: @shixun.id) + + @editable = @shixun.status == 0 # before_action:有判断权限,如果没发布,则肯定是管理人员 @user = current_user end def show @tab = params[:tab].nil? ? 1 : params[:tab].to_i - challenge_num = Challenge.where(shixun_id: @shixun).count - @power = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0 + challenge_num = @shixun.challenges_count + @power = @shixun.status == 0 # 之前验证走过了是不是管理员,因此这里只用判断是否发布 @position = @challenge.position if @position < challenge_num @next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first @@ -206,7 +209,7 @@ class ChallengesController < ApplicationController end # 关卡评测执行文件如果被修改,需要修改脚本内容 script = modify_shixun_script @shixun, @shixun.evaluate_script - @shixun.update_column(:evaluate_script, script) + @shixun.shixun_info.update_column(:evaluate_script, script) # TODO: # if path != params[:challenge][:path] # shixun_modify_status_without_publish(@shixun, 1) @@ -246,8 +249,7 @@ class ChallengesController < ApplicationController next_challenge.update_attribute(:position, next_challenge.position - 1) # 关卡位置被修改,需要修改脚本 script = modify_shixun_script @shixun, @shixun.evaluate_script - @shixun.update_column(:evaluate_script, script) - + @shixun.shixun_info.update_column(:evaluate_script, script) end def index_up @@ -257,7 +259,7 @@ class ChallengesController < ApplicationController last_challenge.update_attribute(:position, last_challenge.position + 1) # 关卡位置被修改,需要修改脚本 script = modify_shixun_script @shixun, @shixun.evaluate_script - @shixun.update_column(:evaluate_script, script) + @shixun.shixun_info.update_column(:evaluate_script, script) end def destroy @@ -268,7 +270,7 @@ class ChallengesController < ApplicationController @challenge.destroy # 关卡位置被删除,需要修改脚本 script = modify_shixun_script @shixun, @shixun.evaluate_script - @shixun.update_column(:evaluate_script, script) + @shixun.shixun_info.update_column(:evaluate_script, script) end @@ -287,7 +289,7 @@ class ChallengesController < ApplicationController def challenge_params params.require(:challenge).permit(:subject, :task_pass, :difficulty, :score, :st, :modify_time, :test_set_average, :path, :exec_path, :show_type, :original_picture_path, :test_set_score, - :expect_picture_path, :picture_path, :web_route, :answer) + :expect_picture_path, :picture_path, :web_route, :answer, :exec_time) end def chooce_params @@ -295,9 +297,8 @@ class ChallengesController < ApplicationController :standard_answer, :score, :difficult) end - def allowed - # 实训为发布前,除实训的管理者外,其他人都不人都不允许访问 - if !current_user.manager_of_shixun?(@shixun) && (@shixun.status < 1 || @shixun.hidden == 1) + def update_allowed + unless current_user.manager_of_shixun?(@shixun) raise Educoder::TipException.new(403, "..") end end diff --git a/app/controllers/commons_controller.rb b/app/controllers/commons_controller.rb index ca68c65d3..0c0fe79af 100644 --- a/app/controllers/commons_controller.rb +++ b/app/controllers/commons_controller.rb @@ -1,7 +1,7 @@ class CommonsController < ApplicationController OBJECT_TYPE = %W[message journals_for_message] - before_action :require_login + before_action :require_login, :check_auth before_action :validate_object_type before_action :find_object before_action :validate_power @@ -42,7 +42,24 @@ class CommonsController < ApplicationController end def validate_power - tip_exception(403, "无操作权限") unless current_user.admin? + code = + case params[:object_type].strip + when 'message' + if current_user.course_identity(@object.board.course) >= Course::STUDENT && @object.author != current_user + 403 + else + 200 + end + when 'journals_for_message' + if current_user.course_identity(@object.jour.course) >= Course::STUDENT && @object.user != current_user + 403 + else + 200 + end + else + current_user.admin? ? 200 : 403 + end + return normal_status(code, "你没有权限操作!") if code == 403 end def action(flag) diff --git a/app/controllers/competitions/base_controller.rb b/app/controllers/competitions/base_controller.rb new file mode 100644 index 000000000..b42a4ce8f --- /dev/null +++ b/app/controllers/competitions/base_controller.rb @@ -0,0 +1,11 @@ +class Competitions::BaseController < ApplicationController + include PaginateHelper + + before_action :require_login + + helper_method :current_competition + + def current_competition + @_current_competition ||= Competition.find_by!(identifier: params[:competition_id]) + end +end \ No newline at end of file diff --git a/app/controllers/competitions/competition_modules_controller.rb b/app/controllers/competitions/competition_modules_controller.rb new file mode 100644 index 000000000..c4692af70 --- /dev/null +++ b/app/controllers/competitions/competition_modules_controller.rb @@ -0,0 +1,38 @@ +class Competitions::CompetitionModulesController < Competitions::BaseController + skip_before_action :require_login, only: [:index, :show] + + before_action :require_business, only: [:update] + + def index + @modules = current_competition.unhidden_competition_modules.order(position: :asc) + end + + def show + @module = current_module + end + + def update + md = current_module.competition_module_md_content || current_module.build_competition_module_md_content + md.name = params[:md_name] + md.content = params[:md_content] + + ActiveRecord::Base.transaction do + md.save! + + attachment_ids = Array.wrap(params[:attachment_ids]).map(&:to_i) + old_attachment_ids = md.attachments.pluck(:id) + + destroy_ids = old_attachment_ids - attachment_ids + md.attachments.where(id: destroy_ids).delete_all + Attachment.where(id: attachment_ids - old_attachment_ids).update_all(container: md) + end + + render_ok + end + + private + + def current_module + @_current_module ||= current_competition.unhidden_competition_modules.find(params[:id]) + end +end diff --git a/app/controllers/competitions/competition_staffs_controller.rb b/app/controllers/competitions/competition_staffs_controller.rb new file mode 100644 index 000000000..39b91e57f --- /dev/null +++ b/app/controllers/competitions/competition_staffs_controller.rb @@ -0,0 +1,4 @@ +class Competitions::CompetitionStaffsController < Competitions::BaseController + def show + end +end diff --git a/app/controllers/competitions/competition_teams_controller.rb b/app/controllers/competitions/competition_teams_controller.rb new file mode 100644 index 000000000..e03810b61 --- /dev/null +++ b/app/controllers/competitions/competition_teams_controller.rb @@ -0,0 +1,70 @@ +class Competitions::CompetitionTeamsController < Competitions::BaseController + def index + admin_or_business? ? all_competition_teams : user_competition_teams + end + + def create + if current_competition.personal? # 个人赛报名 + Competitions::CreatePersonalTeamService.call(current_competition, current_user) + else + team = current_competition.competition_teams.new(user: current_user) + Competitions::SaveTeamService.call(team, save_params) + end + render_ok + + rescue Competitions::CreatePersonalTeamService::Error => ex + render_error(ex.message) + end + + def update + team = current_competition.competition_teams.where(user: current_user).find(params[:id]) + Competitions::SaveTeamService.call(team, save_params) + render_ok + end + + def join + Competitions::JoinTeamService.call(current_competition, current_user, params) + render_ok + rescue Competitions::JoinTeamService::Error => ex + render_error(ex.message) + end + + def leave + team = current_competition.competition_teams.find(params[:id]) + member = team.team_members.find_by(user_id: current_user.id) + return render_error('您不是该战队的成员') if member.blank? + + if member.user_id == team.user_id + team.destroy! # 队长退出,战队解散 + else + member.destroy! + end + + render_ok + end + + private + + def all_competition_teams + teams = current_competition.competition_teams + + keyword = params[:keyword].to_s.strip + if keyword.present? + teams = teams.joins(users: { user_extension: :school }).where('schools.name LIKE ?', "%#{keyword}%") + end + + @count = teams.count + @teams = paginate(teams.includes(:user, users: { user_extension: :school })) + end + + def user_competition_teams + teams = current_competition.competition_teams + teams = teams.joins(:team_members).where(team_members: { user_id: current_user.id }) + @teams = teams.includes(:user, users: { user_extension: :school }).to_a + @count = @teams.size + end + + def save_params + params.permit(:name, teacher_ids: [], member_ids: []) + end +end diff --git a/app/controllers/competitions/competitions_controller.rb b/app/controllers/competitions/competitions_controller.rb new file mode 100644 index 000000000..34dac7350 --- /dev/null +++ b/app/controllers/competitions/competitions_controller.rb @@ -0,0 +1,38 @@ +class Competitions::CompetitionsController < Competitions::BaseController + skip_before_action :require_login + + def index + # 已上架 或者 即将上架 + competitions = Competition.where(status: true).or(Competition.where.not(published_at: nil)) + + competitions = + case params[:category] + when 'nearly_published' then competitions.where(status: false) + when 'progressing' then competitions.where('end_time > NOW()') + when 'ended' then competitions.where('end_time < NOW()') + else competitions + end + + @count = competitions.count + + competitions = competitions.order(published_at: :desc, online_time: :desc) + @competitions = paginate(competitions.includes(current_stage_section: :competition_stage)) + + ids = @competitions.map(&:id) + @member_count_map = TeamMember.where(competition_id: ids).group(:competition_id).count + @stage_count_map = CompetitionStage.where(competition_id: ids).group(:competition_id).count + end + + def show + unless current_competition.published? || admin_or_business? + render_forbidden + return + end + end + + private + + def current_competition + @_current_competition ||= Competition.find_by!(identifier: params[:id]) + end +end \ No newline at end of file diff --git a/app/controllers/competitions/students_controller.rb b/app/controllers/competitions/students_controller.rb new file mode 100644 index 000000000..8fd235fd1 --- /dev/null +++ b/app/controllers/competitions/students_controller.rb @@ -0,0 +1,22 @@ +class Competitions::StudentsController < Competitions::BaseController + def index + keyword = params[:keyword].to_s.strip + if keyword.blank? + @students = [] + return + end + + students = User.joins(:user_extension).where(status: 1, user_extensions: { identity: 1 }) + students = students.where.not(id: params[:student_ids]) if params[:student_ids].present? + students = students.where('LOWER(CONCAT(lastname, firstname, login, nickname)) LIKE ?', "%#{keyword}%") + @students = students.includes(user_extension: :school).limit(20) + + # 队员多次报名限制 + if current_competition.member_multiple_limited? + ids = @students.map(&:id) + members = current_competition.team_members.where(user_id: ids) + members = members.where.not(competition_team_id: params[:team_id]) if params[:team_id].present? + @enrolled_map = members.group(:user_id).count + end + end +end diff --git a/app/controllers/competitions/teachers_controller.rb b/app/controllers/competitions/teachers_controller.rb new file mode 100644 index 000000000..76c7cfe6a --- /dev/null +++ b/app/controllers/competitions/teachers_controller.rb @@ -0,0 +1,22 @@ +class Competitions::TeachersController < Competitions::BaseController + def index + keyword = params[:keyword].to_s.strip + if keyword.blank? + @teachers = [] + return + end + + teachers = User.joins(:user_extension).where(status: 1, user_extensions: { identity: 0 }) + teachers = teachers.where.not(id: params[:teacher_ids]) if params[:teacher_ids].present? + teachers = teachers.where('LOWER(CONCAT(lastname, firstname, login, nickname)) LIKE ?', "%#{keyword}%") + @teachers = teachers.includes(user_extension: :school).limit(10) + + # 老师多次报名限制 + if current_competition.teacher_multiple_limited? + ids = @teachers.map(&:id) + members = current_competition.team_members.where(user_id: ids) + members = members.where.not(competition_team_id: params[:team_id]) if params[:team_id].present? + @enrolled_map = members.group(:user_id).count + end + end +end diff --git a/app/controllers/concerns/controller_rescue_handler.rb b/app/controllers/concerns/controller_rescue_handler.rb index e9563d1e5..bacd6a793 100644 --- a/app/controllers/concerns/controller_rescue_handler.rb +++ b/app/controllers/concerns/controller_rescue_handler.rb @@ -2,6 +2,10 @@ module ControllerRescueHandler extend ActiveSupport::Concern included do + rescue_from Exception do |e| + logger.error e + render json: {status: -1, message: e.message} + end # rescue_from ActionView::MissingTemplate, with: :object_not_found # rescue_from ActiveRecord::RecordNotFound, with: :object_not_found rescue_from Educoder::TipException, with: :tip_show @@ -12,5 +16,8 @@ module ControllerRescueHandler rescue_from ActiveModel::ValidationError do |ex| render_error(ex.model.errors.full_messages.join(',')) end + rescue_from ActiveRecord::RecordInvalid do |ex| + render_error(ex.record.errors.full_messages.join(',')) + end end end \ No newline at end of file diff --git a/app/controllers/concerns/error_common.rb b/app/controllers/concerns/error_common.rb deleted file mode 100644 index 5a5f41673..000000000 --- a/app/controllers/concerns/error_common.rb +++ /dev/null @@ -1,10 +0,0 @@ -module ErrorCommon - extend ActiveSupport::Concern - - included do - rescue_from Exception do |e| - logger.error e - render json: {status: -1, message: e.message} - end - end -end \ No newline at end of file diff --git a/app/controllers/concerns/git_common.rb b/app/controllers/concerns/git_common.rb index 2f977245c..452204419 100644 --- a/app/controllers/concerns/git_common.rb +++ b/app/controllers/concerns/git_common.rb @@ -28,7 +28,6 @@ module GitCommon end def file_content - logger.info("#################{@repo_path}, #{@path}") @content = git_fle_content @repo_path, @path end diff --git a/app/controllers/concerns/git_helper.rb b/app/controllers/concerns/git_helper.rb new file mode 100644 index 000000000..65ebd4074 --- /dev/null +++ b/app/controllers/concerns/git_helper.rb @@ -0,0 +1,62 @@ +module GitHelper + extend ActiveSupport::Concern + + # 版本库目录空间 + def repo_namespace(user_login, shixun_identifier) + "#{user_login}/#{shixun_identifier}.git" + end + + # 版本库文件内容,带转码 + def git_fle_content(repo_path, path) + begin + Rails.logger.info("git file content: repo_path is #{repo_path}, path is #{path}") + content = GitService.file_content(repo_path: repo_path, path: path) + + Rails.logger.info("git file content: content is #{content}") + decode_content = nil + if content.present? + content = content["content"] #6.24 -hs 这个为新增,因为当实训题里含有选择题时,这里会报错,undefined method `[]' for nil:NilClass + + content = Base64.decode64(content) + cd = CharDet.detect(content) + Rails.logger.info "encoding: #{cd['encoding']} confidence: #{cd['confidence']}" + + decode_content = + if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8 + content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '}) + else + content.force_encoding('UTF-8') + end + end + + decode_content + + rescue Exception => e + Rails.logger.error(e.message) + raise Educoder::TipException.new("文档内容获取异常") + end + end + + # 更新文件代码 + # content: 文件内容;message:提交描述 + def update_file_content(content, repo_path, path, mail, username, message) + GitService.update_file(repo_path: repo_path, file_path: path, message: message, + content: content, author_name: username, author_email: mail) + end + + # 版本库Fork功能 + def project_fork(container, original_rep_path, username) + raise Educoder::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank? + # 将要生成的仓库名字 + new_repo_name = "#{username}/#{container.try(:identifier)}#{ Time.now.strftime("%Y%m%d%H%M%S")}" + uid_logger("start fork container: repo_name is #{new_repo_name}") + GitService.fork_repository(repo_path: original_rep_path, fork_repository_path: (new_repo_name + ".git")) + container.update_attributes!(:repo_name => new_repo_name) + end + + #实训题的关卡url初始化 + def challenge_path(path) + cha_path = path.present? ? path.split(";") : [] + cha_path.reject(&:blank?)[0].try(:strip) + end +end \ No newline at end of file diff --git a/app/controllers/concerns/logger_helper.rb b/app/controllers/concerns/logger_helper.rb new file mode 100644 index 000000000..44d0448ce --- /dev/null +++ b/app/controllers/concerns/logger_helper.rb @@ -0,0 +1,16 @@ +module LoggerHelper + extend ActiveSupport::Concern + + extend LoggerHelper + + + # 以用户id开始的日志定义 + def uid_logger(message) + Rails.logger.info("##:#{current_user.try(:id)} --#{message}") + end + + # 以用户id开始的日志定义 + def uid_logger_error(message) + Rails.logger.error("##:#{current_user.try(:id)} --#{message}") + end +end \ No newline at end of file diff --git a/app/controllers/concerns/paginate_helper.rb b/app/controllers/concerns/paginate_helper.rb new file mode 100644 index 000000000..13148bf42 --- /dev/null +++ b/app/controllers/concerns/paginate_helper.rb @@ -0,0 +1,8 @@ +module PaginateHelper + def paginate(objs, **opts) + page = params[:page].to_i <= 0 ? 1 : params[:page].to_i + per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 20 + + Kaminari.paginate_array(objs).page(page).per(per_page) + end +end \ No newline at end of file diff --git a/app/controllers/concerns/render_helper.rb b/app/controllers/concerns/render_helper.rb index 94ac351cd..5ea73e666 100644 --- a/app/controllers/concerns/render_helper.rb +++ b/app/controllers/concerns/render_helper.rb @@ -16,4 +16,8 @@ module RenderHelper render json: { status: 403, message: message } # render status: 403, json: { errors: errors } end + + def render_unauthorized(message = I18n.t('error.unauthorized')) + render json: { status: 401, message: message } + end end \ No newline at end of file diff --git a/app/controllers/course_groups_controller.rb b/app/controllers/course_groups_controller.rb index 8b6737e0f..0e16d1bac 100644 --- a/app/controllers/course_groups_controller.rb +++ b/app/controllers/course_groups_controller.rb @@ -1,8 +1,8 @@ class CourseGroupsController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :set_group, except: [:create] before_action :find_course, only: [:create] - before_action :teacher_allowed + before_action :teacher_or_admin_allowed def create tip_exception("分班名称不能为空") if params[:name].blank? diff --git a/app/controllers/course_modules_controller.rb b/app/controllers/course_modules_controller.rb index d8d4ea128..6e8afd525 100644 --- a/app/controllers/course_modules_controller.rb +++ b/app/controllers/course_modules_controller.rb @@ -1,8 +1,8 @@ class CourseModulesController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :set_module, except: [:unhidden_modules] before_action :find_course, only: [:unhidden_modules] - before_action :teacher_allowed + before_action :teacher_or_admin_allowed # 模块置顶 def sticky_module @@ -16,6 +16,7 @@ class CourseModulesController < ApplicationController # 模块隐藏 def hidden_module + tip_exception("请至少保留一个课堂模块") if @course.none_hidden_course_modules.where.not(id: @course_module.id).size == 0 @course_module.update_attributes(hidden: 1) normal_status(0, "更新成功") end diff --git a/app/controllers/course_second_categories_controller.rb b/app/controllers/course_second_categories_controller.rb index d0f07f47f..af368a8dc 100644 --- a/app/controllers/course_second_categories_controller.rb +++ b/app/controllers/course_second_categories_controller.rb @@ -1,7 +1,7 @@ class CourseSecondCategoriesController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :set_category - before_action :teacher_allowed + before_action :teacher_or_admin_allowed # 目录重命名 def rename_category diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index df23b6b25..1cee38816 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -2,8 +2,6 @@ class CoursesController < ApplicationController include MessagesHelper include ExportHelper - rescue_from ::ActionView::MissingTemplate, with: :missing_template - rescue_from ActiveRecord::RecordNotFound, with: :object_not_found # model validation error rescue_from ActiveRecord::RecordInvalid do |ex| render_error(ex.record.errors.full_messages.join(',')) @@ -13,9 +11,9 @@ class CoursesController < ApplicationController render_error(ex.model.errors.full_messages.join(',')) end - before_action :require_login, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups] + before_action :require_login, :check_auth, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups, :left_banner, :top_banner] before_action :set_course, :user_course_identity, only: [:show, :update, :destroy, :settings, :set_invite_code_halt, - :set_public_or_private, :search_teacher_candidate, :teachers, + :set_public_or_private, :search_teacher_candidate, :teachers, :apply_teachers, :top_banner, :left_banner, :add_teacher_popup, :add_teacher, :graduation_group_list, :create_graduation_group, :join_graduation_group, :course_group_list, :set_course_group, :change_course_admin, :change_course_teacher, @@ -27,11 +25,11 @@ class CoursesController < ApplicationController before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate, :transfer_to_course_group, :delete_from_course, :search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup, :add_teacher] - before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, - :set_course_group, :change_course_admin, :change_course_teacher, - :delete_course_teacher, :teacher_application_review, :create_group_by_importing_file] + before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin, + :set_course_group, :delete_course_teacher, :create_group_by_importing_file] before_action :teacher_or_admin_allowed, only: [:graduation_group_list, :create_graduation_group, :join_graduation_group, - :export_member_scores_excel, :course_group_list] + :change_course_teacher, :export_member_scores_excel, :course_group_list, + :teacher_application_review, :apply_teachers] before_action :validate_course_name, only: [:create, :update] before_action :find_board, only: :board_list before_action :validate_page_size, only: :mine @@ -49,47 +47,55 @@ class CoursesController < ApplicationController @order = params[:order].present? ? params[:order] : "all" order_str = @order != "course_members_count" && @order != "created_at" ? "updated_at" : @order - if @order == "all" - # @course = Course.where(is_delete: 0, is_hidden: 0).find_by_sql("select c.name, c.id, s.name, u.last_name from - # courses c, users u, user_extensions ue, schools s where c.is_delete=0 and c.tea_id=u.id and - # u.id=ue.user_id and ue.school_id=s.id limit 10;") + # if @order == "all" + # @course = Course.where(is_delete: 0, is_hidden: 0).select("select c.name, c.id, s.name, u.login, ifnull(concat(u.lastname,u.firstname), + # u.login), s.name from courses c, users u, user_extensions ue, schools s where c.is_delete=0 and + # c.tea_id=u.id and u.id=ue.user_id and ue.school_id=s.id") - @courses = Course.where(is_delete: 0, is_hidden: 0).select("courses.id, courses.tea_id, courses.name, courses.exercises_count, courses.polls_count, - courses.is_public, courses.is_end, courses.visits, courses.course_members_count,courses.homework_commons_count,(SELECT MAX(created_at) - FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a") - .order("courses.id = 1309 desc, a desc") - elsif @order == "mine" + # @courses = Course.where(is_delete: 0, is_hidden: 0) + # .order("courses.id = 1309 desc, courses.created_at desc") + + # @courses = Course.where(is_delete: 0, is_hidden: 0).select("courses.id, courses.tea_id, courses.name, courses.exercises_count, courses.polls_count, + # courses.is_public, courses.is_end, courses.visits, courses.course_members_count,courses.homework_commons_count,(SELECT MAX(created_at) + # FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a") + # .order("courses.id = 1309 desc, a desc") + if @order == "mine" + tip_exception(401, "..") unless current_user.logged? @courses = Course.joins(:course_members) - .where("is_delete = 0 AND is_hidden = 0 AND course_members.user_id = ?", @user.id) - .order("courses.id = 1309 DESC, courses.#{order_str} DESC") + .where("is_delete = 0 AND is_hidden = 0 AND course_members.user_id = ?", @user.id).distinct elsif @order == "created_at" # REDO:Extension - @courses = Course.joins(teacher: :user_extension) - .where(is_delete: 0, is_hidden: 0, is_end: 0) - .order("courses.id = 1309 DESC, courses.#{order_str} DESC") + @courses = Course.where(is_delete: 0, is_hidden: 0, is_end: 0).distinct else # REDO:Extension - @courses = Course.joins(teacher: :user_extension) - .where(is_delete: 0, is_hidden: 0) - .order("courses.id = 1309 DESC, courses.#{order_str} DESC") + @courses = Course.where(is_delete: 0, is_hidden: 0).distinct end # 根据搜索关键字进一步筛选 if params[:search].present? # REDO:Extension - user_ids = User.includes(user_extension: :school).where("schools.name like ?", "%#{params[:search]}%").pluck(:id) - course_ids = CourseMember.includes(:user, :course).where("course_members.course_id in (?) and course_members.role in (1,2,3) - and CONCAT(users.lastname, users.firstname) like ?", @courses.map(&:id), "%#{params[:search]}%") - .pluck(:course_id) - @courses = @courses.where("name like ?", "%#{params[:search]}%").or(@courses.where(tea_id: user_ids)).or(@courses.where(id: course_ids)) + #user_ids = User.includes(user_extension: :school).where("schools.name like ?", "%#{params[:search]}%").pluck(:id) + #course_ids = CourseMember.includes(:user, :course).where("course_members.course_id in (?) and course_members.role in (1,2,3) + # and CONCAT(users.lastname, users.firstname) like ?", @courses.map(&:id), "%#{params[:search]}%") + # .pluck(:course_id) + #@courses = @courses.where("name like ?", "%#{params[:search]}%").or(@courses.where(tea_id: user_ids)).or(@courses.where(id: course_ids)) + # 6:21 daiao + sql = %Q{ + (course_members.role in(1,2,3) and CONCAT(users.lastname, users.firstname) like :keyword) or courses.name like :keyword + or schools.name like :keyword + } + @courses = @courses.joins(:school, course_members: :user) + .where("#{sql}", keyword: "%#{params[:search]}%").distinct end - @courses_count = @courses.size + @courses_count = @courses.count("courses.id") + @courses = @courses.order("courses.id = 1309 DESC, courses.#{order_str} DESC") # 分页 page = params[:page] || 1 limit = params[:limit] || 16 - @courses= @courses.page(page).per(limit) + @courses = @courses.page(page).per(limit) + @courses = @courses.preload(:school, :none_hidden_course_modules, teacher: :user_extension) end def visits_plus_one @@ -101,6 +107,7 @@ class CoursesController < ApplicationController # GET /courses/1 # GET /courses/1.json def show + # render :json => {first_category_url: module_url(course.course_modules.where.not(module_type: "activity").where(hidden: 0).first, course)} end # GET /courses/new @@ -241,44 +248,52 @@ class CoursesController < ApplicationController if @course.try(:id) != 1309 || current_user.admin? || current_user.try(:id) == 15582 @teacher_list = @course.course_members.joins(:user).where("course_members.role in (1, 2, 3) - and LOWER(concat(users.lastname, users.firstname)) LIKE '%#{@search_str}%'") + and LOWER(concat(users.lastname, users.firstname)) LIKE ?", "%#{@search_str}%") else @teacher_list = @course.course_members.joins(:user).where("(course_members.role in (1, 3) or (course_members.user_id = #{current_user.id} and course_members.role = 2)) and LOWER(concat(users.lastname, users.firstname)) - LIKE '%#{@search_str}%'") + LIKE ?", "%#{@search_str}%") end @teacher_list_size = @teacher_list.size @has_graduation_design = @course.course_modules.graduation_module_not_hidden.any? + sort = params[:sort] || "desc" @order = params[:order].to_i if @order.present? case @order when 1 - @teacher_list = @teacher_list.includes(:user).order("CONVERT(CONCAT(users.lastname, users.firstname) USING gbk) COLLATE gbk_chinese_ci asc") + @teacher_list = @teacher_list.order("role #{sort}") when 2 - @teacher_list = @teacher_list.order("created_at") + @teacher_list = @teacher_list.includes(:user).order("CONVERT(CONCAT(users.lastname, users.firstname) USING gbk) COLLATE gbk_chinese_ci #{sort}") when 3 - @teacher_list = @teacher_list.includes(:course, :graduation_group).order("graduation_groups.name") + @teacher_list = @teacher_list.includes(:course, :graduation_group).order("graduation_groups.name #{sort}") else - @teacher_list = @teacher_list.order("created_at") + @teacher_list = @teacher_list.order("role #{sort}") end else - if @has_graduation_design - @teacher_list = @teacher_list.includes(:course, :graduation_group).order("graduation_groups.name") - else - @teacher_list = @teacher_list.order("created_at") - end + @teacher_list = @teacher_list.order("role #{sort}") end - @is_admin = current_user.creator_of_course? @course + @is_admin = @user_course_identity < Course::PROFESSOR - @applications= CourseMessage.unhandled_join_course_requests_by_course(@course) + @applications_size = CourseMessage.unhandled_join_course_requests_by_course(@course).size page = params[:page] || 1 limit = params[:limit] || 20 @teacher_list = @teacher_list.page(page).per(limit) + @teacher_list = @teacher_list.preload(:graduation_group, :user, :teacher_course_groups) + end + + def apply_teachers + search_str = params[:search].present? ? params[:search].strip : "" + @applications = CourseMessage.unhandled_join_course_requests_by_course(@course). + joins("join users on course_messages.course_message_id=users.id"). + where("LOWER(concat(users.lastname, users.firstname)) LIKE ?", "%#{search_str}%") + @teacher_list_size = @course.teachers.size + @applications_size = CourseMessage.unhandled_join_course_requests_by_course(@course).size + @is_admin = @user_course_identity < Course::PROFESSOR end # 打开添加教师或助教弹窗时访问的接口(需要返回该课堂所有答辩组和所有) @@ -538,6 +553,7 @@ class CoursesController < ApplicationController course_teacher = CourseMember.find_by(user_id: current_user.id, role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR], course_id: @course.id) course_student.destroy! course_teacher.update_attributes(is_active: 1) if course_teacher.present? && !course_teacher.is_active + CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, [current_user.id]) normal_status(0, "退出成功") end @@ -566,6 +582,18 @@ class CoursesController < ApplicationController end new_teacher.save! + + # 课堂管理员才有分配权限,且课堂分班数大于0 + if @user_course_identity < Course::PROFESSOR && @course.course_groups_count > 0 && params[:group_id] && params[:group_id].size > 0 + # 分班全选则是不限,不需要做处理 + unless @course.course_groups.where(id: params[:group_id]).size == @course.course_groups_count + @course.course_groups.where(id: params[:group_id]).each do |group| + unless TeacherCourseGroup.where(course_id: @course.id, user_id: applier_user.id, course_group_id: group.id, course_member_id: new_teacher.id).exists? + TeacherCourseGroup.create(course_id: @course.id, user_id: applier_user.id, course_member_id: new_teacher.id, course_group_id: group.id) + end + end + end + end elsif approval == 2 course_message.reject! else @@ -625,7 +653,8 @@ class CoursesController < ApplicationController page = params[:page] || 1 limit = params[:limit] || 20 - @students= Kaminari.paginate_array(@students).page(page).per(limit) + @students= @students.page(page).per(limit) + @students = @students.includes(:course_group, user: :user_extension) end # 获取当前课程所有分班 @@ -674,11 +703,16 @@ class CoursesController < ApplicationController ActiveRecord::Base.transaction do begin students = params[:students] + student_ids = [] students.each do |student| - course_member = CourseMember.find_by!(id: student[:course_member_id].to_i, course_id: @course.id) - course_member.destroy! + course_member = CourseMember.find_by(id: student[:course_member_id].to_i, course_id: @course.id) + if course_member.present? + student_ids << course_member.user_id + course_member.destroy! + end end + CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, student_ids) if student_ids.present? normal_status(0, "操作成功") rescue => e uid_logger(e.message) @@ -701,7 +735,7 @@ class CoursesController < ApplicationController student_ids = [] user_ids.each do |user_id| - existing_course_member = CourseMember.find_by(user_id: user_id.to_i, course_id: @course.id) + existing_course_member = @course.course_members.find_by(user_id: user_id.to_i) new_student = CourseMember.new(user_id: user_id.to_i, course_id: @course.id, course_group_id: course_group_id, role: 4) if existing_course_member.present? @@ -710,6 +744,7 @@ class CoursesController < ApplicationController else new_student.is_active = 0 if existing_course_member.is_active new_student.save! + student_ids << user_id end else new_student.save! @@ -717,6 +752,7 @@ class CoursesController < ApplicationController end end + CourseAddStudentCreateWorksJob.perform_later(@course.id, student_ids) if student_ids.present? TeacherInviteJoinCourseNotifyJob.perform_later(current_user.id, @course.id, 10, student_ids) if student_ids.present? normal_status(0, "添加成功") rescue => e @@ -727,11 +763,11 @@ class CoursesController < ApplicationController end end - # 获取历史课堂,即用户管理的所有课堂以及课堂下的分班 + # 获取历史课堂,即用户管理的所有课堂以及课堂下的分班(去除当前课堂) def get_historical_courses - user_id = current_user.id - - @courses = Course.includes(:course_groups).where(tea_id: user_id, is_delete: 0) + @courses = Course.where.not(id: @course.id).joins(:course_members). + where(is_delete: 0, course_members: {user_id: current_user.id, role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR]}).includes(:course_groups) + # @courses = Course.includes(:course_groups).where(id: current_user.course_members, is_delete: 0) end # 根据历史课堂的课堂id和分班id获取所有学生 @@ -744,6 +780,7 @@ class CoursesController < ApplicationController @students = @students.where(course_group_id: course_group_id) end + @students = @students.includes(user: [user_extension: :school]) @students_count = @students.size end @@ -765,7 +802,7 @@ class CoursesController < ApplicationController name = attachment.disk_filename if name.split(".").last == "xls" begin - attachment_folder = Rails.configuration.educoder['attachment_folder'] + attachment_folder = edu_setting('attachment_folder') full_path = "#{attachment_folder}/#{path}/#{name}" xls = Roo::Spreadsheet.open(full_path, extension: :xls) worksheet = xls.sheet(0) @@ -788,6 +825,8 @@ class CoursesController < ApplicationController uid_logger_error(e.message) normal_status(-1, "无法完成导入,原因:文件内容无法读取") end + else + normal_status(-1, "只支持xls文件的导入") end end end @@ -841,6 +880,13 @@ class CoursesController < ApplicationController return normal_status(-1, "同一课堂不允许申请多个教师身份") end + # 验证是否存在同学号的学生 + u_extension = current_user.user_extension + if params[:student].present? && u_extension.student? + same_student_id_users = UserExtension.where.not(user_id: current_user.id).where(student_id: u_extension.student_id, identity: %i[student], school_id: u_extension.school_id).pluck(:user_id) + tip_exception("该课堂已存在同学号的学生,暂时无法加入,请联系老师") if course.students.exists?(user_id: same_student_id_users) + end + # 创建学生身份 if params[:student].present? existing_student = CourseMember.find_by(course_id: course.id, role: %i[STUDENT], user_id: current_user.id) @@ -855,6 +901,7 @@ class CoursesController < ApplicationController new_student.course_group_id = course_group.id if course_group.present? new_student.save! + CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id]) StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id) end end @@ -895,15 +942,15 @@ class CoursesController < ApplicationController def top_banner @user = current_user - @is_teacher = @user.teacher_of_course?(@course) - @is_student = @course.course_members.where(user_id: @user.id, role: 4, is_active: 1).present? + @is_teacher = @user_course_identity < Course::STUDENT + @is_student = @user_course_identity == Course::STUDENT @course.increment!(:visits) end def left_banner @user = current_user - @is_teacher = @user.teacher_of_course?(@course) - @course_modules = @course.course_modules.where.not(module_type: "activity").where(hidden: 0) + @is_teacher = @user_course_identity < Course::ASSISTANT_PROFESSOR + @course_modules = @course.course_modules.where(hidden: 0) @hidden_modules = @course.course_modules.where(hidden: 1) @second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group"] end @@ -930,7 +977,7 @@ class CoursesController < ApplicationController @page = params[:page] || 1 @page_size = params[:page_size] || 15 - @courses = Course.by_user(current_user).hidden(false).ended(false).deleted(0).by_keywords(params[:search]).distinct + @courses = Course.by_user(current_user).hidden(false).processing.not_deleted.by_keywords(params[:search]).distinct # @total_count = @courses.count # offset = 0 @@ -946,34 +993,33 @@ class CoursesController < ApplicationController def export_member_scores_excel ActiveRecord::Base.transaction do begin - name = params[:name] ? "#{params[:name].strip}" : "" #用户名或学生学号id搜索 + search = params[:search] ? "#{params[:search].strip}" : "" #用户名或学生学号id搜索 group_id = params[:group_id] #分班的班级id - if group_id && group_id != "0" && group_id != "-1" - @all_members = @course.students.course_find_by_ids("course_group_id",group_id) - elsif group_id && group_id == "0" # 未分班 - @all_members = @course.course_members.ungroup_students - else - @all_members = @course.students - end - if name.present? - nick_name_search = @all_members.joins(:user).where("nickname like ?","%#{name}%") - if nick_name_search.present? - @all_members = nick_name_search - else - @all_members = @all_members.joins(user: [:user_extension]).where('user_extensions.student_id like ? OR user_extensions.student_realname like ?',"%#{name}%","%#{name}%") - end - end - - @c_homeworks = @course.homework_commons.homework_published.order("publish_time asc, created_at asc") - @c_exercises = @course.exercises.is_exercise_published.order("publish_time asc, created_at asc") - @c_polls = @course.polls.publish_or_not.order("publish_time asc, created_at asc") - @c_tasks = @course.graduation_tasks.task_published.order("publish_time asc, created_at asc") + # if group_id && group_id != "0" && group_id != "-1" + # @all_members = @course.students.course_find_by_ids("course_group_id",group_id) + # elsif group_id && group_id == "0" # 未分班 + # @all_members = @course.course_members.ungroup_students + # else + # @all_members = @course.students + # end + # if name.present? + # @all_members = @all_members.joins(user: [:user_extension]).where('concat(users.lastname, users.firstname) like ? or user_extensions.student_id like ?',"%#{name}%","%#{name}%") + # end + + @all_members = student_act_score group_id, search + + @c_homeworks = @course.homework_commons.homework_published.order("homework_commons.publish_time asc, homework_commons.created_at asc") + @c_exercises = @course.exercises.is_exercise_published.order("exercises.publish_time asc, exercises.created_at asc") + # @c_polls = @course.polls.publish_or_not.order("polls.publish_time asc, polls.created_at asc") + @c_tasks = @course.graduation_tasks.task_published.order("graduation_tasks.publish_time asc, graduation_tasks.created_at asc") if @user_course_identity > Course::ASSISTANT_PROFESSOR tip_exception(403,"无权限操作") + elsif @all_members.size == 0 + normal_status(-1,"课堂暂时没有学生") else - member_to_xlsx(@course,@all_members,@c_homeworks,@c_exercises,@c_tasks,@c_polls) - filename = current_user.real_name + "_" + @course.name + "_全部成绩" + Time.now.strftime('%Y%m%d_%H%M%S') - render xlsx: "#{filename.strip.first(30)}",template: "courses/export_member_scores_excel.xlsx.axlsx", + member_to_xlsx(@course, @all_members, @c_homeworks, @c_exercises, @c_tasks) + filename_ = "#{current_user.real_name}_#{@course.name}_全部成绩" + render xlsx: "#{format_sheet_name filename_.strip.first(30)}",template: "courses/export_member_scores_excel.xlsx.axlsx", locals: {course_info:@course_info, activity_level:@user_activity_level, course_scores:@course_user_scores,shixun_works:@shixun_work_arrays, common_works:@common_work_arrays,group_works:@group_work_arrays,task_works:@task_work_arrays, @@ -981,12 +1027,26 @@ class CoursesController < ApplicationController end rescue Exception => e uid_logger_error(e.message) - tip_exception("没有权限") + tip_exception(e.message) raise ActiveRecord::Rollback end end end + def search_slim + courses = current_user.manage_courses.not_deleted.processing + + keyword = params[:keyword].to_s.strip + if keyword.present? + courses = courses.where('name LIKE ?', "%#{keyword}%") + end + + count = courses.count + courses = paginate(courses) + + render_ok(count: count, courses: courses.select(:id, :name).as_json) + end + private # Use callbacks to share common setup or constraints between actions. @@ -1005,6 +1065,7 @@ class CoursesController < ApplicationController tip_exception("课堂名称应以课程名称开头命名") unless params[:course][:name].index(params[:course_list_name]) && params[:course][:name].index(params[:course_list_name]) == 0 tip_exception("课堂所属单位不能为空!") if params[:school].blank? + tip_exception("请至少添加一个课堂模块") if params[:course_module_types].blank? @school = School.find_by!(name: params[:school].strip) end @@ -1029,16 +1090,72 @@ class CoursesController < ApplicationController end end - def member_to_xlsx(course,all_members,homeworks,exercises,tasks,polls) + def student_act_score group_id, search + sql_select = %Q{SELECT cm.*,( + SELECT SUM(student_works.work_score) + FROM student_works,homework_commons + WHERE student_works.homework_common_id = homework_commons.id + AND homework_commons.course_id = #{@course.id} + AND student_works.user_id = cm.user_id + ) AS score, + (SELECT max(student_id) FROM user_extensions WHERE user_extensions.user_id = cm.user_id) AS student_id, + (SELECT count(messages.id) FROM messages join boards on messages.board_id = boards.id WHERE boards.course_id = #{@course.id} + AND messages.author_id = cm.user_id and messages.parent_id is null) AS message_num, + (SELECT count(messages.id) FROM messages join boards on messages.board_id = boards.id WHERE boards.course_id = #{@course.id} + AND messages.author_id = cm.user_id and messages.parent_id is not null) AS message_reply_num, + (SELECT count(attachments.id) FROM attachments WHERE container_id = #{@course.id} and container_type = "Course" + AND attachments.author_id = cm.user_id) AS resource_num, + (SELECT count(jfm.id) FROM journals_for_messages AS jfm, homework_commons hs WHERE jfm.jour_id = hs.id AND + jfm.user_id = cm.user_id and jfm.jour_type = "HomeworkCommon" and hs.course_id = #{@course.id}) AS homework_journal_num, + (SELECT COUNT(gw.id) FROM graduation_works AS gw, graduation_tasks AS gt WHERE gw.graduation_task_id = gt.id AND + gt.course_id = #{@course.id} AND gw.work_status != 0 AND gw.user_id = cm.user_id) AS graduation_num, + (SELECT COUNT(ss.id) FROM student_works AS ss ,homework_commons AS hc WHERE ss.homework_common_id = hc.id AND + hc.course_id = #{@course.id} AND ss.work_status != 0 AND ss.user_id = cm.user_id) AS homework_num, + (SELECT COUNT(eu.id) FROM exercise_users AS eu,exercises WHERE eu.exercise_id = exercises.id AND exercises.course_id = #{@course.id} + AND eu.commit_status = 1 AND eu.user_id = cm.user_id) AS exercise_num, + (SELECT COUNT(pu.id) FROM poll_users AS pu, polls WHERE pu.poll_id = polls.id AND polls.course_id = #{@course.id} + AND pu.commit_status = 1 AND pu.user_id = cm.user_id) AS poll_num + FROM course_members cm} + if search.present? && group_id.present? + sql_select += %Q{ join users on cm.user_id = users.id + joins user_extensions ue on ue.user_id = users.id + WHERE cm.role = 4 and cm.course_id = #{@course.id} and cm.course_group_id = #{group_id} and + (concat(users.lastname, users.firstname) like '%#{search}%' or ue.student_id like '%#{search}%') ORDER BY score desc} + + elsif search.present? + sql_select += %Q{ join users on cm.user_id = users.id + joins user_extensions ue on ue.user_id = users.id + WHERE cm.role = 4 and + (concat(users.lastname, users.firstname) like '%#{search}%' or ue.student_id like '%#{search}%') ORDER BY score desc} + elsif group_id.present? + sql_select += %Q{ WHERE cm.role = 4 and cm.course_id = #{@course.id} and cm.course_group_id = #{group_id} ORDER BY score desc} + else + sql_select += %Q{ WHERE cm.role = 4 and cm.course_id = #{@course.id} ORDER BY score desc} + end + act_scores = CourseMember.find_by_sql(sql_select) + act_scores + end + + def member_to_xlsx(course,all_members,homeworks,exercises,tasks) #课堂的作业信息 - shixun_homeworks = homeworks.search_homework_type(4) #全部实训作业 + shixun_homeworks = homeworks.search_homework_type(4) #全部实训作业 shixun_titles = shixun_homeworks.pluck(:name) + ["总得分"] - common_homeworks = homeworks.search_homework_type(1) #全部普通作业 + shixun_homeworks = shixun_homeworks&.includes(score_student_works: :user) + + common_homeworks = homeworks.search_homework_type(1) #全部普通作业 common_titles = common_homeworks.pluck(:name)+ ["总得分"] + common_homeworks = common_homeworks&.includes(score_student_works: :user) + group_homeworks = homeworks.search_homework_type(3) #全部分组作业 group_titles = group_homeworks.pluck(:name)+ ["总得分"] - task_titles = tasks.pluck(:name)+ ["总得分"] - exercise_titles = exercises.pluck(:exercise_name)+ ["总得分"] + group_homeworks = group_homeworks&.includes(score_student_works: :user) + + task_titles = tasks.pluck(:name) + ["总得分"] + tasks = tasks&.includes(user: :user_extension, score_graduation_works: :user) + + exercise_titles = exercises.pluck(:exercise_name) + ["总得分"] + exercises = exercises&.includes(user: :user_extension, score_exercise_users: :user) + total_user_score_array = [] #学生总成绩集合 #课堂信息 @@ -1047,13 +1164,13 @@ class CoursesController < ApplicationController course_id = course.id course_name = course.name course_list_name = course.course_list.present? ? course.course_list.name : "--" - course_assistants = course.course_members.course_user_role(%i[PROFESSOR ASSISTANT_PROFESSOR]) - course_assistants_count = course_assistants&.count + course_assistants = course.teachers + course_assistants_count = course_assistants&.size course_assistants_name = course_assistants_count > 0 ? course_assistants.map{|m| m.user.real_name}.join('、') : "--" course_teacher_member = course.course_members.course_user_role(%i[CREATOR]) course_teacher = course_teacher_member.present? ? course_teacher_member.first.user.real_name : "--" course_class_counts = course.course_groups_count - course_students_count = course.students.count + course_students_count = course.students.size course_1 = ["课堂编号",course_id] course_2 = ["课程名称",course_list_name] course_3 = ["课堂名称",course_name] @@ -1064,25 +1181,32 @@ class CoursesController < ApplicationController course_main_info = [course_1,course_2,course_3,course_4,course_5,course_6,course_7] course_group_info_head = %w(序号 分班名称 邀请码 学生数量) course_group_info_body = [] - if course.course_groups.present? + none_group_counts = course.none_group_count + + #当有未分班时,应该也做个统计 + if none_group_counts > 0 + none_group_index = 2 + no_group_array = [1,"未分班",course.invite_code,none_group_counts] + course_group_info_body.push(no_group_array) + else + none_group_index = 1 + end + + if course.course_groups.exists? course.course_groups.each_with_index do |group, index| - group_index = (index+1) + group_index = (index+none_group_index) group_name = group.name group_code = group.invite_code group_count = group.course_members_count group_array = [group_index,group_name,group_code,group_count] course_group_info_body.push(group_array) end + end course_group_info = [course_group_info_head,course_group_info_body] @course_info += [course_info_title,course_main_info,course_group_info] #课堂活跃度 - course_homework_ids = homeworks.pluck(:id) #该课堂的全部作业id - course_graduate_task_ids = tasks.pluck(:id) #该课堂的全部毕业任务id - course_exercise_ids = exercises.pluck(:id) #课堂的全部试卷数 - course_poll_ids = polls.pluck(:id) #课堂的全部问卷数 - course_board_ids = course.boards.pluck(:id) #课堂的全部讨论区 @user_activity_level = [] course_user_level = [] course_activity_title = "课堂活跃度统计" @@ -1093,27 +1217,26 @@ class CoursesController < ApplicationController user_login = user.login user_name = user.real_name user_mail = user.mail - user_stu_id = user.student_id.present? ? (user.student_id.to_s + "\t") : "--" + user_stu_id = u.student_id.present? ? (u.student_id.to_s + "\t") : "--" user_course_group = u.course_group_name user_info_array = [user_login,user_name,user_mail,user_stu_id,user_course_group] #用户的信息集合 user_work_scores = [] #课堂活跃度统计 - user_homeworks_num = user.student_works.find_by_homework(course_homework_ids).has_committed.count #完成的作业数 - user_graduate_num = user.graduation_works.find_by_task(course_graduate_task_ids).has_committed.count #毕业任务完成数 - user_exercise_num = user.exercise_users.search_by_exercise(course_exercise_ids).commit_exercise_by_status(1).count #根据试卷的id来查找 - user_poll_num = user.poll_users.search_by_poll(course_poll_ids).commit_by_status(1).count #已完成问卷 - user_file_num = user.attachments.search_by_container(course.id).count - user_messages = user.messages - user_messages_num = user_messages.root_nodes.find_by_boards(course_board_ids).count #帖子发布数 - user_reply_num = user_messages.reply_nodes.find_by_boards(course_board_ids).count #帖子回复数 - user_work_reply_num = user.journals_for_messages.search_by_jour_type("HomeworkCommon",course_homework_ids).count #作业回复数的数量 + user_homeworks_num = u.homework_num.to_i #完成的作业数 + user_graduate_num = u.graduation_num.to_i #毕业任务完成数 + user_exercise_num = u.exercise_num.to_i #根据试卷的id来查找 + user_poll_num = u.poll_num.to_i #已完成问卷 + user_file_num = u.resource_num.to_i + user_messages_num = u.message_num.to_i #帖子发布数 + user_reply_num = u.message_reply_num.to_i #帖子回复数 + user_work_reply_num = u.homework_journal_num.to_i #作业回复数的数量 c_works_num = (user_homeworks_num + user_graduate_num)*10 c_exercise_num = user_exercise_num*10 c_poll_num = user_poll_num*7 c_file_num = user_file_num*5 c_message_num = user_messages_num*2 - c_reply_num = user_reply_num*2 + c_reply_num = user_reply_num user_activity_levels = c_works_num + c_exercise_num + c_poll_num + c_file_num + c_message_num + c_reply_num + user_work_reply_num user_ac_level = { u_1: user_name, @@ -1145,14 +1268,13 @@ class CoursesController < ApplicationController exercise_score_array = [] #实训作业 - if shixun_homeworks.count > 0 + if shixun_homeworks.size > 0 shixun_homeworks.each do |s| - user_student_work = s.student_works.homework_by_user(user.id) #当前用户的对该作业的回答 - if user_student_work.blank? + user_student_work = s.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答 + if user_student_work.nil? h_score = 0.0 #该作业的得分为0 else - user_stu_work = user_student_work.first - h_score = user_stu_work.work_score.nil? ? 0.0 : user_stu_work.work_score #用户对该作业的分数 + h_score = user_student_work.work_score.nil? ? 0.0 : user_student_work.work_score #用户对该作业的分数 end shixun_score_array.push(h_score) end @@ -1162,14 +1284,13 @@ class CoursesController < ApplicationController user_work_scores += user_info_array + shixun_score_array #单个用户的实训作业得分信息 #普通作业 - if common_homeworks.count > 0 + if common_homeworks.size > 0 common_homeworks.each do |c| - user_student_work_1 = c.student_works.homework_by_user(user.id) #当前用户的对该作业的回答 - if user_student_work_1.blank? + user_student_work_1 = c.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答 + if user_student_work_1.nil? h_score_1 = 0.0 #该作业的得分为0 else - user_stu_work_1 = user_student_work_1.first - h_score_1 = user_stu_work_1.work_score.nil? ? 0.0 : user_stu_work_1.work_score #用户对该作业的分数 + h_score_1 = user_student_work_1.work_score.nil? ? 0.0 : user_student_work_1.work_score #用户对该作业的分数 end common_score_array.push(h_score_1) end @@ -1179,14 +1300,13 @@ class CoursesController < ApplicationController user_work_scores += common_score_array #单个用户的普通作业得分信息 #分组作业 - if group_homeworks.count > 0 + if group_homeworks.size > 0 group_homeworks.each do |g| - user_student_work_3 = g.student_works.homework_by_user(user.id) #当前用户的对该作业的回答 - if user_student_work_3.blank? + user_student_work_3 = g.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答 + if user_student_work_3.nil? h_score_3 = 0.0 #该作业的得分为0 else - user_stu_work_3 = user_student_work_3.first - h_score_3 = user_stu_work_3.work_score.nil? ? 0.0 : user_stu_work_3.work_score #用户对该作业的分数 + h_score_3 = user_student_work_3.work_score.nil? ? 0.0 : user_student_work_3.work_score #用户对该作业的分数 end group_score_array.push(h_score_3) end @@ -1196,13 +1316,13 @@ class CoursesController < ApplicationController user_work_scores += group_score_array #单个用户的分组作业得分信息 #毕设作业 - if tasks.count > 0 + if tasks.size > 0 tasks.each do |task| - graduation_works = task.graduation_works.find_by_task_user(user.id) - if graduation_works.empty? + graduation_work = task.score_graduation_works.select{|work| work.user_id == user.id}.first + if graduation_work.nil? t_score = 0.0 else - t_score = graduation_works.first.work_score.nil? ? 0.0 : graduation_works.first.work_score + t_score = graduation_work.work_score.nil? ? 0.0 : graduation_work.work_score end task_score_array.push(t_score) end @@ -1212,13 +1332,13 @@ class CoursesController < ApplicationController user_work_scores += task_score_array #单个用户的分组作业得分信息 #试卷 - if exercises.count > 0 + if exercises.size > 0 exercises.each do |ex| - exercise_works = ex.exercise_users.exercise_commit_users(user.id) - if exercise_works.empty? + exercise_work = ex.score_exercise_users.select{|work| work.user_id == user.id}.first + if exercise_work.nil? e_score = 0.0 else - e_score = exercise_works.first.score.nil? ? 0.0 : exercise_works.first.score + e_score = exercise_work.score.nil? ? 0.0 : exercise_work.score end exercise_score_array.push(e_score) end @@ -1250,73 +1370,60 @@ class CoursesController < ApplicationController @common_work_arrays = [] @task_work_arrays = [] @exercise_work_arrays = [] - count_1 = shixun_homeworks.count - count_2 = common_homeworks.count - count_3 = group_homeworks.count - count_4 = tasks.count - count_5 = exercises.count + count_1 = shixun_homeworks.size + count_2 = common_homeworks.size + count_3 = group_homeworks.size + count_4 = tasks.size #实训作业 - if count_1 > 0 - shixun_homeworks.each_with_index do |s,index| - all_student_works = s.student_works.has_committed.order("work_score desc") #该实训题的全部用户回答 - title_no = index.to_i + 1 - student_work_to_xlsx(all_student_works,s) - shixun_work_display_name = (title_no.to_s + "." + s.name).strip.first(30) - shixun_work_content = [shixun_work_display_name,@work_head_cells,@work_cells_column] - @shixun_work_arrays.push(shixun_work_content) - end + shixun_homeworks.each_with_index do |s,index| + all_student_works = s.score_student_works #该实训题的全部用户回答 + title_no = index.to_i + 1 + student_work_to_xlsx(all_student_works,s) + shixun_work_display_name = format_sheet_name (title_no.to_s + "." + s.name).strip.first(30) + shixun_work_content = [shixun_work_display_name,@work_head_cells,@work_cells_column] + @shixun_work_arrays.push(shixun_work_content) end #普通作业 - if count_2 > 0 - common_homeworks.each_with_index do |c,index| - all_student_works = c.student_works.has_committed.order("work_score desc") #当前用户的对该作业的回答 - title_no = count_1 + index.to_i + 1 - student_work_to_xlsx(all_student_works,c) - - work_name = (title_no.to_s + "." + c.name).strip.first(30) - work_content = [work_name,@work_head_cells,@work_cells_column] - @common_work_arrays.push(work_content) - title_no - end + common_homeworks.each_with_index do |c,index| + all_student_works = c.score_student_works #当前用户的对该作业的回答 + title_no = count_1 + index.to_i + 1 + student_work_to_xlsx(all_student_works,c) + + work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30) + work_content = [work_name,@work_head_cells,@work_cells_column] + @common_work_arrays.push(work_content) + title_no end #分组作业 - if count_3 > 0 - group_homeworks.each_with_index do |c,index| - all_student_works = c.student_works.has_committed.order("work_score desc") #当前用户的对该作业的回答 - title_no = count_1 + count_2 + index.to_i + 1 - student_work_to_xlsx(all_student_works,c) - work_name = (title_no.to_s + "." + c.name).strip.first(30) - work_content = [work_name,@work_head_cells,@work_cells_column] - @group_work_arrays.push(work_content) - end + group_homeworks.each_with_index do |c,index| + all_student_works = c.score_student_works #当前用户的对该作业的回答 + title_no = count_1 + count_2 + index.to_i + 1 + student_work_to_xlsx(all_student_works,c) + work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30) + work_content = [work_name,@work_head_cells,@work_cells_column] + @group_work_arrays.push(work_content) end #毕设任务 - if count_4 > 0 - tasks.each_with_index do |c,index| - all_student_works = c.graduation_works.has_committed.order("work_score desc") #当前用户的对该作业的回答 - title_no = count_1 + count_2 + count_3 + index.to_i + 1 - graduation_work_to_xlsx(all_student_works,c,current_user) - work_name = (title_no.to_s + "." + c.name).strip.first(30) - # work_content = [work_name,@work_head_cells,@work_cells_column] - work_content = [work_name,@head_cells_column,@task_cells_column] - @task_work_arrays.push(work_content) - end + tasks.each_with_index do |c,index| + all_student_works = c.score_graduation_works #当前用户的对该作业的回答 + title_no = count_1 + count_2 + count_3 + index.to_i + 1 + graduation_work_to_xlsx(all_student_works,c,current_user) + work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30) + work_content = [work_name,@head_cells_column,@task_cells_column] + @task_work_arrays.push(work_content) end #试卷的导出 - if count_5 > 0 - exercises.each_with_index do |c,index| - all_student_works = c.exercise_users.exercise_user_committed #当前用户的对该作业的回答 - title_no = count_1 + count_2 + count_3 + count_4 + index.to_i + 1 - get_export_users(c,course,all_student_works) - work_name = (title_no.to_s + "." + c.exercise_name).strip.first(30) - # work_content = [work_name,@work_head_cells,@work_cells_column] - work_content = [work_name,@table_columns,@user_columns] - @exercise_work_arrays.push(work_content) - end + exercises.each_with_index do |c,index| + all_student_works = c.score_exercise_users #当前用户的对该作业的回答 + title_no = count_1 + count_2 + count_3 + count_4 + index.to_i + 1 + get_export_users(c,course,all_student_works) + work_name = format_sheet_name (title_no.to_s + "." + c.exercise_name).strip.first(30) + work_content = [work_name,@table_columns,@user_columns] + @exercise_work_arrays.push(work_content) end end end diff --git a/app/controllers/departments_controller.rb b/app/controllers/departments_controller.rb new file mode 100644 index 000000000..f0fa8fe2c --- /dev/null +++ b/app/controllers/departments_controller.rb @@ -0,0 +1,11 @@ +class DepartmentsController < ApplicationController + def for_option + render_ok(departments: Department.cached_names_data(current_school)) + end + + private + + def current_school + @_current_school ||= School.find(params[:id]) + end +end \ No newline at end of file diff --git a/app/controllers/discusses_controller.rb b/app/controllers/discusses_controller.rb index 6e9c1427e..3b987be51 100644 --- a/app/controllers/discusses_controller.rb +++ b/app/controllers/discusses_controller.rb @@ -7,9 +7,24 @@ class DiscussesController < ApplicationController page = params[:page].to_i offset = page * LIMIT # 总数,分页使用 - @disscuss_count = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil).count - @discusses = Discuss.limit(LIMIT).where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil). - includes(:user, :praise_tread).offset(offset) + if current_user.admin? + @disscuss_count = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil).count + disscusses = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, + :root_id => nil) + else + disscusses = Discuss.where("dis_id = :dis_id and dis_type = :dis_type and root_id is null and + (discusses.hidden = :hidden or discusses.user_id = :user_id)", + {dis_id: @container.id, dis_type: @container.class.to_s, hidden: false, user_id: current_user.id}) + @disscuss_count = disscusses.count("discusses.id") + end + @manger = @container.has_manager?(current_user) + if @manger + @discusses = disscusses.limit(LIMIT).joins("left join games on discusses.challenge_id = games.challenge_id and discusses.user_id = games.user_id") + .select("discusses.*, games.identifier").includes(:user, :praise_treads).offset(offset) + else + @discusses = disscusses.limit(LIMIT).includes(:user, :praise_treads).offset(offset) + end + @current_user = current_user end @@ -23,8 +38,10 @@ class DiscussesController < ApplicationController def create begin - @discuss = Discuss.create!(:dis_id => params[:container_id], :dis_type => params[:container_type], :content => params[:content].gsub(" \;", "").strip, - :user_id => current_user.id, :praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id]) + @discuss = Discuss.create!(:dis_id => params[:container_id], :dis_type => params[:container_type], + :content => params[:content].gsub(" \;", "").strip, :user_id => current_user.id, + :praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id], + :hidden => !current_user.admin?) # 管理员回复的能够显示 rescue Exception => e uid_logger_error("create discuss failed : #{e.message}") raise Educoder::TipException.new("评论异常") diff --git a/app/controllers/ecs/base_controller.rb b/app/controllers/ecs/base_controller.rb index ad11682c3..2cded249a 100644 --- a/app/controllers/ecs/base_controller.rb +++ b/app/controllers/ecs/base_controller.rb @@ -1,15 +1,6 @@ class Ecs::BaseController < ApplicationController - # 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 - - before_action :require_login + before_action :require_login, :check_auth before_action :check_user_permission! helper_method :current_user, :current_school diff --git a/app/controllers/exercise_answers_controller.rb b/app/controllers/exercise_answers_controller.rb index 68ba83276..babdd50f7 100644 --- a/app/controllers/exercise_answers_controller.rb +++ b/app/controllers/exercise_answers_controller.rb @@ -1,6 +1,7 @@ class ExerciseAnswersController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :get_exercise_question + include ExercisesHelper def create #每一次答案的点击,请求一次,实训题不在这里回答 ActiveRecord::Base.transaction do @@ -8,11 +9,11 @@ class ExerciseAnswersController < ApplicationController 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] : "" #为字符串 - if q_type < 4 && choice_id.blank? + 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 == 0 || q_type == 2 #选择题(单选)/判断题 + if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题 ea_choice = ea.search_exercise_answer("exercise_choice_id",choice_id).first answer_option = { :user_id => current_user.id, @@ -29,8 +30,9 @@ class ExerciseAnswersController < ApplicationController ex_a = ExerciseAnswer.new(answer_option) ex_a.save! end - elsif q_type == 1 #多选题的 + 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 # 新增的id @@ -51,7 +53,7 @@ class ExerciseAnswersController < ApplicationController ea_answer = ea.search_answer_users("exercise_choice_id",old_ids) ea_answer.destroy_all end - elsif q_type == 3 #填空题 + elsif q_type == Exercise::COMPLETION #填空题 answer_option = { :user_id => current_user.id, :exercise_question_id => @exercise_question.id, @@ -65,7 +67,7 @@ class ExerciseAnswersController < ApplicationController ex_new = ExerciseAnswer.new(answer_option) ex_new.save! end - elsif q_type == 4 #简答题 + elsif q_type == Exercise::SUBJECTIVE #简答题 answer_option = { :user_id => current_user.id, :exercise_question_id => @exercise_question.id @@ -92,9 +94,10 @@ class ExerciseAnswersController < ApplicationController def get_exercise_question @exercise_question = ExerciseQuestion.find_by_id(params[:exercise_question_id]) - @exercise = @exercise_question.exercise - @course = @exercise.course - @exercise_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first #当前用户 + @exercise = @exercise_question&.exercise + @course = @exercise&.course + @exercise_user = @exercise&.exercise_users.find_by(user_id: current_user.id) #当前用户 + @exercise_user_status = @exercise.get_exercise_status(current_user) if @exercise_question.blank? normal_status(-1,"试卷问题不存在!") @@ -102,15 +105,28 @@ class ExerciseAnswersController < ApplicationController normal_status(-1,"试卷不存在!") elsif @course.blank? normal_status(-1,"该课堂不存在!") - elsif (@exercise_user.present? && @exercise_user.commit_status == 1) || (@exercise.end_time.present? && @exercise.end_time < Time.now) #已提交答案的/时间已结束的试卷不允许再修改 + elsif @exercise_user.blank? + normal_status(-1,"试卷用户不存在!") + elsif @exercise_user.commit_status == 1 normal_status(-1,"已提交/已结束的试卷不允许修改!") - elsif @exercise.time > 0 - user_start_at = @exercise.exercise_users.exercise_commit_users(current_user.id).first.start_at - exercise_time = @exercise.time.to_i - if (user_start_at + exercise_time.minutes) < Time.now - normal_status(-1,"限时试卷已结束!") + else + if (@exercise_user_status == Exercise::DEADLINE && @exercise_user.commit_status == 0) || (@exercise.time > 0 && @exercise_user.start_at.present? && ((@exercise_user.start_at + (@exercise.time.to_i + 1).minutes) < Time.now)) + objective_score = calculate_student_score(@exercise,current_user)[:total_score] + subjective_score = @exercise_user.subjective_score < 0.0 ? 0.0 : @exercise_user.subjective_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 => subjective_score + } + @exercise_user.update_attributes(commit_option) + normal_status(-1,"试卷提交时间已截止!") end end + end end diff --git a/app/controllers/exercise_questions_controller.rb b/app/controllers/exercise_questions_controller.rb index 9e3259e6e..3718e18d5 100644 --- a/app/controllers/exercise_questions_controller.rb +++ b/app/controllers/exercise_questions_controller.rb @@ -1,5 +1,5 @@ class ExerciseQuestionsController < ApplicationController - before_action :require_login #用户需登陆 + before_action :require_login, :check_auth #用户需登陆 before_action :get_exercise,only:[:new,:create] #获取试卷 before_action :get_exercise_question,except: [:new,:create] #获取试卷的问题及试卷 before_action :is_course_teacher #是否为老师 @@ -47,7 +47,7 @@ class ExerciseQuestionsController < ApplicationController if @exercise_question.save #为选择题(包括单选和多选)的时候,创建问题选项 ques_type = @exercise_question.question_type - if ques_type <= 1 + if ques_type <= Exercise::MULTIPLE choices_array = params[:question_choices] choices_count= choices_array.count standard_answer = params[:standard_answers] #为数组格式,因为可能会有单选和多选,标准答案,已提前判断不能为空, @@ -70,13 +70,13 @@ class ExerciseQuestionsController < ApplicationController } question_standard_answer = ExerciseStandardAnswer.new(standard_option) question_standard_answer.save - if standard_answer.count > 1 && ques_type == 0 #当标准答案数大于1,且不为多选时,修改为多选 - @exercise_question.update_attribute("question_type",1) - elsif standard_answer.count == 1 && ques_type == 1 - @exercise_question.update_attribute("question_type",0) + if standard_answer.count > 1 && ques_type == Exercise::SINGLE #当标准答案数大于1,且不为多选时,修改为多选 + @exercise_question.update_attribute("question_type",Exercise::MULTIPLE) + elsif standard_answer.count == 1 && ques_type == Exercise::MULTIPLE + @exercise_question.update_attribute("question_type",Exercise::SINGLE) end end - elsif ques_type == 2 #这个为判断题 + elsif ques_type == Exercise::JUDGMENT #这个为判断题 choices_array = params[:question_choices] #判断的选项,对/错等等 choices_count= choices_array.count (1..choices_count).each do |c| @@ -95,7 +95,7 @@ class ExerciseQuestionsController < ApplicationController } question_standard_answer = ExerciseStandardAnswer.new(standard_option) question_standard_answer.save - elsif ques_type == 3 #填空题,每空的参考答案有多个,那么以位置对应 + elsif ques_type == Exercise::COMPLETION #填空题,每空的参考答案有多个,那么以位置对应 standard_answer = params[:standard_answers] standard_answer.each do |a| null_choice_id = a[:choice_id] @@ -110,7 +110,7 @@ class ExerciseQuestionsController < ApplicationController question_standard_answer.save end end - elsif ques_type == 4 #简答题 + elsif ques_type == Exercise::SUBJECTIVE #简答题 if params[:standard_answers].present? && params[:standard_answers].reject(&:blank?).count > 0 standard_answer = params[:standard_answers] standard_answer.each do |a| @@ -122,12 +122,12 @@ class ExerciseQuestionsController < ApplicationController question_standard_answer.save end end - elsif ques_type == 5 #实训题 + elsif ques_type == Exercise::PRACTICAL #实训题 shixun = Shixun.find_by(id: params[:shixun_id]) shixun_scores = params[:question_scores] #试卷有多个的分值有多个分数表,所以为分数的数组 shixun_name = params[:shixun_name] || shixun.name question_score = 0 - shixun.challenges.each_with_index do |challenge,index| + shixun.challenges.try(:each_with_index) do |challenge,index| shixun_option = { :challenge_id => challenge.id, :shixun_id => shixun.id, @@ -223,16 +223,14 @@ class ExerciseQuestionsController < ApplicationController end end #试卷未发布时,当标准答案存在时,可修改标准答案内容,可增删标准答案,否则只能修改标准答案,不能增删标准答案 - st_count = 0 @exercise_answers_array = @exercise_question.exercise_standard_answers #问卷的全部标准答案 if standard_answer.present? - if @exercise_question.question_type <= 2 #选择题/判断题,标准答案为一个或多个 + if @exercise_question.question_type <= Exercise::JUDGMENT #选择题/判断题,标准答案为一个或多个 exercise_standard_choices = @exercise_answers_array.pluck(:exercise_choice_id) #问题以前的全部标准答案选项位置 common_standard_choices = standard_answer & exercise_standard_choices # 传入的标准答案的选项位置和以前的并集,即表示不用做更改的 old_left_standard_choices = exercise_standard_choices - common_standard_choices # 以前的差集共同的,剩余的表示需要删掉 new_left_standard_choices = standard_answer - common_standard_choices # 传入的标准答案差集共同的,剩余的表示需要新建 if old_left_standard_choices.count > 0 - st_count += 1 @exercise_answers_array.standard_by_ids(old_left_standard_choices).destroy_all end if new_left_standard_choices.count > 0 #新建标准答案 @@ -246,19 +244,18 @@ class ExerciseQuestionsController < ApplicationController end end - if standard_answer.count > 1 && @exercise_question.question_type == 0 #当标准答案数大于1,且不为多选时,修改为多选 - @exercise_question.update_attribute("question_type",1) - elsif standard_answer.count == 1 && @exercise_question.question_type == 1 - @exercise_question.update_attribute("question_type",0) + if standard_answer.count > 1 && @exercise_question.question_type == Exercise::SINGLE #当标准答案数大于1,且不为多选时,修改为多选 + @exercise_question.update_attribute("question_type",Exercise::MULTIPLE) + elsif standard_answer.count == 1 && @exercise_question.question_type == Exercise::MULTIPLE + @exercise_question.update_attribute("question_type",Exercise::SINGLE) end - elsif @exercise_question.question_type == 3 #填空题 + elsif @exercise_question.question_type == Exercise::COMPLETION #填空题 old_ex_answer = @exercise_question.exercise_standard_answers #当前问题的全部标准答案 old_ex_answer_choice_ids = old_ex_answer.pluck(:exercise_choice_id).uniq #全部的答案数组序号 new_ex_answer_choice_ids = standard_answer.map {|a| a[:choice_id]}.uniq #新传入的答案数组序号 #删除多余的选项 if old_ex_answer_choice_ids.count > new_ex_answer_choice_ids.count #有减少的填空 - st_count += 1 delete_ex_answer_choice_ids = old_ex_answer_choice_ids - new_ex_answer_choice_ids old_ex_answer.standard_by_ids(delete_ex_answer_choice_ids).destroy_all end @@ -284,7 +281,6 @@ class ExerciseQuestionsController < ApplicationController ex_answer_pre[n-1].update(standard_option) end if new_add_choice.count > 0 #表示有新增的 - st_count += 1 new_add_choice.each do |i| standard_option = { :exercise_question_id => @exercise_question.id, @@ -306,7 +302,6 @@ class ExerciseQuestionsController < ApplicationController ex_answer_pre[index].update(standard_option) end if new_delete_choice.count > 0 #表示填空题的答案有删减的 - st_count += 1 new_delete_choice.each do |d| ex_answer_pre[d-1].destroy end @@ -326,7 +321,7 @@ class ExerciseQuestionsController < ApplicationController end end end - if @exercise_question.question_type == 4 #主观题 + if @exercise_question.question_type == Exercise::SUBJECTIVE #主观题 main_standard_answer = standard_answer.present? ? standard_answer.first : nil if @exercise_answers_array.present? @exercise_answers_array.first.update_attribute("answer_text",main_standard_answer) @@ -338,7 +333,7 @@ class ExerciseQuestionsController < ApplicationController question_standard_answer = ExerciseStandardAnswer.new(standard_option) question_standard_answer.save end - elsif @exercise_question.question_type == 5 + elsif @exercise_question.question_type == Exercise::PRACTICAL question_score = 0 shixun_name = params[:shixun_name] || @exercise_question.shixun_name @exercise_question.exercise_shixun_challenges.each_with_index do |challenge, index| @@ -350,8 +345,9 @@ class ExerciseQuestionsController < ApplicationController @exercise_question.shixun_name = shixun_name end - #当标准答案修改时,如有已提交的学生,需重新计算分数 - if st_count > 0 + #当试卷已发布时(试卷的总状态),当标准答案修改时,如有已提交的学生,需重新计算分数. + + if @exercise.exercise_status == Exercise::PUBLISHED ex_users_committed = @exercise.exercise_users.exercise_user_committed if ex_users_committed.size > 0 ex_users_committed.each do |ex_user| @@ -364,12 +360,7 @@ class ExerciseQuestionsController < ApplicationController end end end - - if @exercise_question.save - normal_status(0,"试卷更新成功!") - else - normal_status(-1,"试卷更新失败!") - end + normal_status(0,"试卷更新成功!") rescue Exception => e uid_logger_error(e.message) tip_exception("页面调用失败!") @@ -384,24 +375,22 @@ class ExerciseQuestionsController < ApplicationController begin opr = params[:opr] current_q_p = @exercise_question.question_number.to_i #问题的当前位置 - # last_q_p = @exercise.exercise_questions.find_by_custom("question_number",(current_q_p - 1)).first # 当前问题的前一个问题 - # next_q_p = @exercise.exercise_questions.find_by_custom("question_number",(current_q_p + 1)).first # 当前问题的后一个问题 - last_q_p = @exercise.exercise_questions.last_exercise(current_q_p) # 当前问题的前一个问题 - next_q_p = @exercise.exercise_questions.next_exercise(current_q_p) # 当前问题的后一个问题 - if @exercise.exercise_status.to_i == 1 + if @exercise.exercise_status.to_i == Exercise::UNPUBLISHED if opr.present? if opr.to_s == "up" + last_q_p = @exercise.exercise_questions.find_by(question_number: (current_q_p - 1)) # 当前问题的前一个问题 if last_q_p.present? @exercise_question.update_attribute('question_number', (current_q_p - 1)) - last_q_p.update_attribute('question_number', (@exercise_question.question_number.to_i + 1)) # 重新获取当前问题的位置 + last_q_p.update_attribute('question_number', current_q_p) # 重新获取当前问题的位置 normal_status(0, "问题上移成功!") else normal_status(-1, "移动失败,已经是第一个问题了!") end elsif opr.to_s == "down" + next_q_p = @exercise.exercise_questions.find_by(question_number: (current_q_p + 1)) # 当前问题的前一个问题 if next_q_p.present? @exercise_question.update_attribute('question_number', (current_q_p + 1)) - next_q_p.update_attribute('question_number', (@exercise_question.question_number.to_i - 1)) + next_q_p.update_attribute('question_number', current_q_p) normal_status(0, "问题下移成功!") else normal_status(-1, "移动失败,已经是最后一个问题了!") @@ -426,14 +415,9 @@ class ExerciseQuestionsController < ApplicationController begin choice_d_id = params[:choice_no].to_i # 选项的当前位置 question_choices = @exercise_question.exercise_choices - delete_answer = question_choices.find_choice_custom("choice_position",choice_d_id).first - left_choice = question_choices.left_choice_choose("choice_position",choice_d_id) - if left_choice.present? - left_choice.each do |p| - p.choice_position -= 1 - p.save - end - end + delete_answer = question_choices.find_by(choice_position: choice_d_id) + left_choices = question_choices.where("choice_position > ? ",choice_d_id) + left_choices.update_all("choice_position = choice_position - 1") if left_choices if delete_answer.destroy normal_status(0, "答案删除成功!") else @@ -452,13 +436,8 @@ class ExerciseQuestionsController < ApplicationController begin question_d_id = @exercise_question.question_number.to_i #问题的当前位置 exercise_questions = @exercise.exercise_questions - left_question = exercise_questions.left_question_choose("question_number",question_d_id) - if left_question.present? - left_question.each do |q| - q.question_number -= 1 - q.save - end - end + left_questions = exercise_questions.where("question_number > ?", question_d_id) + left_questions.update_all("question_number = question_number - 1") if left_questions if @exercise_question.destroy normal_status(0, "问题删除成功!") else @@ -478,9 +457,9 @@ class ExerciseQuestionsController < ApplicationController ex_obj_score = @exercise_current_user.objective_score #全部客观题得分 ex_subj_score = @exercise_current_user.subjective_score < 0.0 ? 0.0 : @exercise_current_user.subjective_score #全部主观题得分 ex_answers = @exercise_question.exercise_answers.search_answer_users("user_id",@user_id) #当前用户答案的得分 - if @exercise_question.question_type == 3 #当为填空题,更新问题的总分, + if @exercise_question.question_type == Exercise::COMPLETION #当为填空题,更新问题的总分, ex_answer_old = ex_answers.score_reviewed.pluck(:score).sum #每一关的得分总和 - each_right_score = (@c_score / ex_answers.count.to_f).round(1) #调分后,平均每关的分数 + each_right_score = (@c_score / ex_answers.count.to_f) #调分后,平均每关的分数 new_obj_score = ex_obj_score - ex_answer_old + @c_score total_scores = new_obj_score + ex_subj_score ex_scores = { @@ -489,8 +468,8 @@ class ExerciseQuestionsController < ApplicationController } @exercise_current_user.update_attributes(ex_scores) ex_answers.update_all(:score => each_right_score) #所有的正确选项需重新更新 - elsif @exercise_question.question_type == 4 #当为主观题时 - if ex_answers.present? + elsif @exercise_question.question_type == Exercise::SUBJECTIVE #当为主观题时 + if ex_answers.exists? ex_answers_old_score = ex_answers.first.score > 0.0 ? ex_answers.first.score : 0.0 #原分数小于0,取0 new_sub_score = ex_subj_score - ex_answers_old_score + @c_score #原全部主观题总分减去原该主观题得分再加调分后的分数,即为当前全部主观题得分 ex_answers.first.update_attribute("score",@c_score) @@ -502,7 +481,7 @@ class ExerciseQuestionsController < ApplicationController :answer_text => "" } ExerciseAnswer.create(answer_option) - new_sub_score = @c_score + new_sub_score = ex_subj_score + @c_score end total_scores = ex_obj_score + new_sub_score ex_scores = { @@ -511,8 +490,7 @@ class ExerciseQuestionsController < ApplicationController } @exercise_current_user.update_attributes(ex_scores) - elsif @exercise_question.question_type == 5 - # ex_answers = @exercise_question.exercise_shixun_answers.search_shixun_answers("user_id",@user_id).search_shixun_answers("exercise_shixun_challenge_id",@shixun_a_id) + elsif @exercise_question.question_type == Exercise::PRACTICAL ex_answers = @exercise_question.exercise_shixun_answers.where(user_id:@user_id,exercise_shixun_challenge_id:@shixun_a_id) if ex_answers.present? #当为实训题时 @@ -599,23 +577,23 @@ class ExerciseQuestionsController < ApplicationController if @exercise_question.present? @exercise = @exercise_question.exercise if @exercise.blank? - tip_exception(404) + tip_exception(404,"试卷不存在") else @course = @exercise.course if @course.blank? - tip_exception(404) + tip_exception(404,"课堂不存在") end end else - tip_exception(404) + tip_exception(404,"试卷问题不存在") end end def validate_params - normal_status(-1,"题目不允许为空!") if (params[:question_title].blank? && params[:question_type].to_i !=5 ) #除了实训题,其余题目必需有题干 + normal_status(-1,"题目不允许为空!") if (params[:question_title].blank? && params[:question_type].to_i != Exercise::PRACTICAL ) #除了实训题,其余题目必需有题干 normal_status(-1,"问题类型不允许为空!" ) if params[:question_type].blank? normal_status(-1,"分值不允许为空!" ) if params[:question_score].blank? && params[:question_scores].blank? #分值的数组或参数必需存在一个 - if params[:question_score].present? && params[:question_score].to_f.round(1) <= 0.0 #问题类型存在,则分值不能为空,且必需大于0 + if params[:question_score].present? && params[:question_score].to_f <= 0.0 #问题类型存在,则分值不能为空,且必需大于0 normal_status(-1,"分值必需大于0!") elsif (params[:question_score].present? && params[:question_score].to_f.round(1) > 100.0) || (params[:question_scores].present? && (params[:question_scores].map{|a| a.to_f.round(1)}.max > 100.0)) normal_status(-1,"分值不能超过100分!") @@ -628,7 +606,7 @@ class ExerciseQuestionsController < ApplicationController elsif params[:question_type].to_i == 2 && (params[:standard_answers].count > 1 || params[:question_choices].blank? || params[:question_choices].include?("")) #判断题的标准答案不能大于1个,选项不能为空 normal_status(-1,"判断题选项不能为空/标准答案不能大于1个!") elsif params[:question_type].to_i <= 1 && (params[:question_choices].blank? || params[:question_choices].include?("") || params[:question_choices].count < 2) #选择题选项不能为空,且不能小于2 - normal_status(-1,"选择题选项内容不能为空,且不能少于3个!") + normal_status(-1,"选择题选项内容不能为空,且不能少于2个!") elsif params[:question_type].to_i == 3 && (params[:standard_answers].blank? || params[:standard_answers].count > 5 ) #填空题选项最多为5个,且如果为1个的话,不允许修改is_ordered normal_status(-1,"填空题标准答案不能为空/不能超过5个!") elsif params[:question_type].to_i == 4 && params[:standard_answers].count > 2 #简单题参考答案最多为1个 @@ -643,16 +621,16 @@ class ExerciseQuestionsController < ApplicationController end def check_exercise_status - normal_status(-1,"不能更改试卷问题!") if @exercise.exercise_status != 1 + normal_status(-1,"不能更改试卷问题!") if @exercise.exercise_status != Exercise::UNPUBLISHED end #更新时不能修改的内容 def cannot_change_column #已发布的/已截止的/评阅中的状态时,不能修改分数,不能增删问题和答案,不能修改标准答案,可以修改选项内容/题目内容,这里仅指单个问题 - if @exercise.exercise_status != 1 + if @exercise.exercise_status != Exercise::UNPUBLISHED question_score = @exercise_question.question_score #原来的分数 update_question_score = params[:question_score].to_f.round(1) #传入的分数 - choices_count = @exercise_question.exercise_choices.count #原来的选项个数 + choices_count = @exercise_question.exercise_choices.size #原来的选项个数 exercise_choice_ids = @exercise_question.exercise_standard_answers.pluck(:exercise_choice_id).uniq standard_answers_text = @exercise_question.exercise_standard_answers.pluck(:answer_text).uniq update_choices_count = params[:question_choices].present? ? params[:question_choices].count : choices_count #传入的选项个数 @@ -662,12 +640,12 @@ class ExerciseQuestionsController < ApplicationController elsif update_choices_count != choices_count #选项个数有修改 normal_status(-1,"已发布/已截止,不允许增删答案!") elsif standard_answer.present? - if @exercise_question.question_type == 3 + if @exercise_question.question_type == Exercise::COMPLETION exercise_answers_text = standard_answer.map{|a| a[:answer_text]}.sum.uniq unless (standard_answer.count == exercise_choice_ids.count) && (standard_answers_text.count == exercise_answers_text.count) normal_status(-1,"已发布/已截止,不允许增删标准答案!") end - elsif @exercise_question.question_type == 4 + elsif @exercise_question.question_type == Exercise::SUBJECTIVE unless standard_answers_text.count == standard_answer.count normal_status(-1,"已发布/已截止,不允许增删标准答案!") end @@ -677,20 +655,20 @@ class ExerciseQuestionsController < ApplicationController end def check_adjust_score - @c_score = params[:score].to_f.round(1) #调分后的分数 + @c_score = params[:score].to_f #调分后的分数 @user_id = params[:user_id] @exercise_current_user = @exercise.exercise_users.exercise_commit_users(@user_id).first #当前试卷用户的答案内容 if @exercise_current_user.blank? normal_status(-1,"用户不存在!") elsif @c_score.blank? normal_status(-1,"分数不能为空!") - elsif @exercise_question.question_type <= 1 || @exercise_question.question_type == 2 + elsif @exercise_question.question_type <= Exercise::JUDGMENT normal_status(-1,"选择题/判断题不能调分!") elsif params[:comment].present? && params[:comment].length > 100 normal_status(-1,"评语不能超过100个字符!") else @shixun_a_id = params[:shixun_challenge_id] - if @exercise_question.question_type == 5 #当为实训题时,为关卡的分数 + if @exercise_question.question_type == Exercise::PRACTICAL #当为实训题时,为关卡的分数 @shixun_challenge = @exercise_question.exercise_shixun_challenges.cha_id_find(@shixun_a_id) if @shixun_challenge.present? @old_ques_score = @shixun_challenge.first.question_score diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index a18292047..03c943f8d 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -1,5 +1,5 @@ class ExercisesController < ApplicationController - before_action :require_login,except: [:index] + 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, @@ -12,10 +12,10 @@ class ExercisesController < ApplicationController 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,:commit_exercise,:exercise_lists] #判断当前用户在试卷的权限/老师是否属于分班的权限 + 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 :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] @@ -23,7 +23,6 @@ class ExercisesController < ApplicationController before_action :commit_shixun_present,only: [:commit_shixun] include ExportHelper include ExercisesHelper - # require 'pdfkit' def index ActiveRecord::Base.transaction do @@ -32,49 +31,49 @@ class ExercisesController < ApplicationController @exercises_all = @course.exercises member_show_exercises = @exercises_all.is_exercise_published #已发布的或已截止的试卷 @current_user_ = current_user - @exercises_count = @exercises_all.count # 全部页面,需返回 - @exercises_unpublish_counts = @exercises_all.exercise_by_status(1).count #未发布的试卷数 - @exercises_published_counts = @exercises_all.exercise_by_status([2,3]).count # 已发布的试卷数,包含已截止的 - @exercises_ended_counts = @exercises_all.exercise_by_status(3).count #已截止的试卷数 + # 课堂的学生人数 @course_all_members = @course.students #当前课堂的全部学生 - @course_all_members_count = @course_all_members.count #当前课堂的学生数 @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 - # @teacher_groups_ids = @course.teacher_course_groups.get_user_groups(current_user.id).pluck(:course_group_id).reject(&:blank?) - @exercises = @exercises_all #老师能看到全部的试卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同) + @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.present? ? member_show_exercises.unified_setting : [] + @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 - exercise_settings_ids = @course.exercise_group_settings.exercise_group_published.where(course_group_id: member_group_id).pluck(:exercise_id).uniq - @exercises = member_show_exercises.present? ? member_show_exercises.unified_setting.or(member_show_exercises.where(id: exercise_settings_ids)) : [] + not_exercise_ids = @course.exercise_group_settings.exercise_group_not_published.where("course_group_id = #{@member_group_id}").pluck(:exercise_id) + @exercises = member_show_exercises.where.not(id: not_exercise_ids) end else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁 @is_teacher_or = 0 - @exercises = member_show_exercises.present? ? member_show_exercises.unified_setting : [] + @exercises = member_show_exercises.unified_setting end - if @exercises.count > 0 + + if @exercises.size > 0 if params[:type].present? choose_type = params[:type].to_i - member_group_id = @current_student.first.try(:course_group_id).to_i - if @is_teacher_or == 2 && member_group_id > 0 - exercise_groups_sets = @course.exercise_group_settings.where(course_group_id: member_group_id).exercise_group_published - exercise_settings_ids = exercise_groups_sets.pluck(:exercise_id) - exercise_ended_ids = exercise_groups_sets.exercise_group_ended.pluck(:exercise_id).uniq - if choose_type == 2 - @exercises = @exercises_all.present? ? @exercises_all.exercise_by_status(2).unified_setting.or(@exercises_all.where(id: (exercise_settings_ids - exercise_ended_ids).uniq)) : [] - elsif choose_type == 3 - @exercises = @exercises_all.present? ? @exercises_all.exercise_by_status(3).unified_setting.or(@exercises_all.where(id: exercise_ended_ids)) : [] - end + ex_setting_ids = [] + if @is_teacher_or != 2 + @exercises = @exercises.where("exercise_status = #{choose_type}") else - @exercises = @exercises.exercise_by_status(choose_type) + 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 @@ -90,11 +89,16 @@ class ExercisesController < ApplicationController @page = params[:page] || 1 @limit = params[:limit] || 15 @exercises = @exercises.page(@page).per(@limit) - @exercises = @exercises.includes(:exercise_users,:exercise_questions,:exercise_group_settings) + @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) @@ -177,7 +181,7 @@ class ExercisesController < ApplicationController else @is_teacher_or = 0 #为学生 end - @exercise_questions = @exercise.exercise_questions.order("question_number ASC") + @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("试卷创建失败!") @@ -190,28 +194,31 @@ class ExercisesController < ApplicationController 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).count #已提交的用户数 + @user_commit_counts = @exercise.exercise_users.where(commit_status:1).size #已提交的用户数 end - @ex_status = @exercise.get_exercise_status(current_user.id) + @ex_status = @exercise.get_exercise_status(current_user) exercise_id_array = [@exercise.id] - @exercise_publish_count = get_user_permission_course(exercise_id_array,2).count #是否存在已发布的 - @exercise_unpublish_count = get_user_permission_course(exercise_id_array,1).count #是否存在未发布的 + @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 == 1 + if @ex_status == Exercise::UNPUBLISHED @exercise_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候 - elsif @ex_status == 2 + elsif @ex_status == Exercise::PUBLISHED @exercise_publish_count = 1 #试卷未发布,且课堂没有分班的时候 end end + rescue Exception => e uid_logger_error(e.message) tip_exception("没有权限") @@ -306,7 +313,7 @@ class ExercisesController < ApplicationController 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 + 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, @@ -361,7 +368,7 @@ class ExercisesController < ApplicationController exercise_bank_question = current_ex_bank.exercise_bank_questions.new option exercise_bank_question.save ## 试卷选项的输入 - if q.question_type != 5 #不为实训题时,试卷选项加入试题答案库 + if q.question_type != Exercise::PRACTICAL #不为实训题时,试卷选项加入试题答案库 ex_choices = q.exercise_choices ex_standard = q.exercise_standard_answers ex_choices.each do |c| @@ -387,7 +394,7 @@ class ExercisesController < ApplicationController :position => c.position, :challenge_id => c.challenge_id, :shixun_id => q.shixun_id, - :question_score => q.question_score + :question_score => c.question_score } shixun_challenge_bank = exercise_bank_question.exercise_bank_shixun_challenges.new challenge_option shixun_challenge_bank.save @@ -412,10 +419,11 @@ class ExercisesController < ApplicationController @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) #当前用户已发布班级的试卷设置 + @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,2).count #判断当前用户是否有试卷已发布的分班,用于显示立即截止/撤销发布 - @exercise_unpublish_count = get_user_permission_course(exercise_ids,1).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 #判断当前用户是否有试卷未发布的分班,用户显示立即发布 @exercise_users_count = @exercise.exercise_users.commit_exercise_by_status(1).count #判断当前试卷是否有已提交的 # ## 需添加发送消息的接口,稍后添加 rescue Exception => e @@ -431,10 +439,12 @@ class ExercisesController < ApplicationController ActiveRecord::Base.transaction do begin error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。 - course_group_ids = @course.teacher_course_group_ids(current_user.id) #当前老师的班级id数组 - exercise_status = @exercise.get_exercise_status(current_user.id) + # 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 == 1 && (course_group_ids - [0]).count > 0 # 试卷未发布,且老师的分班大于1 ,才可以修改统一设置,否则按试卷默认的来处理 + if exercise_status == Exercise::UNPUBLISHED && course_group_ids.size > 0 # 试卷未发布,且老师的分班大于1 ,才可以修改统一设置,否则按试卷默认的来处理 unified_setting = params[:unified_setting] else unified_setting = @exercise.unified_setting @@ -448,8 +458,8 @@ class ExercisesController < ApplicationController answer_open = params[:answer_open] ? true : false #答案是否公开 # 统一设置或者分班为0,则更新试卷,并删除试卷分组 - if unified_setting || (course_group_ids.count == 0) - params_publish_time = params[:publish_time].blank? ? nil : params[:publish_time].to_time + if unified_setting || (course_group_ids.size == 0) + params_publish_time = params[:publish_time].blank? ? nil : params[:publish_time].to_time params_end_time = nil if params[:end_time].blank? if params_publish_time.present? @@ -459,10 +469,8 @@ class ExercisesController < ApplicationController params_end_time = params[:end_time].to_time end - if exercise_status == 2 && @exercise.publish_time != params_publish_time - normal_status(-1,"已发布,不允许修改发布时间") - elsif exercise_status == 3 && (@exercise.end_time != params_end_time || @exercise.publish_time != params_publish_time) - normal_status(-1,"已截止,不允许修改时间") + 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 @@ -503,12 +511,8 @@ class ExercisesController < ApplicationController else exercise_end_time = t[:end_time].to_time end - # exercise_end_time = t[:end_time].present? ? t[:end_time].to_time : nil exercise_group = exercise_groups.find_in_exercise_group("course_group_id",course_id) #判断该分班是否存在 - if exercise_group.present? && exercise_group.first.end_time <= Time.now && (exercise_end_time != exercise_group.first.end_time || exercise_publish_time != exercise_group.first.publish_time) #已截止且时间改变的,则提示错误 - error_count += 1 - end - if exercise_group.present? && exercise_group.first.publish_time < Time.now && exercise_publish_time != exercise_group.first.publish_time + if exercise_group.present? && (exercise_group.first.publish_time < Time.now) && (exercise_publish_time != exercise_group.first.publish_time) error_count += 1 end if error_count == 0 @@ -585,7 +589,7 @@ class ExercisesController < ApplicationController :end_time => e_time } @exercise.update_attributes(exercise_params) - if @exercise.exercise_status == 2 + 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 @@ -663,6 +667,7 @@ class ExercisesController < ApplicationController #立即发布的弹窗内容 def publish_modal + ActiveRecord::Base.transaction do begin exercise_ids = params[:check_ids] @@ -681,32 +686,29 @@ class ExercisesController < ApplicationController #首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。 def publish + tip_exception("缺少截止时间参数") if params[:end_time].blank? + tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) + tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) ActiveRecord::Base.transaction do begin check_ids = Exercise.where(id: params[:check_ids]) - ex_end_time = params[:end_time] || Time.at(((1.month.since.to_i)/3600.0).ceil * 3600) + 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 = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",params[:group_ids]).exercise_group_not_published.present? ? 1 : 0 + ex_status = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",params[:group_ids]) + .exercise_group_not_published.present? ? 1 : 0 end if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过 g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改 if g_course - course_groups = @course.teacher_course_groups.get_user_groups(current_user.id) - - if course_groups.blank? - user_course_groups = @course.course_groups.present? ? @course.course_groups.pluck(:id) : [] - else - user_course_groups = course_groups.pluck(:course_group_id).reject(&:blank?).uniq - end - + user_course_groups = @course.charge_group_ids(current_user) if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则试卷不用分组,且试卷设定为统一设置,否则则分组设置 exercise.exercise_group_settings.destroy_all ex_unified = true - notify_receiver_ids = @course.students.pluck(:user_id) + e_time = ex_end_time else ex_unified = false g_course.each do |i| @@ -725,21 +727,15 @@ class ExercisesController < ApplicationController new_exercise_group.save end end - - notify_receiver_ids = @course.students.where(course_group_id: params[:group_ids]).pluck(:user_id) + # 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 - notify_receiver_ids = @course.students.pluck(:user_id) - end - if exercise.end_time.blank? e_time = ex_end_time - elsif exercise.exercise_group_settings.end_time_no_null.count > 0 # 该试卷分组有结束时间为空的 - e_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time).max - else - e_time = exercise.end_time end + ex_status = set_exercise_status(Time.now,e_time) exercise_params = { :publish_time => Time.now, @@ -752,7 +748,7 @@ class ExercisesController < ApplicationController 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, notify_receiver_ids) + ExercisePublishNotifyJob.perform_later(exercise.id, g_course) end end end @@ -790,16 +786,11 @@ class ExercisesController < ApplicationController 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.id) - if exercise_status == 2 #跳过已截止的或未发布的 + exercise_status= exercise.get_exercise_status(current_user) + if exercise_status == Exercise::PUBLISHED #跳过已截止的或未发布的 g_course = params[:group_ids] if g_course.present? - user_course_groups= @course.teacher_course_groups.get_user_groups(current_user.id) - if user_course_groups.present? - teacher_course_group_ids = user_course_groups.pluck(:course_group_id) - else - teacher_course_group_ids = @course.course_groups.pluck(:id) - end + teacher_course_group_ids = @course.charge_group_ids(current_user) if g_course.map(&:to_i).sort == teacher_course_group_ids.sort #开始为统一设置 exercise.exercise_group_settings.destroy_all new_ex_status = set_exercise_status(exercise.publish_time,Time.now) @@ -884,13 +875,15 @@ class ExercisesController < ApplicationController 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.id) == 2 #用户已提交且试卷提交中 + 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_attributes(:score => nil, :end_at => nil, :status => nil, :commit_status => 0, :objective_score => 0.0, :subjective_score => -1.0) + exercise_user.update_attributes(: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 = 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 @@ -918,11 +911,13 @@ class ExercisesController < ApplicationController 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}%") + @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}%") + @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}") @@ -957,8 +952,10 @@ class ExercisesController < ApplicationController 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 + 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 @@ -976,7 +973,13 @@ class ExercisesController < ApplicationController def start_answer ActiveRecord::Base.transaction do begin - if @exercise_user_current.blank? + 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_attribute("start_at",Time.now) + end + else if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候,不创建exercise_user表,理论上老师是不能进入答题的 exercise_user_params = { :user_id => @exercise_current_user_id, @@ -986,27 +989,19 @@ class ExercisesController < ApplicationController exercise_user_current = ExerciseUser.new(exercise_user_params) exercise_user_current.save end - else - if @exercise_user_current.start_at.blank? - @exercise_user_current.update_attribute("start_at",Time.now) - end end - if @exercise.time > 0 - exercise_user_start = @exercise_user_current.present? ? @exercise_user_current.start_at.to_i : 0 - exercise_user_left_time = Time.now.to_i - exercise_user_start - time_mill = @exercise.time * 60 #转为毫秒 - @user_left_time = (time_mill < exercise_user_left_time) ? nil : (time_mill - exercise_user_left_time) #当前用户对试卷的回答剩余时间 - end - - @t_user_exercise_status = @exercise.get_exercise_status(current_user.id) + @t_user_exercise_status = @exercise.get_exercise_status(current_user) - if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) || (@exercise_user_current.present? && @exercise_user_current.commit_status == 1) + @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.includes(:exercise_shixun_challenges,:exercise_shixun_answers,:exercise_answers,:exercise_standard_answers) + @exercise_questions = @exercise.exercise_questions if @exercise.question_random @exercise_questions = @exercise_questions.order("RAND()") @@ -1014,11 +1009,15 @@ class ExercisesController < ApplicationController @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 == 3 + 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) + get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,@t_user_exercise_status) rescue Exception => e uid_logger_error(e.message) @@ -1046,9 +1045,9 @@ class ExercisesController < ApplicationController end end @exercise_questions.each do |q| - if q.question_type == 5 #当为实训题时 + 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 != 1 #当前用户的实训是否做完 + if user_myshixun.blank? || user_myshixun.first.status != Exercise::UNPUBLISHED #当前用户的实训是否做完 @shixun_undo += 1 end else @@ -1100,19 +1099,19 @@ class ExercisesController < ApplicationController ActiveRecord::Base.transaction do begin # 1 老师权限,0 学生权限 - @is_teacher_or = @user_course_identity < Course::STUDENT ? 1 : 0 + @is_teacher_or = (@user_course_identity < Course::STUDENT) ? 1 : 0 @student_status = 2 - # @exercise_answerer = User.find_by(id:@exercise_current_user_id) #试卷回答者 - @exercise_questions = @exercise.exercise_questions.order("question_number ASC") + @exercise_questions = @exercise.exercise_questions.includes(:exercise_shixun_challenges,:exercise_standard_answers,:exercise_answers,:exercise_shixun_answers).order("question_number ASC") @question_status = [] - get_exercise_status = @exercise.get_exercise_status(current_user.id) + 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 == 2 #当前用户已提交,且试卷未截止 + 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) + get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,get_exercise_status) end end end @@ -1133,73 +1132,69 @@ class ExercisesController < ApplicationController begin @current_user_id = current_user.id exercise_ids = [@exercise.id] - @exercise_status = @exercise.get_exercise_status(current_user.id) + @exercise_status = @exercise.get_exercise_status(current_user) @course_all_members = @course.students - question_types = @exercise.exercise_questions.pluck(:question_type) - @exercise_publish_count = get_user_permission_course(exercise_ids,2).count #判断是否有已发布的分班 - @exercise_unpublish_count = get_user_permission_course(exercise_ids,1).count #判断是否有未发布的分班 + @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.include?(4) #是否包含主观题 + 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 - if @exercise_status == 1 - @exercise_users_list = [] - @exercise_course_groups = [] - @exercise_unanswers = 0 - @exercise_answers = 0 - else + 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) + get_exercise_answers(@exercise_users_list, @exercise_status) end - elsif @user_course_identity > Course::ASSISTANT_PROFESSOR #当前为学生或者有过答题的(提交/未提交) + 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_current_user = @exercise_all_users.exercise_commit_users(current_user.id) #当前用户是否开始做试卷(提交/未提交/没做) - if exercise_current_user.present? - @exercise_current_user_status = 1 #当前用户的状态,为学生 - if @exercise.score_open && @exercise_status == 3 && exercise_current_user.present? #勾选了成绩公开且试卷已截止的 + 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.present? ? exercise_current_user.distinct : [] + @exercise_users_list = exercise_current_user end - else - @exercise_all_users = @exercise.get_stu_exercise_users - get_exercise_answers(@exercise_all_users) # 未答和已答的 + else #表示为未回答的,或未非课堂成员的 @exercise_current_user_status = 2 #当前用户非课堂成员 - @exercise_users_list = [] - # @exercise_unanswers = 0 - # @exercise_answers = 0 end end - if @exercise_users_list.present? && @exercise_users_list.count > 0 - @exercise_users_count = @exercise_users_list.count #当前显示的全部成员数量 - else - @exercise_users_count = 0 - end if @exercise_unanswers < 0 @exercise_unanswers = 0 end - @teacher_review_count = 0 - @teacher_unreview_count = 0 #筛选/分类,排序 order = params[:order] - if @exercise_users_list.present? && @exercise_users_list.count > 0 + 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.count #已评阅 - @teacher_unreview_count = teacher_unreviews.count #未评阅 + @teacher_review_count = teacher_reviews.size #已评阅 + @teacher_unreview_count = teacher_unreviews.size #未评阅 #是否评阅 if params[:review].present? @@ -1211,14 +1206,6 @@ class ExercisesController < ApplicationController end end - if order == "student_id" - @exercise_users_list = @exercise_users_list.joins(user: [:user_extension]).order("user_extensions.student_id DESC") - elsif order == "score" - @exercise_users_list = @exercise_users_list.order("#{order} DESC") - else - @exercise_users_list = @exercise_users_list.order("end_at DESC, start_at DESC") - end - #答题状态的选择 if params[:commit_status].present? choose_type = params[:commit_status] @@ -1235,50 +1222,51 @@ class ExercisesController < ApplicationController #搜索 if params[:search].present? - search_content = params[:search] - #搜索用户的nickname,如果存在则返回,否则继续查询用户的真实姓名或学生号 - nick_name_search = @exercise_users_list.where(user_id: User.where('CONCAT(users.lastname, users.firstname) like ?',"%#{search_content}%")) - if nick_name_search.present? - @exercise_users_list = nick_name_search - else - @exercise_users_list = @exercise_users_list.joins(user: [:user_extension]).where('user_extensions.student_id like ? OR user_extensions.student_realname like ?',"%#{search_content}%","%#{search_content}%") - end + @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 DESC") + elsif order == "score" + @exercise_users_list = exercise_user_joins.order("#{order} DESC") + else + @exercise_users_list = exercise_user_joins.order("end_at DESC, start_at DESC") end @export_ex_users = @exercise_users_list - @exercise_users_size = @exercise_users_list.count + @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) - respond_to do |format| - format.json - format.xlsx{ - if @user_course_identity > Course::ASSISTANT_PROFESSOR - tip_exception(403,"无权限操作") - else - 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.first(30)}",template: "exercises/exercise_lists.xlsx.axlsx",locals: {table_columns:@table_columns,exercise_users:@user_columns} - end - } - end else @exercise_users_list = [] + @export_ex_users = @exercise_users_list @exercise_users_size = 0 - respond_to do |format| - format.json - format.xlsx{ - normal_status(-1,"暂无用户提交") - } - format.zip{ - normal_status(-1,"暂无用户提交") - } - end 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,"暂无用户提交") + else + respond_to do |format| + format.xlsx{ + 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.first(30)}",template: "exercises/exercise_lists.xlsx.axlsx",locals: {table_columns:@table_columns,exercise_users:@user_columns} + } + end + end + end rescue Exception => e uid_logger_error(e.message) tip_exception("页面调用失败!") @@ -1289,10 +1277,11 @@ class ExercisesController < ApplicationController #导出空白试卷 def export_exercise - @exercise_questions = @exercise.exercise_questions.order("question_number ASC") - filename = "#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.current.strftime('%Y%m%d%H%M%S')}.pdf" + @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" - render pdf: 'exercise_export/blank_exercise', filename: filename, stylesheets: stylesheets + render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets end #空白试卷预览页面,仅供测试使用,无其他任何用途 @@ -1319,15 +1308,12 @@ class ExercisesController < ApplicationController ActiveRecord::Base.transaction do begin exercise_ids = [@exercise.id] - @exercise_publish_count = get_user_permission_course(exercise_ids,2).count #判断是否有已发布的分班 - @exercise_unpublish_count = get_user_permission_course(exercise_ids,1).count #判断是否有未发布的分班 + @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) - # @exercise_course_groups = @exercise.get_ex_published_course(current_user.id) - @exercise_users_list = @exercise.all_exercise_users(current_user.id) - @course_all_members_count = @exercise_users_list.size #班级的选择 if params[:exercise_group_id].present? @@ -1335,11 +1321,15 @@ class ExercisesController < ApplicationController 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.count #试卷的已提交用户人数 - @exercise_status = @exercise.get_exercise_status(current_user.id) + @exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数 + @exercise_status = @exercise.get_exercise_status(current_user) #提交率 if @course_all_members_count == 0 @@ -1374,7 +1364,7 @@ class ExercisesController < ApplicationController :best_counts => best_counts, } - @exercise_questions = @exercise.exercise_questions + @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_answers,:exercise_standard_answers,:exercise_shixun_challenges,:exercise_shixun_answers) @paging_type = "percent" # 按题型排序 @@ -1387,10 +1377,10 @@ class ExercisesController < ApplicationController if @paging_type == "percent" @question_result_hash = ques_result_all.sort_by{|s| s[:percent]} else - @question_result_hash = ques_result_all.sort_by{|s| s["#{@paging_type}"]} + @question_result_hash = ques_result_all.sort_by{|s| s[:"#{@paging_type}"]} end - @exercise_questions_count = @exercise_questions.count + @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) @@ -1420,7 +1410,8 @@ class ExercisesController < ApplicationController 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) + normal_status(-1, "试卷须知不能超过100个字符") if (params[:exercise_description].present? && + params[:exercise_description].length > 100) end #判断设置的时间是否合理 @@ -1466,69 +1457,64 @@ class ExercisesController < ApplicationController end def get_exercise_question_counts #获取试卷的问题数及总分数 - exercise_questions = @exercise.exercise_questions.all - @exercise_ques_count = exercise_questions.count # 全部的题目数 + 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",0) - @exercise_single_ques_count = exercise_single_ques.all.count + 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",1) - @exercise_double_ques_count = exercise_double_ques.all.count + 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",2) - @exercise_ques_judge_count = exercise_ques_judge.all.count + 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",3) - @exercise_ques_null_count = exercise_ques_null.all.count + 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",4) - @exercise_ques_main_count = exercise_ques_main.all.count + 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",5) - @exercise_ques_shixun_count = exercise_ques_shixun.all.count + 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 = [] - g_course_ids = @course.teacher_course_groups.get_user_groups(current_user.id).pluck(:course_group_id).reject(&:blank?).uniq #当前用户有权限的分班 - #用户的班级,理论上用户的班级要大于等于试卷设置的班级 - if g_course_ids.blank? || g_course_ids.include?(0) - user_groups_id = @course.course_groups.pluck(:id) - else - user_groups_id = g_course_ids - end - exercises_all = Exercise.where(id:exercise_ids) + 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.id) #当前用户的能看到的试卷 - if exercise_user_status == exercise_status || exercise_status == 3 #未发布的情况 + 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 - else - unpublish_group = [] end - # unpublish_group = unpublish_group + user_groups_id 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 == 1 + if exercise_status == Exercise::UNPUBLISHED unpublish_group = user_groups_id - ex_group_settings - elsif exercise_status == 3 + 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 #已发布的全部班级减去截止的全部班级 @@ -1542,21 +1528,19 @@ class ExercisesController < ApplicationController unpublish_group = unpublish_group.uniq if unpublish_group.count > 0 course_groups = CourseGroup.by_group_ids(unpublish_group) - else - course_groups = [] 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 + 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 + elsif end_time.present? && (end_time <= time_now_i) 3 - elsif end_time.present? && publish_time.present? && end_time < publish_time + elsif end_time.present? && publish_time.present? && (end_time < publish_time) normal_status(-1,"时间设置错误!") else 1 @@ -1586,7 +1570,7 @@ class ExercisesController < ApplicationController ## 判断开始答题页面的用户权限 def check_user_on_answer - if @user_course_identity == Course::STUDENT && @exercise.get_exercise_status(current_user.id) == 1 #试卷未发布,且当前用户不为老师/管理员 + 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, "试卷暂未公开!") @@ -1594,48 +1578,16 @@ class ExercisesController < ApplicationController end def check_exercise_time - @answer_committed_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first + @answer_committed_user = @exercise.exercise_users.exercise_commit_users(current_user.id)&.first if @answer_committed_user.blank? normal_status(404,"答题用户不存在") - elsif @exercise.get_exercise_status(current_user.id) != 2 || @answer_committed_user.commit_status == 1 # - normal_status(-1,"提交错误,试卷已截止/用户已提交!") - # elsif @exercise.time > 0 - # user_start_at = @answer_committed_user.start_at - # exercise_time = @exercise.time.to_i - # if (user_start_at + exercise_time.minutes) < Time.now - # normal_status(-1,"限时试卷已结束,已自动提交!") - # end - end - end - - def commit_user_exercise - @exercise_user_current = @exercise.exercise_users.exercise_commit_users(@exercise_current_user_id).first #查找当前用户是否有过答题 - if @user_course_identity == Course::STUDENT - if @exercise_user_current.present? - if @exercise.time > 0 && @exercise_user_current.start_at.present? && (@exercise_user_current.commit_status == 0) && ((@exercise_user_current.start_at + (@exercise.time.to_i + 1).minutes) < Time.now) - #当前用户存在,且已回答,且试卷时间已过,且未提交,则自动提交。最好是前端控制 - objective_score = calculate_student_score(@exercise,current_user)[:total_score] - subjective_score = @exercise_user_current.subjective_score < 0.0 ? 0.0 : @exercise_user_current.subjective_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 => subjective_score - } - @exercise_user_current.update_attributes(commit_option) - normal_status(0,"已交卷成功!") - end - end 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.id) != 2 + if @exercise.get_exercise_status(current_user) != Exercise::PUBLISHED normal_status(-1,"非提交中的试卷不允许打回重做!") elsif @exercise_users.count < 1 normal_status(-1,"暂无人提交试卷!") @@ -1645,10 +1597,10 @@ class ExercisesController < ApplicationController #查看试题页面,当为学生时,除非试卷已截止,或已提交才可以查看 def check_exercise_is_end - ex_status = @exercise.get_exercise_status(current_user.id) + 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 == 1 + if ex_status == Exercise::UNPUBLISHED normal_status(-1,"试卷未发布") elsif @ex_user.present? && @ex_user.commit_status == 0 normal_status(-1,"试卷未提交") @@ -1662,7 +1614,8 @@ class ExercisesController < ApplicationController 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.id) == 3 && ex_user.present? && ex_user.commit_status == 1 && @exercise.show_statistic + 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 @@ -1678,19 +1631,25 @@ class ExercisesController < ApplicationController end end - def get_user_answer_status(exercise_questions,user_id) + 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 q.question_type != 5 + if ex_question_random && exercise_user_status != Exercise::DEADLINE + ques_number = index + 1 + else + ques_number = q.question_number + end + if q.question_type != Exercise::PRACTICAL ques_vote = q.exercise_answers.search_exercise_answer("user_id",user_id) else ques_vote = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id) end ques_status = 0 if ques_vote.present? - if q.question_type == 5 + if q.question_type == Exercise::PRACTICAL if ques_vote.pluck(:exercise_shixun_challenge_id).sort == q.exercise_shixun_challenges.pluck(:id).sort #用户的总得分等于问题的分数 ques_status = 1 #全部回答了,才算已答 question_answered += 1 @@ -1698,12 +1657,12 @@ class ExercisesController < ApplicationController else #其他题目,需回答的有内容,才会为已答,否则如内容为空,视为未答 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 <= 2 #选择题和判断题的时候,需要有选项,才算回答 + if q.question_type <= Exercise::JUDGMENT #选择题和判断题的时候,需要有选项,才算回答 if vote_answer_id.size > 0 ques_status = 1 question_answered += 1 end - elsif q.question_type == 3 #填空题的时候,需要有选项和内容,才算回答 + elsif q.question_type == Exercise::COMPLETION #填空题的时候,需要有选项和内容,才算回答 if vote_answer_id.uniq.sort == q.exercise_standard_answers.pluck(:exercise_choice_id).uniq.sort ques_status = 1 question_answered += 1 @@ -1718,12 +1677,12 @@ class ExercisesController < ApplicationController end question_status = { :ques_id => q.id, - :ques_number => index+1, #仅问题的显示位置变化,但是问题的question_number 不会变化,与之相关的choice/standard_answer/answer不会变化 + :ques_number => ques_number, #仅问题的显示位置变化,但是问题的question_number 不会变化,与之相关的choice/standard_answer/answer不会变化 :ques_status => ques_status, } question_options = { :question => q, - :ques_number => index+1, + :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]} diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index 0e00dcc66..d090ae253 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -1,9 +1,9 @@ class FilesController < ApplicationController include MessagesHelper - before_action :require_login, except: %i[index] + before_action :require_login, :check_auth, except: %i[index] before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project] - before_action :find_ids, only: %i[bulk_delete bulk_send bulk_move bulk_public] + before_action :find_ids, only: %i[bulk_delete bulk_send bulk_move bulk_public bulk_publish] before_action :file_validate_sort_type, only: :index before_action :validate_send_message_to_course_params, only: :bulk_send before_action :set_pagination, only: %i[index public_with_course_and_project mine_with_course_and_project] @@ -16,29 +16,36 @@ class FilesController < ApplicationController sort = params[:sort] || 0 # 0: 降序;1: 升序 sort_type = params[:sort_type] || 'created_on' # created_on:时间排序, downloads:下载次数排序; quotes: 引用次数排序 course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id - @user = current_user || nil - @attachments = @course.attachments.by_keywords(params[:search]) + @user = current_user + @attachments = @course.attachments.by_course_second_category_id(course_second_category_id) .includes(attachment_group_settings: :course_group, author: [:user_extension, :course_members]) - .by_course_second_category_id(course_second_category_id) .ordered(sort: sort.to_i, sort_type: sort_type.strip) - get_category(@course, course_second_category_id) - - case @user.course_identity(@course) - when 5 - # 课程学生 - @attachments = @attachments.published - when 6 || 7 - # 非课堂成员 - @attachments = @attachments.publiced.published - end + get_category(@course, course_second_category_id) @total_count = @attachments.size - @public_count = @attachments.publiced.size - @private_count = @total_count - @public_count + @publish_count = @attachments.published.size + @unpublish_count = @total_count - @publish_count + + @attachments = @attachments.by_keywords(params[:search]) + @attachments = + case @user.course_identity(@course) + when 5 + @attachments.published + when 6, 7 + @attachments.publiced.published + else + @attachments + end @attachments = @attachments.page(@page).per(@page_size) end + def bulk_publish + return normal_status(403, "您没有权限进行操作") if current_user.course_identity(@course) >= 5 + @course.attachments.by_ids(@attachment_ids).unpublish.update_all(is_publish: 1, publish_time: Time.now) + render_ok + end + def bulk_delete ActiveRecord::Base.transaction do begin @@ -180,6 +187,8 @@ class FilesController < ApplicationController attach_copied_obj.created_on = Time.now attach_copied_obj.author = current_user attach_copied_obj.is_public = 0 + attach_copied_obj.is_publish = 1 + attach_copied_obj.publish_time = Time.now attach_copied_obj.course_second_category_id = course_second_category_id attach_copied_obj.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from if attach_copied_obj.attachtype == nil @@ -197,7 +206,7 @@ class FilesController < ApplicationController # 资源设置 def update - return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_or_admin?(@course) || @file.author == current_user + return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@course) >= 5 && @file.author != current_user is_unified_setting = params[:is_unified_setting] publish_time = params[:publish_time] diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb index 4aa0b13b8..e6a592f51 100644 --- a/app/controllers/games_controller.rb +++ b/app/controllers/games_controller.rb @@ -1,5 +1,5 @@ class GamesController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :find_game before_action :find_shixun, only: [:show, :answer, :rep_content, :choose_build, :game_build, :game_status] @@ -33,27 +33,24 @@ class GamesController < ApplicationController is_teacher = @user.is_teacher? # 实训超时设置 - time_limit = @shixun.exec_time + time_limit = game_challenge.exec_time # 上一关、下一关 prev_game = @game.prev_of_current_game(@shixun.id, @game.myshixun_id, game_challenge.position) next_game = @game.next_of_current_game(@shixun.id, @game.myshixun_id, game_challenge.position) # 关卡点赞数, praise_or_tread = 1则表示赞过 - praise_count = PraiseTread.where(praise_tread_object_id: game_challenge.id, praise_tread_object_type: "Challenge", - praise_or_tread: 1).count - user_praise = PraiseTread.where(praise_tread_object_id: game_challenge.id, praise_tread_object_type: "Challenge", - user_id: current_user.id, praise_or_tread: 1).present? ? true : false + praise_count = game_challenge.praises_count + user_praise = game_challenge.praise_treads.exists?(user_id:current_user.id, praise_or_tread: 1) # 实训的最大评测次数,这个值是为了优化查询,每次只取最新的最新一次评测的结果集 max_query_index = @game.query_index.to_i # 统计评测时间 - record_onsume_time = EvaluateRecord.where(game_id: @game.id).first.try(:consume_time) + record_onsume_time = EvaluateRecord.where(game_id: @game.id).first.try(:pod_execute) - # power判断用户是否有权限查看隐藏测试集(TPM管理员;平台认证的老师;花费金币查看者) - # myshixun_manager - myshixun_manager = current_user.manager_of_shixun?(@shixun) || (current_user.is_teacher? && current_user.pro_certification?) + # myshixun_manager判断用户是否有权限查看隐藏测试集(TPM管理员;平台认证的老师;花费金币查看者) + myshixun_manager = @identity < User::EDU_GAME_MANAGER # 选择题和编程题公共部分 @base_date = {st: @st, discusses_count: discusses_count, game_count: game_count, myshixun: @myshixun, @@ -62,10 +59,28 @@ class GamesController < ApplicationController praise_count: praise_count, user_praise: user_praise, time_limit: time_limit, tomcat_url: edu_setting('cloud_tomcat_php'), is_teacher: is_teacher, myshixun_manager: myshixun_manager} + if @shixun.vnc + begin + shixun_tomcat = edu_setting('cloud_bridge') + service_host = edu_setting('vnc_url') + uri = "#{shixun_tomcat}/bridge/vnc/getvnc" + params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}"} + res = uri_post uri, params + if res && res['code'].to_i != 0 + raise("实训云平台繁忙(繁忙等级:99)") + end + # 无域名版本 + #@vnc_url = "http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless" + # 有域名版本 + @vnc_url = "https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless" + rescue Exception => e + Rails.logger.error(e.message) + end + end # 区分选择题和编程题,st:0编程题; if @st == 0 - has_answer = game_challenge.challenge_answers.size == 0 ? false : true + has_answer = game_challenge.challenge_answers.size != 0 game_challenge.answer = nil mirror_name = @shixun.mirror_name @@ -75,7 +90,7 @@ class GamesController < ApplicationController rescue uid_logger("实训平台繁忙,繁忙等级(81)") end - tpm_cases_modified = (game_challenge.modify_time != @game.modify_time ? true : false) # modify_time 决定TPM测试集是否有更新 + tpm_cases_modified = (game_challenge.modify_time != @game.modify_time) # modify_time 决定TPM测试集是否有更新 @task_result = {tpm_modified: tpm_modified, tpm_cases_modified: tpm_cases_modified, mirror_name: mirror_name, has_answer: has_answer} @@ -207,12 +222,12 @@ class GamesController < ApplicationController @result = challenge.st == 0 ? challenge.try(:answer) : challenge.choose_answer end - # 获取答案 + # 获取实践题答案 # GET: /tasks/:identifier/get_answer_info # 0 直接查看答案, 1 查看答案弹框, 2 答案详情弹框 def get_answer_info - challenge = @game.challenge - @challenge_answers = challenge.challenge_answers + @challenge = @game.challenge + @challenge_answers = @challenge.challenge_answers # 平台已认证的老师需要控制 @power = (@identity < User::EDU_GAME_MANAGER) if !@power @@ -229,16 +244,29 @@ class GamesController < ApplicationController end end end + end + # 获取选择题答案 + def get_choose_answer + @challenge = @game.challenge + tip_exception("本接口只能获取选择题答案") if @challenge.st != 1 + @power = (@identity < User::EDU_GAME_MANAGER) + # 如果没权限,也没看过答案,则需要解锁 + if @game.answer_open == 0 && !@power + tip_exception(1, @challenge.choose_score) + else + @challenge_chooses = @challenge.challenge_chooses + end end - # 解锁答案 + # 解锁实践题答案 # GET: /tasks/:identifier/get_answer_info?answer_id=? def unlock_answer + @challenge = @game.challenge @answer = ChallengeAnswer.find(params[:answer_id]) challenge = @answer.challenge # 解锁需要本层级的答案是否需要扣分 - points = challenge.challenge_answers.where(level: @game.answer_open+1..@answer.level).sum(:score) + points = challenge.challenge_answers.where(level: @game.answer_open + 1..@answer.level).sum(:score) deduct_score = ((points / 100.0) * challenge.score).to_i uid_logger("############金币数目: #{current_user.grade}") unless current_user.grade.to_i - deduct_score > 0 @@ -249,13 +277,16 @@ class GamesController < ApplicationController begin # 积分消耗情况记录 score = challenge.st.zero? ? -deduct_score : -challenge.choose_score.to_i - RewardGradeService.call(current_user, container_id: @answer.id, container_type: 'Answer', score: score) + RewardGradeService.call(current_user, container_id: @game.id, container_type: 'Answer', score: score) # 通关查看答案 不扣 得分 + answer_open = @challenge.st == 1 ? 1 : @answer.level if @game.status == 2 - @game.update_attributes!(:answer_open => @answer.level) + @game.update_attributes!(:answer_open =>answer_open) else - @game.update_attributes!(:answer_open => @answer.level, :answer_deduction => deduct_score) + # 扣除总分计算 + answer_deduction = challenge.challenge_answers.where("level <= #{@answer.level}").sum(:score) + @game.update_attributes!(:answer_open => answer_open, :answer_deduction => answer_deduction) end rescue Exception => e @@ -263,7 +294,32 @@ class GamesController < ApplicationController raise ActiveRecord::Rollback end end + end + # 解锁选择题答案 + def unlock_choose_answer + @challenge = @game.challenge + score = @challenge.choose_score + unless current_user.grade.to_i - score > 0 + tip_exception("您没有足够的金币") + end + ActiveRecord::Base.transaction do + begin + # 积分消耗情况记录 + RewardGradeService.call(current_user, container_id: @game.id, container_type: 'Answer', score: -score) + # 通关查看答案 不扣 得分 + if @game.status == 2 + @game.update_attributes!(:answer_open => 1) + else + # 扣除总分计算 + @game.update_attributes!(:answer_open => 1, :answer_deduction => 100) + end + @challenge_chooses = @challenge.challenge_chooses + rescue Exception => e + uid_logger_error("#######金币扣除异常: #{e.message}") + raise ActiveRecord::Rollback + end + end end # 查看答案需要扣取金币 @@ -327,11 +383,10 @@ class GamesController < ApplicationController @game.update_attribute(:test_sets_view, true) # 扣分记录 Grade.create(:user_id => current_user.id, :container_id => @game.id, :score => -@minus_grade, :container_type => "testSet") - @status = 0 - @message = "解锁成功!" + max_query_index = @game.query_index.to_i + testset_detail max_query_index, challenge else - @status = -1 - @message = "本操作需要扣除#{ @minus_grade }金币,您的金币不够了" + tip_exception(-1, "本操作需要扣除#{ @minus_grade }金币,您的金币不够了") end end @@ -411,12 +466,12 @@ class GamesController < ApplicationController game_code = GameCode.where(:game_id => @game.try(:id), :path => path).first if game_code.present? content = game_code.try(:new_code) - @content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && content.present? - content.gsub(/\t/, ' ') - else - content - end - update_file_content(@content, @myshixun.repo_path, path, current_user.mail, current_user.full_name, "game passed reset") + # @content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && content.present? + # content.gsub(/\t/, ' ') + # else + # content + # end + update_file_content(content, @myshixun.repo_path, path, current_user.mail, current_user.full_name, "game passed reset") else tip_exception("代码重置失败,代码为空") end @@ -425,7 +480,7 @@ class GamesController < ApplicationController # 获取版本库文件内容 # 注:如果本身path传错,内容肯定也为空;fork成功后,可能短时间内也获取不到版本库内容 # params[:status] 1: 目录树点击的请求 0:正常自动加载 - # 返回参数status : -3 需要重试,带retry参数;-1 给出提示 + # 返回参数status : -1 系统统一报错提示;-3 需要轮训重试,带retry参数;-4 立即重试 def rep_content challenge_path = @game.challenge.try(:path) if challenge_path.blank? @@ -437,22 +492,19 @@ class GamesController < ApplicationController path = path.try(:strip) uid_logger("--rep_content: path is #{path}") begin - @content = git_fle_content(@myshixun.repo_path, path) || "" - rescue - if params[:retry].present? - begin - begin - # 检测TPM对应的路径代码是否正常 - git_fle_content(@myshixun.shixun.repo_path, path) - rescue Exception => e - uid_logger_error("#{e.message}") - if @myshixun.shixun.try(:status) < 2 - tip_exception("代码获取异常,请检查实训模板的评测设置是否正确") - else - tip_exception("代码获取异常,请联系系统管理员") - end - end + if @myshixun.repo_name.nil? + g = Gitlab.client + repo_name = g.project(@myshixun.gpid).path_with_namespace + @myshixun.update_column(:repo_name, repo_name) + @content = git_fle_content("#{repo_name}.git", path) || "" + else + @content = git_fle_content(@myshixun.repo_path, path) || "" + end + rescue Exception => e + # 思路: 异常首先应该考虑去恢复 + if params[:retry].to_i == 1 + begin # 如果模板没有问题,则通过中间层检测实训仓库是否异常 # 监测版本库HEAD是否存在,不存在则取最新的HEAD gitUrl = repo_url @myshixun.repo_path @@ -462,30 +514,41 @@ class GamesController < ApplicationController # 监测版本库HEAD是否存在,不存在则取最新的HEAD uri = "#{shixun_tomcat}/bridge/game/check" res = uri_post uri, rep_params + uid_logger("repo_content to bridge: res is #{res}") # res值:0 表示正常;-1表示有错误;-2表示代码版本库没了 - if status == 0 && res && (res['code'] == -2 || res['code'] == -1) - # 删除不需要的仓库 - begin - GitService.delete_repository(repo_path: @myshixun.repo_path) - rescue Exception => e - uid_logger_error("#{e.message}") + # + if status == 0 && res + # 版本库报错,修复不了 + if res['code'] == -1 || res['code'] == -2 + begin + # GitService.delete_repository(repo_path: @myshixun.repo_path) if res['code'] == -1 + project_fork(@myshixun, @shixun.repo_path, current_user.login) + rescue Exception => e + uid_logger_error("#{e.message}") + tip_exception("#{e.message}") + end end - # fork一个新的仓库 - project_fork(@myshixun, @shixun.repo_path, current_user.login) end rescue Exception => e uid_logger_error(e.message) - # 报错继续retry - tip_exception(-3, "#{e.message}") + + if @myshixun.shixun.try(:status) < 2 + tip_exception("代码获取异常,请检查实训模板的评测设置是否正确") + else + # 报错继续retry + tip_exception(-3, "#{e.message}") + end end end - tip_exception(-3, "#{e.message}") + # 有异常,版本库获取不到代码,前端轮训30S后,调用retry == 1 + tip_exception(0, e.message) end end # 编程题评测 def game_build - game_challenge = Challenge.select([:id, :position, :picture_path]).find(@game.challenge_id) + sec_key = params[:sec_key] + game_challenge = Challenge.select([:id, :position, :picture_path, :exec_time]).find(@game.challenge_id) # 更新评测次数 @game.update_column(:evaluate_count, (@game.evaluate_count.to_i + 1)) @@ -531,9 +594,9 @@ class GamesController < ApplicationController br_params = {:tpiID => "#{@myshixun.id}", :tpiGitURL => "#{gitUrl}", :buildID => "#{@game.id}", :instanceChallenge => "#{step}", :testCases => "#{testCases}", :resubmit => "#{resubmit}", :times => params[:first].to_i, :podType => @shixun.webssh, :content_modified => content_modified, - :containers => "#{Base64.urlsafe_encode64(container_limit(@shixun.mirror_repositories))}", - :persistenceName => @shixun.identifier, :tpmScript => "#{tpmScript}", - :timeLimit => "#{@shixun.exec_time}", :isPublished => (@shixun.status < 2 ? 0 : 1) } + :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}", + :persistenceName => @shixun.identifier, :tpmScript => "#{tpmScript}", :sec_key => sec_key, + :timeLimit => game_challenge.exec_time, :isPublished => (@shixun.status < 2 ? 0 : 1) } # 评测有文件输出的需要特殊传字段 path:表示文件存储的位置 br_params['file'] = Base64.urlsafe_encode64({path: "#{game_challenge.picture_path}"}.to_json) if game_challenge.picture_path.present? @@ -575,7 +638,7 @@ class GamesController < ApplicationController # user_answer虽然是传的数组,但是可能存在多选择提的情况. user_answer_tran = user_answer[index].size > 1 ? user_answer[index].split("").sort.join("") : user_answer[index] standard_answer_tran = choose.standard_answer.size > 1 ? choose.standard_answer.split("").sort.join("") : choose.standard_answer - correct = (user_answer_tran == standard_answer_tran) ? true : false + correct = (user_answer_tran == standard_answer_tran) if str.present? str += "," end @@ -597,13 +660,10 @@ class GamesController < ApplicationController end # 批量插入评测结果 - uid_logger("choose_build") + uid_logger("#------------chooice score: #{score}") sql = "INSERT INTO outputs (game_id, test_set_position, actual_output, result, query_index, created_at, updated_at) VALUES" + str ActiveRecord::Base.connection.execute sql - had_done = @game.had_done - @myshixun.update_attribute(:status, 1) if had_done == 1 - # 没通关或者查看了答案通关的时候经验为0 # 通关但是查看了答案,评测的时候金币显示0(避免用户以为重复扣除),但是在关卡列表中金币显示负数 experience = 0 @@ -613,7 +673,8 @@ class GamesController < ApplicationController if had_passed && !@game.had_passed? @game.update_attributes(:status => 2, :end_time => Time.now) # TPM实训已发布并且没有查看答案 - if @shixun.is_published? && !@game.answer_open + if @shixun.is_published? && @game.answer_open == 0 + uid_logger("@@@@@@@@@@@@@@@@@chooice score: #{score}") # 查看答案的时候处理final_scor和扣分记录 experience = score reward_attrs = { container_id: @game.id, container_type: 'Game', score: score } @@ -622,6 +683,8 @@ class GamesController < ApplicationController final_score = score RewardExperienceService.call(@myshixun.owner, reward_attrs) end + had_done = @game.had_done + @myshixun.update_attribute(:status, 1) if had_done == 1 end grade = @myshixun.owner.try(:grade) @@ -660,6 +723,7 @@ class GamesController < ApplicationController uid_logger("################params[:resubmit]: #{params[:resubmit]}") uid_logger("################resubmit_identifier: #{resubmit_identifier}") uid_logger("################time_out: #{params[:time_out]}") + sec_key = params[:sec_key] if (params[:time_out] == "false") && ((params[:resubmit].blank? && @game.status == 1) || (params[:resubmit].present? && (params[:resubmit] != resubmit_identifier))) # 代码评测的信息 @@ -688,14 +752,14 @@ class GamesController < ApplicationController end else # 重新评测 # 如果满足前面的条件,进入此处只可能是结果已返回并存入了数据库 - if params[:resubmit] == resubmit_identifier # 本次重新评测结果已经返回并存入数据库 + if params[:resubmit] == resubmit_identifier # 本次重新评测结果已经返回并存入数据库 game_status = (@game.retry_status == 2 ? 2 : 0) # retry_status是判断重新评测的通关情况。2表示通关 end end # 实训的最大评测次数,这个值是为了优化查询,每次只取最新的最新一次评测的结果集 max_query_index = @game.query_index - #max_query_index = @game.outputs.first.try(:query_index) + # max_query_index = @game.outputs.first.try(:query_index) # 区分评测过未评测过,未评测过按需求取数据 testset_detail max_query_index.to_i, game_challenge @@ -705,9 +769,10 @@ class GamesController < ApplicationController web_route = game_challenge.try(:web_route) mirror_name = @shixun.mirror_name + e_record = EvaluateRecord.where(:identifier => sec_key).first # 轮询结束,更新评测统计耗时 if game_status == 0 || game_status == 2 - e_record = EvaluateRecord.where(:game_id => @game.id).first + if e_record front_js = format("%.3f", (Time.now.to_f - e_record.try(:updated_at).to_f)).to_f consume_time = format("%.3f", (Time.now - e_record.created_at)).to_f @@ -715,9 +780,10 @@ class GamesController < ApplicationController end end - uid_logger("game is is #{@game.id}, record id is #{e_record.try(:id)}, time is**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") + uid_logger("game is #{@game.id}, record id is #{e_record.try(:id)}, time is**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") # 记录前端总耗时 - record_consume_time = EvaluateRecord.where(:game_id => @game.id).first.try(:consume_time) + record_consume_time = e_record.try(:pod_execute) + max_mem = e_record.try(:max_mem) # 实训制作者当前拥有的金币 grade = User.where(:id => @game.user_id).pluck(:grade).first @@ -728,7 +794,7 @@ class GamesController < ApplicationController @base_date = {grade: grade, gold: score, experience: experience, status: game_status, had_done: had_done, position: game_challenge.position, port: port, record_consume_time: record_consume_time, mirror_name: mirror_name, picture: picture, web_route: web_route, star: @game.star, - next_game: next_game, prev_game: prev_game} + next_game: next_game, prev_game: prev_game, max_mem: max_mem} end # 记录实训花费的时间 @@ -796,11 +862,11 @@ class GamesController < ApplicationController # 评测测试机封装 def testset_detail max_query_index, challenge # 是否允许查看隐藏的测试集,以前的power - @allowed_hidden_testset = @identity < User::EDU_GAME_MANAGER + @allowed_hidden_testset = @identity < User::EDU_GAME_MANAGER || @game.test_sets_view #解锁的用户 if max_query_index > 0 uid_logger("max_query_index is #{max_query_index} game id is #{@game.id}, challenge_id is #{challenge.id}") - @qurey_test_sets = TestSet.find_by_sql("SELECT o.code, o.actual_output, o.out_put, o.result, o.test_set_position, + @qurey_test_sets = TestSet.find_by_sql("SELECT o.code, o.actual_output, o.out_put, o.result, o.test_set_position, o.ts_time, o.ts_mem, o.query_index, t.is_public, t.input, t.output, o.compile_success FROM outputs o, games g, challenges c, test_sets t where g.id=#{@game.id} and c.id=#{challenge.id} and o.query_index=#{max_query_index} and g.id = o.game_id and c.id= g.challenge_id and t.challenge_id = c.id and @@ -814,8 +880,9 @@ class GamesController < ApplicationController end @last_compile_output = @qurey_test_sets.first['out_put'].gsub(/\n/, '
').gsub(/\t/, " \; \; \; \; \; \; \; \;") if @qurey_test_sets.first['out_put'].present? else + # 没有评测过,第一次进来后的呈现方式 @qurey_test_sets = TestSet.find_by_sql("SELECT t.is_public, t.input, t.output, t.position - FROM test_sets t where t.challenge_id = #{challenge.id}") + FROM test_sets t where t.challenge_id = #{challenge.id}") end end @@ -849,7 +916,7 @@ class GamesController < ApplicationController end # actual_output为空表示暂时没有评测答题,不允许查看 actual_output = output.try(:actual_output).try(:strip) - has_answer << choose.answer if choose.answer.present? + #has_answer << choose.answer if choose.answer.present? # 标准答案处理,错误的不让用户查看,用-1替代 standard_answer = (actual_output.blank? || !output.try(:result)) ? -1 : choose.standard_answer result = output.try(:result) @@ -860,7 +927,7 @@ class GamesController < ApplicationController @chooses << sin_choose test_sets << sin_test_set end - @has_answer = has_answer.present? + @has_answer = true # 选择题永远都有答案 @choose_test_cases = {:had_submmit => had_submmit, :challenge_chooses_count => challenge_chooses_count, :choose_correct_num => choose_correct_num, :test_sets => test_sets} end diff --git a/app/controllers/gits_controller.rb b/app/controllers/gits_controller.rb index 778963f6e..910864812 100644 --- a/app/controllers/gits_controller.rb +++ b/app/controllers/gits_controller.rb @@ -1,10 +1,15 @@ class GitsController < ApplicationController - #供git-workhorse反向调用认证 + # 说明: + # 以下Git认证只针对新版git,Gitlab的Git认证不走该控制器 + # 思路: + # 1、用户通过Git客户端推送代码的时候,这个时候Git客户端肯定会强制用户输入邮箱的 + # 2、通过web端版本库界面更新代码(如果用户邮箱不存在,则用系统备用邮箱) + # 供 git-workhorse反向调用认证 def auth # HTTP_AUTHORIZATION: "Basic 这里base64编码的的密码(user:passwd)" - logger.info("11111112222223333#{request.env["HTTP_AUTHORIZATION"]}") - #logger.info("#########-----request_env: #{request.env}") + logger.info("11111112222223333 HTTP_AUTHORIZATION: #{request.env["HTTP_AUTHORIZATION"]}") + # logger.info("#########-----request_env: #{request.env}") # {"service"=>"git-receive-pack", "controller"=>"gits", "action"=>"auth", # "url"=>"forge01/cermyt39.git/info/refs"} # @@ -18,15 +23,16 @@ class GitsController < ApplicationController input_password = username_password.split(":")[1].strip() uid_logger("git start auth: input_username is #{input_username}") + # Git 超级权限用户 - if input_username == gituser && input_password == gitpassword + if input_username.strip == gituser.strip && input_password.strip == gitpassword.strip result = true else # 用户是否对对象拥有权限 system_user = User.find_by_login(input_username) || User.find_by_mail(input_username) || User.find_by_phone(input_username) # 如果用户名密码错误 - if !system_user.check_password?(input_password) + if system_user && !system_user.check_password?(input_password) uid_logger_error("git start: password is wrong") result = false else @@ -43,12 +49,13 @@ class GitsController < ApplicationController if system_user.present? && system_user.manager_of_shixun?(shixun) result = true else - logger.info("git411 start") + uid_logger_error("gituser is not shixun manager") result = false end else - render :json => { :status => 404 } - result = false + uid_logger_error("shixun is not exist") + # result = false + result = true # 为了测试跳出 end end end diff --git a/app/controllers/graduation_tasks_controller.rb b/app/controllers/graduation_tasks_controller.rb index d95716c9b..ab99e8d86 100644 --- a/app/controllers/graduation_tasks_controller.rb +++ b/app/controllers/graduation_tasks_controller.rb @@ -1,5 +1,5 @@ class GraduationTasksController < ApplicationController - before_action :require_login, except: [:index] + before_action :require_login, :check_auth, except: [:index] before_action :find_course, except: [:edit, :update, :settings, :update_settings, :tasks_list, :show, :show_comment] before_action :find_task, only: [:edit, :update, :settings, :update_settings, :tasks_list, :show, :show_comment] before_action :user_course_identity @@ -37,7 +37,7 @@ class GraduationTasksController < ApplicationController @all_count = @course.graduation_tasks.size @published_count = @course.graduation_tasks.where("publish_time <= '#{Time.now}'").size @task_count = @tasks.size - @tasks = @tasks.reorder("#{default_order}").page(page).per(15).includes(:graduation_works, course: [course_members: :teacher_course_groups]) + @tasks = @tasks.reorder("#{default_order}").page(page).per(15).includes(:graduation_works) end # 任务问答 @@ -55,30 +55,33 @@ class GraduationTasksController < ApplicationController page = params[:page] || 1 limit = params[:limit] || 20 @work = @task.graduation_works.where(user_id: current_user.id) + @students = @course.students + @assign_power = @user_course_identity < Course::STUDENT && @task.cross_comment && @task.comment_status == 2 #end_time @task.allow_late ? @task.late_time : @task.end_time # 任务发布的情况下: 是老师身份或者任务已截止的情况下公开任务了作品设置的学生也能查看其他人的作品 if @task.published? && (@user_course_identity < Course::STUDENT || (@user_course_identity == Course::STUDENT && @work.present? && @work.take.work_status > 0 && - @task.status > 1 && @task.open_work)) + ((!@task.allow_late && @task.status > 1) || (@task.allow_late && @task.late_time && @task.late_time < Time.now)) && + (@task.open_work || @task.open_score))) # 如有有分班则看分班内的学生,否则看所有学生的作品 user_ids = if @user_course_identity < Course::STUDENT @course.teacher_group_user_ids(current_user.id) else course_group_id = @course.course_member(current_user.id).course_group_id - @course.course_members.where(course_group_id: course_group_id).pluck(:user_id) + @course.students.where(course_group_id: course_group_id).pluck(:user_id) end @work_list = @task.graduation_works.where(user_id: user_ids).includes(user: [:user_extension]) @all_work_count = @work_list.count - @teachers = @course.teachers + @teachers = @course.teachers.where.not(user_id: current_user.id).includes(:user) # 教师评阅搜索 0: 未评, 1 已评 unless params[:teacher_comment].blank? graduation_work_ids = GraduationWorkScore.where(graduation_work_id: @work_list.map(&:id)).pluck(:graduation_work_id) - if params[:teacher_comment] == 0 - @work_list = @work_list.where.not(id: graduation_work_ids) - elsif params[:teacher_comment] == 1 - @work_list = @work_list.where(id: graduation_work_ids).where.not(work_status: 0) + if params[:teacher_comment].to_i == 0 + @work_list = @work_list.where("work_status != 0") + elsif params[:teacher_comment].to_i == 1 + @work_list = @work_list.where("work_status != 0").where(id: graduation_work_ids) end end @@ -89,7 +92,7 @@ class GraduationTasksController < ApplicationController # 分班情况 unless params[:course_group].blank? - group_user_ids = @course.course_members.where(course_group_id: params[:course_group]).pluck(:user_id) + group_user_ids = @course.students.where(course_group_id: params[:course_group]).pluck(:user_id) # 有分组只可能是老师身份查看列表 @work_list = @work_list.where(user_id: group_user_ids) end @@ -98,7 +101,7 @@ class GraduationTasksController < ApplicationController unless params[:cross_comment].blank? graduation_work_id = @task.graduation_work_comment_assignations.where(:user_id =>current_user.id) .pluck(:graduation_work_id).uniq if @task.graduation_work_comment_assignations - @work_list = @work_list.where(id: graduation_work_id) + @work_list = @task.graduation_works.where(id: graduation_work_id) end # 输入姓名和学号搜索 @@ -109,57 +112,61 @@ class GraduationTasksController < ApplicationController end # 排序 - rorder = params[:order] || "updated_at" - b_order = params[:b_order] || "desc" - if rorder == "created_at" || rorder == "work_score" + rorder = params[:order].blank? ? "update_time" : params[:order] + b_order = params[:b_order].blank? ? "desc" : params[:b_order] + if rorder == "update_time" || rorder == "work_score" @work_list = @work_list.order("graduation_works.#{rorder} #{b_order}") elsif rorder == "student_id" @work_list = @work_list.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}") end + @view_work = @task.open_work || @user_course_identity < Course::STUDENT @work_count = @work_list.count @work_excel = @work_list - @work_list = @work_list.page(page).limit(limit) - respond_to do |format| - format.json - format.xlsx{ - if @user_course_identity >= Course::STUDENT - tip_exception(403, "无权限操作") - else - graduation_work_to_xlsx(@work_excel,@task,current_user) - exercise_export_name = current_user.real_name + "_" + @course.name + "_" + @task.name + "_" + Time.now.strftime('%Y%m%d_%H%M%S') - render xlsx: "#{exercise_export_name.strip.first(30)}",template: "graduation_tasks/tasks_list.xlsx.axlsx",locals: {table_columns:@head_cells_column, task_users:@task_cells_column} + @work_list = @work_list.page(page).per(limit) + + if params[:format] == "xlsx" + complete_works = @work_excel.where("work_status > 0").size + if @user_course_identity >= Course::STUDENT + tip_exception(403, "无权限操作") + elsif complete_works == 0 + normal_status(-1,"暂无用户提交") + else + respond_to do |format| + format.xlsx{ + graduation_work_to_xlsx(@work_excel,@task,current_user) + task_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@task.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" + render xlsx: "#{task_export_name_.strip.first(30)}",template: "graduation_tasks/tasks_list.xlsx.axlsx",locals: {table_columns:@head_cells_column, task_users:@task_cells_column} + } end - } - format.zip{ - if @user_course_identity >= Course::STUDENT - tip_exception(403, "无权限操作") - else - zip_works = @work_excel.where("work_status > 0") - status = checkfileSize(zip_works) - if status == 0 - zipfile = zip_homework_common @task, zip_works - file = decode64(zipfile[0][:base64file]) - send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip' - else - tip_exception(status == -1 ? "文件大小超过500M,请通过微信或者QQ联系管理员辅助您打包下载" : "无附件可下载") + end + elsif params[:format] == "zip" + if @user_course_identity >= Course::STUDENT + tip_exception(403, "无权限操作") + else + zip_works = @work_excel.where("work_status > 0") + status = checkfileSize(zip_works) + if status == 0 + respond_to do |format| + format.zip{ + zipfile = zip_homework_common @task, zip_works + file = decode64(zipfile[0][:base64file]) + send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip' + } end + else + normal_status(status,status == -2 ? "500M" : "无附件可下载") end - } + end end else @work_list = @work + @view_work = false @work_count = @work_list.count @all_work_count = @work_list.count - respond_to do |format| - format.json - format.xlsx{ - normal_status(-1,"作业未发布") - } - format.zip{ - normal_status(-1,"作业未发布") - } + if params[:format] == "xlsx" || params[:format] == "zip" + normal_status(-1,"毕设任务未发布") end end end diff --git a/app/controllers/graduation_topics_controller.rb b/app/controllers/graduation_topics_controller.rb index 6bc3a4c2a..754b472c5 100644 --- a/app/controllers/graduation_topics_controller.rb +++ b/app/controllers/graduation_topics_controller.rb @@ -1,9 +1,9 @@ class GraduationTopicsController < ApplicationController - before_action :require_login, except: [:index] + before_action :require_login, :check_auth, except: [:index] before_action :find_course before_action :teacher_allowed, only: [:new, :create, :update, :edit, :destroys, :set_public, :refuse_student_topic, :accept_student_topic, :export] - before_action :find_graduation_topic, except: [:index, :create, :new, :set_public, :destroys, :export] + before_action :find_graduation_topic, except: [:index, :create, :new, :set_public, :destroys, :export, :add_to_bank] before_action :find_course_teachers, only: [:new, :edit] before_action :user_course_identity, only: [:index, :show, :show_detail, :show_comment] @@ -24,9 +24,7 @@ class GraduationTopicsController < ApplicationController end # 当前用户是否已经选过题 - # @user_selected = StudentGraduationTopic.where(graduation_topic_id: @graduation_topic, user_id: current_user.id).count > 0 - user_graduation_topics = @course.student_graduation_topics.where(user_id: current_user.id, status: [0, 1], graduation_topic_id: @graduation_topic.pluck(:id)) #6.12 -hs - @user_selected = user_graduation_topics.size > 0 + @user_selected = @course.student_graduation_topics.where(user_id: current_user.id, status: [0, 1]).count > 0 #6.12 -hs ## 分页参数 page = params[:page] || 1 limit = params[:limit] || 15 @@ -45,16 +43,9 @@ class GraduationTopicsController < ApplicationController end ## 分页参数 @current_user = current_user - course_group_ids = @course.course_members.where(user_id: current_user.id, role: [1,2,3]).pluck(:course_group_id).uniq - #6.11 -hs - if course_group_ids.present? - if course_group_ids.include?(0) - course_group_ids = @course.course_groups.pluck(:id) - end - end - - @group_list = CourseGroup.where(id: course_group_ids) - + user_graduation_topics = @course.student_graduation_topics.where(user_id: current_user.id, + status: [0, 1]) + @user_selected = user_graduation_topics.size > 0 page = params[:page] || 1 limit = params[:limit] || 50 @users_count = @student_graduation_topics.try(:count).to_i @@ -181,7 +172,7 @@ class GraduationTopicsController < ApplicationController member = @course.course_members.where(:user_id => @graduation_topic.tea_id).first tip_exception("分班名称不能为空") if params[:course_group_name].blank? course_group = CourseGroup.create(:name => params[:course_group_name], :course_id => @course.id) - teacher_group = TeacherCourseGroup.create(:course_id => @course.id, :member_id => member.try(:id), + teacher_group = TeacherCourseGroup.create(:course_id => @course.id, :course_member_id => member.try(:id), :user_id => @graduation_topic.tea_id, :course_group_id => course_group.try(:id)) end @@ -202,8 +193,8 @@ class GraduationTopicsController < ApplicationController def student_select_topic user_unaccept_topics = @course.student_graduation_topics.where(user_id: current_user.id, status: [0, 1]) if user_unaccept_topics.size == 0 - member_id = @course.course_members.find_by_user_id(current_user.id) - StudentGraduationTopic.create(course_id: @course.id, user_id: current_user.id, member_id: member_id, + member = @course.course_members.find_by_user_id(current_user.id) + StudentGraduationTopic.create(course_id: @course.id, user_id: current_user.id, course_member_id: member.try(:id), graduation_topic_id: @graduation_topic.id) @graduation_topic.update_attribute(:status, 1) normal_status("选题成功") @@ -231,7 +222,7 @@ class GraduationTopicsController < ApplicationController # 已加入的更新,未加入的新建 if topic_bank.present? - topic_bank.update_attributes(name: topic, description: topic.description, + topic_bank.update_attributes(name: topic.name, description: topic.description, topic_source: topic.topic_source, topic_property_first: topic.topic_property_first, topic_property_second: topic.topic_property_second, @@ -242,7 +233,7 @@ class GraduationTopicsController < ApplicationController course_list_id: @course.course_list_id) topic_bank.attachments.destroy_all else - topic_bank = GtopicBank.new(name: topic, description: topic.description, + topic_bank = GtopicBank.new(name: topic.name, description: topic.description, topic_source: topic.topic_source, topic_property_first: topic.topic_property_first, topic_property_second: topic.topic_property_second, @@ -275,11 +266,16 @@ class GraduationTopicsController < ApplicationController # 导出功能 def export - course = @course - students = course.students.joins(user: :user_extension).order("user_extensions.student_id") - graduation_topic_to_xlsx(students,course) - exercise_export_name = current_user.real_name + "_" + course.name + "_毕设选题" + "_" + Time.now.strftime('%Y%m%d_%H%M%S') - render xlsx: "#{exercise_export_name.strip.first(30)}",template: "graduation_topics/export.xlsx.axlsx",locals: {table_columns:@topic_head_cells,topic_users:@topic_body_cells} + begin + course = @course + students = course.students.joins(user: :user_extension).order("user_extensions.student_id") + graduation_topic_to_xlsx(students,course) + topic_export_name_ = "#{current_user.real_name}_#{course.name}_毕设选题_#{Time.now.strftime('%Y%m%d_%H%M%S')}" + render xlsx: "#{topic_export_name_.strip.first(30)}",template: "graduation_topics/export.xlsx.axlsx",locals: {table_columns:@topic_head_cells,topic_users:@topic_body_cells} + rescue Exception => e + uid_logger(e.message) + missing_template + end end private diff --git a/app/controllers/graduation_works_controller.rb b/app/controllers/graduation_works_controller.rb index 9117112d3..a4a59a3f5 100644 --- a/app/controllers/graduation_works_controller.rb +++ b/app/controllers/graduation_works_controller.rb @@ -1,5 +1,5 @@ class GraduationWorksController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :find_task, only: [:new, :create, :search_member_list, :check_project, :relate_project, :cancel_relate_project] before_action :find_work, only: [:show, :edit, :update, :revise_attachment, :supply_attachments, :comment_list, @@ -13,6 +13,7 @@ class GraduationWorksController < ApplicationController before_action :published_task, only: [:new, :create, :edit, :update, :search_member_list, :relate_project, :cancel_relate_project, :revise_attachment] before_action :edit_duration, only: [:edit, :update] + before_action :open_work, only: [:show, :supply_attachments, :comment_list] def new if @task.task_type == 2 && @task.base_on_project @@ -432,11 +433,11 @@ class GraduationWorksController < ApplicationController # 交叉评阅分配老师 def assign_teacher tip_exception(-1, "user_id不能为空") if params[:user_id].nil? - @work_assign_teacher = @work.graduation_work_comment_assignations.first + @work_assign_teacher = @work.graduation_work_comment_assignations.find_by(user_id: params[:user_id]) - if @work_assign_teacher + if @work_assign_teacher.present? # graduation_group_id: 已经是答辩组的需要 将答辩组清空 - @work_assign_teacher.update_attributes(user_id: params[:user_id], graduation_group_id: 0) + @work_assign_teacher.update_attributes(graduation_group_id: 0) else @work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new(graduation_task_id: @task.id, user_id: params[:user_id], @@ -489,6 +490,11 @@ class GraduationWorksController < ApplicationController tip_exception("已过了修改时间") if @task.end_time && @task.end_time < Time.now end + # 作品是否公开 + def open_work + tip_exception(403,"没有操作权限") unless (@user_course_identity < Course::STUDENT || current_user == @work.user || @task.open_work) + end + def update_check work tip_exception("作品描述不能为空") if params[:description].blank? if @task.task_type == 2 diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb index d3ece9feb..8fab8dad3 100644 --- a/app/controllers/homework_commons_controller.rb +++ b/app/controllers/homework_commons_controller.rb @@ -3,16 +3,17 @@ class HomeworkCommonsController < ApplicationController include ApplicationHelper include ExportHelper - before_action :require_login, except: [:index, :choose_category] + before_action :require_login, :check_auth, except: [:index, :choose_category] before_action :find_course, only: [:index, :create, :new, :shixuns, :subjects, :create_shixun_homework, :publish_homework, :end_homework, :set_public, :choose_category, :move_to_category, :choose_category, :create_subject_homework, :multi_destroy, :add_to_homework_bank] before_action :find_homework, only: [:edit, :show, :update, :group_list, :homework_code_repeat, :code_review_results, :code_review_detail, :show_comment, :settings, :works_list, :update_settings, - :reference_answer, :publish_groups, :end_groups, :alter_name, :update_explanation] + :reference_answer, :publish_groups, :end_groups, :alter_name, :update_explanation, + :update_score, :update_student_score] before_action :user_course_identity - before_action :homework_publish, only: [:show, :works_list, :code_review_results, :show_comment, :settings, :reference_answer] + before_action :homework_publish, only: [:show, :works_list, :code_review_results, :show_comment, :settings, :reference_answer, :update_student_score] before_action :teacher_allowed, only: [:new, :edit, :create, :update, :shixuns, :subjects, :create_shixun_homework, :publish_homework, :end_homework, :set_public, :choose_category, :move_to_category, :choose_category, :create_subject_homework, :multi_destroy, :group_list, :homework_code_repeat, @@ -81,23 +82,17 @@ class HomeworkCommonsController < ApplicationController end @homework_commons = @homework_commons.joins(:homework_detail_manual).where(sql_str) end - @homework_commons = @homework_commons.order("IF(ISNULL(homework_commons.publish_time),0,1), homework_commons.publish_time DESC, - homework_commons.created_at DESC") - @task_count = @homework_commons.size - @homework_commons = @homework_commons.page(page).per(15) + @homework_commons = @homework_commons.order("IF(ISNULL(homework_commons.publish_time),0,1), homework_commons.publish_time DESC, + homework_commons.created_at DESC").page(page).per(15) if @homework_type == 4 - if @user_course_identity == Course::STUDENT - @homework_commons = @homework_commons.includes(:homework_detail_manual, :homework_group_settings, :shixuns, - student_works: [myshixun: [:games]]) - else - @homework_commons = @homework_commons.includes(:homework_detail_manual, :homework_group_settings, :shixuns, :student_works) - end + @homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings, :shixuns) + elsif @homework_type == 3 + @homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings, :homework_detail_group) else - @homework_commons = @homework_commons.includes(:homework_detail_manual, :homework_group_settings, :homework_detail_group, - :student_works) + @homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings) end end @@ -108,45 +103,43 @@ class HomeworkCommonsController < ApplicationController @shixun = @homework.shixuns.take if @homework.homework_type == "practice" student_works = @homework.all_works - @all_member_count = student_works.count - if @homework.publish_time.nil? || @homework.publish_time > Time.now + @all_member_count = student_works.size + + if @homework.publish_time.blank? || (@homework.publish_time > Time.now) @student_works = [] - respond_to do |format| - format.json - format.xlsx{ - normal_status(-1,"作业未发布") - } - format.zip{ - normal_status(-1,"作业未发布") - } + if (params[:format] == "xlsx") || (params[:format] == "zip") + normal_status(-1,"作业未发布") end else if @user_course_identity == Course::STUDENT @work = @homework.user_work(current_user.id) # 学生已提交作品且补交(提交)已截止、作品公开、非匿评阶段 - if @work.work_status > 0 && @homework.work_public && - ((!@homework.anonymous_comment && @homework.end_or_late) || @homework_detail_manual.comment_status > 4) - @student_works = student_works.where("user_id != #{@work.id}") + if @work&.work_status.to_i > 0 && (@homework.work_public || @homework.score_open) && + ((!@homework.anonymous_comment && @homework.end_or_late) || (@homework_detail_manual.comment_status > 4 && @homework.end_or_late)) + @student_works = student_works.where("user_id != #{@work.user_id}") # 匿评、申诉阶段只能看到分配给自己的匿评作品 - elsif @work.work_status > 0 && @homework.anonymous_comment && @homework_detail_manual.comment_status > 2 + elsif @work&.work_status.to_i > 0 && @homework.anonymous_comment && @homework_detail_manual.comment_status > 2 && @homework_detail_manual.comment_status <= 4 @is_evaluation = true @student_works = student_works.joins(:student_works_evaluation_distributions).where( "student_works_evaluation_distributions.user_id = #{@current_user.id}") else @student_works = [] end + @score_open = @homework.score_open && @work&.work_status.to_i > 0 elsif @user_course_identity < Course::STUDENT - @student_works = @homework.teacher_works(@current_user.id) - @all_member_count = @student_works.count + @student_works = @homework.teacher_works(@member) + @all_member_count = @student_works.size + @score_open = true elsif @user_course_identity > Course::STUDENT && @homework.work_public @student_works = student_works + @score_open = false else @student_works = [] end - unless @student_works.size == 0 + if @student_works.size > 0 # 教师评阅搜索 0: 未评, 1 已评 unless params[:teacher_comment].blank? student_work_ids = StudentWorksScore.where(student_work_id: @student_works.map(&:id)).pluck(:student_work_id) @@ -176,55 +169,121 @@ class HomeworkCommonsController < ApplicationController or student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") end + @work_count = @student_works.size + @work_excel = @student_works.where("work_status > 0") + # 排序 - rorder = params[:order] || "update_time" - b_order = params[:b_order] || "desc" + rorder = params[:order].blank? ? "update_time" : params[:order] + b_order = params[:b_order].blank? ? "desc" : params[:b_order] if rorder == "update_time" || rorder == "work_score" @student_works = @student_works.order("student_works.#{rorder} #{b_order}") elsif rorder == "student_id" @student_works = @student_works.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}") end - @work_count = @student_works.size - @work_excel = @student_works - # 分页参数 page = params[:page] || 1 limit = params[:limit] || 20 - @student_works = @student_works.page(page).per(limit).includes(:student_works_scores) + @student_works = @student_works.page(page).per(limit) + @students = @course.students.where(user_id: @student_works.pluck(:user_id)).preload(:course_group) if @homework.homework_type == "practice" - @student_works = @student_works.includes(user: :user_extension, myshixun: :games) + @student_works = @student_works.includes(:student_works_scores, user: :user_extension, myshixun: :games) else @student_works = @student_works.includes(:student_works_scores, :project, user: :user_extension) end end - respond_to do |format| - format.json - format.xlsx{ - if @user_course_identity >= Course::STUDENT - tip_exception(403, "无权限操作") - else - student_work_to_xlsx(@work_excel,@homework) - exercise_export_name = current_user.real_name + "_" + @course.name + "_" + @homework.name + "_" + Time.now.strftime('%Y%m%d_%H%M%S') - render xlsx: "#{exercise_export_name.strip.first(30)}",template: "homework_commons/works_list.xlsx.axlsx",locals: - {table_columns: @work_head_cells,task_users: @work_cells_column} + + if params[:format] == "xlsx" + if @user_course_identity >= Course::STUDENT + tip_exception(403, "无权限操作") + elsif @work_excel.blank? || @work_excel.size == 0 + normal_status(-1,"暂无用户提交!") + else + respond_to do |format| + format.xlsx{ + student_work_to_xlsx(@work_excel,@homework) + exercise_export_name = "#{current_user.real_name}_#{@course.name}_#{@homework.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" + render xlsx: "#{exercise_export_name.strip.first(30)}",template: "homework_commons/works_list.xlsx.axlsx",locals: + {table_columns: @work_head_cells,task_users: @work_cells_column} + } end - } - format.zip{ - if @user_course_identity >= Course::STUDENT - tip_exception(403, "无权限操作") - else - zip_works = @work_excel.where("work_status > 0") + end + elsif params[:format] == "zip" + if @user_course_identity >= Course::STUDENT + tip_exception(403, "无权限操作") + else + if @work_excel.present? + zip_works = @work_excel&.where("work_status > 0") status = checkfileSize(zip_works) - if status == 0 - zipfile = zip_homework_common @homework, zip_works - file = decode64(zipfile[0][:base64file]) - send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip' - else - tip_exception(status == -1 ? "文件大小超过500M,请通过微信或者QQ联系管理员辅助您打包下载" : "无附件可下载") + else + status = -1 + end + + if status == 0 + respond_to do |format| + format.zip{ + zipfile = zip_homework_common @homework, zip_works + file = decode64(zipfile[0][:base64file]) + send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip' + } end + else + normal_status(status, status == -2 ? "500M" : "无附件可下载") end - } + end + end + end + end + + def update_score + tip_exception("作业还未发布,暂不能计算成绩") if @homework.publish_time.nil? || @homework.publish_time > Time.now + begin + if @homework.unified_setting + student_works = @homework.student_works + user_ids = @course.students.pluck(:user_id) + else + user_ids = @course.students.where(course_group_id: @homework.published_settings.pluck(:course_group_id)).pluck(:user_id) + student_works = @homework.student_works.where(user_id: user_ids) + end + + myshixuns = Myshixun.where(shixun_id: @homework.homework_commons_shixun&.shixun_id, user_id: user_ids). + includes(:games).where(games: {challenge_id: @homework.homework_challenge_settings.pluck(:challenge_id)}) + challenge_settings = @homework.homework_challenge_settings + myshixuns.find_each(batch_size: 100) do |myshixun| + work = student_works.select{|work| work.user_id == myshixun.user_id}.first + if work && myshixun + games = myshixun.games.where(challenge_id: challenge_settings.pluck(:challenge_id)) + HomeworksService.new.update_myshixun_work_score work, myshixun, games, @homework, challenge_settings + end + end + HomeworksService.new.update_student_eff_score @homework if (@homework.allow_late && @homework.late_time < Time.now) || + (!@homework.allow_late && @homework.end_time < Time.now) + @homework.update_attribute('calculation_time', Time.now) + normal_status("更新成功") + rescue Exception => e + uid_logger(e.message) + tip_exception(e.message) + raise ActiveRecord::Rollback + end + end + + def update_student_score + work = @homework.student_works.find_by(user_id: current_user.id) + myshixun = Myshixun.find_by(shixun_id: params[:shixun_id], user_id: current_user.id) + ActiveRecord::Base.transaction do + begin + if work && myshixun + challenge_settings = @homework.homework_challenge_settings + games = myshixun.games.where(challenge_id: challenge_settings.pluck(:challenge_id)) + HomeworksService.new.update_myshixun_work_score work, myshixun, games, @homework, challenge_settings + normal_status("更新成功") + else + normal_status("还开启挑战,暂不能更新成绩") + end + rescue Exception => e + uid_logger(e.message) + tip_exception(e.message) + raise ActiveRecord::Rollback end end end @@ -347,10 +406,8 @@ class HomeworkCommonsController < ApplicationController homework_detail_group = @homework.homework_detail_group param_min = params[:min_num].to_i param_max = params[:max_num].to_i - homework_detail_group.min_num = @homework.has_commit_work ? (param_min > homework_detail_group.min_num ? homework_detail_group.min_num : - param_min) : param_min - homework_detail_group.max_num = @homework.has_commit_work ? (param_max < homework_detail_group.max_num ? homework_detail_group.max_num : - param_max) : param_max + homework_detail_group.min_num = @homework.has_commit_work ? [param_min, homework_detail_group.min_num].min : param_min + homework_detail_group.max_num = @homework.has_commit_work ? [param_max, homework_detail_group.max_num].max : param_max homework_detail_group.base_on_project = params[:base_on_project] unless @homework.has_relate_project homework_detail_group.save! end @@ -387,7 +444,7 @@ class HomeworkCommonsController < ApplicationController tip_exception("发布时间不能早于当前时间") if params[:publish_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S") tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S") tip_exception("截止时间不能早于发布时间") if params[:publish_time] > params[:end_time] - tip_exception("截止时间不能早于课堂结束时间") if @course.end_date.present? && params[:end_time] > @course.end_date.end_of_day + tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:end_time] > @course.end_date.end_of_day @homework.unified_setting = 1 @homework.homework_group_settings.destroy_all @@ -409,7 +466,7 @@ class HomeworkCommonsController < ApplicationController tip_exception("发布时间不能早于当前时间") if setting[:publish_time] <= strf_time(Time.now) tip_exception("截止时间不能早于当前时间") if setting[:end_time] <= strf_time(Time.now) tip_exception("截止时间不能早于发布时间") if setting[:publish_time] > setting[:end_time] - tip_exception("截止时间不能早于课堂结束时间") if @course.end_date.present? && setting[:end_time] > @course.end_date.end_of_day + tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && setting[:end_time] > @course.end_date.end_of_day publish_time = setting[:publish_time] == "" ? Time.now : setting[:publish_time] @@ -443,7 +500,7 @@ class HomeworkCommonsController < ApplicationController if @homework.end_time > Time.now && @homework.unified_setting tip_exception("截止时间不能为空") if params[:end_time].blank? tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) - tip_exception("截止时间不能早于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) + tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) @homework.end_time = params[:end_time] @@ -457,11 +514,11 @@ class HomeworkCommonsController < ApplicationController tip_exception("发布时间不能为空") if setting[:publish_time].blank? tip_exception("截止时间不能为空") if setting[:end_time].blank? # 如果该发布规则 没有已发布的分班则需判断发布时间 - tip_exception("发布时间不能早于当前时间") if setting[:publish_time] <= strf_time(Time.now) && group_settings.group_published.count == 0 + tip_exception("发布时间不能早于等于当前时间") if setting[:publish_time] <= strf_time(Time.now) && group_settings.group_published.count == 0 - tip_exception("截止时间不能早于当前时间") if setting[:end_time] <= strf_time(Time.now) + tip_exception("截止时间不能早于等于当前时间") if setting[:end_time] <= strf_time(Time.now) tip_exception("截止时间不能早于发布时间") if setting[:publish_time] > setting[:end_time] - tip_exception("截止时间不能早于课堂结束时间") if setting[:end_time] > strf_time(@course.end_date.end_of_day) + tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && setting[:end_time] > strf_time(@course.end_date.end_of_day) group_settings.none_published.update_all(publish_time: setting[:publish_time]) group_settings.none_end.update_all(end_time: setting[:end_time]) @@ -529,7 +586,7 @@ class HomeworkCommonsController < ApplicationController if setting && setting.score != score score_change = true setting.update_attributes(score: score) - else + elsif setting.blank? score_change = true HomeworkChallengeSetting.create!(homework_common_id: @homework.id, challenge_id: challenge[:challenge_id], shixun_id: @homework.homework_commons_shixun.try(:shixun_id), score: score) @@ -547,14 +604,14 @@ class HomeworkCommonsController < ApplicationController @homework.score_open = params[:score_open] @homework.save! - if score_change - @homework.student_works.has_committed.each do |student_work| - HomeworksService.new.set_shixun_final_score student_work - end - end + # if score_change + # @homework.student_works.has_committed.each do |student_work| + # HomeworksService.new.set_shixun_final_score student_work + # end + # end # 更新所有学生的效率分(作业允许补交且补交已截止 或者 作业不允许补交且提交已截止) - if (score_change || update_eff_score) && @homework.end_or_late + if update_eff_score && @homework.end_or_late_none_group HomeworksService.new.update_student_eff_score HomeworkCommon.find_by(id: @homework.id) end @@ -584,9 +641,9 @@ class HomeworkCommonsController < ApplicationController # anonymous_comment :true 是启用,false 是不启用 if params[:anonymous_comment] tip_exception("匿评开启时间不能为空") if params[:evaluation_start].blank? - tip_exception("匿评开启时间不能早于截止时间") if params[:evaluation_start] <= strf_time(@homework.end_time) + tip_exception("匿评开启时间不能早于截止时间") if params[:evaluation_start] < strf_time(@homework.end_time) tip_exception("匿评结束时间不能为空") if params[:evaluation_end].blank? - tip_exception("匿评截止时间不能早于匿评开启时间") if params[:evaluation_end] <= params[:evaluation_start] + tip_exception("匿评截止时间必须晚于匿评开启时间") if params[:evaluation_end] <= params[:evaluation_start] tip_exception("匿评截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:evaluation_end] > strf_time(@course.end_date.end_of_day) tip_exception("匿评数必须为正整数") if params[:evaluation_num].blank? || params[:evaluation_num].to_i < 1 @@ -613,8 +670,8 @@ class HomeworkCommonsController < ApplicationController # 匿评未截止时可以更新匿评结束时间 if @homework_detail_manual.comment_status < 4 tip_exception("匿评结束时间不能为空") if @homework.anonymous_comment && params[:evaluation_end].blank? - tip_exception("匿评截止时间不能早于匿评开启时间") if @homework.anonymous_comment && - params[:evaluation_end] <= params[:evaluation_start] + tip_exception("匿评截止时间必须晚于匿评开启时间") if @homework.anonymous_comment && + params[:evaluation_end] <= strf_time(@homework_detail_manual.evaluation_start) tip_exception("匿评截止时间不能晚于课堂结束时间") if @homework.anonymous_comment && @course.end_date.present? && params[:evaluation_end] > strf_time(@course.end_date.end_of_day) @@ -758,6 +815,9 @@ class HomeworkCommonsController < ApplicationController # 选用实训 def shixuns + @main_catrgory = @course.course_modules.where(module_type: "shixun_homework") + @homework_category = @main_catrgory.take.course_second_categories + search = params[:search] type = params[:type] # 超级管理员用户显示所有未隐藏的实训、非管理员显示所有已发布的实训(对本单位公开且未隐藏未关闭) @@ -774,22 +834,82 @@ class HomeworkCommonsController < ApplicationController if params[:search] && params[:search].strip != "" @shixuns = @shixuns.joins(:user).where("shixuns.name like ? or concat(users.lastname, users.firstname) like ?", - "%#{search}%", "%#{search}%").distinct + "%#{search}%", "%#{search}%").distinct end unless type.blank? || type == "all" @shixuns = @shixuns.joins(:shixun_tag_repertoires).where(shixun_tag_repertoires: {tag_repertoire_id: type}).distinct end - @shixuns = @shixuns.select([:id, :name, :status, :myshixuns_count, :identifier]).reorder("shixuns.created_at desc") - @shixuns_count = @shixuns.size + @shixuns = @shixuns.select([:id, :name, :status, :myshixuns_count, :identifier, :user_id, :trainee]) + @total_count = @shixuns.size ## 分页参数 page = params[:page] || 1 - @shixuns = @shixuns.page(page).per(10) - - @main_catrgory = @course.course_modules.where(module_type: "shixun_homework") - @homework_category = @main_catrgory.take.course_second_categories + @shixuns = @shixuns.reorder("shixuns.created_at desc").includes(:challenges, user: [user_extension: :school]).page(page).per(10) + + # 新版用下面的代码 + # ## 我的实训 + # @shixuns = + # if params[:order_by] == 'mine' + # current_user.my_shixuns.unhidden + # else + # if current_user.admin? + # Shixun.unhidden + # else + # none_shixun_ids = ShixunSchool.where("school_id != #{current_user.school_id}").pluck(:shixun_id) + # + # @shixuns = Shixun.where.not(id: none_shixun_ids).unhidden + # end + # end + # + # ## 方向 + # if params[:tag_level].present? && params[:tag_id].present? + # @shixuns = @shixuns.filter_tag(params[:tag_level].to_i, params[:tag_id].to_i) + # case params[:tag_level].to_i + # when 1 #大类 + # @search_tags = Repertoire.find(params[:tag_id].to_i).name + # when 2 #子类 + # @search_tags = SubRepertoire.find(params[:tag_id].to_i).name + # when 3 #tag + # tag = TagRepertoire.find(params[:tag_id].to_i) + # @search_tags = "#{tag.sub_repertoire.name} / #{tag.name}" + # end + # end + # + # ## 搜索关键字创建者、实训名称、院校名称 + # if params[:keyword].present? + # keyword = params[:keyword].strip + # @shixuns = @shixuns.joins(user: [user_extenison: :school]). + # where("schools.name like '%#{keyword}%' + # or concat(lastname, firstname) like '%#{keyword}%' + # or shixuns.name like '%#{keyword.split(" ").join("%")}%'").distinct + # end + # + # ## 筛选 难度 + # if params[:diff].present? && params[:diff].to_i != 0 + # @shixuns = @shixuns.where(trainee: params[:diff]) + # end + # + # ## 排序参数 + # bsort = params[:sort] || 'desc' + # case params[:order_by] || 'hot' + # when 'hot' + # @shixuns = @shixuns.order("myshixuns_count #{bsort}") + # when 'mine' + # @shixuns = @shixuns.order("shixuns.created_at #{bsort}") + # else + # @shixuns = @shixuns.order("myshixuns_count #{bsort}") + # end + # + # @total_count = @shixuns.count + # + # ## 分页参数 + # page = params[:page] || 1 + # limit = params[:limit] || 15 + # + # @shixuns = @shixuns.includes(:challenges, user: [user_extension: :school]).page(page).per(limit) + # end def create_shixun_homework @@ -815,30 +935,69 @@ class HomeworkCommonsController < ApplicationController # 选用实训课程 def subjects + @tags = Repertoire.where(nil).order("updated_at desc") + # select = params[:select] # 路径导航类型 + select = params[:type] # 路径导航类型 + reorder = params[:order] || "myshixun_count" + sort = params[:sort] || "desc" search = params[:search] - type = params[:type] - # 显示所有未隐藏的、已发布的实训课程 - @subjects = Subject.select([:id, :name, :status, :repertoire_id]).visible.unhidden - @tags = Repertoire.select([:id, :name]).where(id: @subjects.pluck(:repertoire_id).uniq).order("updated_at desc") + ## 分页参数 + page = params[:page] || 1 + limit = params[:limit] || 15 + offset = (page.to_i-1) * limit + + # 最热排序 + if reorder == "myshixun_count" + if select && select != "all" + @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, + subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns + on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where + subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' + AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count #{sort}") + else + @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, + subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns + on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where + subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' + GROUP BY subjects.id ORDER BY myshixun_member_count #{sort}") + end + else + # 我的路径 + if reorder == "mine" + mine_subject_id = StageShixun.find_by_sql("select DISTINCT(subject_id) from stage_shixuns where shixun_id in + (select distinct(shixun_id) from myshixuns where user_id=#{current_user.id})").map(&:subject_id) + manage_subject_id = SubjectMember.where(user_id: current_user.id).pluck(:subject_id) + total_subject_id = (mine_subject_id + manage_subject_id).uniq + @subjects = Subject.where(id: total_subject_id) + end - if params[:search] && params[:search].strip != "" - @subjects = @subjects.joins(:user).where("subjects.name like ? or concat(users.lastname, users.firstname) like ?", - "%#{search}%", "%#{search}%") - end + # 类型 + if select && select != "all" + @subjects = @subjects.where(repertoire_id: select) + end - unless type.blank? || type == "all" - @subjects = @subjects.where(repertoire_id: type) - end + if search.present? + @subjects = @subjects.where("name like ?", "%#{search}%") + end - @subjects = @subjects.reorder("subjects.created_at desc") - @subjects_count = @subjects.size + # 排序 + order_str = "updated_at #{sort}" + @subjects = @subjects.reorder(order_str) + end - ## 分页参数 - page = params[:page] || 1 - @subjects = @subjects.page(page).per(10) + @total_count = @subjects.size - @subjects = @subjects.includes(:shixuns) + if reorder != "myshixun_count" + @subjects = @subjects.page(page).per(limit).includes(:shixuns, user: [user_extension: :school]) + else + @subjects = @subjects[offset, limit] + unless @subjects.blank? + subject_ids = @subjects.pluck(:id) + order_ids = subject_ids.size > 0 ? subject_ids.join(',') : -1 + @subjects = Subject.where(id: subject_ids).order("field(id,#{order_ids})").includes(:shixuns, user: [user_extension: :school]) + end + end end def create_subject_homework @@ -889,7 +1048,8 @@ class HomeworkCommonsController < ApplicationController def publish_homework tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0 tip_exception("缺少截止时间参数") if params[:end_time].blank? - tip_exception("截止时间必须晚于当前时间") if params[:end_time] <= strf_time(Time.now) + tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) + tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) homeworks = @course.homework_commons.where(id: params[:homework_ids]) homeworks = homeworks.includes(:homework_group_settings, :homework_detail_manual) @@ -908,15 +1068,15 @@ class HomeworkCommonsController < ApplicationController if @course.course_groups.where(id: publish_groups).size == @course.course_groups.size homework.homework_group_settings.destroy_all homework.unified_setting = true + homework.end_time = params[:end_time] else homework.unified_setting = false # 创建作业分班设置:homework_group_setting create_homework_group_settings(homework) - # 选中的分班设置的发布时间改为当前时间,截止时间不为空的保持原状,为空的改为一个月后 - homework.homework_group_settings.where(course_group_id: publish_groups).update_all(publish_time: Time.now) - homework.homework_group_settings.where(course_group_id: publish_groups, end_time: nil). - update_all(end_time: params[:end_time]) + # 选中的分班设置的发布时间改为当前时间,截止时间改为传的截止时间参数 + homework.homework_group_settings.where(course_group_id: publish_groups).update_all(publish_time: Time.now, + end_time: params[:end_time]) # 发消息 tiding_group_ids = publish_groups end @@ -927,7 +1087,7 @@ class HomeworkCommonsController < ApplicationController homework.publish_time = Time.now - # 截止时间不为空的保持原状,为空的改为一个月后, 非统一设置的更新为最大分班截止时间 + # 截止时间的处理 if homework.end_time.nil? homework.end_time = params[:end_time] elsif homework.max_group_end_time @@ -938,14 +1098,13 @@ class HomeworkCommonsController < ApplicationController if homework.course_acts.size == 0 homework.course_acts << CourseActivity.new(user_id: homework.user_id, course_id: homework.course_id) end - + # 发消息 HomeworkCommonPushNotifyJob.perform_later(homework.id, tiding_group_ids) else create_homework_group_settings(homework) none_publish_settings = homework.homework_group_settings.where(course_group_id: publish_groups).none_published - none_publish_settings.update_all(publish_time: Time.now) - none_publish_settings.where(end_time: nil).update_all(end_time: params[:end_time]) + none_publish_settings.update_all(publish_time: Time.now, end_time: params[:end_time]) if homework.max_group_end_time homework.end_time = homework.max_group_end_time end @@ -960,7 +1119,8 @@ class HomeworkCommonsController < ApplicationController homework.save! - HomeworkPublishUpdateWorkStatusJob.perform_later(tiding_group_ids, homework.id) + # 更新学生状态及成绩(手动点击计算) + # HomeworkPublishUpdateWorkStatusJob.perform_later(tiding_group_ids, homework.id) end normal_status(0, "发布成功") rescue Exception => e @@ -1060,7 +1220,7 @@ class HomeworkCommonsController < ApplicationController =end # 更新所有学生的效率分(重新取homework确保是更新后的) - HomeworksService.new.update_student_eff_score HomeworkCommon.find_by(id: homework.id) if !homework.allow_late && homework.end_time <= time + HomeworkEndUpdateScoreJob.perform_later(homework.id) if !homework.allow_late && homework.end_time <= time end end homework.save! @@ -1259,7 +1419,7 @@ class HomeworkCommonsController < ApplicationController .where(:user_id => user_ids).joins(user: :user_extension) # 按学号和姓名搜索 if params[:search] - @users_reviews = @users_reviews.where("concat(lastname, firstname) like ? or student_id like ?", params[:search], params[:search]) + @users_reviews = @users_reviews.where("concat(lastname, firstname) like :keyword or student_id like :keyword", keyword: "%#{params[:search]}%") end # 抄袭作品数 @copy_reviews_count = @users_reviews.count @@ -1279,7 +1439,7 @@ class HomeworkCommonsController < ApplicationController end - # 代码查重详情 + # 代码查重代码的详情 def code_review_detail @student_work = @homework.student_works.find_by(user_id: params[:user_id]) @user = @student_work.user @@ -1292,7 +1452,7 @@ class HomeworkCommonsController < ApplicationController if results.status == 0 code_info = results.code_info homework_challenge_settings = @homework.homework_challenge_settings - @challenges = @shixun.challenges.where(id: homework_challenge_settings.pluck(:challenge_id), st: 0).includes(:games) + @challenges = @shixun.challenges.where(id: homework_challenge_settings.pluck(:challenge_id), st: 0) @challenges = @challenges.map do |challenge| code_rate = 0 @@ -1306,24 +1466,8 @@ class HomeworkCommonsController < ApplicationController game = challenge.games.find_by(user_id: @user.id) end_time = game.end_time # 用户关卡的得分 - all_score = homework_challenge_settings.find_by(challenge_id: challenge.id).try(:score) - final_score = - if @student_work.challenge_work_scores.where(challenge_id: challenge.id).last.present? - @student_work.challenge_work_scores.where(:challenge_id => game.challenge_id).last.score - else - if game.status == 2 && ((game.end_time && game.end_time < @homework.end_time) || - (@homework.allow_late && (@course.end_date.nil? || - (game.end_time && game.end_time < @course.end_date.end_of_day)))) - answer_open_evaluation = @homework.homework_detail_manual.answer_open_evaluation - # 设置了查看答案也获得满分的话就取总分。否则取关卡的百分比分支 - if answer_open_evaluation.present? - all_score - else - # 关卡的百分比 * 作业设置的分数 = 总得分 - ((game.final_score) / challenge.score) * all_score - end - end - end + all_score = homework_challenge_settings.find_by(challenge_id: challenge.id).try(:score).to_f + final_score = @student_work.work_challenge_score game, all_score # 抄袭用户 copy_user = User.find_by_id(game_codes[0].target_user_id) copy_end_time = copy_user.games.find_by(challenge_id: challenge.id).try(:end_time) if copy_user.present? diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 8e340da73..90da7d8e5 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -3,7 +3,7 @@ class MessagesController < ApplicationController SORT_TYPE = %w[time hot] - before_action :require_login, only: %i[create update sticky_top bulk_delete create destroy bulk_send bulk_move bulk_public] + before_action :require_login, :check_auth, only: %i[create update sticky_top bulk_delete create destroy bulk_send bulk_move bulk_public] before_action :find_board, only: [:create, :index, :bulk_delete, :bulk_move, :bulk_send, :bulk_public] before_action :find_message, only: [:update, :destroy, :sticky_top, :reply_list, :destroy, :reply] before_action :validate_delete_params, only: %i[bulk_delete bulk_public] @@ -17,17 +17,25 @@ class MessagesController < ApplicationController @page = params[:page] || 1 @page_size = params[:page_size] || 15 - sort = params[:sort] || 0 + sort = params[:sort].to_i == 1 ? 'asc' : 'desc' sort_type = params[:sort_type] || 'time' - sort = sort.to_i - sort_type = sort_type.strip - @messages = @board.messages.root_nodes.by_keywords(params[:search]).includes(:praise_treads, :author, :children) - @messages = @messages.ordered(sort: sort, sort_type: sort_type) - @messages = sort_by_all_replies(sort, sort_type, @messages) + messages = @board.messages.root_nodes.by_keywords(params[:search]) - @messages = sort_by_sticky(@messages) - @messages = Kaminari.paginate_array(@messages).page(@page).per(@page_size) + messages = messages.reorder('(sticky = 1) DESC') # 置顶 + + messages = + case sort_type + when 'time' then messages.order("created_on #{sort}") + when 'hot' then messages.order("descendants_count #{sort}") + else messages.order("created_on #{sort}") + end + + messages = messages.includes(:author) + @messages = Kaminari.paginate_array(messages).page(@page).per(@page_size) + + ids = @messages.map(&:id) + @praises_count_map = Message.where(root_id: ids).group(:root_id).sum(:praises_count) end def reply_list @@ -35,41 +43,31 @@ class MessagesController < ApplicationController @page_size = params[:page_size] || 10 @current_user = current_user || nil - @messages = @message.children.preload_messages + @messages = @message.children.preload_messages.includes(:message_detail, :praise_treads) @messages = @messages.ordered(sort: 1) unless @message.parent_id.nil? + @user_course_identity = current_user.course_identity(@message.board.course) + case @user_course_identity + when 5, 6, 7 + @messages = @messages.visible + end + @messages = @messages.page(@page).per(@page_size) end def reply return normal_status(2, "回复内容不能为空") if params[:content].blank? - begin - @reply = Message.create!(board: @message.board, - author: current_user, - parent: @message, - message_detail_attributes: { + @reply = Message.create!(board: @message.board, root_id: @message.root_id || @message.id, + author: current_user, parent: @message, + message_detail_attributes: { content: params[:content] - } - ) - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback - end + }) end def sticky_top return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@message.board.course) - ActiveRecord::Base.transaction do - begin - @message.update_attributes(:sticky => @message.sticky == 1 ? 0 : 1) - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback - end - end + @message.update_attributes(:sticky => @message.sticky == 1 ? 0 : 1) end def bulk_delete @@ -89,7 +87,10 @@ class MessagesController < ApplicationController end def show - @message = Message.includes(:attachments, :message_detail, :children, :author => :user_extension, :board => [{course: :board_course_modules}]).find_by_id params[:id] + @message = Message.includes(:attachments, :message_detail, + :children, :author => :user_extension, + :board => [{course: :board_course_modules}]) + .find_by_id params[:id] return normal_status(-2, "ID为#{params[:id]}的帖子不存在") if @message.nil? @attachment_size = @message.attachments.size @@ -101,7 +102,9 @@ class MessagesController < ApplicationController return normal_status(403, "您没有权限进行该操作") if current_user != @message.author && !current_user.teacher_of_course?(@message.board.course) begin - @message.update_attributes(message_params) + h = {is_md: true} + m_params = message_params.merge(h) + @message.update_attributes(m_params) Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name) @message.update_content(params[:content]) rescue Exception => e @@ -130,7 +133,7 @@ class MessagesController < ApplicationController def destroy begin - return normal_status(403, "您没有权限进行该操作") unless @message.author == current_user || current_user.teacher_of_course?(@message.board.course) + return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@message.board.course) >= 5 || @message.author != current_user @message.destroy! rescue Exception => e uid_logger_error(e.message) @@ -170,15 +173,9 @@ class MessagesController < ApplicationController def bulk_move # 课堂的目录之间移动,有子栏目的才显示此项 - return normal_status(403) unless current_user.teacher_of_course?(@board.course) + return normal_status(403) unless current_user.teacher_of_course?(@board.course) - begin - Message.bulk_move_to_other_board(params[:ids], params[:to_board_id], current_user.id) - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback - end + Message.bulk_move_to_other_board(params[:ids], params[:to_board_id]) end def bulk_public diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb index 042945b6e..0a19f1c08 100644 --- a/app/controllers/myshixuns_controller.rb +++ b/app/controllers/myshixuns_controller.rb @@ -1,7 +1,7 @@ class MyshixunsController < ApplicationController - before_action :require_login, :except => [:training_task_status, :code_runinng_message] - before_action :find_myshixun, :except => [:training_task_status] - before_action :find_repo_name, :except => [:training_task_status] + before_action :require_login, :check_auth, :except => [:training_task_status, :code_runinng_message] + before_action :find_myshixun, :except => [:training_task_status, :code_runinng_message] + before_action :find_repo_name, :except => [:training_task_status, :code_runinng_message] skip_before_action :verify_authenticity_token, :only => [:html_content] ## TPI关卡列表 @@ -15,7 +15,6 @@ class MyshixunsController < ApplicationController # For Admin # 强制重置实训 - # REDO等删除是否可以做成异步 # 前段需要按照操作过程提示 def reset_my_game unless (current_user.admin? || current_user.id == @myshixun.user_id) @@ -34,8 +33,11 @@ class MyshixunsController < ApplicationController uid_logger_error("版本库删除异常,详情:#{e.message}") end - StudentWork.where(:myshixun_id => @myshixun.id).update_all(:myshixun_id => nil, :work_status => 0) + StudentWork.where(:myshixun_id => @myshixun.id).update_all(:myshixun_id => 0, :work_status => 0) + # 实训在申请发布前,是否玩过实训,如果玩过需要更改记录,防止二次重置 + shixun_mod = ShixunModify.where(:shixun_id => @shixun.id, :myshixun_id => @myshixun.id, :status => 1).take + shixun_mod.update_column(:status, 0) if shixun_mod rescue Exception => e uid_logger_error("myshixun reset failed #{e}") raise ActiveRecord::Rollback @@ -44,6 +46,7 @@ class MyshixunsController < ApplicationController end # 代码运行中的信息接口 + # 这个方法是中间层主动调用的,点击评测后,中间层会发送参数过来,告诉目前Pod的启动情况,一次评测会调用两次请求 def code_runinng_message begin jsonTestDetails = JSON.parse(params[:jsonTestDetails]) @@ -86,9 +89,6 @@ class MyshixunsController < ApplicationController # "createPod":"1.610","evaluateAllTime":2820,"evaluateStart":"2017-11-24 11:04:35","execute":"0.294"}' # params[:pics] = "a.png,b.png,c.png" def training_task_status - logger.info("123################{params[:jsonTestDetails]}") - logger.info("456################{params[:timeCost]}") - logger.info("666###############{params}") ActiveRecord::Base.transaction do begin @@ -99,13 +99,16 @@ class MyshixunsController < ApplicationController return_back_time = format("%.3f", ( t1.to_f - brige_end_time.to_f)).to_f status = jsonTestDetails['status'] game_id = jsonTestDetails['buildID'] + sec_key = jsonTestDetails['sec_key'] + logger.info("training_task_status start#1**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") resubmit = jsonTestDetails['resubmit'] outPut = tran_base64_decode64(jsonTestDetails['outPut']) + jenkins_testsets = jsonTestDetails['msg'] compile_success = jsonTestDetails['compileSuccess'] # message = Base64.decode64(params[:msg]) unless params[:msg].blank? - logger.info(outPut) + game = Game.find(game_id) myshixun = game.myshixun challenge = game.challenge @@ -122,11 +125,16 @@ class MyshixunsController < ApplicationController jenkins_testsets.each_with_index do |j_test_set, i| logger.info("j_test_set: ############## #{j_test_set}") actual_output = tran_base64_decode64(j_test_set['output']) + #ts_time += j_test_set['testSetTime'].to_i + # is_public = test_sets.where(:position => j_test_set['caseId']).first.try(:is_public) logger.info "actual_output:################################################# #{actual_output}" + ts_time = format("%.2f", j_test_set['testSetTime'].to_f/1000000000).to_f + ts_mem = format("%.2f", j_test_set['testSetMem'].to_f/1024/1024).to_f + Output.create!(:code => status, :game_id => game_id, :out_put => outPut, :test_set_position => j_test_set['caseId'], :actual_output => actual_output, :result => j_test_set['passed'].to_i, :query_index => max_query_index, - :compile_success => compile_success.to_i) + :compile_success => compile_success.to_i, :sec_key => sec_key, :ts_time => ts_time, :ts_mem => ts_mem) # 如果设置了按测试集给分,则需要统计测试集的分值 if challenge.test_set_score && j_test_set['passed'].to_i == 1 test_set_score += challenge.test_sets.where(:position => j_test_set['caseId']).pluck(:score).first @@ -134,14 +142,14 @@ class MyshixunsController < ApplicationController end end uid_logger("#############status: #{status}") - uid_logger("#############resubmit: #{resubmit}") - record = EvaluateRecord.where(:game_id => game_id).first + record = EvaluateRecord.where(:identifier => sec_key).first logger.info("training_task_status start#3**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") answer_deduction_percentage = (100 - game.answer_deduction) / 100.to_f # 查看答案后剩余分数的百分比. # answer_deduction是查看答案的扣分比例 # status:0表示评测成功 if status == "0" if resubmit.present? + uid_logger("#############resubmitdaiao: #{resubmit}") game.update_attributes!(:retry_status => 2, :resubmit_identifier => resubmit) challenge.path.split(";").each do |path| game_passed_code(path.try(:strip), myshixun, game_id) @@ -167,7 +175,7 @@ class MyshixunsController < ApplicationController end # 更新实训关联的作品分数 TODO: 更新作品分数 - HomeworksService.new.update_myshixun_work_score myshixun + # HomeworksService.new.update_myshixun_work_score myshixun end # 如果过关了,下一关的状态是3(为开启),则需要把状态改成1(已开启) # next_game = game.next_game @@ -182,14 +190,21 @@ class MyshixunsController < ApplicationController test_set_percentage = test_set_score / 100.to_f # 测试集得分比 score = (challenge.score * test_set_percentage * answer_deduction_percentage).to_i # 如果分数比上次多,则更新成绩 - game.update_attributes!(:status => 0, :final_score => score) if game.final_score < score + game_update = + if game.final_score < score + {final_score: score, status: 0} + else + {status: 0} + end + game.update_attributes!(game_update) end end test_cases_time = format("%.3f", (Time.now.to_f - t1.to_f)).to_f if record.present? consume_time = format("%.3f", (Time.now - record.created_at)).to_f - record.update_attributes!(:consume_time => consume_time, :git_pull => timeCost['pull'] , - :create_pod => timeCost['createPod'], :pod_execute => timeCost['execute'], :test_cases => test_cases_time, + + record.update_attributes!(:consume_time => consume_time, :git_pull => timeCost['pull'] , :create_pod => timeCost['createPod'], + :pod_execute => timeCost['execute'], :test_cases => test_cases_time, :brige => timeCost['evaluateAllTime'], :return_back => return_back_time) end uid_logger("training_task_status start#4**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") @@ -211,7 +226,7 @@ class MyshixunsController < ApplicationController shixun_tomcat = edu_setting('tomcat_webssh') uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo" params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), - containers:(Base64.urlsafe_encode64(container_limit @myshixun.shixun.mirror_repositories))} + containers:(Base64.urlsafe_encode64(shixun_container_limit @myshixun.shixun))} res = uri_post uri, params if res && res['code'].to_i != 0 tip_exception("实训云平台繁忙(繁忙等级:92)") @@ -237,55 +252,58 @@ class MyshixunsController < ApplicationController # -----Repository # TODO: 之类需要一个resubmit参数,但是是关于games. def update_file - @hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first - tip_exception("技术平台为空!") if @myshixun.mirror_name.blank? - path = params[:path].strip unless params[:path].blank? - game_id = params[:game_id] - game = Game.find(game_id) - @content_modified = 0 - # params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过 - # 自动保存的时候evaluate为0;点评测的时候为1 - if params[:evaluate] == 1 - record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id) - uid_logger("-- game is #{game_id}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") - student_work_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f - record.update_attributes!(:student_work => student_work_time) - end - unless @hide_code - # 远程版本库文件内容 - last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"] - - content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && params[:content].present? - params[:content].gsub(/\t/, ' ') - else - params[:content] - end - if content != last_content - @content_modified = 1 - - author_name = current_user.full_name - author_email = current_user.mail - message = params[:evaluate] == 0 ? "auto commit" : "task commit" - @content = GitService.update_file(repo_path: @repo_path, - file_path: path, - message: message, - content: content, - author_name: author_name, - author_email: author_email) - - uid_logger("-- file update #{@content}") + begin + @hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first + tip_exception("技术平台为空!") if @myshixun.mirror_name.blank? + path = params[:path].strip unless params[:path].blank? + game_id = params[:game_id] + game = Game.find(game_id) + @content_modified = 0 + + # params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过 + # 自动保存的时候evaluate为0;点评测的时候为1 + if params[:evaluate] == 1 + @sec_key = generate_identifier(EvaluateRecord, 12) + record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id, + :identifier => @sec_key) + uid_logger("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") end - end + unless @hide_code + # 远程版本库文件内容 + last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"] + content = params[:content] + Rails.logger.info("###11222333####{content}") + Rails.logger.info("###222333####{last_content}") + if content != last_content + @content_modified = 1 - if game.status == 2 - @resubmit = Time.now.to_i - end + author_name = current_user.real_name + author_email = current_user.git_mail + message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted" + uid_logger("112233#{author_name}") + uid_logger("112233#{author_email}") + @content = GitService.update_file(repo_path: @repo_path, + file_path: path, + message: message, + content: content, + author_name: author_name, + author_email: author_email) + end + end - # 评测时间记录 - if record.present? - consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f - record.update_attributes!(:file_update => consume_time) + if game.status == 2 + @resubmit = Time.now.to_i + end + + # 评测时间记录 + if record.present? + consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f + record.update_attributes!(:file_update => consume_time) + end + rescue Exception => e + uid_logger_error(e.message) + tip_exception("文件内容更新异常,请稍后重试") end end diff --git a/app/controllers/poll_questions_controller.rb b/app/controllers/poll_questions_controller.rb index 69aef41c0..6a0b9ea47 100644 --- a/app/controllers/poll_questions_controller.rb +++ b/app/controllers/poll_questions_controller.rb @@ -1,5 +1,5 @@ class PollQuestionsController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :get_poll,only:[:new,:create] before_action :get_poll_question,except: [:new,:create] before_action :is_course_teacher @@ -156,14 +156,10 @@ class PollQuestionsController < ApplicationController begin answer_d_id = params[:answer_no].to_i # 答案的当前位置 poll_answers = @poll_question.poll_answers - delete_answer = poll_answers.find_answer_by_custom("answer_position",answer_d_id).first - left_answer = poll_answers.left_answer_choose("answer_position",answer_d_id) - if left_answer.present? - left_answer.each do |p| - p.answer_position -= 1 - p.save - end - end + delete_answer = poll_answers.find_by(answer_position: answer_d_id) + left_answers = poll_answers.where("answer_position > ?",answer_d_id) + left_answers.update_all("answer_position = answer_position - 1") if left_answers + if delete_answer.destroy normal_status(0, "答案删除成功!") else @@ -197,22 +193,23 @@ class PollQuestionsController < ApplicationController begin opr = params[:opr] current_q_p = @poll_question.question_number.to_i #问题的当前位置 - last_q_p = @poll.poll_questions.last_poll(current_q_p) #当前问题的前一个问题 - next_q_p = @poll.poll_questions.next_poll(current_q_p) # 当前问题的后一个问题 if @poll.polls_status.to_i == 1 if opr.present? if opr.to_s == "up" + last_q_p = @poll.poll_questions.find_by(question_number: (current_q_p-1)) #当前问题的前一个问题 if last_q_p.present? - @poll_question.update_attribute(:question_number, (current_q_p - 1)) - last_q_p.update_attribute(:question_number, (@poll_question.question_number.to_i + 1)) # 重新获取当前问题的位置 + @poll_question.update_attribute("question_number", (current_q_p - 1)) + last_q_p.update_attribute("question_number", current_q_p) # 重新获取当前问题的位置 normal_status(0, "问题上移成功!") else normal_status(-1, "移动失败,已经是第一个问题了!") end elsif opr.to_s == "down" + next_q_p = @poll.poll_questions.find_by(question_number: (current_q_p+1)) #当前问题的后一个问题 if next_q_p.present? - @poll_question.update_attribute(:question_number, (current_q_p + 1)) - next_q_p.update_attribute(:question_number, (@poll_question.question_number.to_i - 1)) + @poll_question.update_attribute("question_number", (current_q_p + 1)) + next_q_p.update_attribute("question_number", current_q_p) + normal_status(0, "问题下移成功!") else normal_status(-1, "移动失败,已经是最后一个问题了!") diff --git a/app/controllers/poll_votes_controller.rb b/app/controllers/poll_votes_controller.rb index eef953d5e..b1191d8ea 100644 --- a/app/controllers/poll_votes_controller.rb +++ b/app/controllers/poll_votes_controller.rb @@ -1,9 +1,8 @@ class PollVotesController < ApplicationController #在开始回答和提交问卷的时候,已经做了判断用户的身份权限 - before_action :require_login + before_action :require_login, :check_auth before_action :get_poll_question - before_action :check_answer_in_question,only: [:create] - before_action :check_multi_answers + before_action :check_answer_in_question def create #每一次答案的点击,请求一次 @@ -31,11 +30,13 @@ class PollVotesController < ApplicationController if question_type == 1 if user_votes.present? #用户曾经回答过的,答案选择不一样,否则新建 current_user_answer = user_votes.first - if current_user_answer.poll_answer_id != question_answer_id #如果说更换了答案,则以前的答案删除,并新建记录 + if current_user_answer&.poll_answer_id != question_answer_id #如果说更换了答案,则以前的答案删除,并新建记录 current_user_answer.destroy PollVote.create(vote_answer_params) else + if question_answer_text.present? + current_user_answer.update_attribute("vote_text", question_answer_text) end end @@ -98,9 +99,10 @@ class PollVotesController < ApplicationController @current_question_necessary = @poll_question.is_necessary #问答记录存在,且有值,才会有返回值。 @current_question_status = 0 - if user_votes.present? - vote_answer_id = user_votes.pluck(:poll_answer_id).reject(&:blank?).size - vote_text_count = user_votes.pluck(:vote_text).reject(&:blank?).size + new_user_votes = question_votes.where(user_id: current_user.id) + if new_user_votes.present? + vote_answer_id = new_user_votes.pluck(:poll_answer_id).reject(&:blank?).size + vote_text_count = new_user_votes.pluck(:vote_text).reject(&:blank?).size if vote_text_count > 0 || vote_answer_id > 0 @current_question_status = 1 end @@ -129,29 +131,28 @@ class PollVotesController < ApplicationController normal_status(-1,"课堂不存在!") end end - end def check_answer_in_question - poll_answer_ids = @poll_question.poll_answers.pluck(:id) - if @poll_question.question_type == 1 #单选题/多选题 - unless (params[:poll_answer_id].present? && poll_answer_ids.include?(params[:poll_answer_id].to_i)) || (params[:poll_answer_id].blank? && params[:vote_text].present?) - normal_status(-1, "答案ID错误!") - end - end - end + poll_user_status = @poll.get_poll_status(current_user) + poll_user = @poll.poll_users.find_by(user_id: current_user.id) #当前用户 - def check_multi_answers - if @poll_question.question_type == 2 + question_type = @poll_question&.question_type + if (question_type == 1) && params[:poll_answer_id].blank? + normal_status(-1,"答案ID错误!") + elsif question_type == 2 user_vote_count = params[:poll_answer_id].size if @poll_question.max_choices.present? question_max_choices = @poll_question.max_choices else question_max_choices = 0 end - if question_max_choices > 0 && user_vote_count > question_max_choices + if question_max_choices > 0 && (user_vote_count > question_max_choices) normal_status(-1,"多选题答案超过最大限制!") end + elsif (poll_user.present? && poll_user.commit_status == 1) || poll_user_status == 3 + normal_status(-1,"已提交/已结束的问卷不允许修改!") end end + end diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index 751b725e6..f5003a0c7 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -1,6 +1,6 @@ class PollsController < ApplicationController # before_action :check_poll_status 问卷的发消息和定时任务没有做 - before_action :require_login,except: [:index] + before_action :require_login, :check_auth,except: [:index] before_action :find_course, except: [:show,:poll_setting,:commit_setting,:edit,:update,:start_answer,:commit_poll, :commit_result,:poll_lists,:cancel_publish,:cancel_publish_modal,:common_header] before_action :get_poll_and_course, only: [:show,:poll_setting,:commit_setting,:edit,:update,:start_answer, @@ -18,7 +18,7 @@ class PollsController < ApplicationController before_action :check_user_id_start_answer,only: [:start_answer] before_action :check_poll_question_complete,only: [:commit_poll] #问卷提交前来判断问题是否完成 before_action :check_poll_commit_result,only: [:commit_result] - before_action :get_all_polls_commit, only: [:commit_result] #该问卷全部的用户 + # before_action :get_all_polls_commit, only: [:commit_result] #该问卷全部的用户 before_action :get_left_banner_id, only:[:common_header,:start_answer,:new,:edit,:index] include PollsHelper @@ -31,50 +31,48 @@ class PollsController < ApplicationController @current_user_ = current_user @course_status = @course.is_end ? 0 : 1 # 课堂是否结束 @course_is_public = @course.is_public - @polls_count = @polls_all.count # 全部页面,需返回 - @polls_unpublish_counts = @polls_all.poll_by_status(1).count #未发布的问卷数 - @polls_published_counts = @polls_all.poll_by_status([2, 3]).count # 已发布的问卷数 # 课堂的学生人数 @course_all_members = @course.students #当前课堂的全部学生 - @course_all_members_count = @course_all_members.count #当前课堂的学生数 @current_student = @course_all_members.find_by(user_id: current_user.id) #当前用户是否为课堂的学生 - # polls的不同用户群体的显示 if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教 @is_teacher_or = 1 - @teacher_groups_ids = @course.teacher_course_groups.get_user_groups(current_user.id).pluck(:course_group_id).reject(&:blank?) @polls = @polls_all #老师能看到全部的问卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同) elsif @user_course_identity == Course::STUDENT # 2为课堂成员,能看到统一设置的和自己班级的 @is_teacher_or = 2 - member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id,默认为0 - if member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的) + @member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id,默认为0 + if @member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的) @polls = member_show_polls.size > 0 ? member_show_polls.public_or_unset : [] else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷 # 已发布 当前用户班级分组的 试卷id - poll_settings_ids = @course.poll_group_settings.where(course_group_id: member_group_id).poll_group_published.pluck(:poll_id).uniq # 选择成员的班级id等于课堂问卷设置的班级id - @polls = member_show_polls.present? ? member_show_polls.public_or_unset.or(member_show_polls.where(id: poll_settings_ids)) : [] + not_poll_ids = @course.poll_group_settings.poll_group_not_published.where("course_group_id = #{@member_group_id}").pluck(:poll_id) + @polls = member_show_polls.where.not(id: not_poll_ids) end else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁 @is_teacher_or = 0 - @polls = member_show_polls.size > 0 ? member_show_polls.public_or_unset : [] + @polls = member_show_polls.public_or_unset end + if @polls.count > 0 if params[:type].present? choose_type = params[:type] - member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id,默认为0 - if @is_teacher_or == 2 && member_group_id > 0 - poll_groups_sets = @course.poll_group_settings.where(course_group_id: member_group_id).poll_group_published - poll_settings_ids = poll_groups_sets.pluck(:poll_id) - poll_ended_ids = poll_groups_sets.poll_group_ended.pluck(:poll_id).uniq - # poll_settings_ids = @course.poll_group_settings.where(course_group_id: member_group_id).poll_group_ended.pluck(:poll_id).uniq - if choose_type.to_i == 2 - @polls = @polls_all.present? ? @polls_all.poll_by_status(2).public_or_unset.or(@polls_all.where(id:(poll_settings_ids - poll_ended_ids).uniq)).distinct : [] - elsif choose_type.to_i == 3 - @polls = @polls_all.present? ? @polls_all.poll_by_status(3).public_or_unset.or(@polls_all.where(id: poll_ended_ids)).distinct : [] - end + poll_setting_ids = [] + if @is_teacher_or != 2 + @polls = @polls.where("polls_status = #{choose_type}") else - @polls = @polls.poll_by_status(choose_type) + case choose_type + when 1 + poll_setting_ids = @course.poll_group_settings.where("course_group_id = #{@member_group_id}").poll_group_not_published.pluck(:poll_id) + when 2 + poll_setting_ids = @course.poll_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(:poll_id) + when 3 + poll_setting_ids = @course.poll_group_settings.where("course_group_id = #{@member_group_id}").poll_group_ended.pluck(:poll_id) + end + unified_setting_ids = @polls.public_or_unset.where("polls_status = #{choose_type}").pluck(:id) + ex_ids = (poll_setting_ids + unified_setting_ids).uniq + @polls = @polls.where(id: ex_ids) end end @@ -90,11 +88,16 @@ class PollsController < ApplicationController @limit = params[:limit] || 15 @polls = @polls.page(@page).per(@limit) - @polls = @polls.includes(:poll_users,:poll_questions,:poll_group_settings) - + @polls = @polls&.includes(:published_settings) else @polls = [] end + + @polls_count = @polls_all.size # 全部页面,需返回 + @polls_unpublish_counts = @polls_all.poll_by_status(1).size #未发布的问卷数 + @polls_published_counts = @polls_count - @polls_unpublish_counts # 已发布的问卷数 + @course_all_members_count = @course_all_members.size #当前课堂的学生数 + rescue Exception => e uid_logger_error(e.message) tip_exception(e.message) @@ -146,7 +149,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 +186,7 @@ class PollsController < ApplicationController else @is_teacher_or = 0 end - @poll_questions = @poll.poll_questions.order("question_number ASC") + rescue Exception => e uid_logger_error(e.message) tip_exception("没有权限") @@ -202,15 +205,15 @@ class PollsController < ApplicationController @is_teacher_or = 1 @user_poll_answer = 3 #教师页面 end - poll_status = @poll.get_poll_status(current_user.id) + @poll_status = @poll.get_poll_status(current_user) poll_id_array = [@poll.id] @poll_publish_count = get_user_permission_course(poll_id_array,2).count #是否存在已发布的 @poll_unpublish_count = get_user_permission_course(poll_id_array,1).count #是否存在未发布的 if (@poll_publish_count == 0) && (@poll_unpublish_count == 0) #即表示没有分班 - if poll_status == 1 + if @poll_status == 1 @poll_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候 - elsif poll_status == 2 + elsif @poll_status == 2 @poll_publish_count = 1 #试卷未发布,且课堂没有分班的时候 end end @@ -241,10 +244,13 @@ class PollsController < ApplicationController end #首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。 def publish + tip_exception("缺少截止时间参数") if params[:end_time].blank? + tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) + tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) ActiveRecord::Base.transaction do begin check_ids = Poll.where(id: params[:check_ids]) - ex_end_time = params[:end_time] || Time.at(((1.month.since.to_i)/3600.0).ceil * 3600) + 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 |poll| if poll.unified_setting pl_status = poll.polls_status #则为试卷的状态 @@ -254,16 +260,11 @@ class PollsController < ApplicationController if pl_status == 1 #如果问卷存在已发布的,或者是已截止的,那么则直接跳过 g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数,那么poll的统一设置需修改 if g_course - course_groups = @course.teacher_course_groups.get_user_groups(current_user.id) - if course_groups.blank? - user_course_groups = @course.course_groups.present? ? @course.course_groups.pluck(:id) : [] - else - user_course_groups = course_groups.pluck(:course_group_id) - end + user_course_groups = @course.charge_group_ids(current_user) if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则问卷不用分组,且问卷设定为统一设置,否则则分组设置 poll.poll_group_settings.destroy_all poll_unified = true - notify_student_ids = @course.students.pluck(:user_id) + e_time = ex_end_time else poll_unified = false g_course.each do |i| @@ -282,20 +283,13 @@ class PollsController < ApplicationController new_poll_group.save end end - - notify_student_ids = @course.students.where(course_group_id: params[:group_ids]).pluck(:user_id) + e_time = poll.poll_group_settings.end_time_present.map(&:end_time).max + # group_ids = params[:group_ids] end else poll.poll_group_settings.destroy_all poll_unified = true - notify_student_ids = @course.students.pluck(:user_id) - end - if poll.end_time.blank? e_time = ex_end_time - elsif poll.poll_group_settings.end_time_present.count > 0 # 该问卷分组有结束时间为空的 - e_time = poll.poll_group_settings.end_time_present.map(&:end_time).max - else - e_time = poll.end_time end poll_status = set_poll_status(Time.now,e_time) @@ -309,7 +303,7 @@ class PollsController < ApplicationController if poll.course_acts.size == 0 poll.course_acts << CourseActivity.new(:user_id => poll.user_id,:course_id => poll.course_id) end - PollPublishNotifyJob.perform_later(poll.id, notify_student_ids) + PollPublishNotifyJob.perform_later(poll.id, g_course) end end normal_status(0, "问卷发布成功!") @@ -347,7 +341,7 @@ class PollsController < ApplicationController begin check_ids = Poll.where(id: params[:check_ids]) check_ids.each do |poll| - poll_status = poll.get_poll_status(current_user.id) + poll_status = poll.get_poll_status(current_user) if poll_status == 2 #跳过已截止的或未发布的 g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数,那么poll的统一设置需修改,poll_group_settings if g_course @@ -673,7 +667,7 @@ class PollsController < ApplicationController @user_published_setting = @poll.poll_group_settings.find_in_poll_group("course_group_id",@being_setting_course_ids) poll_ids = [@poll.id] @poll_publish_count = get_user_permission_course(poll_ids,2).count - ## 需添加发送消息的接口,稍后添加 + rescue Exception => e uid_logger_error(e.message) tip_exception("页面调用失败!") @@ -688,10 +682,10 @@ class PollsController < ApplicationController 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数组 - poll_status = @poll.get_poll_status(current_user.id) - if poll_status == 1 && (course_group_ids - [0]).count > 0 # 问卷未发布,且老师的分班大于1 ,才可以修改统一设置,否则按poll默认的来处理 + poll_status = @poll.get_poll_status(current_user) + if poll_status == 1 && course_group_ids.size > 0 # 问卷未发布,且老师的分班大于1 ,才可以修改统一设置,否则按poll默认的来处理 unified_setting = params[:unified_setting] else unified_setting = @poll.unified_setting @@ -849,8 +843,8 @@ class PollsController < ApplicationController def start_answer ActiveRecord::Base.transaction do begin - poll_user_current = @poll.poll_users.find_by_group_ids(@poll_current_user_id).first #查找当前用户是否有过答题 - @poll_status = @poll.get_poll_status(current_user.id) + poll_user_current = PollUser.where(user_id:@poll_current_user_id,poll_id:@poll.id)&.first #查找当前用户是否有过答题 + @poll_status = @poll.get_poll_status(current_user) if poll_user_current.blank? if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候,不创建poll_user表,理论上老师是不能进入答题的 poll_user_params = { @@ -871,7 +865,6 @@ class PollsController < ApplicationController @user_poll_status = 0 #可编辑 end - # @answer_user = User.find_by(id:@poll_current_user_id) @answer_status = [] question_answered = 0 @@ -923,21 +916,26 @@ class PollsController < ApplicationController def commit_result ActiveRecord::Base.transaction do begin - # 分页 + @poll_users = @poll.all_poll_users(current_user.id) + @poll_commit_ids = @poll_users.commit_by_status(1).pluck(:user_id) #问卷提交用户的id @page = params[:page] || 1 @limit = params[:limit] || 10 - @poll_export_questions = @poll_questions.order("question_number ASC") + @poll_export_questions = @poll_questions @poll_questions = @poll_questions.page(@page).per(@limit) - respond_to do |format| - format.json - format.xlsx{ - if @user_course_identity > Course::ASSISTANT_PROFESSOR - tip_exception(403,"无权限操作") - else - polls_export_name = current_user.real_name + "_" + @course.name + "_" + @poll.polls_name + "_" + Time.now.strftime('%Y%m%d_%H%M%S') - render xlsx: "#{polls_export_name.strip.first(30)}",template: "polls/commit_result.xlsx.axlsx",locals: {poll_questions:@poll_export_questions} + if params[:format] == "xlsx" + if @user_course_identity > Course::ASSISTANT_PROFESSOR + tip_exception(403,"无权限操作") + elsif (@poll.polls_status == 1) || (@poll_export_questions.size == 0) || (@poll_commit_ids.size == 0) + normal_status(-1,"暂无用户提交") + else + respond_to do |format| + format.xlsx{ + polls_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@poll.polls_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" + polls_user_commit = poll_commit_result(@poll,@poll_export_questions,@poll_users,@poll_commit_ids) + render xlsx: "#{polls_export_name_.strip.first(30)}",template: "polls/commit_result.xlsx.axlsx",locals: {polls_user_commit:polls_user_commit} + } end - } + end end rescue Exception => e uid_logger_error(e.message) @@ -951,17 +949,17 @@ class PollsController < ApplicationController def poll_lists ActiveRecord::Base.transaction do begin - logger.info("########___________@course.teacher_course_groups)________________####################{@course.teacher_course_groups.where(user_id:current_user.id).pluck(:course_group_id)}") poll_ids = [@poll.id] - @poll_list_status = @poll.get_poll_status(current_user.id) + @poll_list_status = @poll.get_poll_status(current_user) @poll_publish_count = get_user_permission_course(poll_ids,2).count @poll_unpublish_count = get_user_permission_course(poll_ids,1).count @course_all_members = @course.students + @poll_group_counts = @course.course_groups_count + if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的问卷 @poll_current_user_status = 0 - @poll_users_list = @poll.all_poll_users(current_user.id).distinct #该老师分班的全部学生 - get_poll_answers(@poll_users_list) - + @poll_users_list = @poll.all_poll_users(current_user.id) #该老师分班的全部学生 + get_poll_answers(@poll_users_list, @poll_list_status) if @poll_list_status == 1 @poll_course_groups =[] else @@ -973,7 +971,7 @@ class PollsController < ApplicationController end elsif @user_course_identity > Course::ASSISTANT_PROFESSOR @poll_all_users = @poll.get_poll_exercise_users - get_poll_answers(@poll_all_users) # 未答和已答的 + get_poll_answers(@poll_all_users, @poll_list_status) # 未答和已答的 @poll_course_groups = [] #当为学生的时候,不显示分班情况 @poll_current_user_status = 1 #当前用户的状态,为学生 poll_current_user = @poll_all_users.find_by_group_ids(current_user.id) #当前用户是否开始做问卷(提交/未提交/没做) @@ -984,7 +982,7 @@ class PollsController < ApplicationController end else @poll_all_users = @poll.get_poll_exercise_users - get_poll_answers(@poll_all_users) # 未答和已答的 + get_poll_answers(@poll_all_users, @poll_list_status) # 未答和已答的 @poll_current_user_status = 2 #当前用户非课堂成员 @poll_users_list = [] end @@ -1007,14 +1005,8 @@ class PollsController < ApplicationController search_content = params[:search] if @poll_users_list.present? && @poll_users_list.count > 0 - - if order == "student_id" - @poll_users_list = @poll_users_list.joins(user: [:user_extension]).order("user_extensions.student_id DESC") - else - @poll_users_list = @poll_users_list.order("end_at DESC") - end - #答题状态的选择 + # if choose_type.present? @poll_users_list = @poll_users_list.commit_by_status(choose_type) end @@ -1028,20 +1020,23 @@ class PollsController < ApplicationController #搜索 if search_content.present? - #搜索用户的nickname,如果存在则返回,否则继续查询用户的真实姓名或学生号 - nick_name_search = @poll_users_list.where(user_id: User.where('CONCAT(users.lastname, users.firstname) like ?',"%#{search_content}%")) - if nick_name_search.present? - @poll_users_list = nick_name_search - else - @poll_users_list = @poll_users_list.joins(user: [:user_extension]).where('user_extensions.student_id like ? OR user_extensions.student_realname like ?',"%#{search_content}%","%#{search_content}%") - end + @poll_users_list = @poll_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{search_content}%", "%#{search_content}%") + end + + poll_users_joins = @poll_users_list.joins(user: :user_extension) + + if order == "student_id" + @poll_users_list = poll_users_joins.order("user_extensions.student_id DESC") + else + @poll_users_list = poll_users_joins.order("end_at DESC") end @poll_users_size = @poll_users_list.count + # 分页 - @page = params[:page] || 1 - @limit = params[:limit] || 20 - @poll_users_list = @poll_users_list.page(@page).per(@limit) + page = params[:page] || 1 + limit = params[:limit] || 20 + @poll_users_list = @poll_users_list.page(page).per(limit) else @poll_users_list = [] @poll_users_size = 0 @@ -1103,7 +1098,7 @@ class PollsController < ApplicationController ## 判断开始答题页面的用户权限 def check_user_on_answer - poll_status = @poll.get_poll_status(current_user.id) + poll_status = @poll.get_poll_status(current_user) if @user_course_identity == Course::STUDENT && poll_status == 1 #问卷未发布,且当前用户不为老师/管理员 normal_status(-1, "未发布问卷!") elsif @user_course_identity > Course::STUDENT && (!@poll.is_public || (@poll.is_public && !@poll.unified_setting)) ##不为课堂成员,且问卷不为公开的,或问卷公开,但是不是统一设置的 @@ -1151,15 +1146,16 @@ class PollsController < ApplicationController def get_questions_count @poll_questions = @poll.poll_questions.order("question_number ASC") - @poll_questions_count = @poll_questions.count # 全部的题目数 - @poll_question_singles = @poll_questions.ques_count(1).all.count # 单选题 - @poll_question_doubles = @poll_questions.ques_count(2).all.count # 多选题 - @poll_question_mains = @poll_questions.ques_count(3).all.count #主观题 + @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 #主观题 + @poll_questions = @poll_questions&.includes(:poll_answers,:poll_votes).distinct end def check_poll_question_complete #commit_poll 的权限 poll_user_current = @poll.poll_users.find_by_group_ids(current_user.id).first - poll_status = @poll.get_poll_status(current_user.id) + poll_status = @poll.get_poll_status(current_user) if @user_course_identity < Course::STUDENT || (poll_status == 3) || (poll_user_current.present? && poll_user_current.commit_status == 1) normal_status(-1,"用户没有权限!") #老师/管理员在提交时没有权限 else @@ -1181,9 +1177,9 @@ class PollsController < ApplicationController end def check_poll_commit_result - poll_status = @poll.get_poll_status(current_user.id) + poll_status = @poll.get_poll_status(current_user) commit_poll_user = @poll.poll_users.find_by_group_ids(current_user.id).commit_by_status(1) #当前用户已提交问卷的 - unless @user_course_identity < Course::STUDENT || (@poll.show_result && poll_status == 3 && commit_poll_user.present?) + unless (@user_course_identity < Course::STUDENT) || ((@poll.show_result == 1) && (poll_status == 3) && commit_poll_user.present?) normal_status(-1,"没有权限!") #当前为老师/问卷公开统计,且问卷已截止,且用户有过回答的 end end @@ -1213,17 +1209,12 @@ class PollsController < ApplicationController def get_user_permission_course(poll_ids,status) #获取用户权限范围内的已发布/未发布 poll_status = status.to_i unpublish_group = [] - g_course_ids = @course.teacher_course_groups.get_user_groups(current_user.id).pluck(:course_group_id).reject(&:blank?).uniq - if g_course_ids.blank? || g_course_ids.include?(0) #当前用户的分班权限为空,即具体全部的分班权限 - user_groups_id = @course.course_groups.pluck(:id) - else - user_groups_id = g_course_ids - end + user_groups_id = @course.charge_group_ids(current_user) all_polls = Poll.where(id:poll_ids) all_polls.each do |poll| if poll.present? if poll.unified_setting - poll_user_status = poll.get_poll_status(current_user.id) #当前用户的能看到的试卷 + poll_user_status = poll.get_poll_status(current_user) #当前用户的能看到的试卷 if poll_user_status == poll_status || poll_status == 3 #未发布的情况 unpublish_group = unpublish_group + user_groups_id else @@ -1282,8 +1273,6 @@ class PollsController < ApplicationController else normal_status(-1,"请选择分班!") end - # elsif (@poll.poll_status != 1) && (params[:publish_time].to_time != @poll.publish_time) && (@user_course_identity > Course::CREATOR) - # normal_status(-1,"已发布/已截止的不能修发布时间!") #课堂管理员和超级管理员才有权限 end end @@ -1297,4 +1286,99 @@ class PollsController < ApplicationController end end + #问卷的统计结果的导出 + def poll_commit_result(poll,poll_questions,poll_users,poll_commit_ids) + sub_commit = [] + user_commit = [] + poll_users_info = %w(序号) + poll_ques_titles = poll_questions.pluck(:question_title).map {|k| ActionController::Base.helpers.strip_tags(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 = (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_sub_commit = { + sub_title: sheet_row, + sub_user_votes:[sheet_answer_row,sheet_answer_percent,sheet_answer_useful] + } + sub_commit.push(sheet_sub_commit) + else #主观题答案 + user_votes= [] + 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 : "--"] + user_votes.push(q_poll_vote) + end + sheet_sub_commit = { + sub_title: main_show_row, + sub_user_votes:user_votes + } + sub_commit.push(sheet_sub_commit) + end + + end #each_with_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| + 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 + user_commit.push(all_user_cell) + end + + { + poll_users_info:poll_users_info, + sub_commit:sub_commit, + user_commit:user_commit + } + end + end diff --git a/app/controllers/praise_tread_controller.rb b/app/controllers/praise_tread_controller.rb index bf814db77..459eb4bad 100644 --- a/app/controllers/praise_tread_controller.rb +++ b/app/controllers/praise_tread_controller.rb @@ -1,6 +1,6 @@ class PraiseTreadController < ApplicationController include MessagesHelper - before_action :require_login + before_action :require_login, :check_auth before_action :validate_params, only: [:like, :unlike] before_action :find_object diff --git a/app/controllers/question_banks_controller.rb b/app/controllers/question_banks_controller.rb index f814822e8..e30065d09 100644 --- a/app/controllers/question_banks_controller.rb +++ b/app/controllers/question_banks_controller.rb @@ -1,5 +1,5 @@ class QuestionBanksController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :params_filter # 题库选用列表 @@ -178,6 +178,7 @@ class QuestionBanksController < ApplicationController :question_type => q.question_type || 1, :question_number => q.question_number, :question_score => q.question_score, + :shixun_name => q.shixun_name, :shixun_id => q.shixun_id } exercise_question = new_exercise.exercise_questions.new option @@ -240,8 +241,9 @@ class QuestionBanksController < ApplicationController ActiveRecord::Base.transaction do new_task = GraduationTask.new new_task.attributes = task.attributes.dup.except("id", "course_id", "user_id", "quotes", "graduation_task_id", - "course_list_id") + "course_list_id", "gtask_bank_id", "created_at", "updated_at") new_task.course_id = course.id + new_task.gtask_bank_id = task.id new_task.user_id = current_user.id if new_task.save! new_task.create_work_list @@ -264,9 +266,12 @@ class QuestionBanksController < ApplicationController def quote_gtopic_bank topic, course ActiveRecord::Base.transaction do new_topic = GraduationTopic.new - new_topic.attributes = topic.attributes.dup.except("id", "course_id", "user_id", "graduation_topic_id", "course_list_id") + new_topic.attributes = topic.attributes.dup.except("id", "course_id", "user_id", "graduation_topic_id", "quotes", + "course_list_id", "gtopic_bank_id", "created_at", "updated_at") new_topic.course_id = course.id + new_topic.gtopic_bank_id = topic.id new_topic.user_id = current_user.id + new_topic.tea_id = current_user.id new_topic.save topic.attachments.each.try(:each) do |attachment| diff --git a/app/controllers/repertoires_controller.rb b/app/controllers/repertoires_controller.rb new file mode 100644 index 000000000..0ac78a15b --- /dev/null +++ b/app/controllers/repertoires_controller.rb @@ -0,0 +1,5 @@ +class RepertoiresController < ApplicationController + def index + render_ok(repertoires: Repertoire.cache_data) + end +end \ No newline at end of file diff --git a/app/controllers/schools_controller.rb b/app/controllers/schools_controller.rb index 1551091aa..ea94f4c69 100644 --- a/app/controllers/schools_controller.rb +++ b/app/controllers/schools_controller.rb @@ -1,8 +1,16 @@ class SchoolsController < ApplicationController + def school_list + schools = School.all + search = params[:search].to_s.strip + if search.present? + schools = schools.where('name Like ?', "%#{search}%") + end - def school_list - q = params[:search] ? params[:search].strip : "" - @schools = School.where("name like ?", "%#{q}%").pluck(:name) + render_ok(school_names: schools.pluck(:name)) + end + + def for_option + render_ok(schools: School.cached_names_data) end end diff --git a/app/controllers/searchs_controller.rb b/app/controllers/searchs_controller.rb new file mode 100644 index 000000000..1ea1c5d05 --- /dev/null +++ b/app/controllers/searchs_controller.rb @@ -0,0 +1,10 @@ +class SearchsController < ApplicationController + def index + @results = SearchService.call(search_params) + end + + private + def search_params + params.permit(:keyword, :type, :page, :per_page) + end +end \ No newline at end of file diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb index 00ae559b1..be4448a92 100644 --- a/app/controllers/shixuns_controller.rb +++ b/app/controllers/shixuns_controller.rb @@ -1,9 +1,13 @@ class ShixunsController < ApplicationController - before_action :require_login, except: [:download_file, :index] - # before_action :check_auth, except: [:download_file, :index] + include ShixunsHelper + include ApplicationHelper - before_action :find_shixun, except: [:index, :new, :create, :menus, :get_recommend_shixuns, :propaedeutics, - :departments, :apply_shixun_mirror, :get_mirror_script, :download_file] + before_action :require_login, :check_auth, except: [:download_file, :index, :menus] + before_action :check_auth, except: [:download_file, :index, :menus] + + before_action :find_shixun, :shixun_access_allowed, except: [:index, :new, :create, :menus, :get_recommend_shixuns, + :propaedeutics, :departments, :apply_shixun_mirror, + :get_mirror_script, :download_file] before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy] before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish, @@ -13,14 +17,12 @@ class ShixunsController < ApplicationController before_action :special_allowed, only: [:send_to_course, :search_user_courses] - include ShixunsHelper - include ApplicationHelper - ## 获取课程列表 def index ## 我的实训 @shixuns = if params[:order_by] == 'mine' + tip_exception(401, "..") unless current_user.logged? current_user.my_shixuns else Shixun.unhidden @@ -43,11 +45,12 @@ class ShixunsController < ApplicationController ## 搜索关键字 匹配关卡名, 用户名, 实训名 和 空格多搜索 if params[:keyword].present? keyword = params[:keyword].strip - @shixuns = @shixuns.joins(:users, challenges: :challenge_tags). - where("challenge_tags.name like '%#{keyword}%' - or challenges.subject like '%#{keyword}%' - or concat(lastname, firstname) like '%#{keyword}%' - or shixuns.name like '%#{keyword.split(" ").join("%")}%'") + @shixuns = @shixuns.joins(:user, challenges: :challenge_tags). + where("challenge_tags.name like :keyword + or challenges.subject like :keyword + or concat(lastname, firstname) like :keyword + or shixuns.name like :name", + keyword: "%#{keyword}%", name: "%#{keyword.split(" ").join("%")}%").distinct end ## 筛选 状态 @@ -57,7 +60,7 @@ class ShixunsController < ApplicationController end ## 筛选 难度 - if params[:diff].present? && params[:diff].to_i != 0 + if params[:diff].present? && params[:diff].to_i != 0 @shixuns = @shixuns.where(trainee: params[:diff]) end @@ -67,21 +70,27 @@ class ShixunsController < ApplicationController when 'new' @shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.created_at #{bsort}") when 'hot' - @shixuns = @shixuns.order("shixuns.status = 2 desc, myshixuns_count #{bsort}") + @shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.myshixuns_count #{bsort}") when 'mine' @shixuns = @shixuns.order("shixuns.created_at #{bsort}") else - @shixuns = @shixuns.order("shixuns.status = 2 desc, publish_time #{bsort}") + @shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.publish_time #{bsort}") end - - @total_count = @shixuns.count + # 用id计数会快10+MS左右,对于搜索的内容随着数据的增加,性能会提升一些。 + @total_count = @shixuns.count("shixuns.id") ## 分页参数 page = params[:page] || 1 limit = params[:limit] || 16 @shixuns = @shixuns.includes(:tag_repertoires, :challenges).page(page).per(limit) + + @tag_name_map = TagRepertoire.joins(:shixun_tag_repertoires) + .where(shixun_tag_repertoires: { shixun_id: @shixuns.map(&:id) }) + .group('shixun_tag_repertoires.shixun_id') + .select('shixun_id, tag_repertoires.name') + .each_with_object({}) { |r, obj| obj[r.shixun_id] = r.name } end ## 获取顶部菜单 @@ -115,8 +124,8 @@ class ShixunsController < ApplicationController def show_right owner = @shixun.owner - #@fans_count = owner.followers.count - #@followed_count = owner.followed_users.count + #@fans_count = owner.fan_count + #@followed_count = owner.follow_count @user_own_shixuns = owner.shixuns.published.count end @@ -127,7 +136,7 @@ class ShixunsController < ApplicationController select m.user_id, u.login, u.lastname, m.updated_at, (select sum(cost_time) from games g where g.myshixun_id = m.id) as time, (select sum(final_score) from games g where g.myshixun_id = m.id) as score - from (myshixuns m join users u on m.user_id = u.id) where m.shixun_id = #{@shixun.id} and m.status = 1 + from (users u left join myshixuns m on m.user_id = u.id) where m.shixun_id = #{@shixun.id} and m.status = 1 order by score desc, time asc limit 10 " @myshixuns = Myshixun.find_by_sql(sql) @@ -178,6 +187,17 @@ class ShixunsController < ApplicationController ShixunTagRepertoire.create!(:tag_repertoire_id => str.tag_repertoire_id, :shixun_id => @new_shixun.id) end + # 同步配置 + logger.info("########-shixun_service_configs_count: #{@shixun.shixun_service_configs.pluck(:id, :shixun_id)}") + @shixun.shixun_service_configs.each do |config| + ShixunServiceConfig.create!(:shixun_id => @new_shixun.id, + :cpu_limit => config.cpu_limit, + :lower_cpu_limit => config.lower_cpu_limit, + :memory_limit => config.memory_limit, + :request_limit => config.request_limit, + :mirror_repository_id => config.mirror_repository_id) + end + # fork版本库 logger.info("###########fork_repo_path: ######{@repo_path}") project_fork(@new_shixun, @repo_path, current_user.login) @@ -192,6 +212,13 @@ class ShixunsController < ApplicationController new_challenge.user_id = User.current.id new_challenge.shixun_id = @new_shixun.id new_challenge.save! + # 同步参考答案 + challenge.challenge_answers.each do |answer| + new_answer = ChallengeAnswer.new + new_answer.attributes = answer.attributes.dup.except("id","challenge_id") + new_answer.challenge_id = new_challenge.id + new_answer.save! + end if challenge.st == 0 # 评测题 # 同步测试集 if challenge.test_sets.present? @@ -269,7 +296,6 @@ class ShixunsController < ApplicationController @small_type = shixun_small_type end - # 注意这里传参都应该使用params[:shixun]['name']这种格式 def create # 评测脚本的一些操作 main_type, sub_type = params[:main_type], params[:small_type] @@ -314,9 +340,13 @@ class ShixunsController < ApplicationController # 镜像-实训关联表 ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if main_type.present? + # 实训主镜像服务配置 + ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if sub_type.present? sub_type.each do |mirror| ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) + # 实训子镜像服务配置 + ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) end end @@ -362,11 +392,6 @@ class ShixunsController < ApplicationController end def update - h = {test_set_permission: params[:test_set_permission], code_hidden: params[:code_hidden], - task_pass: params[:task_pass], hide_code: params[:hide_code], forbid_copy: params[:forbid_copy]} - - s_params = shixun_params.merge(h) - ActiveRecord::Base.transaction do begin @shixun.shixun_mirror_repositories.destroy_all @@ -378,9 +403,8 @@ class ShixunsController < ApplicationController ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror) end end - - @shixun.update_attributes(s_params) - @shixun.shixun_info.update_attributes(description: params[:description], evaluate_script: params[:evaluate_script]) + @shixun.update_attributes(shixun_params) + @shixun.shixun_info.update_attributes(shixun_info_params) @shixun.shixun_schools.delete_all if params[:scope_partment].present? && params[:user_scope].to_i == 1 arr = [] @@ -394,6 +418,11 @@ class ShixunsController < ApplicationController use_scope = 0 end @shixun.update_attributes!(:use_scope => use_scope) + # 超级管理员和运营人员才能保存 中间层服务器pod信息的配置 + if current_user.admin? || current_user.business? + @shixun.shixun_service_configs.destroy_all + @shixun.shixun_service_configs.create!(service_config_params[:shixun_service_configs]) + end rescue Exception => e uid_logger_error(e.message) tip_exception("实训保存失败") @@ -409,12 +438,12 @@ class ShixunsController < ApplicationController end def propaedeutics - @content = Shixun.where(identifier: params[:identifier]).pluck(:propaedeutics) + @content = Shixun.find_by_identifier!(params[:identifier]).propaedeutics end # 更新背景知识 def update_propaedeutics - @shixun.update_column(:propaedeutics, params[:content]) + @shixun.shixun_info.update_column(:propaedeutics, params[:content]) end # 获取推荐实训接口 2个热门实训 + 2个最新实训 @@ -429,6 +458,7 @@ class ShixunsController < ApplicationController @choice_small_type = @shixun.small_mirror_id @main_type = shixun_main_type @small_type = shixun_small_type + @configs = @shixun.shixun_service_configs #@mirror_script = MirrorScript.select([:id, :script_type]).find(@shixun.mirror_script_id).attributes if @shixun.mirror_script_id && @shixun.mirror_script_id != 0 # @shixun_main_mirror = @shixun.show_shixun_mirror # @script_type = @shixun.script_tag.try(:script_type) || "无" @@ -472,8 +502,8 @@ class ShixunsController < ApplicationController # TODO: 目前实训只做软删除. def destroy - # apply_records = ApplyAction.where(container_id: @shixun.id, container_type: "ApplyShixun") - # apply_records.delete_all if apply_records + apply_records = ApplyAction.where(container_id: @shixun.id, container_type: "ApplyShixun") + apply_records.delete_all if apply_records # HomeworkCommonShixuns.where(shixun_id: @shixun).delete_all # @shixun.destroy @shixun.update_column(:status, -1) @@ -484,21 +514,46 @@ class ShixunsController < ApplicationController # 中间需要一个过渡动画 # TODO: 第一次开启实训都会去判断是否是纯选择题类型,感觉做成在创建关卡的时候就判断该实训是否是纯选择题更加合适 def shixun_exec - current_myshixun = @shixun.current_myshixun(current_user.id) - - if @shixun.opening_time.present? && @shixun.opening_time > Time.now && current_user.shixun_identity(@shixun) > User::EDU_SHIXUN_MEMBER + if is_shixun_opening? tip_show_exception(-3, "#{@shixun.opening_time.strftime('%Y-%m-%d %H:%M:%S')}") end + current_myshixun = @shixun.current_myshixun(current_user.id) + + min_challenges = @shixun.challenges.pluck(:id , :st) - if current_myshixun - # 如果TPM和TPI的管卡数不相等或者关卡顺序错了,说明实训被极大的改动,需要重置 - if current_myshixun.games.count != @shixun.challenges_count || current_myshixun.games.map(&:challenge_id).sort != Challenge.where(shixun_id: @shixun.id).pluck(:id).sort + Rails.logger.info("11111111112#{current_myshixun.try(:id)}") + Rails.logger.info("111111111102#{params[:reset] != 1}") + + # 因为读写分离有延迟,所以如果是重置来的请求可以先跳过,重置过来的params[:reset]为1 + if current_myshixun && params[:reset] != "1" + games = current_myshixun.games + # 如果TPM和TPI的管卡数不相等或者关卡顺序错了,说明实训被极大的改动,需要重置,实训发布前打过的实训都需要重置 + if is_shixun_reset?(games, min_challenges, current_myshixun) # 这里页面弹框要收到 当前用户myshixun的identifier. tip_show_exception("/myshixuns/#{current_myshixun.try(:identifier)}/reset_my_game") end + + if current_myshixun.repo_name.nil? + g = Gitlab.client + repo_name = g.project(current_myshixun.gpid).try(:path_with_namespace) + current_myshixun.update_column(:repo_name, repo_name) + end + + # 如果存在实训,则直接进入实训 - @current_task = current_myshixun.current_task + # 如果实训允许跳关,传参params[:challenge_id]跳入具体的关卡 + @current_task = + if params[:challenge_id] + game = games.where(challenge_id: params[:challenge_id]).take + if @shixun.task_pass || game.status != 3 + game + else + current_myshixun.current_task(games) + end + else + current_myshixun.current_task(games) + end else # 如果未创建关卡一定不能开启实训,否则TPI没法找到当前的关卡 if @shixun.challenges_count == 0 @@ -506,10 +561,10 @@ class ShixunsController < ApplicationController end # 判断实训是否全为选择题 - is_choice_type = @shixun.is_choice_type? + is_choice_type = (min_challenges.size == min_challenges.select{|challenge| challenge.last == 1}.count) if !is_choice_type commit = GitService.commits(repo_path: @repo_path).try(:first) - Rails.logger.info("First comit########{commit}") + uid_logger("First comit########{commit}") tip_exception("开启实战前请先在版本库中提交代码") if commit.blank? commit_id = commit["id"] end @@ -523,6 +578,21 @@ class ShixunsController < ApplicationController onclick_time: Time.now, commit_id: commit_id) uid_logger("myshixun_id is #{myshixun.id}") + + # 其它创建关卡等操作 + challenges = @shixun.challenges + # 之所以增加user_id是为了方便统计查询性能 + game_attrs = %i[challenge_id myshixun_id status user_id open_time identifier modify_time created_at updated_at] + Game.bulk_insert(*game_attrs) do |worker| + base_attr = { myshixun_id: myshixun.id, user_id: myshixun.user_id } + challenges.each_with_index do |challenge, index| + status = (index == 0 ? 0 : 3) + game_identifier = generate_identifier(Game, 12) + worker.add(base_attr.merge(challenge_id: challenge.id, status: status, open_time: Time.now, + identifier: game_identifier, modify_time: challenge.modify_time)) + end + end + # 如果实训是纯选择题,则不需要去fork仓库以及中间层的相关操作了 unless is_choice_type # fork仓库 @@ -534,22 +604,10 @@ class ShixunsController < ApplicationController logger.info("end openGameInstance") params = {tpiID: "#{myshixun.id}", tpmGitURL:rep_url, tpiRepoName: myshixun.repo_name.split("/").last} uid_logger("openGameInstance params is #{params}") - # res = interface_post uri, params, 83, "实训云平台繁忙(繁忙等级:83)" - end - # 其它创建关卡等操作 - challenges = @shixun.challenges - # 之所以增加user_id是为了方便统计查询性能 - challenges.each_with_index do |challenge, index| - status = (index == 0 ? 0 : 3) - game_identifier = generate_identifier(Game, 12) - Game.create!(:challenge_id => challenge.id, :myshixun_id => myshixun.id, :status => status, :user_id => myshixun.user_id, - :open_time => Time.now, :identifier => game_identifier, :modify_time => challenge.modify_time) + interface_post uri, params, 83, "实训云平台繁忙(繁忙等级:83)" end - # REDO:开启实训时更新关联作品的状态 - HomeworksService.new.update_myshixun_work_status myshixun - - @current_task = myshixun.current_task + @current_task = myshixun.current_task(myshixun.games) uid_logger("## shixun exec: myshixun id is #{myshixun.id}") rescue Exception => e uid_logger_error(e.message) @@ -558,10 +616,8 @@ class ShixunsController < ApplicationController end end end - - - end + # gameID 及实训ID # status: 0 , 1 申请过, 2,实训关卡路径未填, 3 实训标签未填, 4 实训未创建关卡 def publish @@ -611,16 +667,27 @@ class ShixunsController < ApplicationController def update_file content = params[:content] author_name = current_user.full_name - author_email = current_user.mail + author_email = current_user.git_mail @content = update_file_content content, @repo_path, @path, author_email, author_name, "Edit by browser" end def add_collaborators - raise("搜索内容不能为空") unless params[:search] - member_ids = "(" + @shixun.shixun_members.map(&:user_id).join(',') + ")" - condition = "%#{params[:search].strip}%".gsub(" ","") - @users = User.where("id not in #{member_ids} and status = 1 and LOWER(concat(lastname, firstname, login, mail, nickname)) LIKE '#{condition}'") - end + member_ids = "(" + @shixun.shixun_members.map(&:user_id).join(',') + ")" + user_name = "%#{params[:user_name].to_s.strip}%" + school_name = "%#{params[:school_name].to_s.strip}%" + if user_name.present? || school_name.present? + @users = User.joins(user_extension: :school).where("users.id not in #{member_ids} AND users.status = 1 AND + (LOWER(users.lastname) LIKE ? or users.phone like ?) AND LOWER(schools.name) LIKE + ?", user_name, user_name, school_name) + else + @users = User.none + end + page = params[:page] || 1 + limit = params[:limit] || 20 + @user_count = @users.count + @users = @users.page(page).per(limit) + + end def shixun_members_added raise("user_ids 不能为空!") if params[:user_ids].blank? @@ -661,14 +728,14 @@ class ShixunsController < ApplicationController limit = params[:limit] || 20 if params[:search] search = "%#{params[:search].to_s.strip.downcase}%" - course_ids = Course.find_by_sql("SELECT c.id FROM courses c, members m, member_roles mr - WHERE m.course_id = c.id AND m.id=mr.member_id AND mr.role_id in (3,7,9) + course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m + WHERE m.course_id = c.id AND m.role in (1,2,3) AND m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0 AND c.name like '#{search}' ").map(&:id) else - course_ids = Course.find_by_sql("SELECT c.id, c.name FROM courses c, members m, member_roles mr - WHERE m.course_id = c.id AND m.id=mr.member_id AND mr.role_id in (3,7,9) + course_ids = Course.find_by_sql("SELECT c.id, c.name FROM courses c, course_members m + WHERE m.course_id = c.id AND m.role in (1,2,3) AND m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0").map(&:id) end @@ -680,7 +747,7 @@ class ShixunsController < ApplicationController # 将实训发送到课程 def send_to_course @course = Course.find(params[:course_id]) - homework = HomeworksService.new.create_homework shixun, @course, nil, current_user + homework = HomeworksService.new.create_homework @shixun, @course, nil, current_user end # 二维码扫描下载 @@ -693,32 +760,40 @@ class ShixunsController < ApplicationController # 撤销发布 def cancel_publish + tip_exception("实训已经发布,无法撤销") if @shixun.status == 2 apply = ApplyAction.where(:container_type => "ApplyShixun", :container_id => @shixun.id).order("created_at desc").first if apply && apply.status == 0 apply.update_attribute(:status, 3) apply.tidings.destroy_all - @shixun.update_column('status', 0) end + @shixun.update_column(:status, 0) end private def shixun_params - raise("实训名称不能为空") if params[:name].blank? + raise("实训名称不能为空") if params[:shixun][:name].blank? params.require(:shixun).permit(:name, :trainee, :webssh, :can_copy, :use_scope, :vnc, :test_set_permission, - :task_pass, :repo_name, :multi_webssh, :opening_time, :mirror_script_id) + :task_pass, :multi_webssh, :opening_time, :mirror_script_id, :code_hidden, + :hide_code, :forbid_copy) + end + + def shixun_info_params + raise("实训描述不能为空") if params[:shixun_info][:description].blank? + raise("评测脚本不能为空") if params[:shixun_info][:evaluate_script].blank? + params.require(:shixun_info).permit(:description, :evaluate_script) + end + + + def service_config_params + params.permit(shixun_service_configs: [:cpu_limit, :lower_cpu_limit, :memory_limit, :request_limit, :mirror_repository_id]) end def find_shixun @shixun = Shixun.find_by_identifier(params[:identifier]) - shixun = Shixun.where(identifier: params[:identifier]).first if @shixun.blank? normal_status(404, "...") return end - - if !current_user.shixun_permission(@shixun) || (@shixun.status == -1 && !current_user.admin?) - tip_exception(403, "..") - end end def find_repo_name @@ -743,4 +818,20 @@ private tip_exception(403, "..") end end + + # 实训是否需要开启 + def is_shixun_opening? + @shixun.opening_time.present? && + @shixun.opening_time > Time.now && + current_user.shixun_identity(@shixun) > User::EDU_SHIXUN_MEMBER + end + + # 实训是否需要重置 + def is_shixun_reset?(games, min_challenges, current_myshixun) + # 用户在申请发布之前,是否玩过实训 TODO: 重置的字段应该迁移到myshixuns表比较合适 + modify_shixun = ShixunModify.exists?(:myshixun_id => current_myshixun.id, :shixun_id => @shixun.id, :status => 1) + games.size != min_challenges.size || + games.map(&:challenge_id) != min_challenges.map{|challenge| challenge.first} || + modify_shixun + end end diff --git a/app/controllers/stages_controller.rb b/app/controllers/stages_controller.rb index 3d0087981..c62832365 100644 --- a/app/controllers/stages_controller.rb +++ b/app/controllers/stages_controller.rb @@ -1,5 +1,5 @@ class StagesController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :find_subject, only: [:create, :index] before_action :find_stage, only: [:update, :destroy, :edit, :up_position, :down_position] before_action :allowed, except: [:index] diff --git a/app/controllers/student_works_controller.rb b/app/controllers/student_works_controller.rb index 46e87e632..d12913852 100644 --- a/app/controllers/student_works_controller.rb +++ b/app/controllers/student_works_controller.rb @@ -2,7 +2,7 @@ class StudentWorksController < ApplicationController include HomeworkCommonsHelper include StudentWorksHelper - before_action :require_login + before_action :require_login, :check_auth before_action :find_homework, only: [:new, :create, :search_member_list, :check_project, :relate_project, :cancel_relate_project] before_action :find_work, only: [:shixun_work_report, :adjust_review_score, :shixun_work, :commit_des, :update_des, @@ -25,7 +25,7 @@ class StudentWorksController < ApplicationController before_action :require_score_id, only: [:destroy_score, :add_score_reply, :appeal_anonymous_score, :deal_appeal_score, :cancel_appeal] - before_action :is_evaluation, only: [:show, :supply_attachments] + before_action :is_evaluation, :open_work, only: [:show, :supply_attachments] def new uid_logger("#######new current_user : 1111") @@ -41,14 +41,16 @@ class StudentWorksController < ApplicationController # 搜索课堂学生 def search_member_list - unless params[:search].blank? - @members = @course.students.joins(:user).where("user_id != #{current_user.id} and - concat(users.lastname, users.firstname) like ?", "%#{params[:search]}%") + # 统一设置的作业取所有学生,否则取已发布的分班学生 + students = @homework.unified_setting? ? @course.students : @course.students.where(course_group_id: @homework.published_settings.pluck(:course_group_id)) + if !params[:search].blank? + @members = students.joins(user: :user_extension).where("course_members.user_id != #{current_user.id} and (concat(users.lastname, users.firstname) + like ? or user_extensions.student_id like ?)", "%#{params[:search]}%", "%#{params[:search]}%") else # 没有搜索条件时搜索课堂所有未提交的学生 user_ids = @homework.student_works.where("work_status = 0").pluck(:user_id) - [current_user.id] - @members = @course.students.where(user_id: user_ids) + @members = students.where(user_id: user_ids) end page = params[:page] ? params[:page].to_i : 1 @@ -332,8 +334,9 @@ class StudentWorksController < ApplicationController ActiveRecord::Base.transaction do begin # 没传score则取上次评分成绩 - score = StudentWorksScore.where(user_id: current_user.id, student_work_id: @work.id).last + reviewer_role = @user_course_identity == Course::STUDENT ? 3 : @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1 new_score = StudentWorksScore.new + score = StudentWorksScore.where(user_id: current_user.id, student_work_id: @work.id, reviewer_role: reviewer_role).last new_score.score = params[:score].blank? ? score.try(:score) : params[:score].to_f new_score.comment = params[:comment] if params[:comment] && params[:comment].strip != "" new_score.user_id = current_user.id @@ -346,7 +349,7 @@ class StudentWorksController < ApplicationController @work.update_attributes(group_id: @homework.max_group_id) if @homework.homework_type == "group" end - new_score.reviewer_role = @user_course_identity == Course::STUDENT ? 3 : @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1 + new_score.reviewer_role = reviewer_role if new_score.save! Attachment.associate_container(params[:attachment_ids], new_score.id, new_score.class) @@ -379,7 +382,7 @@ class StudentWorksController < ApplicationController when 3 #学生评分 学生评分显示平均分 # 匿评分 @work.student_score = new_score.stu_score(@work.id) - if @homework.homework_type == "group" && params[:same_score] && new_score.score.present? + if @homework.homework_type == "group" && new_score.score.present? add_score_to_member @work, @homework, new_score end @@ -427,10 +430,17 @@ class StudentWorksController < ApplicationController def shixun_work_report @user = @work.user @shixun = @homework.shixuns.take - @games = @work.myshixun.games.includes(:challenge, :game_codes,:outputs) if @work.myshixun + # 提示: 这里如果includes outputs表的话: sum(:evaluate_count)会出现错误 + @games = @work.myshixun.games.joins(:challenge).reorder("challenges.position asc") if @work.myshixun # 用户最大评测次数 - @user_evaluate_count = @games.inject(0){|sum, g| sum + g.outputs.pluck(:query_index).first.to_i } if @games + if @games + @user_evaluate_count = @games.pluck(:evaluate_count).sum + @games = @games.includes(:challenge, :game_codes, :outputs) + else + @user_evaluate_count = 0 + end + # 图形效率图的数据 @echart_data = student_efficiency(@homework, @work) end @@ -438,17 +448,17 @@ class StudentWorksController < ApplicationController def export_shixun_work_report @user = @work.user @shixun = @homework.shixuns.take - @games = @work.myshixun.games.includes(:challenge, :game_codes,:outputs) if @work.myshixun + @games = @work.myshixun.games.includes(:challenge, :game_codes, :outputs) if @work.myshixun # 用户最大评测次数 - @user_evaluate_count = @games.inject(0){|sum, g| sum + g.outputs.pluck(:query_index).first.to_i } if @games + @user_evaluate_count = @games.pluck(:evaluate_count).sum if @games # 图形效率图的数据 @echart_data = student_efficiency(@homework, @work) @myself_eff = @echart_data[:efficiency_list].find { |item| item.last == @user.id } @myself_consume = @echart_data[:consume_list].find { |item| item.last == @user.id } - # filename = "实训报告_#{@shixun.name}_#{@use.real_name}_#{Time.current.strftime('%Y%m%d%H%M%S')}.pdf" #下载报错 unknown nil name,下面为修改的-hs-0606 - filename = "实训报告_#{@shixun&.name}_#{@use&.real_name}_#{Time.current.strftime('%Y%m%d%H%M%S')}.pdf" + filename_ = "实训报告_#{@shixun&.name}_#{@use&.real_name}" + filename = Base64.urlsafe_encode64(filename_.strip.first(30)) stylesheets = %w(shixun_work/shixun_work.css shared/codemirror.css) render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets end @@ -580,6 +590,9 @@ class StudentWorksController < ApplicationController score_appeal.tidings.update_all(status: 1) if params[:status].to_i == 3 + # 申诉成功后该评分失效 + score.update_attributes(is_invalid: 1) + # 申诉成功后 扣匿评学生的违规匿评扣分 sw = @homework.student_works.find_by(user_id: score.user_id) sw.update_attribute("appeal_penalty", @homework.homework_detail_manual.appeal_penalty + sw.appeal_penalty) if sw.present? @@ -618,16 +631,35 @@ class StudentWorksController < ApplicationController # 查重作品调分 def adjust_review_score - if params[:score].nil? || params[:challenge_id].nil? || params[:code_rate].nil? || params[:copy_user_id].nil? + tip_exception("缺少type参数") if params[:type].blank? || !["review", "report"].include?(params[:type]) + if params[:type] == "review" && (params[:score].nil? || params[:challenge_id].nil? || params[:code_rate].nil? || params[:copy_user_id].nil?) tip_exception("参数错误,score和challenge_id和code_rate和copy_user_id不能为空") + elsif params[:type] == "report" && (params[:score].nil? || params[:challenge_id].nil?) + tip_exception("参数错误,score和challenge_id") + end + challenge_setting = @homework.homework_challenge_settings.find_by(challenge_id: params[:challenge_id]) + challenge = challenge_setting&.challenge + tip_exception("不能小于零") if params[:score] < 0 + tip_exception("不能大于关卡分值:#{challenge_setting.score}分") if challenge_setting.score < params[:score] + + ActiveRecord::Base.transaction do + begin + if params[:type] == "review" + copy_user = User.find params[:copy_user_id] + comment = "代码查重结果显示与#{copy_user.try(:show_real_name)}的代码相似度#{params[:code_rate]}%" + else + comment = "根据实训报告中最终提交的代码调整第#{challenge.position}关分数" + end + challenge_score = @work.challenge_work_scores.create(challenge_id: params[:challenge_id], user_id: current_user.id, score: params[:score], + comment: comment) + challenge_score.create_tiding current_user.id + HomeworksService.new.update_myshixun_work_score @work, @work&.myshixun, @work&.myshixun&.games, @homework, @homework.homework_challenge_settings + rescue Exception => e + uid_logger(e.message) + tip_exception(e.message) + raise ActiveRecord::Rollback + end end - copy_user = User.find params[:copy_user_id] - comment = "代码查重结果显示与#{copy_user.try(:show_real_name)}的代码相似度#{params[:code_rate]}%" - @work.challenge_work_scores.create(challenge_id: params[:challenge_id], user_id: current_user.id, score: params[:score], - comment: comment) - HomeworksService.new.set_shixun_final_score(@work) - @work_score = @homework.student_works.find_by(id: @work.id).try(:work_score) - end @@ -692,6 +724,11 @@ class StudentWorksController < ApplicationController [3, 4].include?(@homework.homework_detail_manual.comment_status) end + # 作品是否公开 + def open_work + tip_exception(403,"没有操作权限") unless (@user_course_identity < Course::STUDENT || current_user == @work.user || @homework.work_public || @is_evaluation) + end + def allow_add_score # 老师始终有评阅权限,匿评阶段内,学生对分配给该学生的作品有评阅权限 tip_exception(403, "没有权限") unless allow_score(@homework, @user_course_identity, current_user.id, @work) @@ -713,19 +750,19 @@ class StudentWorksController < ApplicationController student_works.each do |st_work| st_score = StudentWorksScore.new(user_id: new_score.user_id, score: new_score.score, reviewer_role: new_score.reviewer_role, comment: new_score.comment) - st_work.student_works_scores << st_score - score = StudentWorksScore.where(user_id: new_score.user_id, student_work_id: st_work.id).last + score = StudentWorksScore.where(user_id: new_score.user_id, student_work_id: st_work.id, reviewer_role: new_score.reviewer_role).last # 该用户的历史评阅无效 score.update_column('is_invalid', true) if score.present? && score.score.present? + st_work.student_works_scores << st_score if new_score.reviewer_role == 1 - st_work.teacher_score = new_score.score + st_work.teacher_score = new_score.score if new_score.score.present? elsif new_score.reviewer_role == 2 if homework.homework_detail_manual.ta_mode == 1 st_work.teaching_asistant_score = new_score.ta_score st_work.id else - st_work.teaching_asistant_score = new_score.score + st_work.teaching_asistant_score = new_score.score if new_score.score.present? end else st_work.student_score = student_work.student_score diff --git a/app/controllers/subjects_controller.rb b/app/controllers/subjects_controller.rb index 4b954584b..4d256f3dc 100644 --- a/app/controllers/subjects_controller.rb +++ b/app/controllers/subjects_controller.rb @@ -1,5 +1,5 @@ class SubjectsController < ApplicationController - before_action :require_login, except: [:index] + before_action :require_login, :check_auth, except: [:index] # before_action :check_auth, except: [:index] before_action :find_subject, except: [:index, :create, :append_to_stage] before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish, @@ -22,21 +22,23 @@ class SubjectsController < ApplicationController # 最热排序 if reorder == "myshixun_count" if select - @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, - subjects.shixuns_count, COUNT(myshixuns.id) AS myshixun_member_count FROM myshixuns, stage_shixuns, subjects - WHERE myshixuns.shixun_id = stage_shixuns.shixun_id AND stage_shixuns.subject_id = subjects.id - AND `subjects`.`hidden` = 0 AND `subjects`.`status` = 2 AND `subjects`.`name` like '%#{search}%' - AND `subjects`.`repertoire_id` = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC") + @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, + subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns + on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where + subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' + AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC") else - @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, - subjects.shixuns_count, COUNT(myshixuns.id) AS myshixun_member_count FROM myshixuns, stage_shixuns, subjects - WHERE myshixuns.shixun_id = stage_shixuns.shixun_id AND stage_shixuns.subject_id = subjects.id - AND `subjects`.`hidden` = 0 AND `subjects`.`status` = 2 AND `subjects`.`name` like '%#{search}%' - GROUP BY subjects.id ORDER BY myshixun_member_count DESC") + @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, + subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns + on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where + subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' + GROUP BY subjects.id ORDER BY myshixun_member_count DESC") end else # 我的路径 if reorder == "mine" + tip_exception(401, "..") unless current_user.logged? + mine_subject_id = StageShixun.find_by_sql("select DISTINCT(subject_id) from stage_shixuns where shixun_id in (select distinct(shixun_id) from myshixuns where user_id=#{current_user.id})").map(&:subject_id) manage_subject_id = SubjectMember.where(user_id: current_user.id).pluck(:subject_id) @@ -65,9 +67,12 @@ class SubjectsController < ApplicationController @total_count = @subjects.size if reorder != "myshixun_count" - @subjects = @subjects.page(page).per(limit).includes(:shixuns) + @subjects = @subjects.page(page).per(limit).includes(:shixuns, :repertoire) else @subjects = @subjects[offset, limit] + subject_ids = @subjects.pluck(:id) + order_ids = subject_ids.size > 0 ? subject_ids.join(',') : -1 + @subjects = Subject.where(id: subject_ids).order("field(id,#{order_ids})").includes(:shixuns, :repertoire) end end @@ -81,6 +86,9 @@ class SubjectsController < ApplicationController @tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq # 用户获取的实训标签 @user_tags = @subject.shixuns.map(&:user_tags_name).flatten.uniq + + # 访问数变更 + @subject.increment!(:visits) end def create @@ -131,7 +139,7 @@ class SubjectsController < ApplicationController if current_user.admin? @shixuns = Shixun.select([:id, :name, :status, :myshixuns_count, :identifier]).where(hidden: 0) else - none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id)}").pluck(:shixun_id) + none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id).to_i}").pluck(:shixun_id) @shixuns = Shixun.select([:id, :name, :status, :myshixuns_count, :identifier]).where.not(id: none_shixun_ids).where(hidden: 0) end @@ -164,11 +172,11 @@ class SubjectsController < ApplicationController end def choose_course - course_ids = Course.find_by_sql("SELECT c.id FROM courses c, members m, member_roles mr - WHERE m.course_id = c.id AND m.id=mr.member_id AND mr.role_id in (3,7,9) + course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m + WHERE m.course_id = c.id AND m.role in (1,2,3) AND m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0").map(&:id) @courses = Course.where(id: course_ids) - @none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id)}").pluck(:shixun_id) + @none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id).to_i}").pluck(:shixun_id) end def send_to_course diff --git a/app/controllers/trial_applies_controller.rb b/app/controllers/trial_applies_controller.rb index f8454e557..acfde75da 100644 --- a/app/controllers/trial_applies_controller.rb +++ b/app/controllers/trial_applies_controller.rb @@ -1,4 +1,5 @@ class TrialAppliesController < ApplicationController + before_action :require_user_login def create Users::ApplyTrailService.call(current_user, create_params) @@ -12,4 +13,10 @@ class TrialAppliesController < ApplicationController def create_params params.permit(:phone, :code, :reason).merge(remote_ip: request.remote_ip) end + + def require_user_login + return if User.current.logged? + + render_unauthorized + end end diff --git a/app/controllers/users/accounts_controller.rb b/app/controllers/users/accounts_controller.rb index e88ff4564..dff5115e1 100644 --- a/app/controllers/users/accounts_controller.rb +++ b/app/controllers/users/accounts_controller.rb @@ -1,4 +1,4 @@ -class Users::AccountsController < Users::BaseController +class Users::AccountsController < Users::BaseAccountController before_action :private_user_resources! def show diff --git a/app/controllers/users/auth_attachments_controller.rb b/app/controllers/users/auth_attachments_controller.rb new file mode 100644 index 000000000..98eff078f --- /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: [:create] + + def create + 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/avatars_controller.rb b/app/controllers/users/avatars_controller.rb index 6d161ba94..3b8c4be84 100644 --- a/app/controllers/users/avatars_controller.rb +++ b/app/controllers/users/avatars_controller.rb @@ -28,6 +28,6 @@ class Users::AvatarsController < Users::BaseAccountController end def avatar_url - ApplicationController.helpers.url_to_avatar(observed_user) + ApplicationController.helpers.url_to_avatar(observed_user).to_s + "?#{Time.now.to_i}" end end diff --git a/app/controllers/users/base_account_controller.rb b/app/controllers/users/base_account_controller.rb index b693eaab5..0d6bb24ec 100644 --- a/app/controllers/users/base_account_controller.rb +++ b/app/controllers/users/base_account_controller.rb @@ -4,4 +4,5 @@ class Users::BaseAccountController < Users::BaseController def observed_user @_observed_user ||= (User.find_by_id(params[:account_id]) || User.find_by_login(params[:account_id])) end + end diff --git a/app/controllers/users/interests_controller.rb b/app/controllers/users/interests_controller.rb new file mode 100644 index 000000000..3f931612d --- /dev/null +++ b/app/controllers/users/interests_controller.rb @@ -0,0 +1,26 @@ +class Users::InterestsController < Users::BaseController + skip_before_action :check_observed_user_exists! + before_action :require_login + + def create + return render_forbidden if current_user.user_extension&.identity.present? + identity = params[:identity].to_s.strip + + extension = current_user.user_extension || current_user.build_user_extension + return render_error('请选择职业') unless %w(teacher student professional).include?(identity) + + ActiveRecord::Base.transaction do + extension.update_column(:identity, identity) + + # 兴趣 + current_user.user_interests.delete_all + UserInterest.bulk_insert(:user_id, :repertoire_id) do |worker| + (Repertoire.pluck(:id) & Array.wrap(params[:interest_ids]).map(&:to_i)).each do |repertoire_id| + worker.add(user_id: current_user.id, repertoire_id: repertoire_id) + end + end + end + + render_ok + 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/controllers/users/shixuns_controller.rb b/app/controllers/users/shixuns_controller.rb index c4c0d4c07..7b840a0a1 100644 --- a/app/controllers/users/shixuns_controller.rb +++ b/app/controllers/users/shixuns_controller.rb @@ -4,6 +4,10 @@ class Users::ShixunsController < Users::BaseController @count = shixuns.count @shixuns = paginate(shixuns.includes(:first_tag_repertoire), special: true) + + ids = @shixuns.map(&:id) + @finished_challenges_count_map = Game.joins(:myshixun).where(user_id: observed_user.id, status: 2) + .where(myshixuns: { shixun_id: ids }).group('myshixuns.shixun_id').count end private diff --git a/app/controllers/users/watches_controller.rb b/app/controllers/users/watches_controller.rb index 95a0b38cd..867106c52 100644 --- a/app/controllers/users/watches_controller.rb +++ b/app/controllers/users/watches_controller.rb @@ -1,5 +1,5 @@ class Users::WatchesController < Users::BaseController - before_action :require_login + before_action :require_login, :check_auth def create if observed_logged_user? diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index dc68f47c6..e9fe4ed94 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -9,10 +9,6 @@ class UsersController < ApplicationController @user = User.find params[:id] @user.update!(user_params) render_ok - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback end # 贴吧获取用户信接口 @@ -41,6 +37,7 @@ class UsersController < ApplicationController end @course_identity = current_user.course_identity(@course) if @course rescue Exception => e + uid_logger_error(e.message) missing_template end @@ -54,6 +51,13 @@ class UsersController < ApplicationController :disposition => 'attachment' #inline can open in browser end + def html_show + @contents = File.read("#{params[:path]}") + respond_to do |format| + format.html {render :layout => false} + end + end + # Redo: 消息总数缓存 def get_navigation_info @old_domain = edu_setting('old_edu_host') @@ -61,7 +65,7 @@ class UsersController < ApplicationController # 新消息数 @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0 - @user_url = "#{@old_domain}/users/#{@user.login}" + @user_url = "/users/#{@user.login}" @career = Career.where(status: true).order("created_at asc").pluck(:id, :name) ec_user = EcSchoolUser.where(:user_id => current_user.id).first @auth = ec_user ? "#{@old_domain}/ecs/department?school_id=#{ec_user.school_id}" : nil @@ -69,21 +73,24 @@ class UsersController < ApplicationController # 用户回复功能 def reply_message - @message = JournalsForMessage.new(reply_message_params) - @message.user_id = current_user.id - @message.save! - #normal_status("回复成功") + message = JournalsForMessage.new(reply_message_params) + message.user_id = current_user.id + message.save! + + render_ok(id: message.id) end # 搜索用户具有管理员角色的项目 def search_user_projects - condition = '%%' - condition = "%#{params[:search].strip}%".gsub(" ","") if !params[:search].blank? + projects = Project.where.not(status: 9) - project_ids = Project.find_by_sql("SELECT p.id FROM projects p, members m, member_roles mr WHERE m.project_id = p.id - AND m.id=mr.member_id AND mr.role_id = 3 AND m.user_id=#{current_user.id} AND p.status != 9 and - p.name like '#{condition}'") - @projects = Project.where(id: project_ids.pluck(:id)) + projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 }) + projects = projects.where(members: { user_id: current_user.id }) + + search = params[:search].to_s.strip + projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present? + + @projects = projects.select(:id, :name) end # 个人主页信息 @@ -91,10 +98,6 @@ class UsersController < ApplicationController def brief_introduction content = params[:content].to_s.strip - if content.blank? - render_error('内容不能为空') - return - end current_user.user_extension.update!(brief_introduction: content) diff --git a/app/controllers/zips_controller.rb b/app/controllers/zips_controller.rb index 89f473499..f4822b96b 100644 --- a/app/controllers/zips_controller.rb +++ b/app/controllers/zips_controller.rb @@ -1,26 +1,24 @@ class ZipsController < ApplicationController - before_action :require_login + before_action :require_login, :check_auth before_action :load_homework, only: [:shixun_report] before_action :get_exercise, only: [:export_exercises] before_action :require_admin_or_teacher def shixun_report - student_work_ids = Array.wrap(params[:student_work_ids]) - - service = BatchExportShixunReportService.new(@homework, student_work_ids) - - filename = filename_for_content_disposition(service.filename) - send_file service.zip, filename: filename, type: 'application/zip' + service = BatchExportShixunReportService.new(@homework, @all_student_works) + filename_ = filename_for_content_disposition(service.filename) + send_file service.zip, filename: filename_, type: 'application/zip' rescue BatchExportShixunReportService::Error => ex normal_status(-1, ex.message) end def export_exercises - exercises = ExportExercisesService.new(@exercise,@ex_users) + @request_url = request.base_url + exercises = ExportExercisesService.new(@exercise,@ex_users,@request_url) - file_name = filename_for_content_disposition(exercises.filename) - send_file exercises.ex_zip, filename: file_name, type: 'application/zip' + file_name_ = filename_for_content_disposition(exercises.filename) + send_file exercises.ex_zip, filename: file_name_, type: 'application/zip' rescue Exception => e normal_status(-1, e.message) end @@ -39,27 +37,53 @@ class ZipsController < ApplicationController def get_exercise ActiveRecord::Base.transaction do begin - @exercise = Exercise.find_by(id:params[:exercise_id]) + @exercise = Exercise.includes(:exercise_users,:exercise_questions).find_by(id:params[:exercise_id]) + @exercise_status = @exercise.present? ? @exercise.get_exercise_status(current_user) : 1 group_id = params[:exercise_group_id] if @exercise.blank? normal_status(-1,"试卷不存在") + elsif @exercise_status == 1 + normal_status(-1,"试卷未发布") else @course = @exercise.course - default_ex_users = @exercise.all_exercise_users(current_user.id).exercise_user_committed - default_ex_users_size = default_ex_users.size @ex_users = default_ex_users #仅导出已提交的,截止后则是全部为提交的。 + + #是否评阅 + if params[:review].present? + review_type = params[:review].first.to_i #已评,则数据为1,未评,则数据为0,前端传过来的为数组 + if review_type == 1 + @ex_users = @ex_users.where("subjective_score >= ?",0.0) + else + @ex_users = @ex_users.where("subjective_score < ?",0.0) + end + end + + #答题状态的选择 + if params[:commit_status].present? && (params[:commit_status].to_i == 1) + @exercise_users_list = @exercise_users_list.where(commit_status:params[:commit_status]) + elsif params[:commit_status].present? && (params[:commit_status].to_i == 0) + normal_status(-1,"暂无用户提交!") + end + #可以分班选择 if group_id.present? - exercise_students = @course.students.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数 - user_ids = exercise_students.pluck(:user_id).reject(&:blank?) - @ex_users = @ex_users.exercise_commit_users(user_ids) + exercise_students = @course.students.where(course_group_id: group_id) # 试卷所分班的全部人数 + user_ids = exercise_students.pluck(:user_id).reject(&:blank?).uniq + @ex_users = @ex_users.where(user_id: user_ids) end - # @ex_users = @ex_users.first(200) - if default_ex_users_size == 0 - normal_status(-1,"导出失败,暂时没有已提交的学生") - elsif default_ex_users_size > 200 - normal_status(-1,"导出数量超过200,请分班导出或联系网站管理员导出") + + #搜索 + if params[:search].present? + @ex_users = @ex_users.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") + end + + default_ex_users_size = @ex_users&.size + + if default_ex_users_size.blank? || default_ex_users_size == 0 + normal_status(-1,"暂无用户提交") + elsif default_ex_users_size > 100 + normal_status(-2,"100") end end rescue Exception => e @@ -71,6 +95,40 @@ class ZipsController < ApplicationController def load_homework @homework = HomeworkCommon.find(params[:homework_common_id]) - @course = @homework.course + @homework_status = @homework.present? ? @homework.homework_detail_manual.comment_status : 0 + if @homework.blank? + normal_status(-1,"该作业不存在") + elsif @homework_status == 0 + normal_status(-1,"该作业未发布") + else + @course = @homework.course + ##7。2 -hs新增 + @member = @course.course_member(current_user.id) + + @all_student_works = @homework.teacher_works(@member).where("work_status > 0") + work_status = params[:work_status] + group_id = params[:course_group] + + unless work_status.blank? + @all_student_works = @all_student_works.where(work_status:work_status) + end + + unless group_id.blank? + group_user_ids = @course.students.where(course_group_id: params[:course_group]).pluck(:user_id) + @all_student_works = @all_student_works.where(user_id: group_user_ids) + end + + unless params[:search].blank? + @all_student_works = @all_student_works.joins(user: :user_extension).where("concat(lastname, firstname) like ? + or student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") + end + + student_work_sizes = @all_student_works&.size + if student_work_sizes.blank? || student_work_sizes == 0 + normal_status(-1,"暂无用户提交") + elsif student_work_sizes > 100 + normal_status(-2,"100") + end + end end end diff --git a/app/decorators/application_decorator.rb b/app/decorators/application_decorator.rb new file mode 100644 index 000000000..ccaf720e5 --- /dev/null +++ b/app/decorators/application_decorator.rb @@ -0,0 +1,9 @@ +module ApplicationDecorator + def display_time_method(*columns, format: '%Y-%m-%d %H:%M:%S') + columns.each do |column_name| + define_method "display_#{column_name}" do + public_send(column_name)&.strftime(format) + end + end + end +end \ No newline at end of file diff --git a/app/decorators/competition_decorator.rb b/app/decorators/competition_decorator.rb new file mode 100644 index 000000000..2be5b3ecb --- /dev/null +++ b/app/decorators/competition_decorator.rb @@ -0,0 +1,6 @@ +module CompetitionDecorator + extend ApplicationDecorator + + display_time_method :start_time, :end_time, :enroll_end_time + +end diff --git a/app/decorators/competition_stage_section_decorator.rb b/app/decorators/competition_stage_section_decorator.rb new file mode 100644 index 000000000..1196cb9ad --- /dev/null +++ b/app/decorators/competition_stage_section_decorator.rb @@ -0,0 +1,5 @@ +module CompetitionStageSectionDecorator + extend ApplicationDecorator + + display_time_method :start_time, :end_time +end \ No newline at end of file diff --git a/app/decorators/shixun_decorator.rb b/app/decorators/shixun_decorator.rb index 50e2e27eb..4b7a0714a 100644 --- a/app/decorators/shixun_decorator.rb +++ b/app/decorators/shixun_decorator.rb @@ -1,8 +1,4 @@ module ShixunDecorator - def finished_challenges_count(user) - Game.joins(:myshixun).where(user_id: user.id, status: 2, myshixuns: { shixun_id: id }).count - end - def human_status I18n.t("shixun.status.#{status}") end diff --git a/app/decorators/user_decorator.rb b/app/decorators/user_decorator.rb index 0ee9a4b43..e00dead39 100644 --- a/app/decorators/user_decorator.rb +++ b/app/decorators/user_decorator.rb @@ -12,48 +12,6 @@ module UserDecorator logged_user? ? real_name : full_name end - # 关注数 - def follow_count - User.watched_by(id).count - end - - # 粉丝数 - def fan_count - watchers.count - end - - # 是否绑定邮箱 - def email_binded? - mail.present? - end - - # 学院的url标识 - def college_identifier - - Department.find_by_id(department_members.pluck(:department_id).first)&.identifier - end - - # 是否能申请试用 - def can_apply_trial? - return false if certification == 1 - - apply = ApplyAction.order(created_at: :desc).find_by(user_id: id, container_type: 'TrialAuthorization') - - apply && !apply.status.zero? - end - - # 是否已经签到 - def attendance_signed? - attendance = Attendance.find_by(user_id: id) - - attendance && Util.days_between(Time.zone.now, attendance.created_at).zero? - end - - # 明日签到金币 - def tomorrow_attendance_gold - Attendance.find_by(user_id: id)&.next_gold - end - # ----------- 账号管理 ------------- def authentication_status if authentication? @@ -74,16 +32,4 @@ module UserDecorator 'uncertified' end end - - def base_info_completed? - user_columns = %i[nickname lastname] - user_extension_columns = %i[gender location location_city identity school_id department] - - user_columns.all? { |column| public_send(column).present? } && - user_extension_columns.all? { |column| user_extension.send(column).present? } - end - - def all_certified? - authentication? && professional_certification? - end end \ No newline at end of file diff --git a/app/forms/add_school_apply_form.rb b/app/forms/add_school_apply_form.rb new file mode 100644 index 000000000..f98e8b05b --- /dev/null +++ b/app/forms/add_school_apply_form.rb @@ -0,0 +1,10 @@ +class AddSchoolApplyForm + include ActiveModel::Model + + attr_accessor :name, :province, :city, :address, :remarks + + validates :name, presence: true + # validates :province, presence: true + # validates :city, presence: true + # validates :address, presence: true +end \ No newline at end of file diff --git a/app/forms/competitions/save_team_form.rb b/app/forms/competitions/save_team_form.rb new file mode 100644 index 000000000..10685d260 --- /dev/null +++ b/app/forms/competitions/save_team_form.rb @@ -0,0 +1,98 @@ +class Competitions::SaveTeamForm + include ActiveModel::Model + + attr_accessor :competition, :team, :creator + attr_accessor :name, :teacher_ids, :member_ids + + validates :name, presence: true + + validate :check_creator_enrollable + def check_creator_enrollable + return unless check_creator_identity_enrollable + + check_creator_multiple_enrollable + end + + validate :check_teachers_enrollable + def check_teachers_enrollable + if competition.teacher_enroll_forbidden? && teacher_ids.present? + errors.add(:teacher_ids, :enroll_forbidden) + return + end + + self.teacher_ids = teacher_ids.map(&:to_i) + all_teachers = creator.is_teacher? ? teacher_ids + [creator.id] : teacher_ids + all_teachers.uniq! + + if all_teachers.size < competition.teacher_staff.minimum || all_teachers.size > competition.teacher_staff.maximum + errors.add(:teacher_ids, :invalid_count, minimum: competition.teacher_staff.minimum, maximum: competition.teacher_staff.maximum) + return + end + + # 老师可多次报名,不检查 + return unless competition.teacher_multiple_limited? + + # 存在已报名老师 + enrolled_teacher_members = competition.team_members.where(user_id: all_teachers) + .where.not(competition_team_id: team.id).includes(:user) + if enrolled_teacher_members.present? + errors.add(:teacher_ids, :enrolled, names: enrolled_teacher_members.map { |m| m.user.real_name }.join(',')) + return + end + end + + validate :check_members_enrollable + def check_members_enrollable + if competition.member_enroll_forbidden? && member_ids.present? + errors.add(:member_ids, :enroll_forbidden) + return + end + + self.member_ids = member_ids.map(&:to_i) + all_members = creator.is_teacher? ? member_ids : member_ids + [creator.id] + all_members.uniq! + + if all_members.size < competition.member_staff.minimum || all_members.size > competition.member_staff.maximum + errors.add(:member_ids, :invalid_count, minimum: competition.member_staff.minimum, maximum: competition.member_staff.maximum) + return + end + + # 成员可多次报名,不检查 + return unless competition.member_multiple_limited? + + # 存在已报名成员 + enrolled_members = competition.team_members.where(user_id: all_members) + .where.not(competition_team_id: team.id).includes(:user) + if enrolled_members.present? + errors.add(:member_ids, :enrolled, names: enrolled_members.map { |m| m.user.real_name }.join(',')) + return + end + end + + private + + # 竞赛是否限制了职业 + def check_creator_identity_enrollable + if user.is_teacher? && competition.teacher_enroll_forbidden? + errors.add(:creator, :teacher_enroll_forbidden) + return false + elsif !user.is_teacher? && competition.member_enroll_forbidden? + errors.add(:creator, :member_enroll_forbidden) + return false + end + + true + end + + # 创建者是否能多次报名 + def check_creator_multiple_enrollable + return unless competition.enrolled?(user) + + if (user.is_teacher? && competition.teacher_multiple_limited?) || (!user.is_teacher? && competition.member_multiple_limited?) + errors.add(:creator, :enrolled) + return false + end + + true + 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/forms/users/update_account_form.rb b/app/forms/users/update_account_form.rb index 68e7fb7bf..d82459fcf 100644 --- a/app/forms/users/update_account_form.rb +++ b/app/forms/users/update_account_form.rb @@ -10,9 +10,9 @@ class Users::UpdateAccountForm validates :gender, presence: true, numericality: { only_integer: true }, inclusion: { in: [0, 1] } validates :location, presence: true validates :location_city, presence: true - validates :identity, presence: true, numericality: { only_integer: true }, inclusion: { in: [0, 1, 2] } - validates :technical_title, presence: true, unless: -> { identity == 1 } - validates :student_id, presence: true, if: -> { identity == 1 } + validates :identity, presence: true, inclusion: { in: %w[teacher student professional ] } + validates :technical_title, presence: true, unless: -> { identity.to_s == 'student' } + validates :student_id, presence: true, if: -> { identity.to_s == 'student' } validates :school_id, presence: true validate :check_school_exist diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ac50e78d3..4c3a449e9 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,6 +1,7 @@ # 所有的方法请按首字母的顺序依次列出 module ApplicationHelper include Educoder::I18n + include GitHelper ONE_MINUTE = 60 * 1000 ONE_HOUR = 60 * ONE_MINUTE @@ -11,7 +12,7 @@ module ApplicationHelper # 全局参数配置 def edu_setting name - EduSetting.find_by_name(name).try(:value) + EduSetting.get(name) end def graduation_navigation graduation @@ -29,8 +30,9 @@ module ApplicationHelper end # git用户 + # git用户命名规则:login+"@educoder.net" def git_username(email) - User.find_by_mail(email) + User.find_by_mail(email) || User.find_by_login(email.split("@").first) end # 不同的类型扩展不同的目录 @@ -109,7 +111,7 @@ module ApplicationHelper # 计算到结束还有多长时间 **天**小时**分 def how_much_time(time) - if time.nil? + if time.nil? || time < Time.now #6.21 -hs 增加小于time.now '' else result = ((time - Time.now.to_i).to_i / (24*60*60)).to_s + " 天 " @@ -128,7 +130,7 @@ module ApplicationHelper if source.class.to_s == 'User' File.join(relative_path, ["#{source.class}", "#{source.id}"]) else - File.join("/images/avatars", ["#{source.class}", "#{source.id}"]) + File.join("images/avatars", ["#{source.class}", "#{source.id}"]) end elsif source.class.to_s == 'User' str = source.user_extension.try(:gender).to_i == 0 ? "b" : "g" @@ -144,9 +146,21 @@ 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}") + File.join("images/#{relative_path}", "#{shixun.class}", "#{shixun.id}") else File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg") end @@ -332,6 +346,24 @@ module ApplicationHelper raw arr.join('') end + + # 导出pdf时,转化markdown为html + def to_markdown(text,origin_url) + return nil if text.blank? + options = { + :autolink => true, + :no_intra_emphasis => true, + :fenced_code_blocks => true, + :lax_html_blocks => true, + :strikethrough => true, + :superscript => true, + :tables => true + } + markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,options) + m_t = markdown.render(text) + m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t + end + end diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb index 8c88f02d0..fa51de6b7 100644 --- a/app/helpers/courses_helper.rb +++ b/app/helpers/courses_helper.rb @@ -232,7 +232,7 @@ module CoursesHelper course.course_groups.includes(:course_members) end group_info = [] - if course_groups.count > 0 + if !course_groups.blank? course_groups.each do |group| group_info << {course_group_id: group.id, group_group_name: group.name, count: group.course_members_count} end @@ -246,15 +246,18 @@ module CoursesHelper def left_group_info course group_info = [] - course.course_groups.each do |course_group| - group_info << {category_id: course_group.id, category_name: course_group.name, position: course_group.position, - category_count: course_group.course_members_count, category_type: false, - second_category_url: "/courses/#{@course.id}/course_groups/#{course_group.id}"} + if course.course_groups_count > 0 + none_group_count = course.students.where(course_group_id: 0).size + group_info << {category_id: 0, category_name: "未分班", position: course.course_groups.pluck(:position).max.to_i + 1, + category_count: none_group_count, category_type: false, + second_category_url: "/courses/#{@course.id}/course_groups/0"} + course.course_groups.each do |course_group| + group_info << {category_id: course_group.id, category_name: course_group.name, position: course_group.position, + category_count: course_group.course_members_count, category_type: false, + second_category_url: "/courses/#{@course.id}/course_groups/#{course_group.id}"} + end end - none_group_count = course.students.where(course_group_id: 0).size - group_info << {category_id: 0, category_name: "未分班", position: course.course_groups.pluck(:position).max.to_i + 1, - category_count: none_group_count, category_type: false, - second_category_url: "/courses/#{@course.id}/course_groups/0"} + group_info end end diff --git a/app/helpers/exercise_questions_helper.rb b/app/helpers/exercise_questions_helper.rb index 28f3fddb0..69dee034f 100644 --- a/app/helpers/exercise_questions_helper.rb +++ b/app/helpers/exercise_questions_helper.rb @@ -32,7 +32,7 @@ module ExerciseQuestionsHelper def shixun_game_scores(challenge,ex_answerer,shixun_type,question_id) game_score = challenge.question_score - game_answers = challenge.exercise_shixun_answers.search_shixun_answers("user_id",ex_answerer.id).search_shixun_answers("exercise_question_id",question_id) + game_answers = challenge.exercise_shixun_answers.where(user_id:ex_answerer.id,exercise_question_id:question_id) if shixun_type == 2 && game_answers.present? #试卷已截止,用户才可以查看答案 s_score = game_answers.first.score else diff --git a/app/helpers/exercises_helper.rb b/app/helpers/exercises_helper.rb index 4f4c015eb..ace9e062e 100644 --- a/app/helpers/exercises_helper.rb +++ b/app/helpers/exercises_helper.rb @@ -1,19 +1,42 @@ module ExercisesHelper + # include GitHelper #获取每个学生对每个题的答案状态 def get_each_student_exercise(exercise_id,exercise_questions,user_id) - @exercise_user = ExerciseUser.current_exercise_user(user_id,exercise_id).first + @exercise_user = ExerciseUser.current_exercise_user(user_id,exercise_id)&.first exercise_obj_status = exercise_questions.find_objective_questions @ex_obj_array = [] exercise_obj_status.each do |q| - if q.question_type == 5 - ques_score = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id).pluck(:score).sum + q_type = q.question_type + if q_type == Exercise::PRACTICAL + answers_content = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id) else - ques_score = q.exercise_answers.search_answer_users("user_id",user_id).score_reviewed.pluck(:score).sum + answers_content = q.exercise_answers.search_answer_users("user_id",user_id) end - if ques_score == q.question_score #满分作答为正确 + if q_type <= Exercise::JUDGMENT + if answers_content.present? #学生有回答时 + answer_choice_array = [] + answers_content.each do |a| + answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 + end + user_answer_content = answer_choice_array.sort + standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个 + if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 + ques_score = q.question_score + else + ques_score = 0.0 + end + else + ques_score = 0.0 + end + else + ques_score = answers_content.select(:score).pluck(:score).sum + end + + if ques_score >= q.question_score #满分作答为正确 + ques_score = q.question_score stand_answer = 1 elsif ques_score > 0.0 #部分作答 stand_answer = 2 @@ -30,21 +53,21 @@ module ExercisesHelper } @ex_obj_array.push(ques_option) end - exercise_sub_status = exercise_questions.find_by_custom("question_type",4) #主观题 + exercise_sub_status = exercise_questions.find_by_custom("question_type",Exercise::SUBJECTIVE) #主观题 @ex_sub_array = [] #主观题的已答/未答 exercise_sub_status.each do |s| sub_answer = s.exercise_answers.search_answer_users("user_id",user_id) #主观题只有一个回答 if sub_answer.present? && sub_answer.first.score >= 0.0 - if s.question_score == sub_answer.first.score + + if s.question_score <= sub_answer.first.score stand_status = 1 else stand_status = 2 end - # stand_status = 1 sub_answer_score = sub_answer.first.score else stand_status = 0 - sub_answer_score = 0.0 + sub_answer_score = nil end sub_score = { @@ -52,65 +75,87 @@ module ExercisesHelper "q_type":s.question_type, "q_position":s.question_number, "stand_status":stand_status, - "user_score":sub_answer_score.round(1).to_s + "user_score":sub_answer_score.present? ? sub_answer_score.round(1).to_s : nil } @ex_sub_array.push(sub_score) end - @ex_obj_array.sort_by {|k| k[:q_position]} - @ex_sub_array.sort_by {|k| k[:q_position]} + @ex_obj_array = @ex_obj_array.sort_by {|k| k[:q_position]} + @ex_sub_array = @ex_sub_array.sort_by {|k| k[:q_position]} end #试卷的统计结果页面计算各题的 def exercise_commit_result(questions,user_ids) question_infos = [] - questions.each do |ex| - ex_total_score = user_ids.count * ex&.question_score #该试卷的已回答的总分 - ex_answers = ex.exercise_answers - if ex.question_type != 5 + percent = 0.0 + questions.includes(:exercise_choices).each do |ex| + ex_total_score = user_ids.count * ex&.question_score.to_f #该试卷的已回答的总分 + # ex_answers = ex.exercise_answers + if ex.question_type != Exercise::PRACTICAL ques_title = ex.question_title ques_less_title = nil + ex_answers = ex.exercise_answers effictive_users = ex_answers.search_answer_users("user_id",user_ids) else ques_title = ex.shixun.name ques_less_title = ex.question_title - effictive_users = ex.exercise_shixun_answers.search_shixun_answers("user_id",user_ids) + ex_answers = ex.exercise_shixun_answers + effictive_users = ex_answers.search_shixun_answers("user_id",user_ids) end - effictive_users_count = effictive_users.count #有效回答数,可能有重复的用户id,这里仅统计是否回答这个问题的全部人数 - ex_answered_scores = effictive_users.score_reviewed.pluck(:score).sum #该问题的全部得分 - if ex_total_score == 0.0 - percent = 0.0 - else - percent = (ex_answered_scores / ex_total_score.to_f).round(3) * 100 #正确率 + + effictive_users_count = effictive_users.size #有效回答数,可能有重复的用户id,这里仅统计是否回答这个问题的全部人数 + + if ex.question_type > Exercise::COMPLETION #当为主观题和实训题时, + ex_answered_scores = effictive_users.score_reviewed.pluck(:score).sum #该问题的全部得分 + percent = (ex_total_score == 0.0 ? 0.0 : (ex_answered_scores / ex_total_score.to_f).round(3) * 100) #正确率 end + question_answer_infos = [] - if ex.question_type <= 2 #单选题 - standard_answer = ex.exercise_standard_answers.pluck(:exercise_choice_id) #标准答案的位置 - ex.exercise_choices.each do |c| - if standard_answer.include?(c.choice_position) #选项的标准答案为选项的位置 - right_answer = true - else - right_answer = false - end - answer_this_choice = effictive_users.search_exercise_answer("exercise_choice_id",c.id) - answer_users_count = answer_this_choice.count - if effictive_users_count == 0 - answer_percent = 0.0 - else - answer_percent = (answer_users_count / effictive_users_count.to_f ).round(3) + if ex.question_type <= Exercise::JUDGMENT #选择题和判断题 + ex_choices = ex.exercise_choices + standard_answer = ex.exercise_standard_answers.pluck(:exercise_choice_id).sort #标准答案的位置 + right_users_count = 0 + #该问题的正确率 + if ex.question_type == Exercise::MULTIPLE #多选题 + right_user_ids = user_ids + standard_answer.each do |choice_position| + standard_answer_choice_id = ex_choices.select{|ec| ec.choice_position == choice_position}.first&.id + right_user_ids = right_user_ids & effictive_users.select{|answer| answer.exercise_choice_id == standard_answer_choice_id}.pluck(:user_id) end + right_users_count = right_user_ids.size + # user_ids.each do |user_id| + # ex_choice_ids = effictive_users.map{|e| e.exercise_choice_id if e.user_id == user_id}.reject(&:blank?).uniq + # answer_choice_array = ex_choices.map{|a| a.choice_position if ex_choice_ids.include?(a.id)}.reject(&:blank?).uniq + # if answer_choice_array.sort == standard_answer + # right_users_count += 1 + # end + # end + else #单选题和判断题 + standard_answer_choice_id = ex_choices.select{|ec| ec.choice_position == standard_answer.first}.first&.id + right_users_count = effictive_users.select{|answer| answer.exercise_choice_id == standard_answer_choice_id}.size + end + + percent = effictive_users_count > 0 ? (right_users_count / effictive_users_count.to_f).round(3)*100 : 0.0 + + #每个选项的正确率 + ex_choices.each do |c| + right_answer = standard_answer.include?(c.choice_position) #选项的标准答案为选项的位置 + answer_users_count = effictive_users.select{|answer| answer.exercise_choice_id == c.id}.size + + answer_percent = (effictive_users_count == 0 ? 0.0 : (answer_users_count / effictive_users_count.to_f ).round(3)) + answer_option = { :choice_position => c.choice_position, :choice_text => c.choice_text, :choice_users_count => answer_users_count, - :choice_percent => answer_percent.round(1), + :choice_percent => answer_percent.round(1).to_s, :right_answer => right_answer } question_answer_infos.push(answer_option) end - elsif ex.question_type == 3 #填空题 + elsif ex.question_type == Exercise::COMPLETION #填空题 ex_ordered = ex.is_ordered null_standard_answer = ex.exercise_standard_answers - null_stand_choice = null_standard_answer.pluck(:exercise_choice_id) + null_stand_choice = null_standard_answer.pluck(:exercise_choice_id) #一个exercise_choice_id可能对应多个answer_text null_stand_text = null_standard_answer.pluck(:answer_text) standard_answer_count = 0 all_user_count = 0 @@ -118,33 +163,24 @@ module ExercisesHelper user_count = 0 s_choice_text = null_stand_text[index] if ex_ordered #有序排列 - user_ids.each do |u| - user_answers = ex_answers.search_answer_users("user_id",u).search_answer_users("exercise_choice_id",s) - user_answers_choice = user_answers.present? ? user_answers.first.answer_text : "" - if s_choice_text == user_answers_choice - user_count += 1 - end - end + user_count = user_count + effictive_users.select{|answer| answer.exercise_choice_id == s && answer.answer_text == s_choice_text}.size else - user_count = user_count + effictive_users.search_exercise_answer("answer_text",s_choice_text).count #回答了标准答案的用户 - end - if effictive_users_count == 0 - answer_percent = 0.0 - else - answer_percent = (user_count / effictive_users_count.to_f ).round(3) + user_count = user_count + effictive_users.select{|answer| answer.answer_text == s_choice_text }.size #回答了标准答案的用户 end + answer_percent = ((effictive_users_count == 0) ? 0.0 : (user_count / effictive_users_count.to_f ).round(3)) answer_option = { :choice_position => index+1, :choice_text => s_choice_text, :choice_users_count => user_count, - :choice_percent => answer_percent.round(1), + :choice_percent => answer_percent.round(1).to_s, :right_answer => true } question_answer_infos.push(answer_option) all_user_count += user_count standard_answer_count += 1 end + percent = effictive_users_count > 0 ? (all_user_count / effictive_users_count.to_f).round(3)*100 : 0.0 user_wrong_count = (effictive_users_count - all_user_count ) if effictive_users_count > 0 && user_wrong_count >= 0 @@ -156,25 +192,22 @@ module ExercisesHelper :choice_position => (standard_answer_count + 1), :choice_text => "wrong", :choice_users_count => user_wrong_count, - :choice_percent => wrong_percent.round(1), + :choice_percent => wrong_percent.round(1).to_s, :right_answer => false } question_answer_infos.push(wrong_answer_position) - elsif ex.question_type == 4 #主观题 + elsif ex.question_type == Exercise::SUBJECTIVE #主观题 ex_score = ex&.question_score - full_scores = effictive_users.search_exercise_answer("score",ex_score).count #满分人数 - no_full_scores = effictive_users.exercise_no_full_scores(ex_score).count #部分分数人数 - all_zero_scores = effictive_users.search_exercise_answer("score",0.0).count #包含为0分的,及未评阅的 - review_scores = ex.exercise_answer_comments.count #主观题的评阅数量 - un_review_scores = effictive_users_count - review_scores #未评阅数 - zero_scores = all_zero_scores - un_review_scores #已评阅,且答案未0分的人数 + full_scores = effictive_users.search_exercise_answer("score",ex_score).size #满分人数 + no_full_scores = effictive_users.exercise_no_full_scores(ex_score).size #部分分数人数 + zero_scores = effictive_users.search_exercise_answer("score",0.0).size #包含为0分的,及未评阅的 + un_review_scores = effictive_users_count - full_scores - no_full_scores - zero_scores #未评阅数 + if un_review_scores < 0 + un_review_scores = 0 + end main_scores_array = [full_scores,no_full_scores,zero_scores,un_review_scores] main_scores_array.each_with_index do |s,index| - if index == 0 - right_answer = true - else - right_answer = false - end + right_answer = (index == 0) if effictive_users_count == 0 || s < 0 s = 0 score_percent = 0.0 @@ -185,37 +218,33 @@ module ExercisesHelper :choice_position => index+1, :choice_text => index+1, :choice_users_count => s, - :choice_percent => score_percent.round(1), + :choice_percent => score_percent.round(1).to_s, :right_answer => right_answer } question_answer_infos.push(answer_option) end - elsif ex.question_type == 5 #实训题 + elsif ex.question_type == Exercise::PRACTICAL #实训题 ex.exercise_shixun_challenges.each do |c| cha_score = c&.question_score cha_shixun_answer = effictive_users.search_shixun_keys("exercise_shixun_challenge_id",c.id) - effictive_users_count = cha_shixun_answer.count #实训题的每个关卡的有效填写量 - full_scores = cha_shixun_answer.search_shixun_keys("score",cha_score).count #满分人数 - no_full_scores = cha_shixun_answer.shixun_no_full_scores(cha_score).count #部分分数人数c - all_zero_scores = cha_shixun_answer.search_shixun_keys("score",0.0).count #满分人数 + effictive_users_count = cha_shixun_answer.size #实训题的每个关卡的有效填写量 + full_scores = cha_shixun_answer.search_shixun_keys("score",cha_score).size #满分人数 + no_full_scores = cha_shixun_answer.shixun_no_full_scores(cha_score).size #部分分数人数c + all_zero_scores = cha_shixun_answer.search_shixun_keys("score",0.0).size #零分人数 + shixun_scores = user_ids.count * cha_score + shixun_answered_scores = cha_shixun_answer.score_reviewed.pluck(:score).sum #该问题的全部得分 + game_percent = (shixun_answered_scores == 0.0 ? 0.0 : (shixun_answered_scores / shixun_scores.to_f).round(3) * 100) #正确率 + shixun_score_array = [full_scores,no_full_scores,all_zero_scores] shixun_chas = [] shixun_score_array.each_with_index do |s,index| - if index == 0 - right_answer = true - else - right_answer = false - end - if effictive_users_count == 0 - score_percent = 0.0 - else - score_percent = (s.to_i / effictive_users_count.to_f ).round(3) - end + right_answer = (index == 0) + score_percent = (effictive_users_count == 0 ? 0.0 : (s.to_i / effictive_users_count.to_f ).round(3)) answer_option = { :choice_position => index+1, :choice_text => index+1, :choice_users_count => s, - :choice_percent => score_percent.round(1), + :choice_percent => score_percent.round(1).to_s, :right_answer => right_answer } shixun_chas.push(answer_option) @@ -224,7 +253,8 @@ module ExercisesHelper :cha_id => c.challenge_id, :cha_name => c.challenge.subject, :cha_position => c.position, - :cha_details => shixun_chas + :cha_details => shixun_chas, + :cha_percent => game_percent.round(1).to_s } question_answer_infos.push(shixun_new_chas) end @@ -244,16 +274,18 @@ module ExercisesHelper end #获取试卷的已答/未答人数 - def get_exercise_answers(ex_users) - @commit_ex_users = ex_users.commit_exercise_by_status(1) #当前老师的全部学生中已提交的 - - @exercise_answers = @commit_ex_users.present? ? @commit_ex_users.size : 0 #表示已经提交了的用户 - course_all_members_count = ex_users.present? ? ex_users.size : 0 - @exercise_unanswers = (course_all_members_count - @exercise_answers) + def get_exercise_answers(ex_users, status) + @exercise_answers = 0 + @exercise_unanswers = 0 + unless status == Exercise::UNPUBLISHED + @exercise_answers = ex_users.commit_exercise_by_status(1).size #表示已经提交了的用户 + course_all_members_count = ex_users.size + @exercise_unanswers = (course_all_members_count - @exercise_answers) + end end def exercise_index_show(exercise,course,is_teacher_or,user) - # exercise_all_users = exercise.exercise_users + # lock_icon 0出现锁,1不出现锁 ex_show_text = [] if course.is_end #课堂停止后,试卷显示为已结束 @@ -261,7 +293,7 @@ module ExercisesHelper elsif is_teacher_or == 1 #当前为老师的时候,显示的是老师身份的对应试卷的状态,因为该试卷,可能对应老师的多个分班 exercise_status = exercise.exercise_status else - exercise_status = exercise.get_exercise_status(user.id) #当前用户查看的试卷的发布状态 + exercise_status = exercise.get_exercise_status(user) #当前用户查看的试卷的发布状态 end case exercise_status @@ -274,15 +306,16 @@ module ExercisesHelper else ex_show_text end + if is_teacher_or == 1 exercise_users_list = exercise.all_exercise_users(user.id) #当前老师所在班级的全部学生 - unreview_count = exercise_users_list.exercise_unreview.size - get_exercise_answers(exercise_users_list) + unreview_count = exercise_status == 1 ? 0 : exercise_users_list.exercise_unreview.size + get_exercise_answers(exercise_users_list, exercise_status) ex_pb_time = exercise.get_exercise_times(user.id,true) exercise_publish_time = ex_pb_time[:publish_time] exercise_end_time = ex_pb_time[:end_time] current_status = 3 - lock_icon = 1 #不显示锁图标 + lock_icon = 0 if exercise_status == 1 ex_show_text.push("未发布") elsif exercise_status == 3 @@ -290,34 +323,38 @@ module ExercisesHelper end elsif is_teacher_or == 2 exercise_users_list = exercise.get_stu_exercise_users - get_exercise_answers(exercise_users_list) # 未答和已答的 - unreview_count = exercise_users_list.exercise_unreview.size + get_exercise_answers(exercise_users_list, exercise_status) # 未答和已答的 + unreview_count = exercise_status == 1 ? 0 : exercise_users_list.exercise_unreview.size ex_pb_time = exercise.get_exercise_times(user.id,false) exercise_publish_time = ex_pb_time[:publish_time] exercise_end_time = ex_pb_time[:end_time] current_status = exercise.check_user_answer_status(user) - lock_icon = 1 #不显示锁图标 + lock_icon = 0 if current_status == 4 ex_show_text.push("未提交") end else exercise_users_list = exercise.get_stu_exercise_users - get_exercise_answers(exercise_users_list) # 未答和已答的 + get_exercise_answers(exercise_users_list, exercise_status) # 未答和已答的 exercise_publish_time = exercise.publish_time exercise_end_time = exercise.end_time unreview_count = nil if exercise.is_public current_status = exercise.check_user_answer_status(user) - lock_icon = 1 #非课堂成员,但是试卷为公开的,不加锁 + lock_icon = 1 #不出现锁 if current_status == 4 ex_show_text.push("未提交") end else current_status = 4 - lock_icon = 0 #显示锁图标 + lock_icon = 0 end end + if (course.is_public == 1) && exercise.is_public + lock_icon = 1 + end + if exercise_status > 1 show_unreview_count = unreview_count else @@ -326,9 +363,7 @@ module ExercisesHelper if exercise_status == 2 && exercise_end_time.present? ex_left_time = how_much_time(exercise_end_time) - elsif exercise_status == 3 && course.end_date.present? - ex_left_time = how_much_time(course.end_date.to_time) - else + else #已截止后不显示时间 ex_left_time = nil end @@ -352,109 +387,144 @@ module ExercisesHelper score2 = 0.0 #填空题 score5 = 0.0 #实训题 ques_stand = [] #问题是否正确 - exercise_questions = exercise.exercise_questions - exercise_questions.each do |q| - if q.question_type != 5 - answers_content = q.exercise_answers.search_answer_users("user_id",user.id) #学生的答案 - else - answers_content = q.exercise_shixun_answers.search_shixun_answers("user_id",user.id) #学生的答案 - end - if q.question_type <= 2 #为选择题或判断题时 - answer_choice_array = [] - answers_content.each do |a| - answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 - end - user_answer_content = answer_choice_array.sort - standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个 - if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 - if standard_answer.count > 0 - multi_each_score = (q.question_score / standard_answer.count) #当多选答案正确时,每个answer的分数均摊。 - else - multi_each_score = 0.0 - end - answers_content.update_all(:score => multi_each_score) - score1 = score1 + q.question_score - end - elsif q.question_type == 3 #填空题 - null_standard_answer = q.exercise_standard_answers - standard_answer_array = null_standard_answer.select(:exercise_choice_id,:answer_text) - standard_answer_ids = standard_answer_array.pluck(:exercise_choice_id).reject(&:blank?).uniq #标准答案的exercise_choice_id数组 - standard_answer_count = standard_answer_ids.count - if standard_answer_count > 0 #存在标准答案时才有分数 - each_standard_score = (q.question_score.to_f / standard_answer_count).round(1) #每一空的得分 + exercise_questions = exercise.exercise_questions.includes(:exercise_answers,:exercise_shixun_answers,:exercise_standard_answers,:exercise_shixun_challenges) + exercise_questions&.each do |q| + begin + if q.question_type != 5 + answers_content = q.exercise_answers.where(user_id: user.id) #学生的答案 else - each_standard_score = 0.0 + answers_content = q.exercise_shixun_answers.where(user_id: user.id) #学生的答案 end - if q.is_ordered - answers_content.each do |u| - i_standard_answer = standard_answer_array.where(exercise_choice_id:u.exercise_choice_id).pluck(:answer_text).reject(&:blank?).map!(&:downcase) #该选项的全部标准答案 - if i_standard_answer.include?(u.answer_text.downcase) #该空的标准答案包含用户的答案才有分数 - u.update_attribute("score",each_standard_score) - score2 = score2 + each_standard_score + if q.question_type <= 2 #为选择题或判断题时 + if answers_content.present? #学生有回答时 + answer_choice_array = [] + answers_content.each do |a| + answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 end - end - else - st_answer_text = standard_answer_array.pluck(:answer_text).reject(&:blank?).map!(&:downcase) - answers_content.each do |u| - u_answer_text = u.answer_text.downcase - if st_answer_text.include?(u_answer_text) #只要标准答案包含用户的答案,就有分数。同时,下一次循环时,就会删除该标准答案。防止用户的相同答案获分 - u.update_attribute("score",each_standard_score) - score2 = score2 + each_standard_score - st_answer_text.delete(u_answer_text) + user_answer_content = answer_choice_array.sort + standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个 + if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 + if standard_answer.size > 0 + q_score_1 = q.question_score + # q_score_1 = (q.question_score.to_f / standard_answer.count) #当多选答案正确时,每个answer的分数均摊。 + else + q_score_1 = 0.0 + end + answers_content.update_all(:score => q_score_1) + score1 = score1 + q.question_score + else + answers_content.update_all(:score => -1.0) + score1 += 0.0 end + else + score1 += 0.0 end - end - elsif 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 - answer_status = 0 - cha_path = challenge_path exercise_cha.challenge.path - if game.status == 2 && game.final_score >= 0 - exercise_cha_score = game.real_score exercise_cha.question_score #每一关卡的得分 - answer_status = 1 + elsif q.question_type == 3 #填空题 + if answers_content.present? + null_standard_answer = q.exercise_standard_answers + standard_answer_array = null_standard_answer.select(:exercise_choice_id,:answer_text) + standard_answer_ids = standard_answer_array.pluck(:exercise_choice_id).reject(&:blank?).uniq #标准答案的exercise_choice_id数组 + standard_answer_count = standard_answer_ids.count + if standard_answer_count > 0 #存在标准答案时才有分数 + q_score_2 = (q.question_score.to_f / standard_answer_count) #每一空的得分 + else + q_score_2 = 0.0 end - if exercise_cha.exercise_shixun_answers.search_shixun_answers("user_id",user.id).blank? #把关卡的答案存入试卷的实训里 - game_challenge = game.game_codes.search_challenge_path(cha_path).first - if game_challenge.present? - game_code = game_challenge - code = game_code.try(:new_code) + if q.is_ordered + answers_content.each do |u| + i_standard_answer = standard_answer_array.where(exercise_choice_id:u.exercise_choice_id).pluck(:answer_text).reject(&:blank?).map!(&:downcase) #该选项的全部标准答案 + if i_standard_answer.include?(u.answer_text.downcase) #该空的标准答案包含用户的答案才有分数 + u.update_column('score',q_score_2) + score2 = score2 + q_score_2 + else + u.update_column('score',-1.0) + score2 += 0.0 + end + end + else + st_answer_text = standard_answer_array.pluck(:answer_text).reject(&:blank?).map!(&:downcase) + answers_content.each do |u| + u_answer_text = u.answer_text.downcase + if st_answer_text.include?(u_answer_text) #只要标准答案包含用户的答案,就有分数。同时,下一次循环时,就会删除该标准答案。防止用户的相同答案获分 + u.update_column("score",q_score_2) + score2 = score2 + q_score_2 + st_answer_text.delete(u_answer_text) + else + u.update_column('score',-1.0) + score2 += 0.0 + end + end + end + else + score2 += 0.0 + end + elsif 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 + 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 = answers_content&.where(exercise_shixun_challenge_id: exercise_cha.id) + code = nil + if exercise_cha.challenge&.path.present? + cha_path = challenge_path(exercise_cha.challenge&.path) + game_challenge = game.game_codes.search_challenge_path(cha_path)&.first + if game_challenge.present? + game_code = game_challenge + code = game_code.try(:new_code) + else + code = git_fle_content(game.myshixun.repo_path,cha_path) + end + end + if ex_shixun_answer_content.blank? #把关卡的答案存入试卷的实训里 + ### Todo 实训题的_shixun_details里的代码是不是直接从这里取出就可以了?涉及到code的多个版本库的修改 + sx_option = { + :exercise_question_id => q.id, + :exercise_shixun_challenge_id => exercise_cha.id, + :user_id => user.id, + :score => exercise_cha_score.round(1), + :answer_text => code, + :status => answer_status + } + ExerciseShixunAnswer.create(sx_option) else - code = git_fle_content(exercise_cha.shixun.repo_path,cha_path) + ex_shixun_answer_content.first.update_attributes(score:exercise_cha_score.round(1),answer_text:code) end - sx_option = { - :exercise_question_id => q.id, - :exercise_shixun_challenge_id => exercise_cha.id, - :user_id => user.id, - :score => exercise_cha_score, - :answer_text => code, - :status => answer_status - } - ExerciseShixunAnswer.create(sx_option) + score5 += exercise_cha_score + else + score5 += 0.0 end - score5 += exercise_cha_score end end + user_scores = answers_content.blank? ? 0.0 : answers_content.score_reviewed.pluck(:score).sum + if user_scores > 0.0 + stand_answer = 1 + else + stand_answer = 0 + end + ques_option = { + "q_id":q.id, #该问题的id + "q_type":q.question_type, + "q_position":q.question_number, #该问题的位置 + "stand_status":stand_answer, #该问题是否正确,1为正确,0为错误 + "user_score":user_scores.round(1) #每个问题的总得分 + } + ques_stand.push(ques_option) + rescue Exception => e + Rails.logger.info("calcuclate_score_have_error____________________________#{e}") + next end - user_scores = answers_content.score_reviewed.pluck(:score).sum - if user_scores > 0 - stand_answer = 1 - else - stand_answer = 0 - end - ques_option = { - "q_id":q.id, #该问题的id - "q_type":q.question_type, - "q_position":q.question_number, #该问题的位置 - "stand_status":stand_answer, #该问题是否正确,1为正确,0为错误 - "user_score":user_scores #每个问题的总得分 - } - ques_stand.push(ques_option) + end total_score = score1 + score2 + score5 { - "total_score":total_score, + "total_score":total_score.round(1), "stand_status":ques_stand } end @@ -467,9 +537,9 @@ module ExercisesHelper ex_user_user = ex_user.user exercise_user_name = ex_user_user.real_name exercise_user_id = ex_user_user.id - ex_user_exercise_status = exercise.get_exercise_status(exercise_user_id) + ex_user_exercise_status = exercise.get_exercise_status(ex_user_user) ex_user_student_id = ex_user_user.student_id - if ex_user.start_at.present? && ex_user.commit_status == 0 #用户已回答,但未提交 + if ex_user.start_at.present? && (ex_user.commit_status == 0) #用户已回答,但未提交 commit_status = 2 #继续答题 else commit_status = ex_user.commit_status @@ -478,18 +548,21 @@ module ExercisesHelper ex_user_end_at = ex_user.end_at course_member = course.students.course_find_by_ids("user_id",ex_user.user.id) current_user_group_id = course_member.first.course_group_id if course_member.present? - course_group = course.course_groups.by_group_ids(current_user_group_id) - current_user_group_name = course_group.first.name if course_group.present? - teacher_review = ex_user.subjective_score < 0.0 ? false : true - if ex_user_exercise_status != 3 || commit_status != 1 #试卷未截止或用户未提交 - # if (user_status != 0 && ex_user_exercise_status != 3)|| commit_status == 0 #不为教师,且试卷未截止;当前用户未提交 不显示分数 - ex_object_score = nil - ex_subject_score = nil - score = nil + if current_user_group_id == 0 + current_user_group_name = "未分班" else + course_group = course.course_groups.by_group_ids(current_user_group_id) + current_user_group_name = course_group.first.name if course_group.present? + end + teacher_review = ex_user.subjective_score < 0.0 ? false : true + if (user_status == 0 && commit_status == 1) || (user_status == 1 && ex_user_exercise_status == 3 && commit_status == 1) #老师都可以看,学生,需在试卷已提交,且已截止的情况下看 ex_object_score = ex_user.objective_score < 0.0 ? 0.0 : ex_user.objective_score.round(1).to_s ex_subject_score = ex_user.subjective_score < 0.0 ? nil : ex_user.subjective_score.round(1).to_s score = ex_user.score.present? ? ex_user.score.round(1).to_s : 0.0.to_s + else + ex_object_score = nil + ex_subject_score = nil + score = nil end { @@ -601,21 +674,47 @@ module ExercisesHelper #学生的分数状态及回答的内容 def user_question_answers(q,ex_answerer_id,student_status,is_teacher_or,ex_status,ques_type,ex_type) answered_content = [] - user_score = 0.0 + user_score = nil shixun_type = 0 question_comment = [] - if q.question_type == 5 + # user_score_pre = nil + if ques_type == 5 exercise_answers = q.exercise_shixun_answers.search_shixun_answers("user_id",ex_answerer_id) else exercise_answers = q.exercise_answers.search_exercise_answer("user_id",ex_answerer_id) #试卷用户的回答 end if student_status == 2 #当前为老师,或为学生且已提交 - user_score = exercise_answers.score_reviewed.pluck(:score).sum + user_score_pre = exercise_answers.score_reviewed + if ques_type == 4 #主观题时,且没有大于0的分数时,为空 + user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : nil + elsif ques_type == 5 || ques_type == 3 + user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : 0.0 + else + if exercise_answers.present? #判断题和选择题时, + answer_choice_array = [] + exercise_answers.each do |a| + answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 + end + user_answer_content = answer_choice_array.sort + standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个 + if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 + user_score = q.question_score + else + user_score = 0.0 + end + else + user_score = 0.0 + end + end + end + + if user_score.present? && (user_score > q.question_score) + user_score = q.question_score end if ques_type <= 2 - answered_content = exercise_answers.pluck(:exercise_choice_id) + answered_content = exercise_answers&.pluck(:exercise_choice_id) elsif ques_type == 3 - exercise_answers.each do |a| + exercise_answers&.each do |a| u_answer = { "choice_id":a.exercise_choice_id, "answer_text": a.answer_text @@ -623,7 +722,7 @@ module ExercisesHelper answered_content.push(u_answer) end elsif ques_type == 4 - answered_content = exercise_answers.pluck(:answer_text) + answered_content = exercise_answers&.pluck(:answer_text) end if ques_type == 5 #存在实训题,及已经做了实训题的 if ex_status == 3 || is_teacher_or == 1 #如果试卷已截止,则可以看到分数,否则不能查看分数 @@ -638,7 +737,7 @@ module ExercisesHelper question_comment = q.exercise_answer_comments.search_answer_comments("exercise_answer_id",q_answer_id) end { - "user_score": user_score.round(1), + "user_score": (user_score.present? ? user_score.round(1).to_s : nil), "answered_content":answered_content, "shixun_type":shixun_type, "question_comment":question_comment @@ -662,8 +761,35 @@ module ExercisesHelper result end + def get_exercise_left_time(exercise,user) + ex_time = exercise.time + user_left_time = nil + time_now_i = Time.now.to_i + if ex_time > 0 + exercise_user = exercise.exercise_users.find_by(user_id:user.id) + time_mill = ex_time * 60 #转为秒 + exercise_end_time = exercise.end_time.present? ? exercise.end_time.to_i : 0 + exercise_user_start = exercise_user&.start_at.present? ? exercise_user.start_at.to_i : 0 + #用户未开始答题时,即exercise_user_start为0 + if exercise_user_start == 0 + if (exercise_end_time - time_now_i) > time_mill + user_left_time = time_mill + else + user_left_time = (exercise_end_time < time_now_i) ? nil : (exercise_end_time - time_now_i) + end + else + if (exercise_user_start + time_mill) > exercise_end_time + time_mill = exercise_end_time - exercise_user_start #如果开始答题时间加试卷的限时长大于试卷的截止时间,则以试卷的截止时间到开始答题时间为试卷的限时 + end + exercise_user_left_time = time_now_i - exercise_user_start #用户已回答的时间 + user_left_time = (time_mill < exercise_user_left_time) ? nil : (time_mill - exercise_user_left_time) #当前用户对试卷的回答剩余时间 + end + end + user_left_time + end + #实训题学生代码的行数 def content_line(content) - content.split(/\r?\n/).length + content.split(/\r?\n/).length + 1 end end diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb index a5e3c5d9d..742deb85b 100644 --- a/app/helpers/export_helper.rb +++ b/app/helpers/export_helper.rb @@ -35,16 +35,23 @@ module ExportHelper else head_cells_add = [] end - normal_head_b_cells = %w(最终成绩 提交时间 更新时间) + normal_head_b_cells = %w(最终成绩 提交时间 更新时间 评语) @work_head_cells = (head_cells_format + group_cells + normal_head_cells + head_cells_add + allow_late_cell + normal_head_b_cells).reject(&:blank?) - works.each_with_index do |w, index| + works.includes(user: :user_extension, student_works_scores: :user).each_with_index do |w, index| w_user = w.user w_1 = (index + 1) - w_2 = w_user.login - w_3 = w_user.real_name - w_3_1 = w_user.mail - w_4 = w_user.student_id.present? ? w_user.student_id : "--" - course_name = course.course_member(w.user_id).try(:course_group_name) + if w_user.present? + w_2 = w_user&.login.present? ? w_user&.login : "--" + w_3 = w_user&.real_name.present? ? w_user&.real_name : "--" + w_3_1 = w_user&.mail.present? ? w_user.mail : "--" + w_4 = w_user.student_id.present? ? w_user.student_id : "--" + else + w_2 = "--" + w_3 = "--" + w_3_1 = "--" + w_4 = "--" + end + course_name = course.students.find_by(user_id: w.user_id).try(:course_group_name) w_5 = course_name.present? ? course_name : "--" #0: 未提交, 1 按时提交, 2 延迟提交 if w.work_status == 0 @@ -85,8 +92,22 @@ module ExportHelper w_15 = w.work_score.nil? ? "未评分" : w.work_score.round(1) w_16 = w.commit_time ? format_time(w.commit_time) : "--" w_17 = w.update_time ? format_time(w.update_time) : "--" + teacher_comments = w.student_works_scores + if teacher_comments.present? + w_18 = "" + teacher_comments.each do |t| + user_name = t.user&.real_name + user_time = format_time(t.updated_at) + user_score = t&.score + user_comment = t.comment.present? ? t.comment : "--" + comment_title = "#{user_name}: #{user_time.to_s} #{user_score.to_s}分\n#{user_comment}\n\n" + w_18 = w_18 + comment_title + end + else + w_18 = "--" + end - row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17] + row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17,w_18] row_cells_column = row_cells_column.reject(&:blank?) @work_cells_column.push(row_cells_column) end @@ -102,17 +123,17 @@ module ExportHelper if allow_late_boolean #允许迟交 eff_score_cell.push("迟交扣分") end - shixun_time_cells = %w(最终成绩 更新时间 提交耗时) + shixun_time_cells = %w(最终成绩 更新时间 提交耗时 评语) @work_head_cells = (head_cells_format + shixun_head_cells + eff_score_cell + shixun_time_cells).reject(&:blank?) - works.each_with_index do |w, index| + works.includes(:student_works_scores, user: :user_extension, myshixun: :games).each_with_index do |w, index| myshixun = w.try(:myshixun) w_user = w.user w_1 = (index + 1) - w_2 = w_user.login - w_3 = w_user.real_name - w_3_1 = w_user.mail + w_2 = w_user&.login.present? ? w_user&.login : "--" + w_3 = w_user&.real_name.present? ? w_user&.real_name : "--" + w_3_1 = w_user&.mail.present? ? w_user.mail : "--" w_4 = w_user.student_id.present? ? w_user.student_id : "--" - course_name = course.course_member(w.user_id).try(:course_group_name) + course_name = course.students.find_by(user_id: w.user_id).try(:course_group_name) w_5 = course_name.present? ? course_name : "--" #0: 未提交, 1 按时提交, 2 延迟提交 if w.work_status == 0 @@ -124,7 +145,7 @@ module ExportHelper else w_6 = "--" end - w_7 = w.work_status == 0 ? '--' : myshixun.try(:passed_count).to_s+"/"+shixun.challenges.count.to_s + w_7 = w.work_status == 0 ? '--' : myshixun.try(:passed_count).to_s+"/"+shixun.challenges_count.to_s w_8 = myshixun ? myshixun.try(:passed_time) == "--" ? "--" : format_time(myshixun.try(:passed_time)) : "--" # 通关时间 w_9 = myshixun ? (myshixun.try(:passed_count) > 0 ? myshixun.total_spend_time : '--') : "--" #总耗时 w_10 = myshixun ? myshixun.output_times : 0 #评测次数 @@ -142,8 +163,22 @@ module ExportHelper end w_15 = w.work_score.nil? ? "--" : w.work_score.round(1) w_16 = w.update_time ? format_time(w.update_time) : "--" "更新时间" - w_17 = w.cost_time - row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17] + w_17 = (game_spend_time w.cost_time) + teacher_comments = w.student_works_scores + if teacher_comments.present? + w_18 = "" + teacher_comments.each do |t| + user_name = t.user&.real_name + user_time = format_time(t.updated_at) + user_score = t&.score + user_comment = t.comment.present? ? t.comment : "--" + comment_title = "#{user_name}: #{user_time.to_s} #{user_score.to_s}分\n#{user_comment}\n\n" + w_18 = w_18 + comment_title + end + else + w_18 = "--" + end + row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17,w_18] row_cells_column = row_cells_column.reject(&:blank?) @work_cells_column.push(row_cells_column) end @@ -170,17 +205,17 @@ module ExportHelper head_cells_format = head_cells_format + ["交叉评分"] end - head_cells_format = head_cells_format + %w(迟交扣分 最终成绩 提交时间 更新时间) + head_cells_format = head_cells_format + %w(迟交扣分 最终成绩 提交时间 更新时间 评语) @head_cells_column = head_cells_format @task_cells_column = [] - items.each_with_index do |work,index| + items.includes(user: :user_extension).each_with_index do |work,index| w_1 = (index+1) w_user = work.user - w_2 = w_user.login - w_3 = w_user.real_name - w_3_1 = w_user.mail + w_2 = w_user&.login.present? ? w_user&.login : "--" + w_3 = w_user&.real_name.present? ? w_user&.real_name : "--" + w_3_1 = w_user&.mail.present? ? w_user.mail : "--" w_4 = w_user.student_id.present? ? w_user.student_id : "--" w_5 = work.class_grouping_name if task_type_boolean #是否分组 @@ -188,7 +223,16 @@ module ExportHelper else w_6 = nil end - w_7 = work.work_status + w_status = work.work_status.to_i + if w_status == 0 + w_7 = "未提交" + elsif w_status == 1 + w_7 = "按时提交" + elsif w_status == 2 + w_7 = "延时提交" + else + w_7 = "--" + end if task_project_boolean #关联项目 w_project = project_info work, current_user, @user_course_identity #因为课堂引用了export_helper w_8 = w_project[:name] @@ -212,8 +256,22 @@ module ExportHelper w_13 = work.work_score.nil? ? "未评分" : work.work_score.round(1) w_14 = work.commit_time.present? ? format_time(work.commit_time) : "--" w_15 = work.update_time.present? ? format_time(work.update_time) : "--" - - row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15] + teacher_comments = work.graduation_work_scores + if teacher_comments.present? + w_16 = "" + teacher_comments.each do |t| + user_name = t.user&.real_name + user_time = format_time(t.updated_at) + user_score = t&.score + user_comment = t.comment.present? ? t.comment : "--" + comment_title = "#{user_name}: #{user_time.to_s} #{user_score.to_s}分\n#{user_comment}\n\n" + # ("教师:" + user_name + "\n" + "时间:" + user_time.to_s + "\n" + "分数:" + user_score.to_s + "分" + "\n" + "评语:" + user_comment + "\n\n") + w_16 = w_16 + comment_title + end + else + w_16 = "--" + end + row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16] row_cells_column = row_cells_column.reject(&:blank?) @task_cells_column.push(row_cells_column) @@ -231,21 +289,11 @@ module ExportHelper else @table_columns = @table_columns + %w(最终成绩 开始答题时间 提交时间) end - export_ex_users.each_with_index do |e_user,index| + export_ex_users.includes(user: :user_extension).each_with_index do |e_user,index| user_info = e_user.user - user_course_id = user_info.course_members.course_find_by_ids("course_id",course.id).first - if user_course_id.present? - get_course_group_id = user_course_id.course_group_id - if get_course_group_id.present? && get_course_group_id != 0 - user_course_info = CourseGroup.by_group_ids(get_course_group_id) - user_course = user_course_info.first.name - else - user_course = "--" - end - else - user_course = "--" - end - user_obj_score = e_user.objective_score < 0.0 ? 0.0 : e_user.subjective_score.round(1).to_s + member = course.students.find_by_user_id(e_user.user_id) + user_course = member.try(:course_group_name) + user_obj_score = e_user.objective_score < 0.0 ? 0.0 : e_user.objective_score.round(1).to_s user_suj_score = e_user.subjective_score < 0.0 ? 0.0 : e_user.subjective_score.round(1).to_s user_score = e_user.score.present? ? e_user.score.round(1).to_s : 0.0 if e_user.commit_status.present? && e_user.commit_status == 1 @@ -256,8 +304,11 @@ module ExportHelper user_start_time = e_user.start_at.present? ? e_user.start_at.strftime('%Y-%m-%d %H:%M') : "--" user_end_time = e_user.end_at.present? ? e_user.end_at.strftime('%Y-%m-%d %H:%M') : "--" user_student_id = user_info.student_id.present? ? user_info.student_id : "--" + user_login = user_info&.login.present? ? user_info.login : "--" + user_real_name = user_info.real_name.present? ? user_info.real_name : "--" + user_mail = user_info&.mail.present? ? user_info.mail : "--" - user_option = [index+1,user_info.login,user_info.real_name, user_info.mail || '--', + user_option = [index+1,user_login,user_real_name, user_mail, user_student_id,user_course,user_commit_stu] if ques_type_boolean other_user_option = [user_obj_score,user_suj_score,user_score,user_start_time,user_end_time] @@ -276,7 +327,7 @@ module ExportHelper @topic_body_cells = [] if students.count > 0 - students.each_with_index do |student, index| + students.includes(user: :user_extension).each_with_index do |student, index| user = student.user student_topic = course.student_graduation_topics.user_topics_accept(user.id).first if student_topic.present? @@ -286,11 +337,11 @@ module ExportHelper topic = nil end w_1 = (index+1) - w_2 = user.login - w_3 = user.real_name - w_3_1 = user.mail - w_4 = user.user_extension.student_id - w_5 = student.course_group_name + w_2 = user&.login.present? ? user&.login : "--" + w_3 = user&.real_name.present? ? user&.real_name : "--" + w_3_1 = user&.mail.present? ? user.mail : "--" + w_4 = user.student_id.present? ? user.student_id : "--" + w_5 = student&.course_group_name.present? ? student.course_group_name : "--" w_6 = topic.present? ? topic.name : "--" w_7 = topic.present? ? topic.teacher.full_name : "--" w_8 = topic.present? ? topic.teacher.identity : "--" @@ -346,11 +397,11 @@ module ExportHelper end if file_size > MAX_DOWN_SIZE - status = -1 + status = -2 elsif file_count > 0 status = 0 else - status = -2 + status = -1 end status end @@ -459,6 +510,8 @@ module ExportHelper zipfile_name = "#{output_path}/#{rename_zipfile}" + # 同名文件重命名时用 + index = 1 Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name)) Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile| files_paths.each do |filename| @@ -468,7 +521,11 @@ module ExportHelper begin zipfile.add(rename_file, filename) rescue Exception => e - zipfile.get_output_stream('FILE_NOTICE.txt'){|os| os.write "该作品中有重复命名文件,请通过文件名学号和姓名信息进入该作业详细界面手动下载"} + rename_file = rename_same_file(rename_file, index) + index += 1 + zipfile.add(rename_file, filename) + + # zipfile.get_output_stream('FILE_NOTICE.txt'){|os| os.write "该作品中有重复命名文件,请通过文件名学号和姓名信息进入该作业详细界面手动下载"} next end end @@ -485,4 +542,14 @@ module ExportHelper attach.filename end + def format_sheet_name name + name = name.gsub(":", "-") + end + + def rename_same_file(name, index) + basename = File.basename(name, ".*") + new_basename = basename + "_" + index.to_s + extname = File.extname(name) + new_basename + extname + end end diff --git a/app/helpers/graduation_tasks_helper.rb b/app/helpers/graduation_tasks_helper.rb index 5253b0d56..2bc059a55 100644 --- a/app/helpers/graduation_tasks_helper.rb +++ b/app/helpers/graduation_tasks_helper.rb @@ -14,7 +14,7 @@ module GraduationTasksHelper # 交叉评阅 def cross_comment task, user_id - if task.cross_comment + if task.cross_comment && task.status >= 3 [{id: 1, name: "只看我的交叉评阅", count: task.graduation_work_comment_assignations.myself(user_id).count}] else [] @@ -67,7 +67,7 @@ module GraduationTasksHelper # 作品数统计:type: 1 已提交 0 未提交 def grduationwork_count task, type works = task.graduation_works - type == 1 ? works.where("work_status !=?", 0).size : works.where("work_status =?", 0).size + type == 1 ? works.select{|work| work.work_status != 0}.size : works.select{|work| work.work_status == 0}.size end # 普通/分组 作业作品状态数组 @@ -131,4 +131,20 @@ module GraduationTasksHelper end end end + + # 阶段剩余时间 + def task_left_time task + if task.publish_time && task.publish_time < Time.now + if task.end_time > Time.now + status = "剩余提交时间" + time = "#{how_much_time(task.end_time)}" + else + if task.allow_late && task.late_time && task.late_time >= Time.now + status = "剩余补交时间" + time = "#{how_much_time(task.late_time)}" + end + end + end + {status: status, time: time} + end end diff --git a/app/helpers/graduation_works_helper.rb b/app/helpers/graduation_works_helper.rb index 177720d24..577efa797 100644 --- a/app/helpers/graduation_works_helper.rb +++ b/app/helpers/graduation_works_helper.rb @@ -15,7 +15,6 @@ module GraduationWorksHelper end end # work_score 最终成绩; late_penalty 迟交扣分; final_score 最终评分 - {username: work.user.full_name, login: work.user.login, work_score: work_score, final_score: work.final_score, - late_penalty:work.late_penalty } + {username: work.user.full_name, login: work.user.login, work_score: work_score, final_score: work.final_score} end end diff --git a/app/helpers/homework_commons_helper.rb b/app/helpers/homework_commons_helper.rb index 0d166729c..c77ae5937 100644 --- a/app/helpers/homework_commons_helper.rb +++ b/app/helpers/homework_commons_helper.rb @@ -65,7 +65,7 @@ module HomeworkCommonsHelper # 作业统一设置、游客身份、超级管理员、分班权限不限的老师身份 if homework_common.unified_setting || identity > Course::STUDENT || identity == Course::ADMIN || - (identity < Course::STUDENT && teacher_course_groups.size == 0) + (identity < Course::STUDENT && teacher_course_groups.blank?) case ho_detail_manual.comment_status when 0 status << "未发布" @@ -174,9 +174,9 @@ module HomeworkCommonsHelper end # 作品数统计:type: 1 已提交 0 未提交 - def studentwork_count homework_common, type, user_id - student_works = homework_common.teacher_works(user_id) - type == 1 ? student_works.select{|work| work.work_status != 0}.size : student_works.select{|work| work.work_status = 0}.size + def studentwork_count homework_common, type, member + student_works = homework_common.teacher_works(member) + type == 1 ? student_works.where("work_status != 0").size : student_works.where(work_status: 0).size end # 上次查重的时间 @@ -223,10 +223,10 @@ module HomeworkCommonsHelper end # 作品状态 - def homework_status homework, user_id - [{id: 0, name: "未提交", count: homework.unfinished_count(user_id)}, - {id: 1, name: "按时提交", count: homework.finished_count(user_id)}, - {id: 2, name: "延时提交", count: homework.delay_finished_count(user_id)}] + def homework_status homework, member + [{id: 0, name: "未提交", count: homework.unfinished_count(member)}, + {id: 1, name: "按时提交", count: homework.finished_count(member)}, + {id: 2, name: "延时提交", count: homework.delay_finished_count(member)}] end # 作品分数的显示 diff --git a/app/helpers/polls_helper.rb b/app/helpers/polls_helper.rb index 5b4702174..52e90f559 100644 --- a/app/helpers/polls_helper.rb +++ b/app/helpers/polls_helper.rb @@ -1,11 +1,15 @@ module PollsHelper #获取试卷的已答/未答人数 - def get_poll_answers(poll_users) - @commit_poll_users = poll_users.commit_by_status(1) #当前老师的全部学生中已提交的 - @poll_answers = @commit_poll_users.present? ? @commit_poll_users.count : 0 #表示已经提交了的用户 - course_all_members_count = poll_users.present? ? poll_users.count : 0 - @poll_unanswers = (course_all_members_count - @poll_answers) + def get_poll_answers(poll_users, status) + if status == 1 + @poll_answers = 0 + @poll_unanswers = 0 + else + @poll_answers = poll_users.commit_by_status(1).size #表示已经提交了的用户 + course_all_members_count = poll_users.size + @poll_unanswers = (course_all_members_count - @poll_answers) + end end def poll_votes_count(votes,user_ids) @@ -55,29 +59,29 @@ module PollsHelper #当前为老师(非课堂成员、统一设置)的时候,显示的是老师身份的对应试卷的状态,因为该试卷,可能对应老师的多个分班 poll_status = poll.polls_status else - poll_status = poll.get_poll_status(user.id) #当前用户查看的试卷的发布状态 + poll_status = poll.get_poll_status(user) #当前用户查看的试卷的发布状态 end if is_teacher_or == 1 poll_users_list = poll.all_poll_users(user.id) #当前老师所在班级的全部学生 - get_poll_answers(poll_users_list) + get_poll_answers(poll_users_list, poll_status) ex_pb_time = poll.get_poll_times(user.id,true) poll_publish_time = ex_pb_time[:publish_time] poll_end_time = ex_pb_time[:end_time] current_status = 3 - lock_icon = 1 #不显示锁图标 + lock_icon = 0 #不显示锁图标 elsif is_teacher_or == 2 poll_users_list = poll.get_poll_exercise_users - get_poll_answers(poll_users_list) # 未答和已答的 + get_poll_answers(poll_users_list, poll_status) # 未答和已答的 # get_poll_answers(poll_all_users) ex_pb_time = poll.get_poll_times(user.id,false) poll_publish_time = ex_pb_time[:publish_time] poll_end_time = ex_pb_time[:end_time] current_status = poll.check_user_votes_status(user) - lock_icon = 1 #不显示锁图标 + lock_icon = 0 #不显示锁图标 else poll_users_list = poll.get_poll_exercise_users - get_poll_answers(poll_users_list) # 未答和已答的 + get_poll_answers(poll_users_list, poll_status) # 未答和已答的 poll_publish_time = poll.publish_time poll_end_time = poll.end_time current_status = 4 @@ -87,6 +91,9 @@ module PollsHelper lock_icon = 0 #显示锁图标 end end + if (course.is_public == 1) && poll.is_public + lock_icon = 1 + end { "publish_time":poll_publish_time, "end_time":poll_end_time, @@ -110,15 +117,22 @@ module PollsHelper poll_user_name = user.nickname end course_member = course_members.find_by(user_id:user.id) - current_user_group_id = course_members.present? ? course_member.course_group_id : nil - course_group = course.course_groups.find_by_id(current_user_group_id) + course_group_id = course_member.present? ? course_member.course_group_id : nil + if course_group_id == 0 + course_group_name = "未分班" + else + course_group = course.course_groups.find_by_id(course_group_id) + course_group_id = course_group&.id + course_group_name = course_group&.name + end { "user_name":poll_user_name, "user_id": user.id, "student_id":user_student_id, - "group_name":course_group.try(:name), - "group_id":course_group.try(:id), + "group_name":course_group_name, + "group_id":course_group_id, "login":user.login } end + end diff --git a/app/helpers/student_works_helper.rb b/app/helpers/student_works_helper.rb index 93a1a3f9a..a7103b4bf 100644 --- a/app/helpers/student_works_helper.rb +++ b/app/helpers/student_works_helper.rb @@ -41,7 +41,7 @@ module StudentWorksHelper def student_efficiency(homework_common, work) myshixun_ids = homework_common.student_works.pluck(:myshixun_id) - myshixuns = Myshixun.where(id: myshixun_ids).includes(games: [:outputs]) + myshixuns = Myshixun.where(id: myshixun_ids).includes(:games) #student_works_user_id = homework_common.student_works.pluck(:user_id).uniq #shixun = homework_common.shixuns.first #logger.info("#########shixun_id: ###{shixun.id}") @@ -54,11 +54,11 @@ module StudentWorksHelper objects = myshixuns.map do |myshixun| # 评测次数 - evaluate_count = myshixun.games.inject(0) {|sum, g| sum + g.outputs.pluck(:query_index).first.to_i} + evaluate_count = myshixun.games.pluck(:evaluate_count).sum # 获取最大评测次数 max_evaluate_count = (evaluate_count > max_evaluate_count ? evaluate_count : max_evaluate_count) # 通关耗时 - pass_consume_time = (myshixun.games.where(status: 2).pluck(:cost_time).sum / 60.0) + pass_consume_time = (myshixun.total_cost_time / 60.0) # 总耗时 all_time = (myshixun.games.pluck(:cost_time).sum / 60.0) # 通关得分 @@ -145,7 +145,7 @@ module StudentWorksHelper else user_name = message_user.real_name user_login = message_user.login - image_url = url_to_avatar(score.user) + image_url = url_to_avatar(message_user) end {user_name: user_name, user_login: user_login, user_image_url: image_url} end diff --git a/app/jobs/course_add_student_create_works_job.rb b/app/jobs/course_add_student_create_works_job.rb new file mode 100644 index 000000000..d8bd6363c --- /dev/null +++ b/app/jobs/course_add_student_create_works_job.rb @@ -0,0 +1,67 @@ +# 学生加入课堂时创建相关任务作品 +class CourseAddStudentCreateWorksJob < ApplicationJob + queue_as :default + + def perform(course_id, student_ids) + course = Course.find_by(id: course_id) + return if course.blank? + + # 如果之前存在相关作品,则更新is_delete字段 + student_works = StudentWork.joins(:homework_common).where(user_id: student_ids, homework_commons: {course_id: course.id}) + student_works.update_all(is_delete: 0) + + exercise_users = ExerciseUser.joins(:exercise).where(user_id: student_ids, exercises: {course_id: course.id}) + exercise_users.update_all(is_delete: 0) + + poll_users = PollUser.joins(:poll).where(user_id: student_ids, polls: {course_id: course.id}) + poll_users.update_all(is_delete: 0) + + graduation_works = course.graduation_works.where(user_id: student_ids) + graduation_works.update_all(is_delete: 0) + + attrs = %i[homework_common_id user_id created_at updated_at] + + StudentWork.bulk_insert(*attrs) do |worker| + student_ids.each do |user_id| + same_attrs = {user_id: user_id} + course.homework_commons.where(homework_type: %i[normal group practice]).each do |homework| + next if homework.student_works.where(user_id: user_id).any? + worker.add same_attrs.merge(homework_common_id: homework.id) + end + end + end + + attrs = %i[exercise_id user_id created_at updated_at] + ExerciseUser.bulk_insert(*attrs) do |worker| + student_ids.each do |user_id| + same_attrs = {user_id: user_id} + course.exercises.each do |exercise| + next if exercise.exercise_users.where(user_id: user_id).any? + worker.add same_attrs.merge(exercise_id: exercise.id) + end + end + end + + attrs = %i[poll_id user_id created_at updated_at] + PollUser.bulk_insert(*attrs) do |worker| + student_ids.each do |user_id| + same_attrs = {user_id: user_id} + course.polls.each do |poll| + next if poll.poll_users.where(user_id: user_id).any? + worker.add same_attrs.merge(poll_id: poll.id) + end + end + end + + attrs = %i[graduation_task_id user_id course_id created_at updated_at] + GraduationWork.bulk_insert(*attrs) do |worker| + student_ids.each do |user_id| + same_attrs = {user_id: user_id, course_id: course.id} + course.graduation_tasks.each do |task| + next if task.graduation_works.where(user_id: user_id).any? + worker.add same_attrs.merge(graduation_task_id: task.id) + end + end + end + end +end diff --git a/app/jobs/course_delete_student_delete_works_job.rb b/app/jobs/course_delete_student_delete_works_job.rb new file mode 100644 index 000000000..a84608b2c --- /dev/null +++ b/app/jobs/course_delete_student_delete_works_job.rb @@ -0,0 +1,19 @@ +class CourseDeleteStudentDeleteWorksJob < ApplicationJob + queue_as :default + + def perform(course_id, student_ids) + course = Course.find_by(id: course_id) + return if course.blank? + + student_works = StudentWork.joins(:homework_common).where(user_id: student_ids, homework_commons: {course_id: course.id}) + student_works.update_all(is_delete: 1) + + exercise_users = ExerciseUser.joins(:exercise).where(user_id: student_ids, exercises: {course_id: course.id}) + exercise_users.update_all(is_delete: 1) + + poll_users = PollUser.joins(:poll).where(user_id: student_ids, polls: {course_id: course.id}) + poll_users.update_all(is_delete: 1) + + course.graduation_works.where(user_id: student_ids).update_all(is_delete: 1) + end +end diff --git a/app/jobs/exercise_publish_notify_job.rb b/app/jobs/exercise_publish_notify_job.rb index c66fa5660..9c43b1978 100644 --- a/app/jobs/exercise_publish_notify_job.rb +++ b/app/jobs/exercise_publish_notify_job.rb @@ -2,10 +2,20 @@ class ExercisePublishNotifyJob < ApplicationJob queue_as :notify - def perform(exercise_id, receiver_ids) + def perform(exercise_id, group_ids) exercise = Exercise.find_by(id: exercise_id) return if exercise.blank? user = exercise.user + course = exercise.course + + if group_ids.present? + students = course.students.where(course_group_id: group_ids) + subquery = course.teacher_course_groups.where(course_group_id: group_ids).select(:course_member_id) + teachers = course.teachers.where(id: subquery) + else + students = course.students + teachers = course.teachers + end attrs = %i[ user_id trigger_user_id container_id container_type parent_container_id parent_container_type @@ -19,14 +29,14 @@ class ExercisePublishNotifyJob < ApplicationJob viewed: 0, tiding_type: 'Exercise' } Tiding.bulk_insert(*attrs) do |worker| - teacher_ids = exercise.course.teachers.pluck(:user_id) + teacher_ids = teachers.pluck(:user_id) unless exercise.tidings.exists?(parent_container_type: 'ExercisePublish', user_id: teacher_ids) - exercise.course.teachers.find_each do |teacher| - worker.add same_attrs.merge(user_id: teacher.user_id) + teacher_ids.each do |user_id| + worker.add same_attrs.merge(user_id: user_id) end end - receiver_ids.each do |user_id| + students.pluck(:user_id).each do |user_id| worker.add same_attrs.merge(user_id: user_id) end end diff --git a/app/jobs/graduation_task_cross_comment_job.rb b/app/jobs/graduation_task_cross_comment_job.rb new file mode 100644 index 000000000..cf2cb613e --- /dev/null +++ b/app/jobs/graduation_task_cross_comment_job.rb @@ -0,0 +1,39 @@ +# 毕设任务的交叉评阅分配 +class GraduationTaskCrossCommentJob < ApplicationJob + queue_as :default + + def perform(graduation_task_id) + task = GraduationTask.find_by(id: graduation_task_id) + return if task.blank? + + course = task.course + task.graduation_task_group_assignations.each do |assignation| + graduation_group = assignation.graduation_group + assign_group = assignation.assign_group + if graduation_group.present? && assign_group.present? + course_group_ids = course.teacher_course_groups.where(course_member_id: graduation_group.course_members.pluck(:id)).pluck(:course_group_id) + graduation_works = task.graduation_works.where(user_id: course.course_members.where(:course_group_id => course_group_ids).map(&:user_id), + work_status: [1, 2]) + if assign_group.course_members.count <= task.comment_num + graduation_works.each do |work| + assign_group.course_members.each do |member| + work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new( + graduation_group_id: assign_group.id, user_id: member.user_id, graduation_task_id: task.id) + end + end + else + member_user_ids = assign_group.course_members.pluck(:user_id) + count = 0 + graduation_works.each do |work| + for i in 1 .. task.comment_num + assign_user_id = member_user_ids[count % member_user_ids.size] + work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new( + graduation_group_id: assign_group.id, user_id: assign_user_id, graduation_task_id: task.id) + count += 1 + end + end + end + end + end + end +end diff --git a/app/jobs/graduation_task_publish_notify_job.rb b/app/jobs/graduation_task_publish_notify_job.rb index 3489aa711..84049fe90 100644 --- a/app/jobs/graduation_task_publish_notify_job.rb +++ b/app/jobs/graduation_task_publish_notify_job.rb @@ -5,6 +5,8 @@ class GraduationTaskPublishNotifyJob < ApplicationJob def perform(graduation_task_id) task = GraduationTask.find_by(id: graduation_task_id) return if task.blank? + course = task.course + return if course.blank? attrs = %i[ user_id trigger_user_id container_id container_type parent_container_id parent_container_type @@ -18,8 +20,8 @@ class GraduationTaskPublishNotifyJob < ApplicationJob viewed: 0, tiding_type: 'GraduationTask' } Tiding.bulk_insert(*attrs) do |worker| - task.course.students.find_each do |student| - worker.add same_attrs.merge(user_id: student.user_id) + course.course_members.pluck(:user_id).uniq.each do |user_id| + worker.add same_attrs.merge(user_id: user_id) end end end diff --git a/app/jobs/homework_absence_penalty_calculation_job.rb b/app/jobs/homework_absence_penalty_calculation_job.rb new file mode 100644 index 000000000..02836d9ec --- /dev/null +++ b/app/jobs/homework_absence_penalty_calculation_job.rb @@ -0,0 +1,33 @@ +class HomeworkAbsencePenaltyCalculationJob < ApplicationJob + queue_as :default + + def perform(homework_common_id) + homework_common = HomeworkCommon.find_by(id: homework_common_id) + return if homework_common.blank? + + #计算缺评扣分 参与匿评 + work_ids = homework_common.student_works.has_committed.pluck(:id) + homework_detail_manual = homework_common.homework_detail_manual + + homework_common.student_works.where("work_status != 0").each do |student_work| + absence_penalty_count = student_work.user.student_works_evaluation_distributions.where(student_work_id: work_ids).count - + student_work.user.student_works_scores.where(student_work_id: work_ids, reviewer_role: 3).group_by(&:student_work_id).count + + student_work.absence_penalty = absence_penalty_count > 0 ? absence_penalty_count * homework_detail_manual.absence_penalty : 0 + student_work.save + end + + # 未参与匿评 + if homework_detail_manual.no_anon_penalty == 0 + all_dis_eva = StudentWorksEvaluationDistribution.where(student_work_id: work_ids) + has_sw_count = all_dis_eva.select("distinct user_id").count + anon_count = all_dis_eva.count / has_sw_count + homework_common.student_works.where("work_status != 0").each do |student_work| + if student_work.user.student_works_evaluation_distributions.where(student_work_id: work_ids).count == 0 + student_work.absence_penalty = homework_detail_manual.absence_penalty * anon_count + student_work.save + end + end + end + end +end diff --git a/app/jobs/homework_anonymous_appeal_start_notify_job.rb b/app/jobs/homework_anonymous_appeal_start_notify_job.rb new file mode 100644 index 000000000..1c3098690 --- /dev/null +++ b/app/jobs/homework_anonymous_appeal_start_notify_job.rb @@ -0,0 +1,28 @@ +# 匿评申诉开启时给分配了匿评的学生发消息 +class HomeworkAnonymousAppealStartNotifyJob < ApplicationJob + queue_as :notify + + def perform(homework_common_id) + homework = HomeworkCommon.find_by(id: homework_common_id) + return if homework.blank? + eva_distribution = StudentWorksEvaluationDistribution.where(student_work_id: homework.student_works.pluck(:id)) + + attrs = %i[ + user_id trigger_user_id container_id container_type parent_container_id parent_container_type + belong_container_id belong_container_type viewed tiding_type created_at updated_at + ] + + same_attrs = { + trigger_user_id: homework.user_id, container_id: homework.id, container_type: 'HomeworkCommon', + parent_container_id: homework.id, parent_container_type: 'AnonymousAppeal', + belong_container_id: homework.course_id, belong_container_type: 'Course', + viewed: 0, tiding_type: 'HomeworkCommon' + } + Tiding.bulk_insert(*attrs) do |worker| + + eva_distribution.pluck(:user_id).uniq.each do |user_id| + worker.add same_attrs.merge(user_id: user_id) + end + end + end +end diff --git a/app/jobs/homework_common_push_notify_job.rb b/app/jobs/homework_common_push_notify_job.rb index 961face58..47956a14c 100644 --- a/app/jobs/homework_common_push_notify_job.rb +++ b/app/jobs/homework_common_push_notify_job.rb @@ -24,7 +24,7 @@ class HomeworkCommonPushNotifyJob < ApplicationJob same_attrs = { trigger_user_id: homework.user_id, container_id: homework.id, container_type: 'HomeworkCommon', parent_container_id: homework.id, parent_container_type: 'HomeworkPublish', - belong_container_id: task.course_id, belong_container_type: 'Course', + belong_container_id: homework.course_id, belong_container_type: 'Course', viewed: 0, tiding_type: 'HomeworkCommon' } Tiding.bulk_insert(*attrs) do |worker| diff --git a/app/jobs/homework_end_update_score_job.rb b/app/jobs/homework_end_update_score_job.rb new file mode 100644 index 000000000..4ba4502fc --- /dev/null +++ b/app/jobs/homework_end_update_score_job.rb @@ -0,0 +1,33 @@ +class HomeworkEndUpdateScoreJob < ApplicationJob + # 不允许补交的作业截止后,或者补交截止后需要重新计算一次作业成绩 + queue_as :default + + def perform(homework_id) + homework = HomeworkCommon.find_by(id: homework_id) + return if homework.blank? + course = homework.course + return if course.blank? + + if homework.unified_setting + student_works = homework.student_works + user_ids = course.students.pluck(:user_id) + else + user_ids = course.students.where(course_group_id: homework.published_settings.pluck(:course_group_id)).pluck(:user_id) + student_works = homework.student_works.where(user_id: user_ids) + end + + shixun_id = homework.homework_commons_shixun.try(:shixun_id) + myshixuns = Myshixun.where(shixun_id: shixun_id, user_id: user_ids). + includes(:games).where(games: {challenge_id: homework.homework_challenge_settings.pluck(:challenge_id)}) + challenge_settings = homework.homework_challenge_settings + myshixuns.find_each(batch_size: 100) do |myshixun| + work = student_works.select{|work| work.user_id == myshixun.user_id}.first + if work && myshixun && (work.update_time.nil? || work.update_time < myshixun.updated_at) + games = myshixun.games.where(challenge_id: challenge_settings.pluck(:challenge_id)) + HomeworksService.new.update_myshixun_work_score work, myshixun, games, homework, challenge_settings + end + end + HomeworksService.new.update_student_eff_score homework + homework.update_attribute('calculation_time', Time.now) + end +end diff --git a/app/jobs/homework_evaluation_comment_assgin_job.rb b/app/jobs/homework_evaluation_comment_assgin_job.rb new file mode 100644 index 000000000..25a7f0a24 --- /dev/null +++ b/app/jobs/homework_evaluation_comment_assgin_job.rb @@ -0,0 +1,48 @@ +class HomeworkEvaluationCommentAssginJob < ApplicationJob + queue_as :default + + def get_assigned_homeworks(student_works, n, index) + student_works += student_works + student_works[index + 1..index + n] + end + + def perform(homework_common_id) + homework_common = HomeworkCommon.find_by(id: homework_common_id) + return if homework_common.blank? + homework_detail_manual = homework_common.homework_detail_manual + + if homework_common.homework_type == "group" + student_works = homework_common.student_works.where("work_status != 0").group(:group_id) + student_work_projects = homework_common.student_works.where("work_status != 0").shuffle + student_work_projects.each do |pro_work| + n = homework_detail_manual.evaluation_num + n = (n < student_works.length && n != -1) ? n : student_works.length - 1 + work_index = -1 + student_works.each_with_index do |stu_work, stu_index| + if stu_work.group_id.to_i == pro_work.group_id.to_i + work_index = stu_index + end + end + assigned_homeworks = get_assigned_homeworks(student_works, n, work_index) + assigned_homeworks.each do |h| + student_works_evaluation_distributions = StudentWorksEvaluationDistribution.new(user_id: pro_work.user_id, student_work_id: h.id) + student_works_evaluation_distributions.save + end + end + + else + student_works = homework_common.student_works.has_committed + student_works = student_works.shuffle + student_works.each_with_index do |work, index| + user = work.user + n = homework_detail_manual.evaluation_num + n = (n < student_works.size && n != -1) ? n : student_works.size - 1 + assigned_homeworks = get_assigned_homeworks(student_works, n, index) + assigned_homeworks.each do |h| + student_works_evaluation_distributions = StudentWorksEvaluationDistribution.new(user_id: user.id, student_work_id: h.id) + student_works_evaluation_distributions.save + end + end + end + end +end diff --git a/app/jobs/homework_evaluation_start_notify_job.rb b/app/jobs/homework_evaluation_start_notify_job.rb new file mode 100644 index 000000000..709c37b32 --- /dev/null +++ b/app/jobs/homework_evaluation_start_notify_job.rb @@ -0,0 +1,30 @@ +class HomeworkEvaluationStartNotifyJob < ApplicationJob + queue_as :notify + + def perform(homework_common_id, content) + homework = HomeworkCommon.find_by(id: homework_common_id) + return if homework.blank? + course = homework.course + members = content.blank? ? course.course_members : course.teachers + tiding_type = content.blank? ? "HomeworkCommon" : "System" + + attrs = %i[ + user_id trigger_user_id container_id container_type parent_container_id parent_container_type + belong_container_id belong_container_type viewed tiding_type extra created_at updated_at + ] + + same_attrs = { + trigger_user_id: homework.user_id, container_id: homework.id, container_type: 'HomeworkCommon', + parent_container_id: homework.id, parent_container_type: 'AnonymousComment', + belong_container_id: homework.course_id, belong_container_type: 'Course', + viewed: 0, tiding_type: tiding_type, extra: content + } + Tiding.bulk_insert(*attrs) do |worker| + member_ids = members.pluck(:user_id).uniq + + member_ids.each do |user_id| + worker.add same_attrs.merge(user_id: user_id) + end + end + end +end diff --git a/app/jobs/poll_publish_notify_job.rb b/app/jobs/poll_publish_notify_job.rb index bc31957e0..52660abd1 100644 --- a/app/jobs/poll_publish_notify_job.rb +++ b/app/jobs/poll_publish_notify_job.rb @@ -2,10 +2,20 @@ class PollPublishNotifyJob < ApplicationJob queue_as :notify - def perform(poll_id, receiver_ids) + def perform(poll_id, group_ids) poll = Poll.find_by(id: poll_id) return if poll.blank? user = poll.user + course = poll.course + + if group_ids.present? + students = course.students.where(course_group_id: group_ids) + subquery = course.teacher_course_groups.where(course_group_id: group_ids).select(:course_member_id) + teachers = course.teachers.where(id: subquery) + else + students = course.students + teachers = course.teachers + end attrs = %i[ user_id trigger_user_id container_id container_type parent_container_id parent_container_type @@ -19,14 +29,14 @@ class PollPublishNotifyJob < ApplicationJob viewed: 0, tiding_type: 'Poll' } Tiding.bulk_insert(*attrs) do |worker| - teacher_ids = poll.course.teachers.pluck(:user_id) + teacher_ids = teachers.pluck(:user_id) unless poll.tidings.exists?(parent_container_type: 'PollPublish', user_id: teacher_ids) - poll.course.teachers.find_each do |teacher| - worker.add same_attrs.merge(user_id: teacher.user_id) + teacher_ids.each do |user_id| + worker.add same_attrs.merge(user_id: user_id) end end - receiver_ids.each do |user_id| + students.pluck(:user_id).each do |user_id| worker.add same_attrs.merge(user_id: user_id) end end diff --git a/app/jobs/submit_graduation_work_notify_job.rb b/app/jobs/submit_graduation_work_notify_job.rb index 17cfc21d2..d4bb21cc4 100644 --- a/app/jobs/submit_graduation_work_notify_job.rb +++ b/app/jobs/submit_graduation_work_notify_job.rb @@ -19,11 +19,12 @@ class SubmitGraduationWorkNotifyJob < ApplicationJob next unless User.exists?(id: user_id) work = task.graduation_works.find_by(user_id: user_id) - next if work.blank? + member = course.students.find_by(user_id: user_id) + next if work.blank? || member.blank? attrs = same_attrs.merge(trigger_user_id: user_id, container_id: work.id) - course.course_member(user_id).member_teachers.find_each do |teacher| + member.member_teachers.find_each do |teacher| worker.add attrs.merge(user_id: teacher.user_id) end end diff --git a/app/jobs/submit_student_work_notify_job.rb b/app/jobs/submit_student_work_notify_job.rb index acb7873ac..c4dff264c 100644 --- a/app/jobs/submit_student_work_notify_job.rb +++ b/app/jobs/submit_student_work_notify_job.rb @@ -19,11 +19,12 @@ class SubmitStudentWorkNotifyJob < ApplicationJob next unless User.exists?(id: user_id) work = homework.student_works.find_by(user_id: user_id) - next if work.blank? + member = course.students.find_by(user_id: user_id) + next if work.blank? || member.blank? attrs = same_attrs.merge(trigger_user_id: user_id, container_id: work.id) - course.course_member(user_id).member_teachers.find_each do |teacher| + member.member_teachers.find_each do |teacher| worker.add attrs.merge(user_id: teacher.user_id) end end diff --git a/app/jobs/update_myshixun_work_status_job.rb b/app/jobs/update_myshixun_work_status_job.rb new file mode 100644 index 000000000..27a53408f --- /dev/null +++ b/app/jobs/update_myshixun_work_status_job.rb @@ -0,0 +1,10 @@ +class UpdateMyshixunWorkStatusJob < ApplicationJob + queue_as :default + + def perform(myshixun_id) + myshixun = Myshixun.find_by(id: myshixun_id) + return if myshixun.blank? + + HomeworksService.new.update_myshixun_work_status myshixun + end +end diff --git a/app/libs/base64_image_converter.rb b/app/libs/base64_image_converter.rb index 2a8155283..2dc9aa41e 100644 --- a/app/libs/base64_image_converter.rb +++ b/app/libs/base64_image_converter.rb @@ -35,7 +35,7 @@ class Base64ImageConverter end def size_limit - EduSetting.find_by_name('upload_avatar_max_size')&.value + EduSetting.get('upload_avatar_max_size') end class Image diff --git a/app/libs/util.rb b/app/libs/util.rb index f6c8855b9..6c7784606 100644 --- a/app/libs/util.rb +++ b/app/libs/util.rb @@ -28,4 +28,18 @@ module Util end end end + + def logger_error(exception) + Rails.logger.error(exception.message) + exception.backtrace.each { |message| Rails.logger.error(message) } + end + + def map_or_pluck(relation, name) + relation.is_a?(Array) || relation.loaded? ? relation.map(&name.to_sym) : relation.pluck(name) + end + + def extract_content(str) + return '' if str.blank? + str.gsub(/<\/?.*?>/, '').gsub(/[\n\t\r]/, '').gsub(/ /, '') + end end \ No newline at end of file diff --git a/app/models/applied_message.rb b/app/models/applied_message.rb new file mode 100644 index 000000000..ed02a5445 --- /dev/null +++ b/app/models/applied_message.rb @@ -0,0 +1,5 @@ +class AppliedMessage < ApplicationRecord + belongs_to :user + belongs_to :applied, polymorphic: true + +end \ No newline at end of file diff --git a/app/models/apply_add_department.rb b/app/models/apply_add_department.rb new file mode 100644 index 000000000..3deeaa97e --- /dev/null +++ b/app/models/apply_add_department.rb @@ -0,0 +1,15 @@ +class ApplyAddDepartment < ApplicationRecord + belongs_to :user + belongs_to :school + belongs_to :department + + has_many :applied_messages, as: :applied + has_many :tidings, as: :container, dependent: :destroy + + after_create :send_notify + + private + def send_notify + tidings.create!(user_id: 1, trigger_user_id: user_id, belong_container: school, tiding_type: 'Apply', status: 0) + end +end \ No newline at end of file diff --git a/app/models/apply_add_school.rb b/app/models/apply_add_school.rb new file mode 100644 index 000000000..bae65d24f --- /dev/null +++ b/app/models/apply_add_school.rb @@ -0,0 +1,14 @@ +class ApplyAddSchool < ApplicationRecord + belongs_to :school + + has_many :applied_messages, as: :applied + has_many :tidings, as: :container, dependent: :destroy + + after_create :send_notify + + private + + def send_notify + tidings.create!(user_id: 1, status: 0, trigger_user_id: user_id, belong_container: school, tiding_type: 'Apply') + end +end \ No newline at end of file diff --git a/app/models/apply_user_authentication.rb b/app/models/apply_user_authentication.rb index 3907c3f16..c7fb5019e 100644 --- a/app/models/apply_user_authentication.rb +++ b/app/models/apply_user_authentication.rb @@ -6,4 +6,5 @@ class ApplyUserAuthentication < ApplicationRecord scope :real_name_auth, -> { where(auth_type: 1) } scope :professional_auth, -> { where(auth_type: 2) } scope :processing, -> { where(status: 0) } + scope :passed, -> { where(status: 1) } end diff --git a/app/models/challenge.rb b/app/models/challenge.rb index a5d9874ce..0bea54eb4 100644 --- a/app/models/challenge.rb +++ b/app/models/challenge.rb @@ -10,17 +10,19 @@ class Challenge < ApplicationRecord has_many :games, :dependent => :destroy has_many :challenge_chooses, :dependent => :destroy has_many :homework_challenge_settings, :dependent => :destroy - has_many :praise_tread, as: :praise_tread_object, dependent: :destroy + has_many :praise_treads, as: :praise_tread_object, dependent: :destroy has_one :praise_tread_cache, as: :object, dependent: :destroy has_many :tidings # 参考答案 has_many :challenge_answers, :dependent => :destroy has_many :exercise_bank_shixun_challenges, :dependent => :destroy + # 回复 + has_many :discusses, :dependent => :destroy # acts_as_attachable scope :base_attrs, -> { select([:id, :subject, :position, :shixun_id, :st, :score, :path, :task_pass, :modify_time, - :web_route, :answer]) } + :web_route, :answer, :exec_time, :praises_count]) } scope :choose_type, -> { where(st: 1) } scope :practice_type, -> { where(st: 0) } @@ -38,7 +40,7 @@ class Challenge < ApplicationRecord ## 选择题总分 def choose_score - self.challenge_chooses.sum(:score) + self.challenge_chooses.pluck(:score).sum end # 关卡总分 @@ -51,9 +53,8 @@ class Challenge < ApplicationRecord end # 开启挑战 - def open_game(user_id) - game = self.games.select([:status, :identifier]).where(user_id: user_id).first - shixun = self.shixun + def open_game user_id, shixun + game = self.games.where(user_id: user_id).first if game.present? shixun.task_pass || game.status != 3 ? "/tasks/#{game.identifier}" : "" else @@ -61,18 +62,35 @@ class Challenge < ApplicationRecord end end + # # 开启挑战 + # def open_game(user_id, shixun) + # + # + # game = self.games.select([:status, :identifier]).where(user_id: user_id).first + # game = self.games.select{|game| game.user_id == user_id} + # if game.present? + # shixun.task_pass || game.status != 3 ? "/tasks/#{game.identifier}" : "" + # else + # "/api/shixuns/#{shixun.identifier}/shixun_exec" + # end + # end + ## 用户关卡状态 0: 不能开启实训; 1:直接开启; 2表示已完成 def user_tpi_status user_id # todo: 以前没加索引导致相同关卡,同一用户有多个games - game = self.games.where(user_id: user_id).last - status = - if game.blank? - self.position == 1 ? 1 : 0 - elsif game.status == 2 - 2 - else - 1 - end + # 允许跳关则直接开启 + game = games.where(user_id: user_id).take + if game.blank? + position == 1 ? 1 : 0 + else + if game.status == 3 + shixun.task_pass ? 1 : 0 + elsif game.status == 2 + 2 + else + 1 + end + end end ## 选择题答案 @@ -98,5 +116,4 @@ class Challenge < ApplicationRecord end # 关卡评测文件 - end diff --git a/app/models/challenge_tag.rb b/app/models/challenge_tag.rb index 6f176cc67..acea39770 100644 --- a/app/models/challenge_tag.rb +++ b/app/models/challenge_tag.rb @@ -1,5 +1,6 @@ class ChallengeTag < ApplicationRecord + include Searchable::Dependents::ChallengeTag belongs_to :challenge, counter_cache: true - belongs_to :challenge_choose + belongs_to :challenge_choose, optional: true end diff --git a/app/models/challenge_work_score.rb b/app/models/challenge_work_score.rb index 8316e228b..1e7c9f7fe 100644 --- a/app/models/challenge_work_score.rb +++ b/app/models/challenge_work_score.rb @@ -2,4 +2,12 @@ class ChallengeWorkScore < ApplicationRecord belongs_to :user belongs_to :student_work belongs_to :challenge + has_many :tidings, as: :container, dependent: :destroy + + def create_tiding trigger_user_id + tidings << Tiding.new(user_id: student_work.user_id, trigger_user_id: trigger_user_id, container_id: id, + container_type: "ChallengeWorkScore", parent_container_id: student_work_id, + parent_container_type: "StudentWork", belong_container_id: student_work&.homework_common&.course_id, + belong_container_type: "Course", viewed: 0, tiding_type: "HomeworkCommon") + end end diff --git a/app/models/competition.rb b/app/models/competition.rb new file mode 100644 index 000000000..024478ad6 --- /dev/null +++ b/app/models/competition.rb @@ -0,0 +1,70 @@ +class Competition < ApplicationRecord + + has_many :competition_modules, dependent: :destroy + has_many :unhidden_competition_modules, -> { where(hidden: false) }, class_name: 'CompetitionModule' + + has_many :competition_stages, dependent: :destroy + has_many :competition_stage_sections, dependent: :destroy + has_one :current_stage_section, -> { where('end_time > NOW()') }, class_name: 'CompetitionStageSection' + + has_many :competition_teams, dependent: :destroy + has_many :team_members, dependent: :destroy + + has_many :competition_staffs, dependent: :destroy + has_one :teacher_staff, -> { where(category: :teacher) }, class_name: 'CompetitionStaff' + has_one :member_staff, -> { where.not(category: :teacher) }, class_name: 'CompetitionStaff' + + has_many :attachments, as: :container + + after_create :create_competition_modules + + # 是否上架 + def published? + status? + end + + # 是否为个人赛 + def personal? + competition_staffs.maximum(:maximum) == 1 + end + + # 报名是否结束 + def enroll_ended? + enroll_end_time.blank? || enroll_end_time < Time.now + end + + # 是否已经报名 + def enrolled?(user) + team_members.exists?(user_id: user.id) + end + + # 是否禁止教师报名 + def teacher_enroll_forbidden? + teacher_staff.blank? || teacher_staff.maximum.zero? + end + + # 是否禁止学生报名 + def member_enroll_forbidden? + member_staff.blank? || member_staff.maximum.zero? + end + + # 老师是否能多次报名 + def teacher_multiple_limited? + teacher_staff.mutiple_limited? + end + + # 队员是否能多次报名 + def member_multiple_limited? + member_staff.mutiple_limited? + end + + private + + def create_competition_modules + CompetitionModule.bulk_insert(*%i[competition_id name position]) do |worker| + %w(首页 报名 通知公告 排行榜 资料下载).each_with_index do |name, index| + worker.add(competition_id: id, name: name, position: index + 1) + end + end + end +end diff --git a/app/models/competition_entry.rb b/app/models/competition_entry.rb new file mode 100644 index 000000000..685faca24 --- /dev/null +++ b/app/models/competition_entry.rb @@ -0,0 +1,4 @@ +class CompetitionEntry < ApplicationRecord + belongs_to :competition_stage + belongs_to :competition_stage_section +end \ No newline at end of file diff --git a/app/models/competition_module.rb b/app/models/competition_module.rb new file mode 100644 index 000000000..be73bf3c1 --- /dev/null +++ b/app/models/competition_module.rb @@ -0,0 +1,7 @@ +class CompetitionModule < ApplicationRecord + default_scope { order('position ASC') } + + belongs_to :competition + + has_one :competition_module_md_content, dependent: :destroy +end diff --git a/app/models/competition_module_md_content.rb b/app/models/competition_module_md_content.rb new file mode 100644 index 000000000..9dfcfca84 --- /dev/null +++ b/app/models/competition_module_md_content.rb @@ -0,0 +1,8 @@ +class CompetitionModuleMdContent < ApplicationRecord + belongs_to :competition_module + + has_many :attachments, as: :container, dependent: :destroy + + validates :name, presence: true + validates :content, presence: true +end \ No newline at end of file diff --git a/app/models/competition_staff.rb b/app/models/competition_staff.rb new file mode 100644 index 000000000..2630a5d3d --- /dev/null +++ b/app/models/competition_staff.rb @@ -0,0 +1,3 @@ +class CompetitionStaff < ApplicationRecord + belongs_to :competition +end \ No newline at end of file diff --git a/app/models/competition_stage.rb b/app/models/competition_stage.rb new file mode 100644 index 000000000..60d4b1644 --- /dev/null +++ b/app/models/competition_stage.rb @@ -0,0 +1,7 @@ +class CompetitionStage < ApplicationRecord + belongs_to :competition + + has_many :competition_stage_sections, dependent: :destroy + has_many :competition_entries, dependent: :destroy + +end \ No newline at end of file diff --git a/app/models/competition_stage_section.rb b/app/models/competition_stage_section.rb new file mode 100644 index 000000000..027e7ec69 --- /dev/null +++ b/app/models/competition_stage_section.rb @@ -0,0 +1,6 @@ +class CompetitionStageSection < ApplicationRecord + belongs_to :competition + belongs_to :competition_stage + + has_many :competition_entries, dependent: :destroy +end \ No newline at end of file diff --git a/app/models/competition_team.rb b/app/models/competition_team.rb new file mode 100644 index 000000000..625b29421 --- /dev/null +++ b/app/models/competition_team.rb @@ -0,0 +1,33 @@ +class CompetitionTeam < ApplicationRecord + + CODE_CHARS = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z).freeze + + belongs_to :user + belongs_to :competition + + has_many :team_members, dependent: :destroy + has_many :users, through: :team_members, source: :user + has_many :members, -> { without_teachers }, class_name: 'TeamMember' + has_many :teachers, -> { only_teachers }, class_name: 'TeamMember' + + def group_team_type? + team_type.zero? + end + + def personal_team_type? + team_type == 1 + end + + def en_team_type + group_team_type? ? 'group' : 'personal' + end + + def generate_invite_code + code = CODE_CHARS.sample(6).join + while self.class.exists?(invite_code: code) + code = CODE_CHARS.sample(6).join + end + self.code = code + code + end +end \ No newline at end of file diff --git a/app/models/course.rb b/app/models/course.rb index dd2248d7c..1f38827ae 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -1,4 +1,6 @@ class Course < ApplicationRecord + include Searchable::Course + has_many :boards, dependent: :destroy belongs_to :teacher, class_name: 'User', foreign_key: :tea_id # 定义一个方法teacher,该方法通过tea_id来调用User表 @@ -8,6 +10,7 @@ class Course < ApplicationRecord has_many :course_infos, dependent: :destroy # 课堂左侧导航栏的模块 has_many :course_modules, dependent: :destroy + has_many :none_hidden_course_modules, -> { not_hidden }, class_name: "CourseModule" has_many :board_course_modules, -> { board_module }, class_name: "CourseModule" has_many :attachment_course_modules, -> { attachment_module }, class_name: "CourseModule" has_many :common_course_modules, -> { common_homework_module }, class_name: "CourseModule" @@ -22,6 +25,8 @@ class Course < ApplicationRecord has_many :graduation_groups, dependent: :destroy has_many :course_members, dependent: :destroy + has_many :teacher_course_members, -> { teachers_and_admin }, class_name: 'CourseMember' + has_many :teacher_users, through: :teacher_course_members, source: :user has_many :course_messages, dependent: :destroy has_many :homework_commons, dependent: :destroy has_many :homework_group_settings @@ -61,6 +66,8 @@ class Course < ApplicationRecord scope :hidden, ->(is_hidden = true) { where(is_hidden: is_hidden) } scope :ended, ->(is_end = true) { where(is_end: is_end) } + scope :processing, -> { where(is_end: false) } + scope :not_deleted, -> { where(is_delete: 0) } scope :deleted, ->(is_delete = 1) { where(is_delete: is_delete) } scope :by_user, ->(user) { joins(:course_members).where('course_members.user_id = ?', user.id).order(updated_at: :desc) } scope :by_keywords, lambda { |keywords| @@ -96,7 +103,7 @@ class Course < ApplicationRecord # 未分班的学生数 def none_group_count - course_members.where(role: 4, course_group_id: 0).count + course_members.where(role: 4, course_group_id: 0).size end def course_member(user_id) @@ -121,8 +128,8 @@ class Course < ApplicationRecord end #当前老师的班级id - def teacher_course_group_ids(user_id) - course_teacher_member = teacher_course_groups.get_user_groups(user_id) #获取当前老师的分班 + def teacher_course_ids(user_id) + course_teacher_member = teacher_course_groups.get_user_groups(user_id).select(:course_group_id) #获取当前老师的分班 if course_teacher_member.blank? if none_group_count > 0 #有未分班的,则发布到未发布分班 un_group_ids = [0] @@ -139,9 +146,9 @@ class Course < ApplicationRecord def teacher_group_user_ids user_id teachers = teacher_course_groups.where(user_id: user_id) if teachers.exists? - course_members.where(course_group_id: teachers.pluck(:course_group_id)).pluck(:user_id) + students.where(course_group_id: teachers.pluck(:course_group_id)).pluck(:user_id) else - course_members.where(role: 4).pluck(:user_id) + students.pluck(:user_id) end end @@ -163,7 +170,7 @@ class Course < ApplicationRecord all_course_module_types.each do |type| hidden_value = course_module_types.include?(type) ? 0 : 1 - course_module = get_course_module_by_type(type, self.id) + course_module = course_modules.where(module_type: type).first course_module.update_attribute(:hidden, hidden_value) if course_module.present? end end @@ -172,8 +179,9 @@ class Course < ApplicationRecord %w[activity shixun_homework common_homework group_homework graduation exercise poll attachment board course_group] end - def get_course_module_by_type(type, course_id) - CourseModule.where(course_id: course_id, module_type: type).first + def get_course_module_by_type(type) + #CourseModule.where(course_id: course_id, module_type: type).first + self.course_modules.where(module_type: type).first end # 创建课程讨论区 @@ -255,7 +263,7 @@ class Course < ApplicationRecord # 是否具有分班权限,返回分班的id def group_course_power(user_id) - teacher_course_groups.where(user_id: user_id).pluck(:id) + teacher_course_groups.where(user_id: user_id).pluck(:course_group_id) end #课程动态公共表记录 @@ -303,15 +311,13 @@ class Course < ApplicationRecord #获取试卷/问卷已发布的班级id,名称和人数。当为统一设置时,显示全部,否则只显示当前已发布的班级信息 def get_ex_published_course(common_ids) teacher_power_courses = [] - if course_groups.present? - common_ids.each do |i| - student_count = students.where(course_group_id:i).count - if i == 0 - teacher_power_courses << {course_name:"未分班",course_id:0,student_count:student_count} - else - course_group_name = course_groups.find_by(id:i) - teacher_power_courses << {course_name:course_group_name&.name,course_id:i,student_count:student_count} - end + publish_groups = course_groups.where(id: common_ids) + if common_ids.include?(0) + teacher_power_courses << {course_name:"未分班", course_id: 0, student_count: none_group_count} + end + if publish_groups.present? + publish_groups.each do |group| + teacher_power_courses << {course_name: group&.name,course_id: group&.id, student_count: group&.course_members_count} end end teacher_power_courses diff --git a/app/models/course_member.rb b/app/models/course_member.rb index d9995d463..65849e5de 100644 --- a/app/models/course_member.rb +++ b/app/models/course_member.rb @@ -20,8 +20,8 @@ class CourseMember < ApplicationRecord # 未分班 scope :ungroup_students, -> { where(course_group_id: 0, role: 4) } - after_destroy :delete_works - after_create :work_operation + # after_destroy :delete_works + # after_create :work_operation def delete_works if self.role == "STUDENT" course = self.course @@ -52,13 +52,13 @@ class CourseMember < ApplicationRecord def recover_works course = self.course - student_works = StudentWork.where(user_id: self.user_id, homework_common_id: course.homework_commons) + student_works = StudentWork.joins(:homework_common).where(user_id: self.user_id, homework_commons: {course_id: course.id}) student_works.update_all(is_delete: 0) - exercise_users = ExerciseUser.where(user_id: self.user_id, exercise_id: course.exercises) + exercise_users = ExerciseUser.joins(:exercise).where(user_id: self.user_id, exercises: {course_id: course.id}) exercise_users.update_all(is_delete: 0) - poll_users = PollUser.where(user_id: self.user_id, poll_id: course.polls) + poll_users = PollUser.joins(:poll).where(user_id: self.user_id, polls: {course_id: course.id}) poll_users.update_all(is_delete: 0) graduation_works = course.graduation_works.where(user_id: self.user_id) @@ -146,11 +146,11 @@ class CourseMember < ApplicationRecord def member_teachers teacher_groups = course.teacher_course_groups if teacher_groups.count > 0 - member_ids = teacher_groups.where(course_group_id: self.try(:course_group_id)).pluck(:course_member_id) + member_ids = teacher_groups.where(course_group_id: self.try(:course_group_id)).pluck(:course_member_id).compact - none_group_teachers = teacher_groups.pluck(:course_member_id).size > 0 ? teacher_groups.pluck(:course_member_id).join(',') : -1 - teachers = course.teachers.where("members.id not in (#{none_group_teachers}) or - members.id in (#{member_ids.size > 0 ? member_ids.join(',') : -1})") + none_group_teachers = teacher_groups.pluck(:course_member_id).compact.size > 0 ? teacher_groups.pluck(:course_member_id).compact.join(',') : -1 + teachers = course.teachers.where("course_members.id not in (#{none_group_teachers}) or + course_members.id in (#{member_ids.size > 0 ? member_ids.join(',') : -1})") else teachers = course.teachers end diff --git a/app/models/course_module.rb b/app/models/course_module.rb index 7b96a044f..641c70425 100644 --- a/app/models/course_module.rb +++ b/app/models/course_module.rb @@ -7,6 +7,7 @@ class CourseModule < ApplicationRecord validates :module_name, length: { maximum: 20 } + scope :not_hidden, -> { where(hidden: 0) } scope :graduation_module, -> { where(module_type: "graduation") } scope :graduation_module_not_hidden, -> { graduation_module.where(hidden: 0) } scope :board_module, -> { where(module_type: 'board') } diff --git a/app/models/department.rb b/app/models/department.rb index 15a8a7c1b..bf5c3a90e 100644 --- a/app/models/department.rb +++ b/app/models/department.rb @@ -2,4 +2,26 @@ class Department < ApplicationRecord belongs_to :school has_many :department_members, dependent: :destroy + + after_create_commit :reset_data_cache + after_update_commit :reset_data_cache + + def self.cached_names_data(school) + Rails.cache.fetch(names_data_cache_key(school.id), expires_in: 7.days) do + school.departments.select(:id, :name).as_json + end + end + + private + + def reset_data_cache + # 清除部门名称缓存 + if new_record? || name_previously_changed? + Rails.cache.delete(self.class.names_data_cache_key(school_id)) + end + end + + def self.names_data_cache_key(school_id) + "schools/#{school_id}/department_names_data" + end end diff --git a/app/models/discuss.rb b/app/models/discuss.rb index 602813e66..2d9c00110 100644 --- a/app/models/discuss.rb +++ b/app/models/discuss.rb @@ -5,10 +5,11 @@ class Discuss < ApplicationRecord belongs_to :parent, class_name: 'Discuss', foreign_key: :parent_id, optional: true has_many :children, -> { reorder(created_at: :asc) }, class_name: 'Discuss', foreign_key: :parent_id - has_many :praise_tread, as: :praise_tread_object, dependent: :destroy + has_many :praise_treads, as: :praise_tread_object, dependent: :destroy has_many :tidings, as: :container, dependent: :destroy has_one :praise_tread_cache, as: :object, dependent: :destroy + belongs_to :challenge after_create :send_tiding scope :children, -> (discuss_id){ where(parent_id: discuss_id).includes(:user).reorder(created_at: :asc) } @@ -33,10 +34,14 @@ class Discuss < ApplicationRecord "/tasks/#{game&.identifier}" end - def contents(shixun, user) - return content unless hidden? + # def contents(shixun, user) + # return content unless hidden? + # + # shixun.has_manager?(user) ? content : '' + # end - shixun.has_manager?(user) ? content : '违规评论已被屏蔽!' + def child_discuss(user) + Discuss.where(parent_id: self.id).includes(:user).reorder(created_at: :asc) end private diff --git a/app/models/edu_setting.rb b/app/models/edu_setting.rb index db6d545f0..835aaec76 100644 --- a/app/models/edu_setting.rb +++ b/app/models/edu_setting.rb @@ -1,5 +1,25 @@ class EduSetting < ApplicationRecord + after_commit :expire_value_cache + + def value_cache_key + self.class.value_cache_key(name) + end + def self.get(key) - find_by_name(key.to_s)&.value + Rails.cache.fetch(value_cache_key(key), expires_in: 1.days) do + find_by_name(key.to_s)&.value + end + end + + def self.value_cache_key(name) + raise ArgumentError if name.blank? + + "educoder/edu-settings/#{name.to_s}" + end + + private + + def expire_value_cache + Rails.cache.write(value_cache_key, value) end end diff --git a/app/models/evaluate_record.rb b/app/models/evaluate_record.rb index 451409493..392b12360 100644 --- a/app/models/evaluate_record.rb +++ b/app/models/evaluate_record.rb @@ -1,3 +1,11 @@ +# 字段说明: +# consume_time:总耗时,包括前端发出请求,到最后前端显示效果 +# git_pull:中间层pull代码耗时 +# create_pod:创建pod耗时 +# pod_execute:pod执行时间耗时,也就代码执行耗时,是各个测试集的总耗时 +# test_cases:outpus表中存储及处理测试集的时间耗时 +# brige:中间层总耗时 +# return_back:回调耗时,从中间层发送请求到educoder所耗时间 class EvaluateRecord < ApplicationRecord default_scope { order("evaluate_records.id desc") } belongs_to :game diff --git a/app/models/exercise.rb b/app/models/exercise.rb index e2623c692..825f7cd9f 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -3,11 +3,14 @@ class Exercise < ApplicationRecord belongs_to :exercise_bank, optional: true belongs_to :user - has_many :exercise_users,:dependent => :destroy - has_many :exercise_questions,:dependent => :destroy - has_many :exercise_group_settings,:dependent => :destroy + has_many :exercise_users, -> { where("is_delete = 0") }, :dependent => :delete_all + has_many :score_exercise_users, -> { where("is_delete = 0 and commit_status != 0").order("score desc") }, class_name: "ExerciseUser" + has_many :exercise_questions, :dependent => :delete_all + has_many :exercise_group_settings, :dependent => :delete_all + has_many :published_settings, -> { exercise_group_published }, class_name: "ExerciseGroupSetting" + has_many :tidings, as: :container - has_many :course_acts, class_name: 'CourseActivity', as: :course_act, dependent: :destroy + has_many :course_acts, class_name: 'CourseActivity', as: :course_act, :dependent => :delete_all scope :is_exercise_published, -> { where("exercise_status > ? ",1)} scope :unified_setting, -> { where("unified_setting = ?",true) } @@ -20,6 +23,21 @@ class Exercise < ApplicationRecord after_create :create_exercise_list + # 试卷的问题类型 + SINGLE = 0 #单选题 + MULTIPLE = 1 #多选题 + JUDGMENT = 2 #判断题 + COMPLETION = 3 # 填空题 + SUBJECTIVE = 4 # 主观题 + PRACTICAL = 5 #实训题 + + # 试卷的状态 + UNPUBLISHED = 1 #未发布 + PUBLISHED = 2 #已发布 + DEADLINE = 3 #已截止 + ENDED = 4 #课堂已结束 + + def create_exercise_list str = "" # TODO: 一次性为所有学生创建数据是否存在问题? @@ -39,9 +57,9 @@ class Exercise < ApplicationRecord if unified_setting #试卷统一设置 exercise_users else - ex_group_setting_ids = exercise_group_settings.exercise_group_published.pluck(:course_group_id) - course_user_ids = course.students.where(course_group_id:ex_group_setting_ids).pluck(:user_id) - exercise_users.where(user_id:course_user_ids) + ex_group_setting_ids = published_settings.pluck(:course_group_id) + exercise_users.joins("join course_members on exercise_users.user_id=course_members.user_id"). + where(course_members: {course_group_id: ex_group_setting_ids}) end end @@ -54,102 +72,104 @@ class Exercise < ApplicationRecord end end - #统一设置,为当前老师有权限的分班学生,分班设置,也为当前老师有权限的分班的学生 + # 根据是否统一发布获取作业的作品列表 + def all_works + ex_users = self.unified_setting ? exercise_users : + exercise_users.joins("join course_members on exercise_users.user_id=course_members.user_id"). + where(course_members: {course_group_id: published_settings.pluck(:course_group_id)}) + end + + # 分班权限的老师可见的作品列表 def all_exercise_users(user_id) - ex_users = self.exercise_users - group_ids = common_published_ids(user_id) - if group_ids.present? - ex_users = ex_users.where(user_id: course.students.where(course_group_id: group_ids).pluck(:user_id)) + # member = course.course_member(user_id) + teacher_course_groups = course.teacher_course_groups.where(user_id:user_id) + ex_users = self.all_works + # 有分班权限的统计管理的分班且已发布的学生情况 + if teacher_course_groups.exists? + group_ids = teacher_course_groups.pluck(:course_group_id) + ex_users = ex_users.joins("join course_members on exercise_users.user_id=course_members.user_id"). + where(course_members: {course_group_id: group_ids}) end ex_users end + # #统一设置,为当前老师有权限的分班学生,分班设置,也为当前老师有权限的分班的学生 + # def all_exercise_users(user_id) + # ex_users = exercise_users + # group_ids = common_published_ids(user_id) + # if group_ids.present? + # ex_users = ex_users.joins("join course_members on exercise_users.user_id=course_members.user_id"). + # where(course_members: {course_group_id: group_ids}) + # end + # ex_users + # end + #当前用户已发布的班级id和试卷分组已发布的班级id的交集 def common_published_ids(user_id) - current_user_groups = course.teacher_course_group_ids(user_id) + current_user_groups = course.teacher_course_ids(user_id) if unified_setting - if course.none_group_count > 0 #有未分班的,则发布到未发布分班 - un_group_ids = [0] - else - un_group_ids = [] - end - published_group_ids = (current_user_groups + un_group_ids).uniq #统一设置时,为当前用户的分班id及未分班 + published_group_ids = current_user_groups else - ex_group_setting = exercise_group_settings.pluck("course_group_id").uniq + ex_group_setting = exercise_group_settings.select(:course_group_id).pluck("course_group_id").uniq common_all_ids = ex_group_setting & current_user_groups #当前用户有权限的已发布的分班id #非统一设置时,为当前用户有权限的且已发布分班的id published_group_ids = common_all_ids.uniq end published_group_ids end - #判断用户是否属于试卷分班的学生中 def check_user_in_course(user_id,user_identity) ex_group_settings = exercise_group_settings.pluck(:course_group_id) member = course.course_members.course_find_by_ids("user_id",user_id) member_group_id = member.pluck(:course_group_id).uniq - if (member_group_id & ex_group_settings).size > 0 || user_identity < Course::STUDENT - true - else - false - end + ((member_group_id & ex_group_settings).size > 0 || user_identity < Course::STUDENT) ? true : false end #判断是否为分班,如果分班,试卷的截止时间为当前分班时间,否则为试卷的截止时间 - def get_exercise_status(user_id) - user_group = course.course_members.find_by(user_id: user_id) - if user_group.present? - if user_group.role == "STUDENT" #为学生 - is_teacher = false - else - is_teacher = true - end - ex_time = get_exercise_times(user_id,is_teacher) - - pb_time = ex_time[:publish_time] - ed_time = ex_time[:end_time] - - if pb_time.present? && ed_time.present? && pb_time <= Time.now && ed_time > Time.now - status = 2 - elsif ed_time.present? && ed_time <= Time.now - status = 3 + def get_exercise_status(user) + if course.is_end + status = 4 + else + if user.present? && user.student_of_course?(course) #当为学生的时候,需根据分班来判断试卷状态 + ex_time = get_exercise_times(user_id,false) + pb_time = ex_time[:publish_time] + ed_time = ex_time[:end_time] + if pb_time.present? && ed_time.present? && pb_time <= Time.now && ed_time > Time.now + status = Exercise::PUBLISHED + elsif ed_time.present? && ed_time <= Time.now + status = Exercise::DEADLINE + else + status = Exercise::UNPUBLISHED + end else - status = 1 + status = exercise_status #当为老师的时候,则为试卷的总状态 end - else - status = exercise_status end status end #获取试卷的发布时间和截止时间。teacher 为boolean,当为true时,表示的是当前为老师 def get_exercise_times(user_id,teacher) - if unified_setting + if unified_setting || teacher #当试卷为统一设置或当前为老师的时候 pb_time = publish_time en_time = end_time + if (exercise_status != 3) && en_time.present? && (en_time <= Time.now) + update_column("exercise_status",3) + end else - ex_group_setting = exercise_group_settings - if teacher #当前为老师,为设置组的最大值和最小值 - user_group = course.teacher_course_groups.get_user_groups(user_id) - user_group_ids = user_group.present? ? user_group.pluck(:course_group_id) : course.course_groups.pluck(:id) - user_ex_group_settings = ex_group_setting.find_in_exercise_group("course_group_id",user_group_ids) - pb_time_min = user_ex_group_settings.publish_time_no_null.map(&:publish_time) - en_time_max = user_ex_group_settings.end_time_no_null.map(&:end_time) - pb_time = pb_time_min.size > 0 ? pb_time_min.min : nil - en_time = en_time_max.size > 0 ? en_time_max.max : nil + # ex_group_setting = exercise_group_settings + user_group = course.students.where(user_id:user_id).select(:course_group_id) + if user_group.exists? + user_group_id = user_group.first&.course_group_id + user_ex_group_setting = exercise_group_settings.where(course_group_id:user_group_id).select(:publish_time,:end_time) + pb_time = user_ex_group_setting.first&.publish_time + en_time = user_ex_group_setting.first&.end_time else - user_group = course.students.course_find_by_ids("user_id",user_id) - if user_group.present? - user_group_id = user_group.first.course_group_id - user_ex_group_setting = ex_group_setting.find_in_exercise_group("course_group_id",user_group_id) - pb_time = user_ex_group_setting.present? ? user_ex_group_setting.first.publish_time : nil - en_time = user_ex_group_setting.present? ? user_ex_group_setting.first.end_time : nil - else - pb_time = nil - en_time = nil - end + pb_time = nil + en_time = nil end end + { "publish_time":pb_time, "end_time":en_time @@ -158,16 +178,15 @@ class Exercise < ApplicationRecord #判断当前用户的答题状态 def check_user_answer_status(user) - ex_answer_user = exercise_users.find_by(user_id: user.id) - user_ex_status = get_exercise_status(user.id) + ex_answer_user = exercise_users.where(user_id: user.id).select(:start_at,:end_at,:commit_status) + user_ex_status = get_exercise_status(user) user_status = 2 - if ex_answer_user.present? && (ex_answer_user.start_at.present? || ex_answer_user.end_at.present?) #学生有过答题的,或者立即截止,但学生未做试卷的 - user_status = ex_answer_user.commit_status + if ex_answer_user.present? && (ex_answer_user.first&.start_at.present? || ex_answer_user.first&.end_at.present?) #学生有过答题的,或者立即截止,但学生未做试卷的 + user_status = ex_answer_user.first.commit_status end - if ex_answer_user.present? && ex_answer_user.start_at.blank? && user_ex_status == 3 + if ex_answer_user.present? && ex_answer_user.first&.start_at.blank? && user_ex_status == 3 user_status = 4 end - user_status end diff --git a/app/models/exercise_answer.rb b/app/models/exercise_answer.rb index 465fa036b..11558f937 100644 --- a/app/models/exercise_answer.rb +++ b/app/models/exercise_answer.rb @@ -3,7 +3,7 @@ class ExerciseAnswer < ApplicationRecord belongs_to :user belongs_to :exercise_question belongs_to :exercise_choice, optional: true - has_many :exercise_answer_comments, :dependent => :destroy + has_many :exercise_answer_comments, :dependent => :delete_all scope :search_exercise_answer, lambda { |name,key| where("#{name} = ?",key)} scope :search_answer_users, lambda {|name,ids| where("#{name}":ids)} diff --git a/app/models/exercise_choice.rb b/app/models/exercise_choice.rb index 525251ce6..72dc30c9d 100644 --- a/app/models/exercise_choice.rb +++ b/app/models/exercise_choice.rb @@ -1,9 +1,10 @@ class ExerciseChoice < ApplicationRecord belongs_to :exercise_question - has_many :exercise_answers, :dependent => :destroy - has_many :exercise_standard_answers, :dependent => :destroy + has_many :exercise_answers, :dependent => :delete_all + has_many :exercise_standard_answers, :dependent => :delete_all scope :find_choice_custom, lambda {|k,v| where("#{k} = ?",v)} #根据传入的参数查找问题 scope :left_choice_choose, lambda {|k,v| where("#{k} > ?",v)} #根据传入的参数查找问题 + end \ No newline at end of file diff --git a/app/models/exercise_question.rb b/app/models/exercise_question.rb index ae58a7592..2c9b281c3 100644 --- a/app/models/exercise_question.rb +++ b/app/models/exercise_question.rb @@ -4,19 +4,18 @@ class ExerciseQuestion < ApplicationRecord belongs_to :exercise belongs_to :shixun, optional: true - has_many :exercise_choices, :dependent => :destroy - has_many :exercise_answers, :dependent => :destroy - has_many :exercise_shixun_challenges,:dependent => :destroy - has_many :exercise_shixun_answers, :dependent => :destroy - has_many :exercise_answer_comments, :dependent => :destroy - has_many :exercise_standard_answers, :dependent => :destroy + has_many :exercise_choices, :dependent => :delete_all + has_many :exercise_answers + has_many :exercise_shixun_challenges, :dependent => :delete_all + has_many :exercise_shixun_answers + has_many :exercise_answer_comments + has_many :exercise_standard_answers scope :insert_question_ex, lambda {|k| where("question_number > ?",k)} scope :find_by_custom, lambda {|k,v| where("#{k} = ?",v)} #根据传入的参数查找问题 scope :left_question_choose, lambda {|k,v| where("#{k} > ?",v)} #根据传入的参数查找问题 scope :find_objective_questions, -> {where("question_type != ?",4)} #查找全部客观题 - scope :next_exercise, lambda {|k| where("question_number > ?",k).first} - scope :last_exercise, lambda {|k| where("question_number < ?",k).last} + def question_type_name case self.question_type diff --git a/app/models/exercise_shixun_answer.rb b/app/models/exercise_shixun_answer.rb index 8548e497d..a9550c024 100644 --- a/app/models/exercise_shixun_answer.rb +++ b/app/models/exercise_shixun_answer.rb @@ -2,7 +2,7 @@ class ExerciseShixunAnswer < ApplicationRecord belongs_to :exercise_question belongs_to :user belongs_to :exercise_shixun_challenge - has_many :exercise_answer_comments, :dependent => :destroy + has_many :exercise_answer_comments, :dependent => :delete_all # status 0: 未通过, 1:通过 # attr_accessible :answer_text, :score, :status scope :search_shixun_answers, lambda {|name,ids| where("#{name}":ids)} diff --git a/app/models/game.rb b/app/models/game.rb index c08884afb..ae056a702 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -20,9 +20,9 @@ class Game < ApplicationRecord #全部关卡数 scope :ch_games, lambda { |challenge_id| where(challenge_id:challenge_id) } # 已通关的数量 - scope :finished_num, -> (challenge_id) { where(:challenge_id => challenge_id, :status => 1)} + scope :finished_num, -> (challenge_id) { where(:challenge_id => challenge_id, :status => 2)} # 正在通关的数量 - scope :doing_num, -> (challenge_id) { where(:challenge_id => challenge_id, :status => 0)} + scope :doing_num, -> (challenge_id) { where(:challenge_id => challenge_id, :status => [0,1])} #用户的全部关卡 scope :user_games, lambda { |user_id,challenge_id| where("user_id = ? AND challenge_id = ?",user_id,challenge_id) } @@ -31,7 +31,7 @@ class Game < ApplicationRecord # 根据得分比例来算实际得分(试卷、实训作业) def real_score score - final_score == challenge.score ? score : (final_score.to_f / challenge.score) * score + (final_score.to_f / challenge.all_score) * score end # 判断实训是否全部通关 @@ -61,7 +61,7 @@ class Game < ApplicationRecord if self.status == 2 # 通关了则取实际得分,没通关则取总分 gold = (shixun_status <= 1) ? 0 : self.final_score.to_i # 只要过关了,查看了答案经验值就是0;通关前查看了答案金final_score为负数 - experience = (shixun_status <= 1 || self.final_score.to_i < 0) ? 0 : challenge.score.to_i + experience = (shixun_status <= 1 || self.final_score.to_i < 0) ? 0 : self.final_score.to_i else gold = challenge.score.to_i experience = gold @@ -69,7 +69,7 @@ class Game < ApplicationRecord else if self.status == 2 gold = (shixun_status <= 1) ? 0 : self.final_score.to_i - experience = (shixun_status <= 1 || self.final_score.to_i < 0) ? 0 : challenge.score.to_i + experience = (shixun_status <= 1 || self.final_score.to_i < 0) ? 0 : challenge.choose_score.to_i else # 选择题只有在全对的时候才会获取final score总分,错任何一个题final_score就为0 gold = challenge.choose_score @@ -115,9 +115,9 @@ class Game < ApplicationRecord end # 评测次数 - def evaluate_count - self.outputs.pluck(:query_index).first - end + #def evaluate_count + # self.outputs.pluck(:query_index).first + #end # 用户关卡得分 def get_user_final_score diff --git a/app/models/graduation_task.rb b/app/models/graduation_task.rb index 308c51be4..e247f2b6e 100644 --- a/app/models/graduation_task.rb +++ b/app/models/graduation_task.rb @@ -16,9 +16,12 @@ class GraduationTask < ApplicationRecord has_many :graduation_task_group_assignations, dependent: :destroy has_many :graduation_work_comment_assignations, dependent: :destroy - has_many :graduation_works, -> { where("is_delete != 1") } + has_many :graduation_works, -> { where("is_delete = 0") } + has_many :score_graduation_works, -> { where("is_delete = 0 and work_status != 0").order("work_score desc") }, class_name: "GraduationWork" has_many :graduation_work_scores + belongs_to :gtask_bank, optional: true + validates :name, length: { maximum: 60 } validates :description, length: { maximum: 5000 } @@ -97,15 +100,15 @@ class GraduationTask < ApplicationRecord SELECT count(distinct graduation_work_id) cnt FROM graduation_work_scores WHERE reviewer_role IN(1,2) AND graduation_work_id IN(SELECT id FROM graduation_works WHERE graduation_task_id = #{self.id} AND user_id IN(SELECT user_id FROM course_members WHERE role = 4 AND course_group_id - IN(SELECT course_group_id FROM teacher_course_groups WHERE id IN(#{course_group_ids.join(",")})) + IN(#{course_group_ids.join(",")}) ) ) } else %Q{ SELECT COUNT(distinct graduation_work_id) cnt FROM graduation_works gw - JOIN graduation_work_scores gwc ON gw.graduation_task_id = gwc.graduation_task_id - WHERE reviewer_role IN(1,2) AND gwc.graduation_task_id = #{self.id} + JOIN graduation_work_scores gwc ON gw.id = gwc.graduation_work_id + WHERE reviewer_role IN(1,2) AND gw.graduation_task_id = #{self.id} } end GraduationWorkScore.find_by_sql(sql).first.try(:cnt).to_i @@ -124,7 +127,7 @@ class GraduationTask < ApplicationRecord sql = %Q{ SELECT count(*) cnt FROM graduation_works gw WHERE work_status = 0 AND gw.graduation_task_id = #{self.id} AND gw.user_id IN( SELECT user_id FROM course_members WHERE role = 4 AND course_group_id - IN( SELECT course_group_id FROM teacher_course_groups WHERE id not IN(#{course_group_ids.join(",")}) ) + IN(#{course_group_ids.join(",")}) ) } GraduationWork.find_by_sql(sql).first.try(:cnt) @@ -141,7 +144,7 @@ class GraduationTask < ApplicationRecord sql = %Q{ SELECT count(*) cnt FROM graduation_works gw WHERE work_status = 1 AND gw.graduation_task_id = #{self.id} AND gw.user_id IN( SELECT user_id FROM course_members WHERE role = 4 AND course_group_id - IN( SELECT course_group_id FROM teacher_course_groups WHERE id IN(#{course_group_ids.join(",")}) ) + IN(#{course_group_ids.join(",")}) ) } GraduationWork.find_by_sql(sql).first.try(:cnt) @@ -157,7 +160,7 @@ class GraduationTask < ApplicationRecord sql = %Q{ SELECT count(*) cnt FROM graduation_works gw WHERE work_status = 2 AND gw.graduation_task_id = #{self.id} AND gw.user_id IN( SELECT user_id FROM course_members WHERE role = 4 AND course_group_id - IN( SELECT course_group_id FROM teacher_course_groups WHERE id IN(#{course_group_ids.join(",")}) ) + IN(#{course_group_ids.join(",")}) ) } GraduationWork.find_by_sql(sql).first.try(:cnt) @@ -166,6 +169,8 @@ class GraduationTask < ApplicationRecord end end + + # 是否具有分组 def have_grouping? self.task_type == 2 diff --git a/app/models/graduation_topic.rb b/app/models/graduation_topic.rb index 3aed72d9c..294bfa785 100644 --- a/app/models/graduation_topic.rb +++ b/app/models/graduation_topic.rb @@ -10,7 +10,7 @@ class GraduationTopic < ApplicationRecord has_many :journals_for_messages, :as => :jour, :dependent => :destroy # 题库 - + belongs_to :gtopic_bank, optional: true scope :search_by_name, ->(name) { where("graduation_topics.name LIKE ?", "%#{name}%")} scope :search_by_status, ->(status) {where(status: status)} @@ -50,10 +50,10 @@ class GraduationTopic < ApplicationRecord def student_graduation_topic_status sgt = self.student_graduation_topics status = - if sgt.is_accepting.count == 0 - 2 - elsif sgt.is_refused.count == self.student_graduation_topics.size + if sgt.where(status: [0, 1]).count.zero? 0 + elsif sgt.is_accepting.count.zero? + 2 else 1 end diff --git a/app/models/graduation_work.rb b/app/models/graduation_work.rb index 11255ce4e..235bfcac6 100644 --- a/app/models/graduation_work.rb +++ b/app/models/graduation_work.rb @@ -53,7 +53,7 @@ class GraduationWork < ApplicationRecord # 分班名 def class_grouping_name - CourseMember.find_by(user_id: self.user_id, course_id: self.course_id).try(:course_group).try(:name) || '未分班' + CourseMember.find_by(course_id: self.course_id, user_id: self.user_id, role: 4).try(:course_group).try(:name) || '未分班' end # 分组名 @@ -63,12 +63,12 @@ class GraduationWork < ApplicationRecord #用户是否有查看分数的权限 def check_score_power? current_user, course_identity - self.work_score.present? || course_identity < Course::STUDENT || self.user_id = current_user.id + self.work_score.present? && (course_identity < Course::STUDENT || self.user_id = current_user.id || graduation_task.open_score) end # 作品是否能够分配指导老师 def assign_power?(course_identity) - course_identity < Course::STUDENT && self.graduation_task.cross_comment.present? && self.graduation_task.comment_status == 2 + course_identity < Course::STUDENT && graduation_task.cross_comment && graduation_task.comment_status == 2 end # 老师评阅分 @@ -100,8 +100,7 @@ class GraduationWork < ApplicationRecord "未批阅" else if self.check_score_power?(current_user, course_identity) - "#{format("%.1f", self.cross_score.round(1))}(#{self.graduation_work_scores - .where(reviewer_role: 2).group_by(&:user_id).count})" + "#{format("%.1f", self.cross_score.round(1))}" else "**" end @@ -109,6 +108,10 @@ class GraduationWork < ApplicationRecord end end + def cross_comment_num + graduation_work_scores.where(reviewer_role: 2).group_by(&:user_id).count + end + def scored? graduation_work_scores.where.not(reviewer_role: 3).exists? end diff --git a/app/models/homework_common.rb b/app/models/homework_common.rb index 74d85e2ae..ac64b92c1 100644 --- a/app/models/homework_common.rb +++ b/app/models/homework_common.rb @@ -2,7 +2,9 @@ class HomeworkCommon < ApplicationRecord # homework_type 1:普通作业 2:编程作业(弃用) 3:分组作业 4:实训作业 enum homework_type: { normal: 1, program: 2, group: 3, practice: 4 }, _suffix: true has_many :homework_group_settings, dependent: :destroy - has_many :student_works, -> { where("is_delete != 1") } + has_many :published_settings, -> { group_published }, class_name: "HomeworkGroupSetting" + has_many :student_works, -> { where("is_delete = 0") } + has_many :score_student_works, -> { where("is_delete = 0 and work_status != 0").order("work_score desc") }, class_name: "StudentWork" has_one :homework_detail_manual, dependent: :destroy # 分组作业的设置 @@ -69,7 +71,7 @@ class HomeworkCommon < ApplicationRecord if self.course_second_category.present? {category_id: self.course_second_category.try(:id), category_name: self.course_second_category.try(:name)} else - {category_id: course.shixun_course_modules.first.try(:id), category_name: course.shixun_course_modules.first.try(:module_name)} + {category_id: course.shixun_course_modules.take.try(:id), category_name: course.shixun_course_modules.take.try(:module_name)} end end end @@ -77,20 +79,20 @@ class HomeworkCommon < ApplicationRecord # 根据是否统一发布获取作业的作品列表 def all_works student_works = self.unified_setting ? self.student_works : - self.student_works.where(user_id: self.course.students.where( - course_group_id: self.homework_group_settings.group_published.pluck(:course_group_id)). - pluck(:user_id)) + self.student_works.joins("join course_members on student_works.user_id=course_members.user_id"). + where(course_members: {course_group_id: self.published_settings.pluck(:course_group_id)}) end # 分班权限的老师可见的作品列表 - def teacher_works user_id - member = course.course_member(user_id) + def teacher_works member + # member = course.course_member(user_id) teacher_course_groups = member.try(:teacher_course_groups) all_student_works = self.all_works # 有分班权限的统计管理的分班且已发布的学生情况 - if member.present? && teacher_course_groups.size > 0 + if member.present? && teacher_course_groups.exists? group_ids = teacher_course_groups.pluck(:course_group_id) - all_student_works = all_student_works.where(user_id: course.students.where(course_group_id: group_ids).pluck(:user_id)) + all_student_works = all_student_works.joins("join course_members on student_works.user_id=course_members.user_id"). + where(course_members: {course_group_id: group_ids}) end all_student_works end @@ -118,6 +120,11 @@ class HomeworkCommon < ApplicationRecord status end + # 作业是否补交截止或者不允许补交且提交截止(不考虑分班) + def end_or_late_none_group + course.is_end || (allow_late && late_time < Time.now) || (!allow_late && end_time < Time.now) + end + # 作业是否可以查重 def code_review self.homework_type == 'practice' && self.publish_time.present? && self.publish_time < Time.now && self.homework_group_reviews.count == 0 @@ -169,12 +176,8 @@ class HomeworkCommon < ApplicationRecord #删除时更新题库中的引用数 def update_homework_bank_quotes - old_banks = HomeworkBank.where(homework_common_id: self.id) - unless old_banks.blank? - old_banks.each do |bank| - bank.update_attributes(quotes: (bank.quotes - 1) > 0 ? (bank.quotes - 1) : 0, homework_common_id: nil) - end - end + old_bank = self.homework_bank + old_bank.update_attributes(quotes: (old_bank.quotes - 1) > 0 ? (old_bank.quotes - 1) : 0, homework_common_id: nil) if old_bank.present? end # 查重是否有新结果 @@ -194,7 +197,7 @@ class HomeworkCommon < ApplicationRecord JOIN student_works_scores sws on sws.student_work_id = sw.id WHERE reviewer_role IN(1,2) AND sw.id IN (SELECT id FROM student_works WHERE homework_common_id = #{self.id} AND user_id IN (SELECT user_id FROM course_members WHERE role = 4 AND course_group_id - IN (SELECT course_group_id FROM teacher_course_groups WHERE id IN(#{course_group_ids.join(",")})) + IN (#{course_group_ids.join(",")}) ) ) } @@ -215,17 +218,17 @@ class HomeworkCommon < ApplicationRecord end # 作品未提交数 - def unfinished_count user_id - self.teacher_works(user_id).unfinished.count + def unfinished_count member + self.teacher_works(member).unfinished.count end # 任务按时提交数 - def finished_count user_id - self.teacher_works(user_id).finished.count + def finished_count member + self.teacher_works(member).finished.count end - def delay_finished_count user_id - self.teacher_works(user_id).delay_finished.count + def delay_finished_count member + self.teacher_works(member).delay_finished.count end # 分组作业的最大分组id @@ -235,17 +238,30 @@ class HomeworkCommon < ApplicationRecord # 作业的分班设置时间 def homework_group_setting user_id - member = course.course_member(user_id) - group_setting = self.homework_group_settings.find_by_course_group_id(member.try(:course_group_id)) - homework_setting = group_setting.present? ? group_setting : self + if unified_setting + homework_setting = self + else + member = course.course_member(user_id) + group_setting = self.homework_group_settings.find_by_course_group_id(member.try(:course_group_id)) + homework_setting = group_setting.present? ? group_setting : self + end homework_setting end def min_group_publish_time - HomeworkGroupSetting.where("homework_common_id = #{self.id} and publish_time is not null").pluck(:publish_time).min + #HomeworkGroupSetting.where("homework_common_id = #{self.id} and publish_time is not null").pluck(:publish_time).min + # 可以使用includes + self.homework_group_settings.where("publish_time is not null").pluck(:publish_time).min end def max_group_end_time - HomeworkGroupSetting.where("homework_common_id = #{self.id} and end_time is not null").pluck(:end_time).max + #HomeworkGroupSetting.where("homework_common_id = #{self.id} and end_time is not null").pluck(:end_time).max + # 可以使用includes + self.homework_group_settings.where("end_time is not null").pluck(:end_time).max + + end + + def challenge_score challenge_id + homework_challenge_settings.find_by(challenge_id: challenge_id)&.score.to_f end end diff --git a/app/models/memo.rb b/app/models/memo.rb index 524c37a96..610a7684d 100644 --- a/app/models/memo.rb +++ b/app/models/memo.rb @@ -1,4 +1,5 @@ class Memo < ApplicationRecord + include Searchable::Memo has_many :memo_tag_repertoires, :dependent => :destroy has_many :tag_repertoires, :through => :memo_tag_repertoires @@ -9,6 +10,9 @@ class Memo < ApplicationRecord belongs_to :author, class_name: 'User', foreign_key: 'author_id' belongs_to :parent, class_name: 'Memo', foreign_key: 'parent_id' + has_many :descendants, foreign_key: :root_id, class_name: 'Memo' + has_many :children, foreign_key: :parent_id, class_name: 'Memo' + scope :field_for_list, lambda{ select([:id, :subject, :author_id, :sticky, :updated_at, :language, :reward, :all_replies_count, :viewed_count, :forum_id]) } diff --git a/app/models/message.rb b/app/models/message.rb index ae804e991..7588ddc2a 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -4,6 +4,8 @@ class Message < ApplicationRecord belongs_to :board, counter_cache: true belongs_to :author, class_name: "User", foreign_key: 'author_id' belongs_to :parent, class_name: "Message", foreign_key: "parent_id", counter_cache: :replies_count, optional: true + belongs_to :root, class_name: 'Message', foreign_key: :root_id, counter_cache: :descendants_count, optional: true + has_one :message_detail, dependent: :destroy accepts_nested_attributes_for :message_detail, update_only: true @@ -12,10 +14,11 @@ class Message < ApplicationRecord has_many :tidings, as: :container, dependent: :destroy has_many :attachments, as: :container, dependent: :destroy has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy # 课程动态 + has_many :descendants, class_name: 'Message', foreign_key: :root_id, dependent: :destroy scope :root_nodes, -> { where("parent_id IS NULL") } #判断该信息是帖子还是回复。null为发布的帖子 scope :reply_nodes, -> { where("parent_id IS NOT NULL") } - scope :visible, -> { where(is_hidden: false)} + scope :visible, -> { where(is_hidden: false) } scope :by_user, ->(user) { visible if user.nil? || !user.admin? } scope :preload_messages, -> { includes(:author, :message_detail) } scope :short, -> { select(:id, :subject, :created_on, :replies_count, :visits, :sticky, :praises_count) } @@ -47,33 +50,39 @@ class Message < ApplicationRecord end end - def self.bulk_move_to_other_board(message_ids, to_board_id, author_id) - message_ids.each do |id| - message = Message.find id - message.update_attributes(board_id: to_board_id, author_id: author_id) if message.parent_id.nil? # TODO 暂时只支持跟节点移动 + def self.bulk_move_to_other_board(message_ids, to_board_id) + to_board = Board.find(to_board_id) + + messages = Message.where(id: message_ids, parent_id: nil).select(:id, :board_id).to_a + return if messages.blank? + + from_board = Board.find(messages.first.board_id) + + root_ids = messages.map(&:id) + children_ids = Message.where(parent_id: root_ids).pluck(:id) + second_children_ids = Message.where(parent_id: children_ids).pluck(:id) + + ids = root_ids.concat(children_ids).concat(second_children_ids).uniq + + ActiveRecord::Base.transaction do + Message.where(id: ids, board_id: from_board.id).update_all(board_id: to_board.id) + to_board.increment!(:messages_count, ids.size) + from_board.increment!(:messages_count, - ids.size) end end # 包含二级回复的总点赞数 def total_praises_count - praises_count + children.includes(:children).reduce(0) { |count, filed| - sub_sum_count = filed.children.reduce(0) { |sub_count, sub_filed| sub_count += sub_filed.praises_count } - count += filed.praises_count - sub_sum_count += count - } + praises_count + descendants.sum(:praises_count) end # 包含二级回复数的总回复数 def total_replies_count - replies_count + children.includes(:children).reduce(0) { |count, child| - sub_sum_count = child.children.reduce(0) { |sub_count, sub_child| sub_count += sub_child.replies_count } - count += child.replies_count - sub_sum_count += count - } + descendants_count end def has_replies - children.present? + children.exists? end # diff --git a/app/models/myshixun.rb b/app/models/myshixun.rb index 089b416de..a4f05f2ce 100644 --- a/app/models/myshixun.rb +++ b/app/models/myshixun.rb @@ -18,7 +18,7 @@ class Myshixun < ApplicationRecord end def output_times - games.sum(:evaluate_count) + games.pluck(:evaluate_count).sum.to_i end def repo_path @@ -53,23 +53,14 @@ class Myshixun < ApplicationRecord end # 当前任务:一个实训中只可能一个未完成任务(status 0或1只会存在一条记录) - # status:0 可以测评的,正在测评的 + # status:0 可以测评的; 1 正在测评的; 2评测通过的; 3未开启的 # 如果都完成,则当前任务为最后一个任务 - def current_task - - current_game = self.games.select{|game| game.status == 1 || game.status == 0}.first + def current_task games + current_game = games.select{|game| game.status == 1 || game.status == 0}.last if current_game.blank? - if self.status == 1 - logger.info("@3333333333344444444#{self.id}") - current_game = Game.find_by_sql("SELECT g.* FROM games g, challenges c where g.myshixun_id=#{self.id} and - g.challenge_id = c.id and g.status = 2 order by c.position desc").first - else - # 如果没开启过的,status都为3,所以应该进入第一关 - current_game = Game.find_by_sql("SELECT g.* FROM games g, challenges c where g.myshixun_id=#{self.id} and - g.challenge_id = c.id and g.status = 3 order by c.position asc").first - end + current_game = games.last end - return current_game + current_game end @@ -81,12 +72,12 @@ class Myshixun < ApplicationRecord # 个人实训得分 def total_score - self.games.where("status = 2 and final_score > 0").sum(:final_score).to_i + self.games.select{|game| game.status == 2 && game.final_score > 0}.pluck(:final_score).sum.to_i end # 个人通关数 def passed_count - self.games.where(status: 2).count + self.games.select{|game| game.status == 2}.size end # 通关时间 @@ -96,12 +87,12 @@ class Myshixun < ApplicationRecord # 耗时 def total_spend_time - game_spend_time self.games.where(status: 2).sum(:cost_time).to_i + game_spend_time total_cost_time end # 通关总耗时 def total_cost_time - self.games.where(status: 2).sum(:cost_time).to_i + self.games.select{|game| game.status == 2}.map(&:cost_time).sum.to_i end end diff --git a/app/models/output.rb b/app/models/output.rb index b813f6070..7a4a22e7e 100644 --- a/app/models/output.rb +++ b/app/models/output.rb @@ -1,3 +1,15 @@ +# 字段说明: +# code:-1表示评测未通过,0表示评测成功,实质是status的值 +# mes: +# out_put: +# test_set_position: 测试集序号(排序) +# actual_output: +# result: +# is_public:测试集是否是公开 +# query_index:评测次数 +# compile_success: +# text_scor: +# sec_key:每次评测的唯一标识 class Output < ApplicationRecord belongs_to :game end diff --git a/app/models/poll.rb b/app/models/poll.rb index 7ebcceafd..7f0d2fd94 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -4,13 +4,14 @@ class Poll < ApplicationRecord belongs_to :exercise_bank, optional: true # belongs_to :exercise_bank - has_many :poll_questions,dependent: :destroy - has_many :poll_users, :dependent => :destroy + has_many :poll_questions,dependent: :delete_all + has_many :poll_users, -> { where("is_delete != 1") }, :dependent => :delete_all has_many :users, :through => :poll_users #该文件被哪些用户提交答案过 - has_many :poll_group_settings, :dependent => :destroy - has_many :course_acts, class_name: 'CourseActivity', as: :course_act, dependent: :destroy + has_many :poll_group_settings, :dependent => :delete_all + has_many :published_settings, -> { poll_group_published }, class_name: "PollGroupSetting" + has_many :course_acts, class_name: 'CourseActivity', as: :course_act, dependent: :delete_all - has_many :tidings, as: :container, dependent: :destroy + has_many :tidings, as: :container, dependent: :delete_all scope :publish_or_not, -> { where("polls_status > ? ",1)} scope :only_public, -> {where("is_public = ?",true)} @@ -44,90 +45,98 @@ class Poll < ApplicationRecord if unified_setting #试卷统一设置 poll_users else - ex_group_setting_ids = poll_group_settings.poll_group_published.pluck(:course_group_id) - course_user_ids = course.students.where(course_group_id:ex_group_setting_ids).pluck(:user_id) - poll_users.where(user_id:course_user_ids) + ex_group_setting_ids = published_settings.pluck(:course_group_id) + poll_users.joins("join course_members on poll_users.user_id=course_members.user_id"). + where(course_members: {course_group_id: ex_group_setting_ids}) end end - # 统一设置,为当前老师有权限的分班学生,分班设置,也为当前老师有权限的分班的学生 - def all_poll_users(user_id) - poll_users = self.poll_users - group_ids = poll_published_ids(user_id) - logger.info("##########_________group_ids______#########################{group_ids}") - if group_ids.present? - poll_users = poll_users.where(user_id: course.students.where(course_group_id: group_ids).pluck(:user_id)) + # 根据是否统一发布获取作业的作品列表 + def all_works + po_users = unified_setting ? poll_users : + poll_users.joins("join course_members on poll_users.user_id=course_members.user_id"). + where(course_members: {course_group_id: published_settings.pluck(:course_group_id)}) + end + + # 分班权限的老师可见的作品列表 + def all_poll_users user_id + # member = course.course_member(user_id) + teacher_course_groups = course.teacher_course_groups.get_user_groups(user_id) + poll_users = self.all_works + # 有分班权限的统计管理的分班且已发布的学生情况 + if teacher_course_groups.exists? + group_ids = teacher_course_groups.pluck(:course_group_id) + poll_users = poll_users.joins("join course_members on poll_users.user_id=course_members.user_id"). + where(course_members: {course_group_id: group_ids}) end poll_users end + # # 统一设置,为当前老师有权限的分班学生,分班设置,也为当前老师有权限的分班的学生 + # def all_poll_users(user_id) + # poll_all_users = poll_users + # group_ids = poll_published_ids(user_id) + # if group_ids.present? + # poll_all_users = poll_all_users.where(user_id: course.students.where(course_group_id: group_ids).select(:user_id).pluck(:user_id).uniq) + # end + # poll_all_users + # end + #当前用户已发布的班级id和试卷分组已发布的班级id的交集 def poll_published_ids(user_id) - current_user_groups = course.teacher_course_group_ids(user_id) - logger.info("##########_________current_user_groups______#########################{current_user_groups}") + current_user_groups = course.teacher_course_ids(user_id) if unified_setting - if course.none_group_count > 0 #有未分班的,则发布到未发布 - un_group_ids = [0] - else - un_group_ids = [] - end - (current_user_groups + un_group_ids).uniq #统一设置时,为当前用户的分班id + current_user_groups.uniq + # if course.none_group_count > 0 #有未分班的,则发布到未发布 + # un_group_ids = [0] + # else + # un_group_ids = [] + # end + # (current_user_groups + un_group_ids).uniq #统一设置时,为当前用户的分班id else - ex_group_setting = poll_group_settings.pluck("course_group_id").uniq - ex_group_setting & current_user_groups #当前用户有权限的已发布的分班id #非统一设置时,为当前用户有权限的且已发布分班的id + ex_group_setting = poll_group_settings.select(:course_group_id).pluck("course_group_id").uniq + (ex_group_setting & current_user_groups).uniq #当前用户有权限的已发布的分班id #非统一设置时,为当前用户有权限的且已发布分班的id end end - def get_poll_status(user_id) - user_group = course.course_members.find_by(user_id: user_id, is_active: 1) - if user_group.present? - if user_group.role == "STUDENT" #为学生 - is_teacher = false - else - is_teacher = true - end - ex_time = get_poll_times(user_id,is_teacher) - pb_time = ex_time[:publish_time] - ed_time = ex_time[:end_time] - if pb_time.present? && ed_time.present? && pb_time <= Time.now && ed_time > Time.now - status = 2 - elsif ed_time.present? && ed_time <= Time.now - status = 3 + def get_poll_status(user) + if course.is_end + status = 4 + else + if user.present? && user.student_of_course?(course) + ex_time = get_poll_times(user_id,false) + pb_time = ex_time[:publish_time] + ed_time = ex_time[:end_time] + if pb_time.present? && ed_time.present? && pb_time <= Time.now && ed_time > Time.now + status = 2 + elsif ed_time.present? && ed_time <= Time.now + status = 3 + else + status = 1 + end else - status = 1 + status = polls_status end - else - status = polls_status end status end #获取问卷的发布时间和截止时间。teacher 为boolean,当为true时,表示的是当前为老师 def get_poll_times(user_id,teacher) - if unified_setting + if unified_setting || teacher pb_time = publish_time en_time = end_time else poll_group_setting = poll_group_settings - if teacher #当前为老师,为设置组的最大值和最小值 - user_group = course.teacher_course_groups.get_user_groups(user_id) - user_group_ids = user_group.present? ? user_group.pluck(:course_group_id) : course.course_groups.pluck(:id) - user_poll_group_settings = poll_group_setting.find_in_poll_group("course_group_id",user_group_ids) - pb_time_min = user_poll_group_settings.publish_time_present.map(&:publish_time) - en_time_max = user_poll_group_settings.end_time_present.map(&:end_time) - pb_time = pb_time_min.size > 0 ? pb_time_min.min : nil - en_time = en_time_max.size > 0 ? en_time_max.max : nil + user_group = course.course_members.where(user_id: user_id).select(:course_group_id) + if user_group.exists? + user_group_id = user_group.first&.course_group_id + user_p_group_setting = poll_group_setting.where(course_group_id: user_group_id).select(:publish_time,:end_time) + pb_time = user_p_group_setting.first&.publish_time + en_time = user_p_group_setting.first&.end_time else - user_group = course.students.find_by(user_id: user_id) - if user_group.present? - user_group_id = user_group.course_group_id - user_p_group_setting = poll_group_setting.find_by(course_group_id: user_group_id) - pb_time = user_p_group_setting.present? ? user_p_group_setting.publish_time : nil - en_time = user_p_group_setting.present? ? user_p_group_setting.end_time : nil - else - pb_time = nil - en_time = nil - end + pb_time = nil + en_time = nil end end { @@ -138,18 +147,11 @@ class Poll < ApplicationRecord #判断当前用户的答题状态 def check_user_votes_status(user) - poll_answer_user = poll_users.find_by(user_id: user.id) - user_poll_status = get_poll_status(user.id) + poll_answer_user = poll_users.where(user_id: user.id).select(:start_at,:end_at,:commit_status) user_status = 2 - - if poll_answer_user.present? && (poll_answer_user.start_at.present? || poll_answer_user.end_at.present?) #学生有过答题的,或者立即截止,但学生未做试卷的 - user_status = poll_answer_user.commit_status - end - - if poll_answer_user.present? && poll_answer_user.start_at.blank? && user_poll_status == 3 - user_status = 4 + if poll_answer_user.exists? && (poll_answer_user.first&.start_at.present? || poll_answer_user.first&.end_at.present?) #学生有过答题的,或者立即截止,但学生未做试卷的 + user_status = poll_answer_user.first.commit_status end - user_status end diff --git a/app/models/poll_answer.rb b/app/models/poll_answer.rb index 423198bbf..8e2421328 100644 --- a/app/models/poll_answer.rb +++ b/app/models/poll_answer.rb @@ -3,7 +3,7 @@ class PollAnswer < ApplicationRecord # include Redmine::SafeAttributes belongs_to :poll_question - has_many :poll_votes, :dependent => :destroy + has_many :poll_votes, :dependent => :delete_all scope :find_answer_by_custom, lambda {|k,v| where("#{k}":v)} #根据传入的参数查找问题 scope :left_answer_choose, lambda {|k,v| where("#{k} > ?",v)} #根据传入的参数查找问题 diff --git a/app/models/poll_question.rb b/app/models/poll_question.rb index 958b69acd..a0854aa48 100644 --- a/app/models/poll_question.rb +++ b/app/models/poll_question.rb @@ -1,15 +1,13 @@ class PollQuestion < ApplicationRecord belongs_to :poll - has_many :poll_answers, :dependent => :destroy + has_many :poll_answers, :dependent => :delete_all attr_accessor :question_answers, :question_other_anser - has_many :poll_votes, :dependent => :destroy + has_many :poll_votes scope :ques_count, lambda {|k| where("question_type = ?",k)} scope :ques_necessary, -> {where("is_necessary = ?",1)} scope :insert_question, lambda {|k| where("question_number > ?",k)} - scope :next_poll, lambda {|k| where("question_number > ?",k).first} - scope :last_poll, lambda {|k| where("question_number < ?",k).last} def question_type_name case self.question_type diff --git a/app/models/relationship.rb b/app/models/relationship.rb index d5c754745..d71987867 100644 --- a/app/models/relationship.rb +++ b/app/models/relationship.rb @@ -1,6 +1,8 @@ +# TODO: 已废弃 class Relationship < ApplicationRecord belongs_to :follower, class_name: "User" belongs_to :followed, class_name: "User" + validates :follower_id, presence: true validates :followed_id, presence: true end diff --git a/app/models/repertoire.rb b/app/models/repertoire.rb index 400cef494..140416658 100644 --- a/app/models/repertoire.rb +++ b/app/models/repertoire.rb @@ -1,6 +1,25 @@ class Repertoire < ApplicationRecord - - has_many :sub_repertoires + has_many :sub_repertoires, ->{order(updated_at: :desc)}, :dependent => :destroy has_many :tag_repertoires, through: :sub_repertoires + has_many :user_interests, dependent: :delete_all + + after_create_commit :reset_cache_data + after_update_commit :reset_cache_data + + def self.cache_data + Rails.cache.fetch(data_cache_key, expires_in: 1.days) do + Repertoire.select(:id, :name).order(:created_at).as_json + end + end + + def self.data_cache_key + 'repertoire/cache_data' + end + + private + + def reset_cache_data + Rails.cache.delete(self.class.data_cache_key) + end end diff --git a/app/models/school.rb b/app/models/school.rb index af04ed0c7..983a93735 100644 --- a/app/models/school.rb +++ b/app/models/school.rb @@ -1,4 +1,6 @@ class School < ApplicationRecord + has_many :departments, dependent: :destroy + has_many :shixun_schools, :dependent => :destroy has_many :shixuns, :through => :shixun_schools @@ -8,6 +10,9 @@ class School < ApplicationRecord has_many :ec_major_schools, :dependent => :destroy has_many :ec_majors, :through => :ec_major_schools + after_create_commit :reset_data_cache + after_update_commit :reset_data_cache + # 学校管理员 def manager?(user) ec_school_users.exists?(user_id: user.id) @@ -28,4 +33,23 @@ class School < ApplicationRecord def manage_permission?(user) manager?(user) || major_manager?(user) || course_manager?(user) end + + def self.cached_names_data + Rails.cache.fetch(names_data_cache_key, expires_in: 7.days) do + School.select(:id, :name).as_json + end + end + + private + + def reset_data_cache + # 清除学校名称缓存 + if new_record? || name_previously_changed? + Rails.cache.delete(self.class.names_data_cache_key) + end + end + + def self.names_data_cache_key + 'schools/names_data' + end end diff --git a/app/models/searchable.rb b/app/models/searchable.rb new file mode 100644 index 000000000..b8649a75c --- /dev/null +++ b/app/models/searchable.rb @@ -0,0 +1,3 @@ +module Searchable + MAXIMUM_LENGTH = 10922 # 最大字节数为32766 ,一个汉字3个字节 +end \ No newline at end of file diff --git a/app/models/searchable/course.rb b/app/models/searchable/course.rb new file mode 100644 index 000000000..93c69c9e8 --- /dev/null +++ b/app/models/searchable/course.rb @@ -0,0 +1,37 @@ +module Searchable::Course + extend ActiveSupport::Concern + + included do + searchkick language: 'chinese', callbacks: :async + + scope :search_import, -> { includes(:teacher_users, teacher: { user_extension: :school } ) } + end + + def searchable_title + name + end + + def search_data + { + name: name, + author_name: teacher&.real_name + } + end + + def to_searchable_json + { + id: id, + author_name: teacher.real_name, + author_school_name: teacher.school_name, + visits_count: visits, + members_count: members_count, + is_public: is_public == 1 + } + end + + module ClassMethods + def searchable_includes + { teacher: { user_extension: :school } } + end + end +end diff --git a/app/models/searchable/dependents.rb b/app/models/searchable/dependents.rb new file mode 100644 index 000000000..66751a475 --- /dev/null +++ b/app/models/searchable/dependents.rb @@ -0,0 +1,2 @@ +module Searchable::Dependents +end diff --git a/app/models/searchable/dependents/challenge_tag.rb b/app/models/searchable/dependents/challenge_tag.rb new file mode 100644 index 000000000..51ef804dd --- /dev/null +++ b/app/models/searchable/dependents/challenge_tag.rb @@ -0,0 +1,16 @@ +module Searchable::Dependents::ChallengeTag + extend ActiveSupport::Concern + + included do + after_create_commit :check_searchable_dependents + after_update_commit :check_searchable_dependents + end + + private + + def check_searchable_dependents + if new_record? || name_previously_changed? + challenge.shixun.reindex + end + end +end \ No newline at end of file diff --git a/app/models/searchable/dependents/stage.rb b/app/models/searchable/dependents/stage.rb new file mode 100644 index 000000000..d4207fec8 --- /dev/null +++ b/app/models/searchable/dependents/stage.rb @@ -0,0 +1,15 @@ +module Searchable::Dependents::Stage + extend ActiveSupport::Concern + + included do + after_update_commit :check_searchable_dependents + end + + private + + def check_searchable_dependents + if name_previously_changed? || description_previously_changed? + subject.reindex + end + end +end \ No newline at end of file diff --git a/app/models/searchable/dependents/user.rb b/app/models/searchable/dependents/user.rb new file mode 100644 index 000000000..f6dcaa430 --- /dev/null +++ b/app/models/searchable/dependents/user.rb @@ -0,0 +1,22 @@ +module Searchable::Dependents::User + extend ActiveSupport::Concern + + included do + after_update_commit :check_searchable_dependents + end + + private + + def check_searchable_dependents + if firstname_previously_changed? || lastname_previously_changed? || user_extension.school_id_previously_changed? + # reindex shixun + created_shixuns.each(&:reindex) + + # reindex course + manage_courses.each(&:reindex) + + # reindex subject + created_subjects.each(&:reindex) + end + end +end \ No newline at end of file diff --git a/app/models/searchable/memo.rb b/app/models/searchable/memo.rb new file mode 100644 index 000000000..648f4671b --- /dev/null +++ b/app/models/searchable/memo.rb @@ -0,0 +1,47 @@ +module Searchable::Memo + extend ActiveSupport::Concern + + included do + searchkick language: 'chinese', callbacks: :async + + scope :search_import, -> { includes(:descendants) } + end + + def searchable_title + subject + end + + def should_index? + hidden.zero? && root_id.blank? && parent_id.blank? + end + + def search_data + { + name: subject, + content: Util.extract_content(content)[0..Searchable::MAXIMUM_LENGTH], + }.merge!(searchable_descendants_data) + end + + def searchable_descendants_data + { + descendants_contents: Util.map_or_pluck(descendants, :content) + .map { |content| Util.extract_content(content)[0..Searchable::MAXIMUM_LENGTH] } + .join('
') + } + end + + def to_searchable_json + { + id: id, + author_name: author.full_name, + visits_count: viewed_count, + all_replies_count: all_replies_count + } + end + + module ClassMethods + def searchable_includes + [:author] + end + end +end diff --git a/app/models/searchable/shixun.rb b/app/models/searchable/shixun.rb new file mode 100644 index 000000000..49e066eac --- /dev/null +++ b/app/models/searchable/shixun.rb @@ -0,0 +1,60 @@ +module Searchable::Shixun + extend ActiveSupport::Concern + + included do + searchkick language: 'chinese', callbacks: :async + + scope :search_import, -> { includes(:shixun_info, :challenges, :challenge_tags, :users, user: { user_extension: :school }) } + end + + def searchable_title + name + end + + def search_data + { + name: name, + description: Util.extract_content(description)[0..Searchable::MAXIMUM_LENGTH] + }.merge!(searchable_user_data) + .merge!(searchable_challenge_data) + end + + def searchable_user_data + { + author_name: user&.real_name, + author_school_name: user&.school_name, + } + end + + def searchable_challenge_data + challenge_names = Util.map_or_pluck(challenges, :subject) + .each_with_index.map { |subject, index| "第#{index + 1}关 #{subject}" } + + { + challenge_names: challenge_names.join(' '), + challenge_tag_names: Util.map_or_pluck(challenge_tags, :name).uniq.join(' ') + } + end + + def should_index? + status == 2 # published + end + + def to_searchable_json + { + id: id, + identifier: identifier, + author_name: user.real_name, + author_school_name: user.school_name, + visits_count: visits, + challenges_count: challenges_count, + study_count: myshixuns_count + } + end + + module ClassMethods + def searchable_includes + { user: { user_extension: :school } } + end + end +end diff --git a/app/models/searchable/subject.rb b/app/models/searchable/subject.rb new file mode 100644 index 000000000..94a5c1383 --- /dev/null +++ b/app/models/searchable/subject.rb @@ -0,0 +1,55 @@ +module Searchable::Subject + extend ActiveSupport::Concern + + included do + searchkick language: 'chinese', callbacks: :async + + scope :search_import, -> { includes(:users, :stages, user: { user_extension: :school }) } + end + + def searchable_title + name + end + + def should_index? + !hidden? && status == 2 # published + end + + def search_data + { + name: name, + description: Util.extract_content(description)[0..Searchable::MAXIMUM_LENGTH] + }.merge!(searchable_user_data) + .merge!(searchable_stages_data) + end + + def searchable_user_data + { + author_name: user.real_name, + author_school_name: user.school_name, + } + end + + def searchable_stages_data + subject_stages = stages.map { |stage| "#{stage.name} #{Util.extract_content(stage.description)}"[0..Searchable::MAXIMUM_LENGTH] } + + { subject_stages: subject_stages.join('
') } + end + + def to_searchable_json + { + id: id, + author_name: user.real_name, + author_school_name: user.school_name, + visits_count: visits, + stage_count: stages_count, + stage_shixuns_count: stage_shixuns_count + } + end + + module ClassMethods + def searchable_includes + { user: { user_extension: :school } } + end + end +end diff --git a/app/models/shixun.rb b/app/models/shixun.rb index 9ccefca92..d274f0a6d 100644 --- a/app/models/shixun.rb +++ b/app/models/shixun.rb @@ -1,6 +1,11 @@ class Shixun < ApplicationRecord + include Searchable::Shixun + # status: 0:编辑 1:申请发布 2:正式发布 3:关闭 -1:软删除 + # hide_code: 隐藏代码窗口 + # code_hidden: 隐藏代码目录 has_many :challenges, dependent: :destroy + has_many :challenge_tags, through: :challenges has_many :myshixuns, :dependent => :destroy has_many :shixun_members, dependent: :destroy has_many :users, through: :shixun_members @@ -30,7 +35,8 @@ class Shixun < ApplicationRecord has_one :shixun_info, dependent: :destroy belongs_to :user - + # 实训服务配置 + has_many :shixun_service_configs, :dependent => :destroy scope :search_by_name, ->(keyword) { where("name like ? or description like ? ", "%#{keyword}%", "%#{keyword}%") } @@ -48,7 +54,7 @@ class Shixun < ApplicationRecord end } - scope :visible, -> { where("status != -1") } + scope :visible, -> { where.not(status: -1) } scope :published, lambda{ where(status: 2) } scope :unhidden, lambda{ where(hidden: 0, status: 2) } scope :field_for_recommend, lambda{ select([:id, :name, :identifier, :myshixuns_count]) } @@ -69,9 +75,8 @@ class Shixun < ApplicationRecord # 实训用户tag def user_tags_name(user = User.current) - challenge_ids = challenges.pluck(:id) - user_challenge_ids = user.games.where(challenge_id: challenge_ids, status: 2).pluck(:challenge_id) - ChallengeTag.where(challenge_id: user_challenge_ids).pluck(:name).uniq + Shixun.joins(challenges: [:challenge_tags, :games]).where(games: {status: 2, user_id: user.id}, shixuns: {id:id}) + .pluck("challenge_tags.name").uniq end # 实训关卡tag @@ -154,13 +159,11 @@ class Shixun < ApplicationRecord # 实训评分信息 # return [实训评分, 5星评分比例, 4星评分比例, 3星评分比例, 2星评分比例, 1星评分比例] def shixun_preference_info - game_star_info = Game.find_by_sql("select g.star from - (games g left join (myshixuns m join shixuns s on s.id = m.shixun_id) on m.id = g.myshixun_id) - where g.star != 0 and s.id = #{self.id}") + game_star_info = Game.joins(challenge: :shixun).where(shixuns: {id: id}).where.not(games: {star: 0}).pluck(:star) star_info = [] if game_star_info.present? 5.downto(1) do |i| - star_info << ((game_star_info.select{|s| s.star == i}.count / game_star_info.count.to_f) * 100).round + star_info << ((game_star_info.select{|s| s == i}.count / game_star_info.count.to_f) * 100).round end sum = star_info.sum max = star_info.max @@ -171,7 +174,7 @@ class Shixun < ApplicationRecord star_info = star_info.map{|s| s == max ? s + 1 : s} end cnt = game_star_info.count - sum = game_star_info.sum(&:star) + sum = game_star_info.sum star_info.unshift((sum / cnt.to_f).round(1)) else star_info = [5.0, 100, 0, 0, 0, 0] @@ -233,4 +236,8 @@ class Shixun < ApplicationRecord shixun_members.where(role: [1, 2]).exists?(user_id: user.id) end + + def finished_challenges_count(user) + Game.joins(:myshixun).where(user_id: user.id, status: 2, myshixuns: { shixun_id: id }).count + end end diff --git a/app/models/shixun_service_config.rb b/app/models/shixun_service_config.rb new file mode 100644 index 000000000..6d106fc07 --- /dev/null +++ b/app/models/shixun_service_config.rb @@ -0,0 +1,4 @@ +class ShixunServiceConfig < ApplicationRecord + belongs_to :shixun + belongs_to :mirror_repository +end diff --git a/app/models/stage.rb b/app/models/stage.rb index 7c80c4f9c..d255cddeb 100644 --- a/app/models/stage.rb +++ b/app/models/stage.rb @@ -1,4 +1,6 @@ class Stage < ApplicationRecord + include Searchable::Dependents::Stage + belongs_to :subject, counter_cache: true has_many :stage_shixuns, -> { order("stage_shixuns.position ASC") }, dependent: :destroy diff --git a/app/models/student_work.rb b/app/models/student_work.rb index 0e674dd4c..9151ca501 100644 --- a/app/models/student_work.rb +++ b/app/models/student_work.rb @@ -39,24 +39,34 @@ class StudentWork < ApplicationRecord # 助教评分次数 def ta_comment_count - self.student_works_scores.where(reviewer_role: 2).group_by(&:user_id).count + self.student_works_scores.select{|score| score.reviewer_role == 2}.group_by(&:user_id).count end # 匿评次数 def student_comment_num - homework_common.homework_detail_manual.comment_status > 2 ? self.student_works_scores.where(reviewer_role: 3).group_by(&:user_id).count : 0 + homework_common.homework_detail_manual.comment_status > 2 ? self.student_works_scores.select{|score| score.reviewer_role == 3}.group_by(&:user_id).count : 0 end # 匿评申诉总条数 def appeal_all_count - homework_common.homework_detail_manual.comment_status >= 3 ? self.student_works_scores.where("reviewer_role = 3 and appeal_status != 0"). - group_by(&:user_id).count : 0 + homework_common.homework_detail_manual.comment_status >= 3 ? self.student_works_scores. + select{|score| score.reviewer_role == 3 && score.appeal_status != 0}.group_by(&:user_id).count : 0 end # 匿评申诉待处理条数 def appeal_deal_count - homework_common.homework_detail_manual.comment_status >= 3 ? self.student_works_scores.where("reviewer_role = 3 and appeal_status = 1"). - group_by(&:user_id).count : 0 + homework_common.homework_detail_manual.comment_status >= 3 ? self.student_works_scores. + select{|score| score.reviewer_role == 3 && score.appeal_status == 1}.group_by(&:user_id).count : 0 + end + + # 当前用户该作品的匿评申诉总条数 + def my_appeal_all_count user_id + student_works_scores.select{|score| score.reviewer_role == 3 && score.appeal_status != 0 && score.user_id == user_id}.size + end + + # 当前用户该作品的匿评申诉总条数 + def my_appeal_deal_count user_id + student_works_scores.select{|score| score.reviewer_role == 3 && score.appeal_status == 1 && score.user_id == user_id}.size end # 分组名 @@ -183,4 +193,19 @@ class StudentWork < ApplicationRecord def scored? student_works_scores.where.not(reviewer_role: 3).exists? end + + def work_challenge_score game, score + game_score = 0 + adjust_score = challenge_work_scores.where(challenge_id: game.challenge_id).last + if adjust_score.present? + game_score = adjust_score.score + else + setting = homework_common.homework_group_setting user_id + if game.status == 2 && ((game.end_time && game.end_time < setting.end_time) || (homework_common.allow_late && game.end_time && game.end_time < homework_common.late_time)) + answer_open_evaluation = homework_common.homework_detail_manual.answer_open_evaluation + game_score = answer_open_evaluation ? score : (game.final_score > 0 ? game.real_score(score) : 0) + end + end + game_score + end end diff --git a/app/models/sub_repertoire.rb b/app/models/sub_repertoire.rb index d94db66c7..d6a6c1b3d 100644 --- a/app/models/sub_repertoire.rb +++ b/app/models/sub_repertoire.rb @@ -1,3 +1,5 @@ class SubRepertoire < ApplicationRecord - has_many :tag_repertoires + belongs_to :repertoire + has_many :tag_repertoires, ->{order(updated_at: :desc)} ,:dependent => :destroy + end diff --git a/app/models/subject.rb b/app/models/subject.rb index ced610377..064efb7a6 100644 --- a/app/models/subject.rb +++ b/app/models/subject.rb @@ -2,6 +2,8 @@ # 可以在初始创建的时候 class Subject < ApplicationRecord + include Searchable::Subject + #status :0 编辑中 1 审核中 2 发布 belongs_to :repertoire belongs_to :user @@ -31,7 +33,7 @@ class Subject < ApplicationRecord # 挑战过路径的成员数 def member_count - shixuns.sum(:myshixuns_count) + shixuns.pluck(:myshixuns_count).sum end def all_score @@ -88,4 +90,9 @@ class Subject < ApplicationRecord def published? status == 2 end + + def shixun_tags + challenges = Challenge.where(shixun_id: shixuns.unhidden) + @tags = ChallengeTag.where(challenge_id: challenges).pluck(:name).uniq + end end \ No newline at end of file diff --git a/app/models/team_member.rb b/app/models/team_member.rb new file mode 100644 index 000000000..31890ea2e --- /dev/null +++ b/app/models/team_member.rb @@ -0,0 +1,16 @@ +class TeamMember < ApplicationRecord + belongs_to :user + belongs_to :competition + belongs_to :competition_team + + scope :only_teachers, -> { where(is_teacher: true) } + scope :without_teachers, -> { where(is_teacher: false) } + + def creator? + role == 1 + end + + def en_role + is_teacher? ? 'teacher' : 'member' + end +end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index 60765b852..73036c73e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,7 @@ class User < ApplicationRecord include Watchable + include Searchable::Dependents::User + # Account statuses STATUS_ANONYMOUS = 0 STATUS_ACTIVE = 1 @@ -28,6 +30,7 @@ class User < ApplicationRecord accepts_nested_attributes_for :user_extension, update_only: true has_many :memos, foreign_key: 'author_id' + has_many :created_shixuns, class_name: 'Shixun' has_many :shixun_members, :dependent => :destroy has_many :shixuns, :through => :shixun_members has_many :myshixuns, :dependent => :destroy @@ -47,14 +50,6 @@ class User < ApplicationRecord has_many :graduation_works, dependent: :destroy - # 关注 - has_many :relationships, foreign_key: "follower_id", dependent: :destroy - has_many :followed_users, through: :relationships, source: :followed - # 粉丝 - has_many :reverse_relationships, foreign_key: "followed_id", - class_name: "Relationship", - dependent: :destroy - has_many :followers, through: :reverse_relationships, source: :follower has_many :students_for_courses, foreign_key: :student_id, dependent: :destroy has_one :onclick_time, :dependent => :destroy @@ -63,6 +58,7 @@ class User < ApplicationRecord has_many :tidings, :dependent => :destroy has_many :games, :dependent => :destroy + has_many :created_subjects, foreign_key: :user_id, class_name: 'Subject' has_many :subjects, :through => :subject_members has_many :subject_members, :dependent => :destroy has_many :grades, :dependent => :destroy @@ -123,6 +119,10 @@ class User < ApplicationRecord has_many :attendances + # 兴趣 + has_many :user_interests, dependent: :delete_all + has_many :interests, through: :user_interests, source: :repertoire + # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } @@ -155,25 +155,25 @@ class User < ApplicationRecord Token.where(:user_id => id, :action => 'session', :value => value).delete_all end + def git_mail + mail || "#{login}@educoder.net" + end # 学号 def student_id self.user_extension.try(:student_id) end - # 关注总数 - def following?(other_user) - relationships.find_by(followed_id: other_user) + # 关注数 + def follow_count + Watcher.where(user_id: id, watchable_type: %w(Principal User)).count + # User.watched_by(id).count end - # 关注 - def follow!(other_user) - relationships.create!(followed_id: other_user) - end - - # 取消关注 - def unfollow!(other_user) - relationships.find_by(followed_id: other_user.id).destroy + # 粉丝数 + def fan_count + Watcher.where(watchable_type: %w(Principal User), watchable_id: id).count + # watchers.count end # 判断当前用户是否为老师 @@ -220,22 +220,22 @@ class User < ApplicationRecord # 课堂的老师(创建者、老师、助教) def teacher_of_course?(course) - course.course_members.exists?(user_id: id, role: [1,2,3], is_active: 1) || admin? + course.course_members.exists?(user_id: id, role: [1,2,3], is_active: 1) || admin? || business? end # 课堂的老师(创建者、老师、助教),不用考虑当前身份 def teacher_of_course_non_active?(course) - course.course_members.exists?(user_id: id, role: [1,2,3]) || admin? + course.course_members.exists?(user_id: id, role: [1,2,3]) || admin? || business? end # 是否是教师,课堂管理员或者超级管理员 def teacher_or_admin?(course) - course.course_members.exists?(user_id: id, role: [1,2], is_active: 1) || admin? + course.course_members.exists?(user_id: id, role: [1,2], is_active: 1) || admin? || business? end # 课堂的创建者(考虑到多重身份的用户) def creator_of_course?(course) - course.course_members.exists?(user_id: id, role: 1, is_active: 1) || admin? + course.course_members.exists?(user_id: id, role: 1, is_active: 1) || admin? || business? end # 课堂的学生 @@ -260,7 +260,7 @@ class User < ApplicationRecord # 实训管理员:实训合作者、admin def manager_of_shixun?(shixun) - shixun.shixun_members.exists?(role: [1,2], user_id: id) || admin? + shixun.shixun_members.exists?(role: [1,2], user_id: id) || admin? || business? end # 实训管理员 @@ -386,13 +386,22 @@ class User < ApplicationRecord end # 用户是否有权限查看实训 + # 1、实训删除只有管理员能看到 + # 2、实训隐藏了只有管理员、实训合作者能看到 + # 3、如果有限制学校范围,则学校的用户、管理员、实训合作者能看到 def shixun_permission(shixun) - # 性能优化:先处理不需要权限的实训(已发布并且没有单位权限限制的实训) - return true if manager_of_shixun?(shixun) # 实训管理员 - return false if shixun.status != 2 || shixun.hidden # 隐藏或者未发布的实训:false - return true if shixun.use_scope == 0 # 对所有学校公开 - return true if shixun.use_scope == 1 && shixun.shixun_schools.exists?(school_id: school_id) # 对部分高校公开 - return false + case shixun.status + when -1 # 软删除只有管理员能访问 + admin? + when 0, 1, 3 # 申请发布或者已关闭的实训,只有实训管理员可以访问 + manager_of_shixun?(shixun) + when 2 + if shixun.hidden + manager_of_shixun?(shixun) + else + shixun.use_scope == 0 || manager_of_shixun?(shixun) || shixun.shixun_schools.exists?(school_id: school_id) + end + end end # 用户在平台名称的显示方式 @@ -406,9 +415,8 @@ class User < ApplicationRecord # 用户的真实姓名(不考虑用户是否隐藏了真实姓名,课堂模块都用真实姓名) def real_name return '游客' unless logged? - name = lastname + firstname - name.blank? ? (nickname.blank? ? login : nickname) : name + name = name.blank? ? (nickname.blank? ? login : nickname) : name name.gsub(/\s+/, '').strip #6.11 -hs end @@ -499,14 +507,6 @@ class User < ApplicationRecord user = find_by_login(login) end - if user - # user is already in local database - raise("账号已被注销,请联系管理员") if user.locked? - raise("密码错误") unless user.check_password?(password) - else - raise("账号未注册") - end - user rescue => text raise text @@ -536,6 +536,42 @@ class User < ApplicationRecord Educoder::Utils.random_hex(16) end + # 全部已认证 + def all_certified? + authentication? && professional_certification? + end + + # 是否绑定邮箱 + def email_binded? + mail.present? + end + + # 学院的url标识 + def college_identifier + Department.find_by_id(department_members.pluck(:department_id).first)&.identifier + end + + # 是否能申请试用 + def can_apply_trial? + return false if certification == 1 + + apply = ApplyAction.order(created_at: :desc).find_by(user_id: id, container_type: 'TrialAuthorization') + + apply.present? && !apply.status.zero? + end + + # 是否已经签到 + def attendance_signed? + attendance = Attendance.find_by(user_id: id) + + attendance.present? && Util.days_between(Time.zone.now, attendance.created_at).zero? + end + + # 明日签到金币 + def tomorrow_attendance_gold + Attendance.find_by(user_id: id)&.next_gold || 60 # 基础50,连续签到+10 + end + protected def validate_password_length # 管理员的初始密码是5位 diff --git a/app/models/user_agent.rb b/app/models/user_agent.rb new file mode 100644 index 000000000..538369f1a --- /dev/null +++ b/app/models/user_agent.rb @@ -0,0 +1,6 @@ +class UserAgent < ApplicationRecord + has_many :user_actionss, :foreign_key => "ip", :primary_key => "ip" + USER_AD = 1 # 广告宣传的引流 + USER_REGISTER = 2 # 引流注册 + USER_COMPETITION = 3 # 引流参加竞赛 +end diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 3d8457ce3..5a0dc8a37 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -2,9 +2,9 @@ class UserExtension < ApplicationRecord # identity 0: 教师教授 1: 学生, 2: 专业人士, 3: 开发者 enum identity: { teacher: 0, student: 1, professional: 2, developer: 3 } - belongs_to :user - belongs_to :school - belongs_to :department + belongs_to :user, touch: true + belongs_to :school, optional: true + belongs_to :department, optional: true def identity_text I18n.t("user.identity.#{identity}") diff --git a/app/models/user_interest.rb b/app/models/user_interest.rb new file mode 100644 index 000000000..bdb6e77d4 --- /dev/null +++ b/app/models/user_interest.rb @@ -0,0 +1,4 @@ +class UserInterest < ApplicationRecord + belongs_to :user + belongs_to :repertoire +end \ No newline at end of file diff --git a/app/services/batch_export_shixun_report_service.rb b/app/services/batch_export_shixun_report_service.rb index 6ea38b23f..d71235790 100644 --- a/app/services/batch_export_shixun_report_service.rb +++ b/app/services/batch_export_shixun_report_service.rb @@ -3,20 +3,23 @@ class BatchExportShixunReportService MAX_BATCH_LIMIT = 20 - attr_reader :homework, :student_work_ids + attr_reader :homework, :all_student_works - def initialize(homework, student_work_ids) + + def initialize(homework, all_student_works) @homework = homework - @student_work_ids = student_work_ids + # @student_work_ids = student_work_ids + @all_student_works = all_student_works + end def filename - @_filename ||= "#{Time.now.strftime('%Y%m%d%H%M%S')}-#{homework.name}.zip" + @_filename ||= "#{homework.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" end def zip - validate! - student_works = homework.student_works.where(id: student_work_ids).includes(:myshixun, user: :user_extension) + # validate! + student_works = all_student_works.includes(:myshixun, user: :user_extension) if student_works.count.zero? raise Error, '请选择要导出的学生实训报告' @@ -33,7 +36,7 @@ class BatchExportShixunReportService rescue => ex Rails.logger.error(ex.message) - zip.get_output_stream('FILE_NOTICE.txt'){|os| os.write('文件重复') } + zip.get_output_stream('FILE_NOTICE.txt'){|os| os.write("文件重复:#{export.filename}") } next end end @@ -41,15 +44,4 @@ class BatchExportShixunReportService end end - private - - def validate! - if student_work_ids.size.zero? - raise Error, '请选择学生实训作业' - end - - if student_work_ids.size > MAX_BATCH_LIMIT - raise Error, '导出实训报告太多,请分批导出' - end - end end diff --git a/app/services/competitions/create_personal_team_service.rb b/app/services/competitions/create_personal_team_service.rb new file mode 100644 index 000000000..12b595cae --- /dev/null +++ b/app/services/competitions/create_personal_team_service.rb @@ -0,0 +1,27 @@ +class Competitions::CreatePersonalTeamService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :competition, :user + + def initialize(competition, user) + @competition = competition + @user = user + end + + def call + raise Error, '个人赛才能报名' unless competition.personal? + + is_teacher = user.is_teacher? + raise Error, '本竞赛的参赛者限定为:学生' if is_teacher && competition.teacher_enroll_forbidden? + raise Error, '本竞赛的参赛者限定为:教师' if !is_teacher && competition.member_enroll_forbidden? + + enrolled = competition.competition_teams.exists?(user_id: user.id) + multiple_limited = (is_teacher && competition.teacher_multiple_limited?) || (!is_teacher && competition.member_multiple_limited?) + raise Error, '您已报名该竞赛' if enrolled && multiple_limited + + ActiveRecord::Base.transaction do + team = competition.competition_teams.create!(name: user.show_name, user_id: user.id) + team.team_members.create!(competition_id: competition, user_id: user.id, role: 1, is_teacher: is_teacher) + end + end +end \ No newline at end of file diff --git a/app/services/competitions/join_team_service.rb b/app/services/competitions/join_team_service.rb new file mode 100644 index 000000000..df889abe2 --- /dev/null +++ b/app/services/competitions/join_team_service.rb @@ -0,0 +1,35 @@ +class Competitions::JoinTeamService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :competition, :user, :params + + def initialize(competition, user, params) + @competition = competition + @user = user + @params = params + end + + def call + invite_code = params[:invite_code].to_s.strip + raise Error, '战队邀请码不能为空' if invite_code.blank? + + is_teacher = user.is_teacher? + raise Error, '本竞赛的参赛者限定为:学生' if is_teacher && competition.teacher_enroll_forbidden? + raise Error, '本竞赛的参赛者限定为:教师' if !is_teacher && competition.member_enroll_forbidden? + + team = competition.competition_teams.find_by(invite_code: invite_code) + raise Error, '战队邀请码无效' if team.blank? + raise Error, '您已加入该战队' if team.team_members.exists?(user_id: user.id) + + enrolled = competition.team_members.exists?(user_id: user.id) + if enrolled && (is_teacher && competition.teacher_multiple_limited?) || (!is_teacher && competition.member_multiple_limited?) + raise Error, '您已加入其它战队' + end + + raise Error, '该战队教师人数已满' if is_teacher && team.teachers.count == competition.teacher_staff.maximum + raise Error, '该战队队员人数已满' if !is_teacher && team.members.count == competition.member_staff.maximum + + role = is_teacher ? 3 : 2 + team.team_members.create!(competition_id: competition.id, user_id: user, role: role, is_teacher: is_teacher) + end +end \ No newline at end of file diff --git a/app/services/competitions/save_team_service.rb b/app/services/competitions/save_team_service.rb new file mode 100644 index 000000000..1021e6e6d --- /dev/null +++ b/app/services/competitions/save_team_service.rb @@ -0,0 +1,71 @@ +class Competitions::SaveTeamService < ApplicationService + attr_reader :competition, :team, :creator, :params + + TEAM_MEMBER_ATTRIBUTES = %i[competition_id competition_team_id user_id role is_teacher created_at updated_at] + + def initialize(team, params) + @team = team + @competition = team.competition + @creator = team.user + @params = params + end + + def call + Competitions::SaveTeamForm.new(form_params).validate! + + new_record = team.new_record? + is_teacher = team.user.is_teacher? + ActiveRecord::Base.transaction do + team.generate_invite_code if new_record + team.team_type = 1 # 组队竞赛 + team.name = params[:name].to_s.strip + team.save! + + # 创建者 + team.team_members.create!(user_id: creator.id, competition_id: competition.id, role: 1, is_teacher: is_teacher) if new_record + + update_teacher_team_members! + update_member_team_members! + end + end + + private + + def update_teacher_team_members! + teacher_ids = Array.wrap(params[:teacher_ids]).map(:to_i) + old_teacher_ids = team.team_members.where(role: 3).pluck(:user_id) + + destroy_teacher_ids = old_teacher_ids - teacher_ids + team.team_members.where(role: 3).where(user_id: destroy_teacher_ids).delete_all + + new_teacher_ids = teacher_ids - old_teacher_ids + TeamMember.bulk_insert(*TEAM_MEMBER_ATTRIBUTES) do |worker| + base_attr = { competition_id: competition.id, competition_team_id: team.id, role: 3, is_teacher: true } + new_teacher_ids.each do |teacher_id| + next if teacher_id == creator.id + worker.add(base_attr.merge(user_id: teacher_id)) + end + end + end + + def update_member_team_members! + member_ids = Array.wrap(params[:member_ids]).map(:to_i) + old_member_ids = team.team_members.where(role: 2).pluck(:user_id) + + destroy_member_ids = old_member_ids - member_ids + team.team_members.where(role: 2).where(user_id: destroy_member_ids).delete_all + + new_member_ids = member_ids - old_member_ids + TeamMember.bulk_insert(*TEAM_MEMBER_ATTRIBUTES) do |worker| + base_attr = { competition_id: competition.id, competition_team_id: team.id, role: 2, is_teacher: false } + new_member_ids.each do |member_id| + next if member_id == creator.id + worker.add(base_attr.merge(user_id: member_id)) + end + end + end + + def form_params + params.merge(competition: competition, team: team, creator: creator) + end +end \ No newline at end of file diff --git a/app/services/concerns/elasticsearch_able.rb b/app/services/concerns/elasticsearch_able.rb new file mode 100644 index 000000000..c1640470c --- /dev/null +++ b/app/services/concerns/elasticsearch_able.rb @@ -0,0 +1,49 @@ +module ElasticsearchAble + extend ActiveSupport::Concern + + private + + def default_options + { + debug: Rails.env.development?, + highlight: highlight_options, + body_options: body_options, + page: page, + per_page: per_page + } + end + + def keyword + params[:keyword].to_s.strip.presence || '*' + end + + def highlight_options + { + fragment_size: EduSetting.get('es_highlight_fragment_size') || 30, + tag: '', + fields: { + challenge_names: { type: 'plain' }, + challenge_tag_names: { type: 'plain' }, + description: { type: 'plain' }, + subject_stages: { type: 'plain' }, + content: { type: 'plain' }, + descendants_contents: { type: 'plain' }, + } + } + end + + def body_options + { + min_score: EduSetting.get('es_min_score') || 10 + } + end + + def per_page + per_page = params[:per_page].to_s.strip.presence || params[:limit].to_s.strip.presence + per_page.to_i <= 0 ? 20 : per_page.to_i + end + + def page + params[:page].to_i <= 0 ? 1 : params[:page].to_i + end +end \ No newline at end of file diff --git a/app/services/create_add_department_apply_service.rb b/app/services/create_add_department_apply_service.rb new file mode 100644 index 000000000..f1d6cf852 --- /dev/null +++ b/app/services/create_add_department_apply_service.rb @@ -0,0 +1,43 @@ +class CreateAddDepartmentApplyService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :user, :params + + def initialize(user, params) + @user = user + @params = params + end + + def call + name = params[:name].to_s.strip + raise Error, '名称不能为空' if name.blank? + + school = School.find_by(id: params[:school_id]) + raise Error, '学校/单位不存在' if school.blank? + + department = Department.new + department.name = name + department.school = school + + ActiveRecord::Base.transaction do + department.save! + + attrs = { + user_id: user.id, department: department, school: school, + name: department.name, remarks: params[:remarks], status: 0, + } + apply = ApplyAddDepartment.create!(attrs) + + unless user.professional_certification? + user.user_extension.update!(department_id: department.id) + end + + # 向管理员发送通知 + message = AppliedMessage.new(user_id: 1, status: 0, applied_user_id: user.id, viewed: 0, + applied_id: apply.id, applied_type: 'ApplyAddDepartment', name: department.name) + message.save(validate: false) + end + + school + end +end diff --git a/app/services/create_add_school_apply_service.rb b/app/services/create_add_school_apply_service.rb new file mode 100644 index 000000000..96619c681 --- /dev/null +++ b/app/services/create_add_school_apply_service.rb @@ -0,0 +1,37 @@ +class CreateAddSchoolApplyService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :user, :params + + def initialize(user, params) + @user = user + @params = params + end + + def call + AddSchoolApplyForm.new(params).validate! + + name = params[:name].to_s.strip + raise Error, '学校/单位已经存在' if name.present? && School.exists?(name: name) + + school = School.new + school.name = name + school.province = params[:province].to_s.strip + school.city = params[:city].to_s.strip + school.address = params[:address].to_s.strip + + ActiveRecord::Base.transaction do + school.save! + + school_attrs = school.as_json(only: %i[name province city address]) + ApplyAddSchool.create!(school_attrs.merge(school: school, user_id: user.id, remarks: params[:remarks])) + + # 向管理员发送通知 + message = AppliedMessage.new(user_id: 1, status: 0, applied_user_id: user.id, viewed: 0, + applied_id: school.id, applied_type: 'ApplyAddSchools', name: school.name) + message.save(validate: false) + end + + school + end +end diff --git a/app/services/exercise_user_pdf_service.rb b/app/services/exercise_user_pdf_service.rb index 5f92aee9c..73711192f 100644 --- a/app/services/exercise_user_pdf_service.rb +++ b/app/services/exercise_user_pdf_service.rb @@ -2,19 +2,21 @@ class ExerciseUserPdfService include ExercisesHelper include ApplicationHelper include StudentWorksHelper + include GitHelper - attr_reader :exercise, :ex_user + attr_reader :exercise, :ex_user, :request_url - def initialize(exercise, ex_user) + def initialize(exercise, ex_user,request_url) @exercise = exercise @ex_user = ex_user + @request_url = request_url @ex_user_user = @ex_user.user @course = @exercise.course end def filename - user_course = @course.course_members.find_by(user_id:@ex_user_user.id).course_group_name - exercise_user_name = user_course + "_" + exercise.exercise_name + "_" + @ex_user_user.real_name + user_course = @course.course_members.find_by(user_id:@ex_user_user.id)&.course_group_name + exercise_user_name = "#{@ex_user_user.real_name}_#{user_course.present? ? user_course : "未分班"}_#{exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M')}" "#{exercise_user_name.strip}.pdf" end @@ -37,11 +39,10 @@ class ExerciseUserPdfService kit = PDFKit.new(html) base_css = %w(app/templates/exercise_export/exercise_export.css) base_css.each { |css| kit.stylesheets << Rails.root.join(css) } - #-----正式需删掉 + # #-----正式需删掉 # aa = File.open(Rails.root.join("public/123.html"),"w+") # aa.syswrite(kit.source) - #正式需删掉------- - + # #正式需删掉-------s file = Tempfile.new(filename) kit.to_pdf(file.path) file @@ -49,42 +50,41 @@ class ExerciseUserPdfService def load_data @exercise_questions = exercise.exercise_questions - @exercise_ques_count = @exercise_questions.count # 全部的题目数 + @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",0) - @exercise_single_ques_count = exercise_single_ques.all.count + @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",1) - @exercise_double_ques_count = exercise_double_ques.all.count + @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",2) - @exercise_ques_judge_count = exercise_ques_judge.all.count + @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",3) - @exercise_ques_null_count = exercise_ques_null.all.count + @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",4) - @exercise_ques_main_count = exercise_ques_main.all.count + @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",5) - @exercise_ques_shixun_count = exercise_ques_shixun.all.count + @exercise_ques_shixun_count = exercise_ques_shixun.size @exercise_ques_shixun_scores = exercise_ques_shixun.pluck(:question_score).sum - challenge_ids = @exercise_questions.joins(:exercise_shixun_challenges).pluck("exercise_shixun_challenges.challenge_id") - + @exercise_questions = @exercise_questions&.includes(:exercise_choices,:exercise_shixun_challenges,:exercise_answers,:exercise_shixun_answers,:exercise_answer_comments,:exercise_standard_answers) get_each_student_exercise(exercise.id,@exercise_questions,@ex_user_user.id) - @games = @exercise_user.user.games.ch_games(challenge_ids) + end end \ No newline at end of file diff --git a/app/services/export_exercises_service.rb b/app/services/export_exercises_service.rb index 12b5501f9..ca2d347a6 100644 --- a/app/services/export_exercises_service.rb +++ b/app/services/export_exercises_service.rb @@ -1,15 +1,16 @@ class ExportExercisesService include ExercisesHelper include StudentWorksHelper - attr_reader :exercise, :ex_users + attr_reader :exercise, :ex_users, :request_url - def initialize(exercise, ex_users) + def initialize(exercise, ex_users, request_url) @exercise = exercise @ex_users = ex_users + @request_url = request_url end def filename - exercise_export_name = exercise.user.real_name + "_" + exercise.exercise_name + "_" + Time.now.strftime('%Y%m%d_%H%M%S') + exercise_export_name = "#{exercise.user.real_name}_#{exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" "#{exercise_export_name.strip}.zip" end @@ -18,7 +19,7 @@ class ExportExercisesService pdfs = [] Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip| ex_users.each do |ex_user| - export = ExerciseUserPdfService.new(exercise, ex_user) + export = ExerciseUserPdfService.new(exercise, ex_user,@request_url) pdf = export.ex_pdf pdfs << pdf begin diff --git a/app/services/export_shixun_report_service.rb b/app/services/export_shixun_report_service.rb index 8358d422e..f9da3d6f2 100644 --- a/app/services/export_shixun_report_service.rb +++ b/app/services/export_shixun_report_service.rb @@ -10,7 +10,7 @@ class ExportShixunReportService end def filename - @_filename ||= "#{homework.name}-#{work.user.user_extension&.student_id}-#{work.user.real_name}.pdf".gsub(' ', '-').gsub('/', '_') + @_filename ||= "#{homework.name}-#{work.user&.student_id}-#{work.user.real_name}.pdf".gsub(' ', '-').gsub('/', '_') end def prepare_binding @@ -45,7 +45,8 @@ class ExportShixunReportService @games = @work.myshixun.games.includes(:challenge, :game_codes,:outputs) if @work.myshixun # 用户最大评测次数 - @user_evaluate_count = @games.inject(0){|sum, g| sum + g.outputs.pluck(:query_index).first } if @games + @user_evaluate_count = @games.pluck(:evaluate_count).sum if @games + # @user_evaluate_count = @games.inject(0){|sum, g| sum + g.outputs.pluck(:query_index)&.first } if @games # 图形效率图的数据 @echart_data = student_efficiency(homework, @work) @myself_eff = @echart_data[:efficiency_list].find { |item| item.last == @user.id } diff --git a/app/services/git_service.rb b/app/services/git_service.rb index 4b6bf17ef..076f62920 100644 --- a/app/services/git_service.rb +++ b/app/services/git_service.rb @@ -15,7 +15,7 @@ class GitService private def root_url - new_git_address = EduSetting.find_by_name('git_address_domain').try(:value) + new_git_address = EduSetting.get('git_address_domain') raise 'error: new_git_address not configuration' unless new_git_address.present? new_git_address end @@ -33,7 +33,12 @@ class GitService res = https.request(req) body = res.body logger.info("--uri_exec: .....res is #{body}") + content = JSON.parse(body) + if content["code"] != 0 + raise("版本库异常") + logger.error("repository error: #{content['msg']}") + end #raise content["msg"] if content["code"] != 0 content["data"] diff --git a/app/services/homeworks_service.rb b/app/services/homeworks_service.rb index 536d62c66..b835685a6 100644 --- a/app/services/homeworks_service.rb +++ b/app/services/homeworks_service.rb @@ -81,7 +81,7 @@ class HomeworksService pass_consume_time += (game.cost_time / 60.0).to_f user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i adjust_score = student_work.challenge_work_scores.where(challenge_id: setting.challenge_id).last - final_score += adjust_score.present? ? adjust_score.score : (answer_open_evaluation ? setting.score : (game.final_score >= 0 ? setting.score : 0)) + final_score += adjust_score.present? ? adjust_score.score : (answer_open_evaluation ? setting.score : (game.final_score > 0 ? game.real_score(setting.score) : 0)) max_endtime = max_endtime == "" ? game.end_time : (game.end_time > max_endtime ? game.end_time : max_endtime) else compelete = false @@ -111,7 +111,7 @@ class HomeworksService if homework.work_efficiency if homework.max_efficiency < student_work.efficiency # homework.max_efficiency = student_work.efficiency - homework.update_column("max_efficiency", homework.max_efficiency) + homework.update_column("max_efficiency", student_work.efficiency) end # eff_score = homework.max_efficiency == 0 ? 0 : student_work.efficiency / homework.max_efficiency * homework.eff_score # student_work.eff_score = format("%.2f", eff_score) @@ -156,7 +156,7 @@ class HomeworksService end # 用户评测时更新实训作业成绩 - def update_myshixun_work_score myshixun + def update_myshixun_work_score_old myshixun ActiveRecord::Base.transaction do student_works = myshixun.student_works.where(user_id: myshixun.user_id) #logger.info("#############student_works_count: #{student_works.count}") @@ -165,7 +165,7 @@ class HomeworksService homework = work.homework_common #logger.info("#############member_course_group_id: #{member.try(:course_group_id)}") setting_time = homework.homework_group_setting work.user_id - if setting_time.end_time.present? && (setting_time.end_time > Time.now || (homework.allow_late && !homework.course.is_end)) + if setting_time.end_time.present? && (setting_time.end_time > Time.now || (homework.allow_late && homework.late_time && homework.late_time > Time.now)) #logger.info("#############setting_time: #{setting_time.end_time}") user_total_score = 0 @@ -177,7 +177,7 @@ class HomeworksService pass_consume_time += (game.cost_time / 60.0).to_f user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i adjust_score = work.challenge_work_scores.where(:challenge_id => setting.challenge_id).last - final_score += adjust_score.present? ? adjust_score.score : (homework.homework_detail_manual.answer_open_evaluation ? setting.score : (game.final_score >= 0 ? setting.score : 0)) + final_score += adjust_score.present? ? adjust_score.score : (homework.homework_detail_manual.answer_open_evaluation ? setting.score : (game.final_score > 0 ? game.real_score(setting.score) : 0)) end end if work.work_status == 0 @@ -200,7 +200,7 @@ class HomeworksService # 如果作业的最大效率值有变更则更新所有作品的效率分 if homework.work_efficiency && homework.max_efficiency < work.efficiency - homework.update_column("max_efficiency", homework.max_efficiency) + homework.update_column("max_efficiency", work.efficiency) end end @@ -272,4 +272,67 @@ class HomeworksService end end end + + # 计算实训作品成绩 + def update_myshixun_work_score work, myshixun, games, homework, challenge_settings + user_total_score = 0 + pass_consume_time = 0 + final_score = 0 + setting_time = homework.homework_group_setting myshixun.user_id + homework_end_or_late_time = homework.allow_late ? homework.late_time : setting_time.end_time + games.each do |game| + # 在截止时间前通关的关卡才考虑得分 + if game.status == 2 && game.end_time <= homework_end_or_late_time + challenge_setting = challenge_settings.select{|setting| setting.challenge_id == game.challenge_id}.first + pass_consume_time += (game.cost_time / 60.0).to_f + user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i + adjust_score = work.challenge_work_scores.where(:challenge_id => game.challenge_id).last + final_score += if adjust_score.present? + adjust_score.score + elsif homework.homework_detail_manual.answer_open_evaluation + challenge_setting.score + elsif game.final_score > 0 + game.real_score(challenge_setting.score) + else + 0 + end + end + end + + myshixun_endtime = games.select{|game| game.status == 2}.size == games.size ? games.map(&:end_time).max : nil + if myshixun_endtime.present? + work.cost_time = myshixun_endtime.to_i - setting_time.publish_time.to_i + + efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0)) + work.efficiency = format("%.2f", efficiency) + + if myshixun_endtime <= homework_end_or_late_time + work.compelete_status = myshixun_endtime < setting_time.publish_time ? 2 : 1 + + # 如果作业的最大效率值有变更则更新所有作品的效率分 + homework.update_column("max_efficiency", work.efficiency) if homework.work_efficiency && homework.max_efficiency < work.efficiency + end + end + + if work.work_status == 0 + is_complete = myshixun_endtime && (myshixun_endtime < setting_time.end_time) + if is_complete || (myshixun.created_at < setting_time.end_time && (!homework.allow_late || setting_time.end_time >= Time.now)) + work.work_status = 1 + elsif homework.allow_late && myshixun.created_at < homework.late_time + work.work_status = 2 + end + work.late_penalty = work.work_status == 2 ? homework.late_penalty : 0 + work.commit_time = myshixun.created_at > setting_time.publish_time ? setting_time.publish_time : myshixun.created_at + work.myshixun_id = myshixun.id + end + + work.update_time = myshixun.updated_at + + work.final_score = final_score + score = work.final_score + work.eff_score - work.late_penalty + work.work_score = format("%.2f",(score < 0 ? 0 : score).to_f) unless work.ultimate_score + #logger.info("#############work_score: #{score}") + work.calculation_time = Time.now + work.save! + end end \ No newline at end of file diff --git a/app/services/review_service.rb b/app/services/review_service.rb index 7602aa51b..df004fd19 100644 --- a/app/services/review_service.rb +++ b/app/services/review_service.rb @@ -4,7 +4,7 @@ require 'net/http' require 'uri' class ReviewService - @review_server_url = EduSetting.find_by_name('review_server_url').try(:value) + @review_server_url = EduSetting.get('review_server_url') def self.logger diff --git a/app/services/search_service.rb b/app/services/search_service.rb new file mode 100644 index 000000000..7cd1857bd --- /dev/null +++ b/app/services/search_service.rb @@ -0,0 +1,39 @@ +class SearchService < ApplicationService + include ElasticsearchAble + + attr_reader :params + + def initialize(params) + @params = params + end + + def call + Searchkick.search(keyword, search_options) + end + + private + + def search_options + { + index_name: index_names, + model_includes: model_includes + }.merge(default_options) + end + + def index_names + @_index_names ||= + case params[:type].to_s.strip + when 'shixun' then [Shixun] + when 'course' then [Course] + when 'subject' then [Subject] + when 'memo' then [Memo] + else [Shixun, Course, Subject, Memo] + end + end + + def model_includes + index_names.each_with_object({}) do |klass, obj| + obj[klass] = klass.searchable_includes + end + end +end \ No newline at end of file diff --git a/app/services/search_shixun_service.rb b/app/services/search_shixun_service.rb new file mode 100644 index 000000000..2e77e82d8 --- /dev/null +++ b/app/services/search_shixun_service.rb @@ -0,0 +1,96 @@ +class SearchShixunService < ApplicationService + include ElasticsearchAble + + attr_reader :user, :params + + def initialize(user, params) + @user = user + @params = params + end + + def call + Shixun.search(keyword, + fields: search_fields, + where: where_clauses, + order: order_clauses, + includes: includes_clauses, + page: page, + per_page: per_page) + end + + private + + def tag_filter_shixun_ids + return [] if params[:tag_level].to_i == 0 || params[:tag_id].blank? + + case params[:tag_level].to_i + when 1 then + Repertoire.find(params[:tag_id]).tag_repertoires.joins(:shixun_tag_repertoires) + .pluck('shixun_tag_repertoires.shixun_id') + when 2 then + SubRepertoire.find(params[:tag_id]).tag_repertoires.joins(:shixun_tag_repertoires) + .pluck('shixun_tag_repertoires.shixun_id') + when 3 then + TagRepertoire.find(params[:tag_id]).shixun_tag_repertoires.pluck(:shixun_id) + else + [] + end + end + + def user_filter_shixun_ids + return [] if params[:order_by] != 'mine' + + user.shixun_members.pluck(:shixun_id) + user.myshixuns.pluck(:shixun_id) + end + + def keyword + params[:keyword].to_s.strip.presence || '*' + end + + def search_fields + %w(name^10 author_name challenge_names description challenge_tag_names) + end + + def where_clauses + hash = {} + + ids = user_filter_shixun_ids + tag_filter_shixun_ids + hash[:id] = ids if ids.present? + + if params[:order_by] == 'mine' + hash[:status] = { not: -1 } + else + hash.merge!(hidden: false, status: 2) + end + + unless params[:status].to_i.zero? + params[:status] = [0, 1] if params[:status].to_i == 1 + hash[:status] = params[:status] + end + + hash[:trainee] = params[:diff].to_i unless params[:diff].to_i.zero? + + hash + end + + def includes_clauses + [] + end + + def order_clauses + hash = { _score: :desc } + publish_order = { type: 'number', order: :desc, script: 'doc["status"].value=="2" ? 1 : 0' } + + sort = params[:sort].to_s.strip == 'asc' ? 'asc' : 'desc' + clauses = + case params[:order_by].presence + when 'new' then { _script: publish_order, created_at: sort } + when 'hot' then { _script: publish_order, myshixuns_count: sort } + when 'mine' then { created_at: sort } + else { _script: publish_order, publish_time: sort } + end + hash.merge!(clauses) + + hash + end +end \ No newline at end of file diff --git a/app/services/shixuns_service.rb b/app/services/shixuns_service.rb index 83d61b352..4efefd4c2 100644 --- a/app/services/shixuns_service.rb +++ b/app/services/shixuns_service.rb @@ -47,7 +47,7 @@ class ShixunsService if current_user.admin? disscuss_count = Discuss.where(dis_id: dis_id, dis_type: dis_type, root_id: nil).count discusses = Discuss.where(dis_id: dis_id, dis_type: dis_type, root_id: nil) - .includes(:user, :praise_tread).limit(LIMIT).offset(offset) + .includes(:user, :praise_treads).limit(LIMIT).offset(offset) else disscusses = Discuss.where( 'dis_id = :dis_id and dis_type = :dis_type and root_id is null and (hidden = :hidden or user_id = :user_id)', @@ -55,7 +55,7 @@ class ShixunsService ) disscuss_count = disscusses.count - discusses = disscusses.includes(:user, :praise_tread).limit(LIMIT).offset(offset) + discusses = disscusses.includes(:user, :praise_treads).limit(LIMIT).offset(offset) end base_data discusses, dis, current_user @@ -81,7 +81,7 @@ class ShixunsService offset = page * LIMIT find_status = true if position end - discusses = Discuss.limit(LIMIT).where(:dis_id => dis_id, :dis_type => dis_type, :root_id => nil).includes(:user, :praise_tread).offset(offset) + discusses = Discuss.limit(LIMIT).where(:dis_id => dis_id, :dis_type => dis_type, :root_id => nil).includes(:user, :praise_treads).offset(offset) base_data discusses, dis, current_user Myshixun.find(params[:myshixun_id]).update_attribute(:onclick_time, Time.now) @@ -109,8 +109,8 @@ class ShixunsService if discusses.present? discusses.each do |d| # 总点赞数 - praise_count = d.praise_tread.where(:praise_or_tread => 1).count - user_praise= d.praise_tread.select{|pt| pt.user_id == current_user.id}.length > 0 ? true : false + praise_count = d.praises_count + user_praise= d.praise_treads.select{|pt| pt.user_id == current_user.id}.length > 0 ? true : false manager = current_user.manager_of_shixun?(dis, current_user) game_url = if manager diff --git a/app/services/users/apply_authentication_service.rb b/app/services/users/apply_authentication_service.rb new file mode 100644 index 000000000..9e0901ef4 --- /dev/null +++ b/app/services/users/apply_authentication_service.rb @@ -0,0 +1,54 @@ +class Users::ApplyAuthenticationService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :user, :params + + def initialize(user, params) + @user = user + @params = params + end + + def call + raise Error, '请先完善基本信息' unless user.profile_completed? + + 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..07afe18ae --- /dev/null +++ b/app/services/users/apply_professional_auth_service.rb @@ -0,0 +1,64 @@ +class Users::ApplyProfessionalAuthService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :user, :params + + def initialize(user, params) + @user = user + @params = params + end + + def call + raise Error, '请先完善基本信息' unless user.profile_completed? + + 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/services/users/bind_email_service.rb b/app/services/users/bind_email_service.rb index 02cf8b91a..1ad9ad6b4 100644 --- a/app/services/users/bind_email_service.rb +++ b/app/services/users/bind_email_service.rb @@ -13,7 +13,7 @@ class Users::BindEmailService < ApplicationService raise Error, '该邮箱已被绑定' if User.where.not(id: user.id).exists?(mail: params[:email]) - code = VerificationCode.where(mail: params[:email], code: params[:code], code_type: 4).last + code = VerificationCode.where(email: params[:email], code: params[:code], code_type: 4).last raise Error, '验证码无效' unless code&.effective? ActiveRecord::Base.transaction do diff --git a/app/services/users/course_service.rb b/app/services/users/course_service.rb index 6271db17b..9eb34917e 100644 --- a/app/services/users/course_service.rb +++ b/app/services/users/course_service.rb @@ -11,7 +11,7 @@ class Users::CourseService end def call - courses = category_scope_courses.deleted(false) + courses = category_scope_courses.not_deleted courses = status_filter(courses) @@ -38,9 +38,9 @@ class Users::CourseService case params[:status] when 'processing' then - relations.ended(false) + relations.processing when 'end' then - relations.ended(true) + relations.ended else relations end diff --git a/app/services/users/shixun_service.rb b/app/services/users/shixun_service.rb index b5e5586f1..4730a5777 100644 --- a/app/services/users/shixun_service.rb +++ b/app/services/users/shixun_service.rb @@ -58,7 +58,7 @@ class Users::ShixunService when 'passed' then 1 when 'processing' then 0 end - relations.where(myshixuns: { status: status }) if status + relations = relations.where(myshixuns: { status: status }) if status relations end diff --git a/app/services/users/subject_service.rb b/app/services/users/subject_service.rb index e0d8377c2..745b7cce2 100644 --- a/app/services/users/subject_service.rb +++ b/app/services/users/subject_service.rb @@ -14,7 +14,7 @@ class Users::SubjectService subjects = category_scope_subjects subjects = user_policy_filter(subjects) - custom_sort(subjects, :updated_at, params[:sort_direction]) + custom_sort(subjects.distinct, :updated_at, params[:sort_direction]) end private @@ -65,7 +65,7 @@ class Users::SubjectService when 'finished' then subjects.having('finished = 1').map(&:id) end - relations.where(id: subject_ids) if subject_ids.present? + relations = relations.where(id: subject_ids) if subject_ids.present? relations end @@ -75,7 +75,7 @@ class Users::SubjectService when 'applying' then 1 when 'published' then 2 end - relations.where(status: status) if status + relations = relations.where(status: status) if status relations end diff --git a/app/services/users/update_account_service.rb b/app/services/users/update_account_service.rb index 6a8588dee..d603cec8c 100644 --- a/app/services/users/update_account_service.rb +++ b/app/services/users/update_account_service.rb @@ -35,6 +35,13 @@ class Users::UpdateAccountService < ApplicationService extension.technical_title = params[:technical_title] end + # 职业、学校变动需要重新进行职业认证 + if extension.identity_changed? || extension.school_id_changed? + user.professional_certification = false + # 撤销之前的职业认证 + user.apply_user_authentication.professional_auth.passed.update_all(status: 3) + end + # 表示资料完整 user.profile_completed = true diff --git a/app/tasks/exercise_publish_task.rb b/app/tasks/exercise_publish_task.rb new file mode 100644 index 000000000..220512664 --- /dev/null +++ b/app/tasks/exercise_publish_task.rb @@ -0,0 +1,126 @@ +class ExercisePublishTask + include ExercisesHelper + include GitHelper + + def publish + Rails.logger.info("log--------------------------------exercise_publish start") + puts "--------------------------------exercise_publish start" + exercises = Exercise.includes(:exercise_users).where("publish_time is not null and exercise_status = 1 and publish_time <=?",Time.now) + exercises&.each do |exercise| + exercise.update_column('exercise_status', 2) + + if exercise.unified_setting + ExercisePublishNotifyJob.perform_later(exercise.id, nil) + else + course = exercise.course + teachers = course.teachers.where.not(id: course.teacher_course_groups.select(:course_member_id)) + tid_str = "" + teachers.find_each do |member| + tid_str += "," if tid_str != "" + tid_str += "(#{member.user_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + if tid_str != "" + tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str + ActiveRecord::Base.connection.execute tid_sql + end + end + + exercise.course_acts << CourseActivity.new(user_id: exercise.user_id, course_id: exercise.course_id) if !exercise.course_acts.exists? + end + + # 分组设置发布时间的测验 + exercise_group_settings = ExerciseGroupSetting.where("publish_time < ? and publish_time > ?", Time.now + 900, Time.now - 900) + exercise_group_settings&.each do |exercise_group| + exercise = exercise_group.exercise + if exercise.present? + exercise.update_attributes(:exercise_status => 2) if exercise.exercise_status == 1 + ExercisePublishNotifyJob.perform_later(exercise.id, [exercise_group.course_group_id]) + end + end + Rails.logger.info("log--------------------------------exercise_publish end") + puts "--------------------------------exercise_publish end" + end + + def end + Rails.logger.info("log--------------------------------exercise_end start") + puts "--------------------------------exercise_end start" + # 1。统一设置的试卷 + exercises = Exercise.includes(:exercise_users,:exercise_questions).where("exercise_status = 2 AND unified_setting = true AND end_time <= ?",Time.now + 900) + exercises&.each do |exercise| + ex_type = exercise.exercise_questions.pluck(:question_type).uniq + exercise.update_column('exercise_status', 3) + exercise.exercise_users&.each do |exercise_user| + begin + if (exercise_user&.commit_status == 0) && (exercise_user&.start_at.present?) + s_score = calculate_student_score(exercise, exercise_user.user)[:total_score] + if ex_type.include?(4) #是否包含主观题 + subjective_score = exercise_user.subjective_score + else + subjective_score = -1.0 + end + total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score + total_score = s_score + total_score_subjective_score + commit_option = { + :status => 1, + :commit_status => 1, + :end_at => Time.now, + :objective_score => s_score, + :score => total_score, + :subjective_score => subjective_score + } + exercise_user.update_attributes(commit_option) + end + rescue Exception => e + Rails.logger.info("rescue errors ___________________________#{e}") + next + end + + end + end + + # 2.非统一的试卷 + all_exercises = Exercise.includes(:exercise_group_settings,:exercise_users,:exercise_questions).where("unified_setting = false AND exercise_status = 2 AND end_time > ?",Time.now + 900) + exercise_ids = all_exercises.blank? ? "(-1)" : "(" + all_exercises.map(&:id).join(",") + ")" + ex_group_settings = ExerciseGroupSetting.where("end_time <= '#{Time.now}' and exercise_id in #{exercise_ids}") + ex_group_settings&.each do |exercise_setting| + exercise = exercise_setting.exercise + if exercise.end_time <= Time.now + exercise.update_column('exercise_status', 3) + end + + ex_types = exercise.exercise_questions.pluck(:question_type).uniq + users = exercise.course.students.where(:course_group_id => exercise_setting.course_group_id) + exercise_users = exercise.exercise_users.where(:user_id => users.pluck(:user_id)) + exercise_users&.each do |exercise_user| + begin + if exercise_user.commit_status == 0 && !exercise_user.start_at.nil? + if ex_types.include?(4) #是否包含主观题 + subjective_score = exercise_user.subjective_score + else + subjective_score = -1.0 + end + s_score = calculate_student_score(exercise, exercise_user.user)[:total_score] + total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score + total_score = s_score + total_score_subjective_score + commit_option = { + :status => 1, + :commit_status => 1, + :end_at => Time.now, + :objective_score => s_score, + :score => total_score, + :subjective_score => subjective_score + } + exercise_user.update_attributes(commit_option) + end + rescue Exception => e + Rails.logger.info("unified_setting_false_rescue errors ___________________________#{e}") + next + end + + end + end + Rails.logger.info("log--------------------------------exercise_end end") + puts "--------------------------------exercise_end end" + end + +end \ No newline at end of file diff --git a/app/templates/exercise_export/blank_exercise.html.erb b/app/templates/exercise_export/blank_exercise.html.erb index 61bde0d27..4a2373f3f 100644 --- a/app/templates/exercise_export/blank_exercise.html.erb +++ b/app/templates/exercise_export/blank_exercise.html.erb @@ -13,13 +13,13 @@

- <%= @exercise.try(:exercise_description).nil? ? "" : @exercise.try(:exercise_description).html_safe %> + <%= @exercise.try(:exercise_description).nil? ? "" : @exercise.try(:exercise_description)&.html_safe %>

-
+
-
+

<% if @exercise_single_ques_count > 0 %> 单选题<%= @exercise_single_ques_count %>题, 共<%= @exercise_single_ques_scores %> @@ -44,16 +44,24 @@ 实训题<%= @exercise_ques_shixun_count %>题, 共<%= @exercise_ques_shixun_scores %> <% end %> -

-
合计<%= @exercise_ques_count %>题, - 共<%= @exercise_ques_scores %>分 -
+ + <% if @exercise_ques_count > 0 %> + + 合计<%= @exercise_ques_count %>题 + + + 共<%= @exercise_ques_scores %>分 + + <% end %> + +

+
<% @exercise_questions.each do |q| %>
-
+
<%= q.question_number %>、 @@ -63,38 +71,38 @@
<% if q.question_type == 5 %> - <%= q.shixun_name.present? ? q.shixun_name.html_safe : "" %> + <%= to_markdown(q.shixun_name,@request_url) %>
- <%= q.question_title.present? ? q.question_title.html_safe : "" %> + <%= to_markdown(q.question_title,@request_url) %>
<% else %> - <%= q.question_title.present? ? q.question_title.html_safe : "" %> + <%= to_markdown(q.question_title,@request_url) %> <% end %>
<% if q.question_type == 0 %> <% q.exercise_choices.each_with_index do |s,index| %> -

- - <%= convert_to_char((index+1).to_s)%><%= s.choice_text%> -

+
+ + <%= to_markdown("#{(index+65).chr}.#{s.choice_text}",@request_url) %> +
<% end %> <% elsif q.question_type == 1 %> <% q.exercise_choices.each_with_index do |s,index| %> -

- - <%= convert_to_char((index+1).to_s)%><%= s.choice_text%> -

+
+ + <%= to_markdown("#{(index+65).chr}.#{s.choice_text}",@request_url) %> +
<% end %> <% elsif q.question_type == 2 %> -

+

<% q.exercise_choices.each_with_index do |s,index| %> - - <%= s.choice_text %> + + <%= "#{(index+65).chr}.#{s.choice_text}" %> <% end %> -

+
<% elsif q.question_type == 3 %> <% st_counts = q.exercise_standard_answers.pluck(:exercise_choice_id).uniq %> <% st_counts.each_with_index do |s,index| %> @@ -126,4 +134,5 @@
+ \ No newline at end of file diff --git a/app/templates/exercise_export/exercise_export.css b/app/templates/exercise_export/exercise_export.css index 91f25e45e..119d92a05 100644 --- a/app/templates/exercise_export/exercise_export.css +++ b/app/templates/exercise_export/exercise_export.css @@ -1,5 +1,8 @@ body{ - font-size:14px;} + font-size:14px; + font-family: "微软雅黑","宋体"; +} + p{ margin:0; } @@ -37,11 +40,17 @@ p{ margin-bottom: 10px; } .mt8{ - margin-top:8px; + margin-top:7px; +} +.mt10{ + margin-top:10px; } .mbt10{ margin: 10px 0; } +.mt5{ + margin-top:5px; +} .pull-right{ float:right; } @@ -80,9 +89,15 @@ p{ .ml20{ margin-left:20px; } +.ml10{ + margin-left:10px; +} .mr3{ margin-right:3px; } +.mr8{ + margin-right:8px; +} .mr15{ margin-right:15px; } @@ -98,6 +113,9 @@ p{ white-space: normal; min-height:12px; } +.null-answer p{ + display: inline-block; +} .choose-radio{ display: inline-block; width: 12px; @@ -154,7 +172,7 @@ p{ position: absolute; display: inline-block; bottom: 6px; - /*left: 1px;*/ + left: 1px; } .line-line { @@ -229,7 +247,7 @@ p{ position: absolute; display: inline-block; bottom: 9px; - left: 3px; + left: 2px; } .circle-right:after{ color:#fff; @@ -239,14 +257,14 @@ p{ position: absolute; display: inline-block; bottom: 9px; - left: 0; + left: 2px; } table{ width:100%; text-align:center; } -table, tr, td, th, tbody, thead, tfoot,textarea{ +table, tr, td, th, tbody, thead, tfoot,textarea,.main-choice{ page-break-inside: avoid; } table th{ @@ -302,7 +320,31 @@ textarea{ border:none; background-color:#eee; line-height:2; + +} +.clearfix{ + clear:both; + zoom:1; } +.choice-text p{ + margin-bottom:0; +} +.mt-2{ + margin-top:-2px; +} +.width100{ + width:100%; +} +.ex-scores{ + /*width:100%;*/ + /*display:inline-block;*/ + word-break: break-all; + line-height:2; +} + + + + diff --git a/app/templates/exercise_export/exercise_user.html.erb b/app/templates/exercise_export/exercise_user.html.erb index 713f09ee4..8d4da5ca2 100644 --- a/app/templates/exercise_export/exercise_user.html.erb +++ b/app/templates/exercise_export/exercise_user.html.erb @@ -1,348 +1,367 @@ - - - - - - - -
-
-
-
-

<%= @exercise.try(:exercise_name) %>

-
-
-

- <%= @exercise.try(:exercise_description).nil? ? "" : @exercise.try(:exercise_description).html_safe %> -

-
-
-
-
-
- <% if @exercise_single_ques_count > 0 %> - 单选题<%= @exercise_single_ques_count %>题, - 共<%= @exercise_single_ques_scores %> - <% end %> - <% if @exercise_double_ques_count > 0 %> - 多选题<%= @exercise_double_ques_count %>题, - 共<%= @exercise_double_ques_scores %> - <% end %> - <% if @exercise_ques_judge_count > 0 %> - 判断题<%= @exercise_ques_judge_count %>题, - 共<%= @exercise_ques_judge_scores %> - <% end %> - <% if @exercise_ques_null_count > 0 %> - 填空题<%= @exercise_ques_null_count %>题, - 共<%= @exercise_ques_null_scores %> - <% end %> - <% if @exercise_ques_main_count > 0 %> - 主观题<%= @exercise_ques_main_count %>题, - 共<%= @exercise_ques_main_scores %> - <% end %> - <% if @exercise_ques_shixun_count > 0 %> - 实训题<%= @exercise_ques_shixun_count %>题, - 共<%= @exercise_ques_shixun_scores %> - <% end %> -
-
- 合计<%= @exercise_ques_count %>题, - 共<%= @exercise_ques_scores %>分 -
-
-
-
- <% if @ex_obj_array.size > 0 %> -
-

- 客观题 - 正确 - 错误 - 部分得分 - 总分:<%= @exercise_user.score %>分 -

-
-
- <% @ex_obj_array.each do |s| %> - <% if s[:stand_status] == 1 %> -
- <%= s[:q_position] %> -
- <% elsif s[:stand_status] == 0 %> -
- <%= s[:q_position] %> -
- <% else %> -
- <%= s[:q_position] %> -
- <% end %> - <% end %> -
- <% end %> - <% if @ex_sub_array.size > 0 %> -
-

- 主观题 - 已评 - 未评 - 开始答题时间:<%= @exercise_user.start_at.present? ? @exercise_user.start_at.strftime("%Y-%m-%d %H:%M") : "--" %> -

-
-
- <% @ex_sub_array.each do |s| %> - <% if s[:stand_status] == 0 %> -
- <%= s[:q_position] %> -
- <% else %> -
- <%= s[:q_position] %> -
- <% end %> - <% end %> -
- <% end %> -
-
- <% @exercise_questions.each do |q| %> - <% q_type = q.question_type %> - <% user_answer = (q_type == 5 ? q.exercise_shixun_answers.where(user_id: @ex_user_user.id) : q.exercise_answers.where(user_id: @ex_user_user.id)) %> - <% this_ques_status = @ex_obj_array.detect{|f| f[:q_id] == q.id} %> - <% main_ques_status = @ex_sub_array.detect{|f| f[:q_id] == q.id} %> - <% ques_comment = q.exercise_answer_comments.where("exercise_answer_id",user_answer.first&.id) %> -
-
-
-
- <%= q.question_number %>、  - - <%= q.question_type_name %> - - (<%= q&.question_score %>分) - <% if q_type == 5 %> - - <% if this_ques_status.present? && this_ques_status[:stand_status] == 1 %> - - <%= this_ques_status[:user_score] %>分 - <% elsif this_ques_status.present? && this_ques_status[:stand_status] == 2 %> - - <%= this_ques_status[:user_score] %>分 - <% else %> - - 0.0分 - <% end %> - - <% elsif q_type == 4 %> - - <% if main_ques_status.present? && main_ques_status[:stand_status] == 1 %> - - <%= main_ques_status[:user_score] %>分 - <% elsif main_ques_status.present? && main_ques_status[:stand_status] == 2 %> - - <%= main_ques_status[:user_score] %>分 - <% else %> - 未批 - <% end %> - - <% else %> - - <% if this_ques_status.present? && this_ques_status[:stand_status] == 1 %> - - <%= this_ques_status[:user_score] %>分 - <% elsif this_ques_status.present? && this_ques_status[:stand_status] == 2 %> - - <%= this_ques_status[:user_score] %>分 - <% else %> - - 0.0分 - <% end %> - - <% end %> -
-
- <% if q_type == 5 %> - <%= q.shixun_name.html_safe %> -
- <%= q.question_title.html_safe %> -
- <% elsif q_type == 4 %> - <%= q.question_title.html_safe %> - <% else %> - <%= q.question_title.html_safe %> - <% end %> -
-
-
- <% if q_type == 0 %> - <% q.exercise_choices.each_with_index do |s,index| %> - <% check_answer = (user_answer.present? && (s.id == user_answer.first.exercise_choice_id)) ? "choose-answer" : '' %> -

- - <%= convert_to_char((index+1).to_s)%><%= s.choice_text%> -

- <% end %> - <% elsif q_type == 1 %> - <% q.exercise_choices.each_with_index do |s,index| %> - <% check_answer = (user_answer.present? && (user_answer.pluck(:exercise_choice_id).include?(s.id))) ? true : false %> -

- <% if check_answer %> - - <% else %> - - <% end %> - <%= convert_to_char((index+1).to_s)%><%= s.choice_text%> -

- <% end %> - <% elsif q_type == 2 %> -

- <% q.exercise_choices.each do |s| %> - <% if user_answer.present? && (s.id == user_answer.first.exercise_choice_id) %> - <% check_answer = 'choose-answer' %> - <% else %> - <% check_answer = '' %> - <% end %> - - - <%= s.choice_text %> - - <% end %> -

- <% elsif q_type == 3 %> - <% st_counts = q.exercise_standard_answers.pluck(:exercise_choice_id).uniq %> - <% st_counts.each_with_index do |s,index| %> - <% if user_answer.present? && user_answer.where(exercise_choice_id:s).present? %> - <% check_answer = user_answer.where(exercise_choice_id:s).first.answer_text %> - <% else %> - <% check_answer = "--" %> - <% end %> -

- 答案(填空<%= index+1 %>): - <%= check_answer.html_safe %> -

- <% end %> - <% elsif q_type == 4 %> - <% check_answer = (user_answer.present? ? user_answer.first.answer_text : '--') %> -

- <%= check_answer.html_safe %> -

- <% else %> -
-

- 阶段成绩 -

- - - - - - - - - - - - <% if @games.size > 0 %> - <% @games.each_with_index do |game, index| %> - <% user_score = q.exercise_shixun_answers.where(exercise_shixun_challenge_id:game.challenge.id,user_id: @ex_user_user.id) %> - <% game_score = q.exercise_shixun_challenges.where(challenge_id:game.challenge.id) %> - - - - - - - - - - <% end %> - <% else %> - <% q.exercise_shixun_challenges.each_with_index do |game, index| %> - <% game_score = q.exercise_shixun_challenges.where(challenge_id:game.challenge.id) %> - - - - - - - - - - <% end %> - <% end %> - -
关卡任务名称评测次数完成时间耗时经验值得分/满分
<%= index + 1 %> - <%= game.challenge.subject %> - <%= game.evaluate_count %><%= game.end_time.present? ? game.end_time.strftime("%Y-%m-%d %H:%M") : "--" %><%= ApplicationController.helpers.time_consuming game %><%= game.final_score %> / <%= game.challenge.all_score %><%= user_score.present? ? user_score.first.score : 0.0 %> / <%= game_score.present? ? game_score.first.question_score : 0.0 %>
<%= index + 1 %> - <%= game.challenge.subject %> - 0----0.0 / <%= game.challenge.all_score %>0.0 / <%= game_score.present? ? game_score.first.question_score : 0.0 %>
-
-
-

- 实训详情 -

- <% @games.each_with_index do |game, index| %> -
-

- 第<%= index+1 %>关<%= game.challenge.subject %> -

-
- <% if game.outputs.present? %> - - - - - - - <% outputs = game.outputs.group("query_index") %> - <% outputs.reverse.try(:each) do |output| %> - - - - - <% end %> - -
评测次数评测信息
<%= "第#{output.query_index}次" %><%= output_detail(game, output) %>
- <% end %> - <% if game.try(:lastest_code).present? && game.challenge.st == 0 %> - <% con_rows = content_line(game.lastest_code) %> -
-

- - 最近通过的代码 - <%= game.challenge.path %> - -

-
- -
-
- <% end %> -
-
- <% end %> -
- <% end %> -
-
-
- <% if ques_comment.present? && ques_comment.first.comment.present? %> - <% ques_user = ques_comment.first.user %> -
-
-
- -
-
-

<%= ques_user.real_name %><%= ques_comment.first.updated_at.strftime('%Y-%m-%d %H:%M') %>

-

<%= ques_comment.first.comment %>

-
-
-
- <% end %> - <% end %> -
-
-
- - + + + + + + + +
+
+
+
+

<%= @exercise.try(:exercise_name) %>

+
+
+

+ <%= @exercise.try(:exercise_description).nil? ? "" : @exercise.try(:exercise_description)&.html_safe %> +

+
+
+
+
+

+ <% if @exercise_single_ques_count > 0 %> + 单选题<%= @exercise_single_ques_count %>题, + 共<%= @exercise_single_ques_scores %> + <% end %> + <% if @exercise_double_ques_count > 0 %> + 多选题<%= @exercise_double_ques_count %>题, + 共<%= @exercise_double_ques_scores %> + <% end %> + <% if @exercise_ques_judge_count > 0 %> + 判断题<%= @exercise_ques_judge_count %>题, + 共<%= @exercise_ques_judge_scores %> + <% end %> + <% if @exercise_ques_null_count > 0 %> + 填空题<%= @exercise_ques_null_count %>题, + 共<%= @exercise_ques_null_scores %> + <% end %> + <% if @exercise_ques_main_count > 0 %> + 主观题<%= @exercise_ques_main_count %>题, + 共<%= @exercise_ques_main_scores %> + <% end %> + <% if @exercise_ques_shixun_count > 0 %> + 实训题<%= @exercise_ques_shixun_count %>题, + 共<%= @exercise_ques_shixun_scores %> + <% end %> + + <% if @exercise_ques_count > 0 %> + + 合计<%= @exercise_ques_count %>题 + + + 共<%= @exercise_ques_scores %>分 + + <% end %> + +

+
+
+
+
+ <% if @ex_obj_array.size > 0 %> +
+

+ 客观题 + 正确 + 错误 + 部分得分 + 总分:<%= @exercise_user&.score %>分 +

+
+
+ <% @ex_obj_array.each do |s| %> + <% if s[:stand_status] == 1 %> +
+ <%= s[:q_position] %> +
+ <% elsif s[:stand_status] == 0 %> +
+ <%= s[:q_position] %> +
+ <% else %> +
+ <%= s[:q_position] %> +
+ <% end %> + <% end %> +
+ <% end %> + <% if @ex_sub_array.size > 0 %> +
+

+ 主观题 + 已评 + 未评 + 开始答题时间:<%= @exercise_user.start_at.present? ? @exercise_user.start_at.strftime("%Y-%m-%d %H:%M") : "--" %> +

+
+
+ <% @ex_sub_array.each do |s| %> + <% if s[:stand_status] == 0 %> +
+ <%= s[:q_position] %> +
+ <% else %> +
+ <%= s[:q_position] %> +
+ <% end %> + <% end %> +
+ <% end %> +
+
+ <% @exercise_questions.each do |q| %> + <% q_type = q.question_type %> + <% games =( q_type == 5 ? @ex_user_user.games.ch_games(q.exercise_shixun_challenges.pluck(:challenge_id)) : nil) %> + <% user_answer = (q_type == 5 ? q.exercise_shixun_answers.where(user_id: @ex_user_user.id) : q.exercise_answers.where(user_id: @ex_user_user.id)) %> + <% this_ques_status = @ex_obj_array.detect{|f| f[:q_id] == q.id} %> + <% main_ques_status = @ex_sub_array.detect{|f| f[:q_id] == q.id} %> + <% ques_comment = q.exercise_answer_comments.where("exercise_answer_id",user_answer.first&.id) %> +
+
+
+
+ <%= q.question_number %>、  + + <%= q.question_type_name %> + + (<%= q&.question_score %>分) + <% if q_type == 5 %> + + <% if this_ques_status.present? && this_ques_status[:stand_status] == 1 %> + + <%= this_ques_status[:user_score] %>分 + <% elsif this_ques_status.present? && this_ques_status[:stand_status] == 2 %> + + <%= this_ques_status[:user_score] %>分 + <% else %> + + 0.0分 + <% end %> + + <% elsif q_type == 4 %> + + <% if main_ques_status.present? && main_ques_status[:stand_status] == 1 %> + + <%= main_ques_status[:user_score] %>分 + <% elsif main_ques_status.present? && main_ques_status[:stand_status] == 2 %> + + <%= main_ques_status[:user_score] %>分 + <% else %> + 未批 + <% end %> + + <% else %> + + <% if this_ques_status.present? && this_ques_status[:stand_status] == 1 %> + + <%= this_ques_status[:user_score] %>分 + <% elsif this_ques_status.present? && this_ques_status[:stand_status] == 2 %> + + <%= this_ques_status[:user_score] %>分 + <% else %> + + 0.0分 + <% end %> + + <% end %> +
+
+ <% if q.question_type == 5 %> + <%= to_markdown(q.shixun_name,@request_url) %> +
+ <%= to_markdown(q.question_title,@request_url) %> +
+ <% else %> + <%= to_markdown(q.question_title,@request_url) %> + <% end %> +
+
+
+
+ <% if q_type == 0 %> + <% q.exercise_choices.each_with_index do |s,index| %> + <% check_answer = (user_answer.present? && (s.id == user_answer.first.exercise_choice_id)) ? "choose-answer" : '' %> +
+ + <%= to_markdown("#{(index+65).chr}.#{s.choice_text}",@request_url) %> +
+ <% end %> +
+ <% elsif q_type == 1 %> + <% q.exercise_choices.each_with_index do |s,index| %> + <% check_answer = (user_answer.present? && (user_answer.pluck(:exercise_choice_id).include?(s.id))) ? true : false %> +
+ <% if check_answer %> + + <% else %> + + <% end %> + <%= to_markdown("#{(index+65).chr}.#{s.choice_text}",@request_url) %> +
+ <% end %> +
+ <% elsif q_type == 2 %> +
+ <% q.exercise_choices.each_with_index do |s,index| %> + <% if user_answer.present? && (s.id == user_answer.first.exercise_choice_id) %> + <% check_answer = 'choose-answer' %> + <% else %> + <% check_answer = '' %> + <% end %> + + + <%= "#{(index+65).chr}.#{s.choice_text}" %> + + <% end %> +
+
+ <% elsif q_type == 3 %> + <% st_counts = q.exercise_standard_answers.pluck(:exercise_choice_id).uniq %> + <% st_counts.each_with_index do |s,index| %> + <% if user_answer.present? && user_answer.where(exercise_choice_id:s).present? %> + <% check_answer = user_answer.where(exercise_choice_id:s).first.answer_text %> + <% else %> + <% check_answer = "--" %> + <% end %> +
+ 答案(填空<%= index+1 %>): + <%= to_markdown(check_answer,@request_url) %> +
+
+ <% end %> + <% elsif q_type == 4 %> + <% check_answer = (user_answer.present? ? user_answer.first.answer_text : '--') %> +
+
+ <%= to_markdown(check_answer,@request_url) %> +
+
+
+ <% else %> +
+

+ 阶段成绩 +

+ + + + + + + + + + + + <% if games.present? %> + <% games&.each_with_index do |game, index| %> + <% game_score = q.exercise_shixun_challenges.where(challenge_id:game.challenge.id) %> + <% user_score = q.exercise_shixun_answers.where(exercise_shixun_challenge_id: game_score&.first&.id,user_id: @ex_user_user.id) %> + + + + + + + + + + <% end %> + <% else %> + <% q.exercise_shixun_challenges.each_with_index do |game, index| %> + <% game_score = q.exercise_shixun_challenges.where(challenge_id:game.challenge.id) %> + + + + + + + + + + <% end %> + <% end %> + +
关卡任务名称评测次数完成时间耗时经验值得分/满分
<%= index + 1 %> + <%= game.challenge.subject %> + <%= game.evaluate_count %><%= game.end_time.present? ? game.end_time.strftime("%Y-%m-%d %H:%M") : "--" %><%= ApplicationController.helpers.time_consuming game %><%= game.final_score %> / <%= game.challenge.all_score %><%= user_score.present? ? user_score.first.score : 0.0 %> / <%= game_score.present? ? game_score.first.question_score : 0.0 %>
<%= index + 1 %> + <%= game.challenge.subject %> + 0----0.0 / <%= game.challenge.all_score %>0.0 / <%= game_score.present? ? game_score.first.question_score : 0.0 %>
+
+
+

+ 实训详情 +

+ <% games&.each_with_index do |game, index| %> +
+

+ 第<%= index+1 %>关<%= game.challenge.subject %> +

+
+ <% if game.outputs.present? %> + + + + + + + <% outputs = game.outputs.group("query_index") %> + <% outputs.reverse.try(:each) do |output| %> + + + + + <% end %> + +
评测次数评测信息
<%= "第#{output.query_index}次" %><%= output_detail(game, output) %>
+ <% end %> + <% if game.try(:lastest_code).blank? %> + <% cha_path = challenge_path(game.challenge&.path) %> + <% latest_code = git_fle_content(game.myshixun.repo_path,cha_path) %> + <% else %> + <% latest_code = game.try(:lastest_code) %> + <% end %> + <% con_rows = content_line(latest_code) %> +
+

+ + 最近通过的代码 + <%= game.challenge&.path %> + +

+
+ +
+
+
+
+ <% end %> +
+
+ <% end %> +
+
+
+ <% if ques_comment.present? && ques_comment.first.comment.present? %> + <% ques_user = ques_comment.first.user %> +
+
+
+ +
+
+

<%= ques_user.real_name %><%= ques_comment.first.updated_at.strftime('%Y-%m-%d %H:%M') %>

+

<%= ques_comment.first.comment %>

+
+
+
+ <% end %> + <% end %> +
+
+
+ + diff --git a/app/views/accounts/register.json.jbuilder b/app/views/accounts/register.json.jbuilder deleted file mode 100644 index 9a3dba175..000000000 --- a/app/views/accounts/register.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.redirect_uri subjects_url \ No newline at end of file diff --git a/app/views/boards/destroy.json.jbuilder b/app/views/boards/destroy.json.jbuilder index a9d8fbdaf..0fd68dc8c 100644 --- a/app/views/boards/destroy.json.jbuilder +++ b/app/views/boards/destroy.json.jbuilder @@ -1,2 +1,2 @@ json.status 0 -json.right_url course_board_messages_path(@course, @course_board) \ No newline at end of file +json.right_url board_messages_path(@course_board) diff --git a/app/views/challenges/edit.json.jbuilder b/app/views/challenges/edit.json.jbuilder index 64848a4e6..2774b5a05 100644 --- a/app/views/challenges/edit.json.jbuilder +++ b/app/views/challenges/edit.json.jbuilder @@ -7,7 +7,7 @@ json.chooses do end if @tab == 0 # 本关任务tab的编辑模式 - json.(@challenge, :id, :subject, :task_pass, :difficulty, :score) + json.(@challenge, :id, :subject, :task_pass, :difficulty, :score, :exec_time) json.tags @challenge.challenge_tags.map(&:name) elsif @tab == 1 # 评测设置的编辑模式 diff --git a/app/views/challenges/index.json.jbuilder b/app/views/challenges/index.json.jbuilder index 0b90b5ca5..a542b8119 100644 --- a/app/views/challenges/index.json.jbuilder +++ b/app/views/challenges/index.json.jbuilder @@ -13,11 +13,11 @@ if @challenges.present? json.position challenge.position json.st challenge.st json.name challenge.subject - json.score challenge.score + json.score challenge.all_score json.passed_count challenge.user_passed_count json.playing_count challenge.playing_count json.name_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) - json.open_game challenge.open_game(@user.id) + #json.open_game challenge.open_game(@user.id, @shixun) if @editable json.edit_url edit_shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) json.delete_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) diff --git a/app/views/challenges/show.json.jbuilder b/app/views/challenges/show.json.jbuilder index 332879eac..cffe77ebb 100644 --- a/app/views/challenges/show.json.jbuilder +++ b/app/views/challenges/show.json.jbuilder @@ -1,6 +1,6 @@ # 导航栏公共数据 json.partial! "challenges/top_common_data", shixun_identifier: @shixun.identifier -json.(@challenge, :id, :subject, :task_pass, :difficulty, :score) +json.(@challenge, :id, :subject, :task_pass, :difficulty, :score, :exec_time) json.tags @challenge.challenge_tags.map(&:name) diff --git a/app/views/competitions/competition_modules/index.json.jbuilder b/app/views/competitions/competition_modules/index.json.jbuilder new file mode 100644 index 000000000..decfcb415 --- /dev/null +++ b/app/views/competitions/competition_modules/index.json.jbuilder @@ -0,0 +1,7 @@ + +json.modules do + json.array! @modules.each do |m| + json.extract! m, :id, :name, :position, :url + end +end +json.count @modules.size diff --git a/app/views/competitions/competition_modules/show.json.jbuilder b/app/views/competitions/competition_modules/show.json.jbuilder new file mode 100644 index 000000000..69cdcc544 --- /dev/null +++ b/app/views/competitions/competition_modules/show.json.jbuilder @@ -0,0 +1,11 @@ +json.extract! @module, :id, :name, :position, :url, :md_edit + +md = @module.competition_module_md_content +if md.present? + json.md_name md.name + json.md_content md.content + json.created_at md.created_at.strftime('%Y-%m-%d %H:%M:%S') + json.attachments do + json.array! md.attachments, partial: 'attachments/attachment_simple', as: :attachment + end +end \ No newline at end of file diff --git a/app/views/competitions/competition_staffs/show.json.jbuilder b/app/views/competitions/competition_staffs/show.json.jbuilder new file mode 100644 index 000000000..c490aaf5f --- /dev/null +++ b/app/views/competitions/competition_staffs/show.json.jbuilder @@ -0,0 +1,27 @@ +competition = current_competition + +json.personal competition.personal? +json.enroll_ended competition.enroll_ended? +json.enrolled competition.enrolled?(current_user) + +# 教师报名设置 +if competition.teacher_staff.present? + json.teacher_staff do + json.minimum competition.teacher_staff.minimum + json.maximum competition.teacher_staff.maximum + json.mutiple_limited competition.teacher_staff.mutiple_limited + end +else + json.teacher_staff nil +end + +# 教师报名设置 +if competition.member_staff.present? + json.member_staff do + json.minimum competition.member_staff.minimum + json.maximum competition.member_staff.maximum + json.mutiple_limited competition.member_staff.mutiple_limited + end +else + json.member_staff nil +end diff --git a/app/views/competitions/competition_teams/index.json.jbuilder b/app/views/competitions/competition_teams/index.json.jbuilder new file mode 100644 index 000000000..b641b28e6 --- /dev/null +++ b/app/views/competitions/competition_teams/index.json.jbuilder @@ -0,0 +1,26 @@ +json.count @count +json.competition_teams do + json.array! @teams.each do |team| + json.extract! team, :id, :name, :invite_code + json.team_type team.en_team_type + json.school_name team.user.school_name + + json.manage_permission current_user.id == team.user_id + + json.creator do + json.partial! 'users/user_simple', user: team.user + json.role team.team_members.find(&:creator?).en_role + end + + json.team_members do + json.array! team.team_members.each do |member| + json.partial! 'users/user_simple', user: member.user + json.user_id member.user_id + json.role member.en_role + json.identity member.user.identity + json.school_name member.user.school_name + json.student_id member.user.student_id + end + end + end +end diff --git a/app/views/competitions/competitions/index.json.jbuilder b/app/views/competitions/competitions/index.json.jbuilder new file mode 100644 index 000000000..f0d70f69e --- /dev/null +++ b/app/views/competitions/competitions/index.json.jbuilder @@ -0,0 +1,29 @@ +json.count @count +json.competitions do + json.array! @competitions.each do |competition| + json.extract! competition, :id, :identifier, :name, :sub_title + + json.visits_count competition.visits + member_count = @member_count_map&.fetch(competition.id, 0) || competition.team_members.count + json.member_count member_count.zero? ? 268 : member_count + + json.image url_to_avatar(competition) + json.published competition.published? + json.nearly_published competition.published_at.present? + json.single_stage (@stage_count_map&.fetch(competition.id, 0) || competition.competition_stages.count) == 1 + + json.start_time competition.display_start_time + json.end_time competition.display_end_time + json.enroll_end_time competition.display_enroll_end_time + + section = competition.current_stage_section + if section + json.current_stage do + + json.name = section.competition_stage.name + json.start_time section.display_start_time + json.end_time section.display_end_time + end + end + end +end \ No newline at end of file diff --git a/app/views/competitions/competitions/show.json.jbuilder b/app/views/competitions/competitions/show.json.jbuilder new file mode 100644 index 000000000..18216ee92 --- /dev/null +++ b/app/views/competitions/competitions/show.json.jbuilder @@ -0,0 +1,36 @@ +competition = current_competition +json.extract! competition, :id, :name, :sub_title, :identifier + +json.start_time competition.display_start_time +json.end_time competition.display_end_time +json.enroll_end_time competition.display_enroll_end_time + +json.images do + json.array! competition.attachments, partial: 'attachments/attachment_simple', as: :attachment +end + +json.competition_stages do + stages = competition.competition_stages.includes(competition_stage_sections: :competition_entries) + json.array! stages.each do |stage| + json.extract! stage, :id, :name + + json.sections do + json.array! stage.competition_stage_sections.each do |section| + json.extract! section, :id, :name + + decorator_section = ActiveDecorator::Decorator.instance.decorate(section) + json.start_time decorator_section.display_start_time + json.end_time decorator_section.display_end_time + + is_start = section.start_time > Time.now + json.entries do + json.array! section.competition_entries.each do |entry| + json.extract! entry, :id, :name + + json.url is_start ? entry.url : '' + end + end + end + end + end +end \ No newline at end of file diff --git a/app/views/competitions/students/index.json.jbuilder b/app/views/competitions/students/index.json.jbuilder new file mode 100644 index 000000000..73ccd7d2d --- /dev/null +++ b/app/views/competitions/students/index.json.jbuilder @@ -0,0 +1,9 @@ +json.teachers do + json.array! @students.each do |student| + json.id student.id + json.name student.full_name + json.student_id student.student_id + json.school_name student.school_name + json.enrollable !current_competition.member_multiple_limited? || !@enrolled_map.key?(student.id) + end +end \ No newline at end of file diff --git a/app/views/competitions/teachers/index.json.jbuilder b/app/views/competitions/teachers/index.json.jbuilder new file mode 100644 index 000000000..4a8d2961d --- /dev/null +++ b/app/views/competitions/teachers/index.json.jbuilder @@ -0,0 +1,9 @@ +json.teachers do + json.array! @teachers.each do |teacher| + json.id teacher.id + json.name teacher.full_name + json.identity teacher.identity + json.school_name teacher.school_name + json.enrollable !current_competition.teacher_multiple_limited? || !@enrolled_map.key?(teacher.id) + end +end \ No newline at end of file diff --git a/app/views/courses/apply_teachers.json.jbuilder b/app/views/courses/apply_teachers.json.jbuilder new file mode 100644 index 000000000..aee0803b4 --- /dev/null +++ b/app/views/courses/apply_teachers.json.jbuilder @@ -0,0 +1,13 @@ +json.teacher_list_size @teacher_list_size +json.apply_size @applications_size +json.is_admin @is_admin +json.application_list do + json.array! @applications do |application| + json.application_id application.id + json.user_id application.course_message_id + json.name application.application_user.real_name + json.name_link user_path(application.application_user) + json.login application.application_user.login + json.role application.content.to_i == 3 || application.content.to_i == 7 ? "助教" : application.content.to_i == 2 || application.content.to_i == 9 ? "教师" : "" + end +end \ No newline at end of file diff --git a/app/views/courses/export_member_scores_excel.xlsx.axlsx b/app/views/courses/export_member_scores_excel.xlsx.axlsx index da8c05f7a..5b226a09c 100644 --- a/app/views/courses/export_member_scores_excel.xlsx.axlsx +++ b/app/views/courses/export_member_scores_excel.xlsx.axlsx @@ -4,7 +4,7 @@ wb.styles do |s| no_wrap_sz = s.add_style :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: false,:horizontal => :center,:vertical => :center } sz_all = s.add_style :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center } row_cell = s.add_style :bg_color=> "FAEBDC",:border => { :style => :thin, :color =>"000000" },alignment: {wrap_text: true,:horizontal => :center,:vertical => :center } - blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 20,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center} + blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 25,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center} #课堂信息摘要 wb.add_worksheet(name:course_info[0]) do |sheet| @@ -32,12 +32,12 @@ wb.styles do |s| sheet.sheet_view.show_grid_lines = false sheet_title = activity_level[1] sheet_content = activity_level[2] - sheet.add_row sheet_title, :style => blue_cell + sheet.add_row sheet_title, :height => 25,:style => blue_cell if sheet_content.count > 0 sheet_content.each_with_index do |c,index| c_1 = (index+1) c_2 = [c_1] + c.values - sheet.add_row c_2, :style => sz_all #用户id + sheet.add_row c_2, :height => 25, :style => sz_all #用户id end sheet.column_widths *([20]*sheet.column_info.count) sheet.column_info.first.width = 8 @@ -82,7 +82,7 @@ wb.styles do |s| sheet_content.each_with_index do |c,index| c_1 = (index+1) c_2 = [c_1] + c - sheet.add_row c_2, :style => sz_all #用户id + sheet.add_row c_2, :height => 25,:style => sz_all #用户id end end sheet.column_widths *([15]*sheet.column_info.count) @@ -100,7 +100,7 @@ wb.styles do |s| sheet.add_row head_title, :style => blue_cell if content_shixun.count > 0 content_shixun.each do |user| - sheet.add_row user, :style => sz_all + sheet.add_row user, :height => 25,:style => sz_all end #each_widh_index end sheet.column_widths *([20]*sheet.column_info.count) @@ -119,7 +119,7 @@ wb.styles do |s| sheet.add_row head_title, :style => blue_cell if content_.count > 0 content_.each do |user| - sheet.add_row user, :style => no_wrap_sz + sheet.add_row user, :height => 25,:style => no_wrap_sz end #each_widh_index end sheet.column_widths *([20]*sheet.column_info.count) @@ -138,7 +138,7 @@ wb.styles do |s| sheet.add_row head_title, :style => blue_cell if content_.count > 0 content_.each do |user| - sheet.add_row user, :style => sz_all + sheet.add_row user, :height => 25,:style => sz_all end #each_widh_index end sheet.column_widths *([20]*sheet.column_info.count) @@ -155,7 +155,7 @@ wb.styles do |s| content_ = task[2] sheet.add_row task[1], :style => blue_cell content_.each do |user| - sheet.add_row user, :style => sz_all + sheet.add_row user, :height => 25,:style => sz_all end #each_widh_index sheet.column_widths *([20]*sheet.column_info.count) sheet.column_info.first.width = 12 @@ -171,7 +171,7 @@ wb.styles do |s| content_ = ex[2] sheet.add_row ex[1], :style => blue_cell content_.each do |user| - sheet.add_row user, :style => sz_all #用户id + sheet.add_row user, :height => 25,:style => sz_all #用户id end #each_widh_index sheet.column_widths *([20]*sheet.column_info.count) sheet.column_info.first.width = 12 diff --git a/app/views/courses/get_historical_course_students.json.jbuilder b/app/views/courses/get_historical_course_students.json.jbuilder index a2d3a3f57..be58ff06a 100644 --- a/app/views/courses/get_historical_course_students.json.jbuilder +++ b/app/views/courses/get_historical_course_students.json.jbuilder @@ -1,9 +1,9 @@ json.students do json.array! @students do |student| - json.course_member_id student.id + json.user_id student.user_id json.name student.user.real_name - json.student_id student.user.user_extension.try(:student_id) - json.school_name student.user.user_extension.school.try(:name) + json.student_id student.user.student_id + json.school_name student.user.school_name end end json.students_count @students_count \ No newline at end of file diff --git a/app/views/courses/index.json.jbuilder b/app/views/courses/index.json.jbuilder index ec9ebfc3f..32a7047b7 100644 --- a/app/views/courses/index.json.jbuilder +++ b/app/views/courses/index.json.jbuilder @@ -1,18 +1,16 @@ -json.courses do - json.array! @courses do |course| +json.courses @courses do |course| json.id course.id json.name course.name json.avatar_url url_to_avatar(course.teacher) json.creator course.teacher.real_name - json.school course.teacher.school_name - json.technical_title course.teacher.user_extension.technical_title + json.school course.school&.name + json.technical_title course.teacher.identity json.course_members_count course.course_members_count json.tasks_count get_tasks_count course json.visits course.visits json.is_public course.is_public - json.is_accessible @user.present? ? @user.member_of_course?(course) || @user.creator_of_course?(course) : course.is_public == 1 + json.is_accessible course.is_public == 1 || @user.course_identity(course) < Course::NORMAL json.is_end course.is_end - json.first_category_url module_url(course.course_modules.where.not(module_type: "activity").where(hidden: 0).order(position: :desc).first, course) - end + json.first_category_url module_url(course.none_hidden_course_modules.first, course) end json.courses_count @courses_count diff --git a/app/views/courses/teachers.json.jbuilder b/app/views/courses/teachers.json.jbuilder index 25df05097..040ffb2aa 100644 --- a/app/views/courses/teachers.json.jbuilder +++ b/app/views/courses/teachers.json.jbuilder @@ -2,14 +2,16 @@ json.teacher_list do json.array! @teacher_list do |teacher| json.course_member_id teacher.id json.name teacher.user.real_name - json.name_link user_path(teacher.user.login) + json.name_link user_path(teacher.user) json.login teacher.user.login json.user_id teacher.user.id json.role teacher.role == "CREATOR" ? "管理员" : teacher.role == "PROFESSOR" ? "教师" : "助教" json.course_groups do - json.array! CourseGroup.where(id: TeacherCourseGroup.where(course_member_id: teacher.id, user_id: teacher.user.id, course_id: @course.id).pluck(:course_group_id)) do |course_group| - json.name course_group.name - json.id course_group.id + if @course.course_groups_count > 0 + json.array! @course.course_groups.select{|group| teacher.teacher_course_groups.pluck(:course_group_id).include?(group.id)} do |course_group| + json.name course_group.name + json.id course_group.id + end end end json.graduation_group teacher.graduation_group.try(:name) @@ -17,14 +19,5 @@ json.teacher_list do end end json.teacher_list_size @teacher_list_size -json.application_list do - json.array! @applications do |application| - json.application_id application.id - json.user_id application.course_message_id - json.name application.application_user.real_name - json.name_link user_path(application.application_user) - json.login application.application_user.login - json.role application.content.to_i == 3 || application.content.to_i == 7 ? "助教" : application.content.to_i == 2 || application.content.to_i == 9 ? "教师" : "" - end -end -json.is_admin @is_admin +json.apply_size @applications_size +json.is_admin @is_admin \ No newline at end of file diff --git a/app/views/courses/top_banner.json.jbuilder b/app/views/courses/top_banner.json.jbuilder index ddf860709..c0a1ff956 100644 --- a/app/views/courses/top_banner.json.jbuilder +++ b/app/views/courses/top_banner.json.jbuilder @@ -11,7 +11,7 @@ json.course_end @course.is_end json.deadline course_end_date @course.end_date json.educoder_teacher @user.is_teacher? #json.is_student @is_student -json.is_admin @user.creator_of_course?(@course) +json.is_admin @user_course_identity < Course::PROFESSOR json.is_public @course.is_public == 1 json.code_halt @course.invite_code_halt == 1 json.invite_code @course.invite_code_halt == 0 ? @course.generate_invite_code : "" @@ -20,7 +20,7 @@ json.switch_to_teacher switch_teacher_role(@is_student, @course, @user) json.switch_to_assistant switch_assistant_role(@is_student, @course, @user) #json.join_course !@user.member_of_course?(@course) #json.copy_course !@user.member_of_course?(@course) && @user.is_teacher? -json.course_identity @user.course_identity(@course) +json.course_identity @user_course_identity if @course.is_end == 0 json.days_remaining (@course.end_date.to_date - Time.now.to_date).to_i end diff --git a/app/views/discusses/_discuss.json.jbuilder b/app/views/discusses/_discuss.json.jbuilder index 1fcf150bc..400798150 100644 --- a/app/views/discusses/_discuss.json.jbuilder +++ b/app/views/discusses/_discuss.json.jbuilder @@ -2,20 +2,21 @@ json.author do json.partial! 'users/user', user: discuss.user end json.id discuss.id -json.content discuss.contents(container, current_user) +json.content discuss.content json.time time_from_now(discuss.created_at) json.position discuss.position json.shixun_id discuss.dis_id json.hidden discuss.hidden -json.manage current_user.manager_of_shixun?(container) +json.manage @manger json.reward discuss.reward -json.game_url discuss.game_url(container, current_user) +#json.game_url discuss.game_url(container, current_user) +json.game_url "/tasks/#{discuss.identifier}" if @manger && !children # 主贴和回复有一些不同点 if discuss.parent_id json.can_delete discuss.can_deleted?(current_user) else - json.praise_count discuss.praise_tread.where(praise_or_tread: 1).count - json.user_praise discuss.praise_tread.select{|pt| pt.user_id == current_user.id}.length > 0 ? true : false + json.praise_count discuss.praises_count + json.user_praise discuss.praise_treads.select{|pt| pt.user_id == current_user.id}.length > 0 end diff --git a/app/views/discusses/index.json.jbuilder b/app/views/discusses/index.json.jbuilder index 3d0ee9fc9..7ddfb31fb 100644 --- a/app/views/discusses/index.json.jbuilder +++ b/app/views/discusses/index.json.jbuilder @@ -1,9 +1,8 @@ json.disscuss_count @disscuss_count json.all @current_user.admin? json.comments @discusses do |discuss| - json.partial! 'discusses/discuss', locals: { discuss: discuss, container: @container, current_user: @current_user } - child_discuss = Discuss.children(discuss.id) - json.children child_discuss do |c_d| - json.partial! 'discusses/discuss', locals: { discuss: c_d, container: @container, current_user: @current_user } + json.partial! 'discusses/discuss', locals: { discuss: discuss, container: @container, current_user: @current_user, children: false} + json.children discuss.child_discuss(current_user) do |c_d| + json.partial! 'discusses/discuss', locals: { discuss: c_d, container: @container, current_user: @current_user, children: true } end end diff --git a/app/views/exercise_questions/_exercise_questions.json.jbuilder b/app/views/exercise_questions/_exercise_questions.json.jbuilder index 10dc46abf..bfaf6b736 100644 --- a/app/views/exercise_questions/_exercise_questions.json.jbuilder +++ b/app/views/exercise_questions/_exercise_questions.json.jbuilder @@ -1,14 +1,19 @@ json.question_id question.id -json.question_number question.question_number +q_positon = question.question_number +if ques_position.present? + q_positon = ques_position +end +json.q_position q_positon json.question_title question.question_title json.question_type question.question_type json.question_score question.question_score.round(1).to_s if question.question_type <= 2 #当为选择题或判断题时,只显示选项的位置 standard_answers_array = question.get_standard_answer_ids - exercise_choices = choices.order("choice_position ASC") ex_choice_random_boolean = (exercise_type.present? && exercise_type == 3 && (question.exercise.choice_random)) ? true : false #问题的选项随机打乱 if ex_choice_random_boolean - exercise_choices = exercise_choices.order("RAND()") + exercise_choices = choices.order("RAND()") + else + exercise_choices = choices.order("choice_position ASC") end json.question_choices do json.array! exercise_choices.each_with_index.to_a do |a,index| @@ -16,7 +21,7 @@ if question.question_type <= 2 #当为选择题或判断题时,只显示选 user_answer_b = user_answer.include?(a.id) json.c_position (index+1) if ex_choice_random_boolean #当选项随机时,选项位置以此为准,否则不出现 json.choice_id a.id - json.choice_text a.choice_text + json.choice_text "#{(index+65).chr}.#{a.choice_text}" json.choice_position a.choice_position if exercise_type == 1 || exercise_type == 4 #1为教师编辑/预览 试卷或问题,2为空白试卷,即标准答案和用户答案都不显示,3为用户开始答题的显示,4为老师评阅试卷或学生在截止后查看试卷 json.standard_boolean standard_answer_b @@ -84,7 +89,7 @@ elsif question.question_type == 5 user_get_score = games_score[:s_score].present? ? games_score[:s_score] : 0.0 json.shixun_challenge_id s.id if games_score[:games].count > 0 - json.partial! "exercises/shixun_details",games: games_score[:games], user_score: user_get_score,game_score: games_score[:game_score] + json.partial! "exercises/shixun_details",games: games_score[:games], user_score: user_get_score,game_score: games_score[:game_score],shixun_challenge:s else json.partial! "exercises/shixun_undo",games: [s], user_score: user_get_score ,game_score: s.question_score end diff --git a/app/views/exercise_questions/edit.json.jbuilder b/app/views/exercise_questions/edit.json.jbuilder index 32567d813..35db720c7 100644 --- a/app/views/exercise_questions/edit.json.jbuilder +++ b/app/views/exercise_questions/edit.json.jbuilder @@ -5,4 +5,5 @@ json.partial! "exercise_questions/exercise_questions", choices:@exercise_choices, shixun_challenges: @exercise_question_shixun, exercise_type:1, - user_answer:[] \ No newline at end of file + user_answer:[], + ques_position:nil \ No newline at end of file diff --git a/app/views/exercise_questions/show.json.jbuilder b/app/views/exercise_questions/show.json.jbuilder index e8662a611..c27fe21a5 100644 --- a/app/views/exercise_questions/show.json.jbuilder +++ b/app/views/exercise_questions/show.json.jbuilder @@ -5,4 +5,5 @@ json.partial! "exercise_questions/exercise_questions", choices:@exercise_choices, shixun_challenges: @exercise_question_shixun, exercise_type:1, - user_answer:[] + user_answer:[], + ques_position:nil diff --git a/app/views/exercises/_shixun_details.json.jbuilder b/app/views/exercises/_shixun_details.json.jbuilder index 033ac3dc1..4a73a9bbb 100644 --- a/app/views/exercises/_shixun_details.json.jbuilder +++ b/app/views/exercises/_shixun_details.json.jbuilder @@ -7,7 +7,7 @@ json.stage_list do json.evaluate_count game.evaluate_count json.finished_time finished_time game.end_time json.time_consuming time_consuming game - json.myself_experience game.final_score #经验值 + json.myself_experience game.final_score < 0 ? 0 : game.final_score #经验值 json.experience game.challenge.all_score #经验值 json.user_score user_score.round(1).to_s #用户获得的分数 json.game_score game_score.round(1).to_s #该关卡的总分数 @@ -26,6 +26,17 @@ json.shixun_detail do json.position output.query_index json.output_detail output_detail game, output end - json.passed_code game.try(:lastest_code) + + latest_code = nil + if shixun_challenge.challenge&.path.present? + if game.try(:lastest_code).blank? + cha_path = challenge_path(shixun_challenge.challenge&.path) + latest_code = git_fle_content(game.myshixun.repo_path,cha_path) + else + latest_code = game.try(:lastest_code) + end + end + + json.passed_code latest_code end end \ No newline at end of file diff --git a/app/views/exercises/_user_exercise_info.json.jbuilder b/app/views/exercises/_user_exercise_info.json.jbuilder index a3b7b208c..e690f4867 100644 --- a/app/views/exercises/_user_exercise_info.json.jbuilder +++ b/app/views/exercises/_user_exercise_info.json.jbuilder @@ -36,10 +36,10 @@ elsif student_status == 1 json.question_status question_status end -exercise_status = exercise.get_exercise_status(ex_answerer.id) +# exercise_status = exercise.get_exercise_status(ex_answerer) #当前为老师,或为学生,但在试卷截止后且答案选择公开的 -if is_teacher_or == 1 || (exercise_status == 3 && exercise.answer_open) +if is_teacher_or == 1 || (ex_answer_status == Exercise::ENDED && exercise.answer_open) ex_type = 4 else ex_type = 3 @@ -47,14 +47,13 @@ end json.exercise_questions do json.array! exercise_questions do |q| - - user_ques_answers = user_question_answers(q,ex_answerer.id,student_status,is_teacher_or,exercise_status,q.question_type,ex_type) + user_ques_answers = user_question_answers(q,ex_answerer.id,student_status,is_teacher_or,ex_answer_status,q.question_type,ex_type) user_ques_comments = user_ques_answers[:question_comment] if all_question_status.size > 0 this_ques_status = all_question_status.detect {|f| f[:q_id] == q.id} json.answer_status this_ques_status[:stand_status] end - json.user_score user_ques_answers[:user_score].to_s + json.user_score user_ques_answers[:user_score] json.partial! "exercise_questions/exercise_questions", question: q, ex_answerer: ex_answerer, @@ -62,7 +61,8 @@ json.exercise_questions do shixun_challenges: q.exercise_shixun_challenges, exercise_type: ex_type, user_answer: user_ques_answers[:answered_content], - shixun_type: user_ques_answers[:shixun_type] + shixun_type: user_ques_answers[:shixun_type], + ques_position: nil if user_ques_comments.count > 0 json.question_comments do json.partial! "exercises/exercise_comments", question_comment:user_ques_answers[:question_comment].first diff --git a/app/views/exercises/blank_exercise.json.jbuilder b/app/views/exercises/blank_exercise.json.jbuilder index 631f0dcb3..16b5449fb 100644 --- a/app/views/exercises/blank_exercise.json.jbuilder +++ b/app/views/exercises/blank_exercise.json.jbuilder @@ -11,7 +11,8 @@ json.exercise_questions do choices:q.exercise_choices, shixun_challenges: q.exercise_shixun_challenges, exercise_type:2, - user_answer:[] + user_answer:[], + ques_position:nil end end diff --git a/app/views/exercises/common_header.json.jbuilder b/app/views/exercises/common_header.json.jbuilder index 68fa45a67..5d33aca66 100644 --- a/app/views/exercises/common_header.json.jbuilder +++ b/app/views/exercises/common_header.json.jbuilder @@ -1,5 +1,7 @@ json.course_is_end @course.is_end # true表示已结束,false表示未结束 -json.extract! @exercise, :id,:exercise_name,:exercise_description,:show_statistic,:time +json.extract! @exercise, :id,:exercise_name,:exercise_description,:show_statistic +json.time @user_left_time + json.exercise_status @ex_status json.user_permission do diff --git a/app/views/exercises/edit.json.jbuilder b/app/views/exercises/edit.json.jbuilder index 61ec71db5..71a6fcf07 100644 --- a/app/views/exercises/edit.json.jbuilder +++ b/app/views/exercises/edit.json.jbuilder @@ -15,7 +15,8 @@ json.exercise_questions do shixun_challenges: q.exercise_shixun_challenges, exercise_type:1, user_answer:[], - shixun_type:0 + shixun_type:0, + ques_position:nil end end diff --git a/app/views/exercises/exercise_lists.json.jbuilder b/app/views/exercises/exercise_lists.json.jbuilder index b51e781c7..26723c894 100644 --- a/app/views/exercises/exercise_lists.json.jbuilder +++ b/app/views/exercises/exercise_lists.json.jbuilder @@ -15,6 +15,7 @@ json.exercise_types do json.exercise_id @exercise.id json.subjective @subjective_type #是否包含主观题,1为包括,0为不包括 json.exercise_end_time ((@ex_user_end_time.nil? || @ex_user_end_time < Time.now) ? "--" : how_much_time(@ex_user_end_time)) + json.groups_count @c_group_counts end if @exercise_current_user_status == 0 #当为老师的时候 @@ -29,7 +30,6 @@ if @exercise_current_user_status == 0 #当为老师的时候 else json.course_groups [] end - end if @current_user_ex_answers.present? diff --git a/app/views/exercises/exercise_result.json.jbuilder b/app/views/exercises/exercise_result.json.jbuilder index b0d1be9d2..2c4b3ded7 100644 --- a/app/views/exercises/exercise_result.json.jbuilder +++ b/app/views/exercises/exercise_result.json.jbuilder @@ -32,11 +32,18 @@ json.commit_results do json.ques_position q[:position] json.right_percent q[:percent] json.effictive_counts q[:ques_effictive_counts] - if q[:type] != 5 + if q[:type] != Exercise::PRACTICAL json.ques_details do - json.array! q[:ques_details] do |d| + json.array! q[:ques_details].each_with_index.to_a do |d,index| + if q[:type] <= Exercise::MULTIPLE + ques_index = (index+65).chr + elsif q[:type] == Exercise::JUDGMENT + ques_index = (index+1).to_s + else + ques_index = nil + end json.choice_position d[:choice_position] - json.choice_text d[:choice_text] + json.choice_text ques_index.present? ? "#{ques_index}.#{d[:choice_text]}" : d[:choice_text] json.choice_users_count d[:choice_users_count] json.choice_percent d[:choice_percent] json.choice_right_boolean d[:right_answer] @@ -48,6 +55,7 @@ json.commit_results do json.challenge_id cha[:cha_id] json.challenge_name cha[:cha_name] json.challenge_position cha[:cha_position] + json.challenge_percent cha[:cha_percent] json.challenge_details do json.array! cha[:cha_details] do |ch| json.choice_position ch[:choice_position] diff --git a/app/views/exercises/index.json.jbuilder b/app/views/exercises/index.json.jbuilder index 661a8886d..e5da76786 100644 --- a/app/views/exercises/index.json.jbuilder +++ b/app/views/exercises/index.json.jbuilder @@ -1,27 +1,13 @@ -json.exercises_counts do - json.exercises_total_counts @exercises_count #全部试卷数 - json.exercises_all_counts @exercises_select_count #选择后的全部试卷数 - json.exercises_unpublish_counts @exercises_unpublish_counts #未发布试卷数 - json.exercises_published_counts @exercises_published_counts #已发布试卷数 - json.exercises_ended_counts @exercises_ended_counts #已截止试卷数 - json.left_banner_id @left_banner_id - json.left_banner_name @left_banner_name -end - -json.course_types do - json.course_status @course.is_end ? 1 : 0 #课堂的当前是否结束,如结束,则为1,否则为0 - json.course_end_time @course.end_date #课堂的截止时间 - json.course_is_public @course.is_public #判断课堂是否为公开,只有公开课才有设为公开的按钮 - json.user_permission @is_teacher_or # 当前用户存在且为课堂教师/管理员/超级管理员时为1 ,课堂成员为2,否则为0 -end - - if @exercises_count > 0 json.exercises do json.array! @exercises do |exercise| + json.extract! exercise, :id, :exercise_name,:is_public,:created_at + if @is_teacher_or == 2 + second_left = get_exercise_left_time(exercise,@current_user_) + json.time second_left.present? ? (second_left / 60) : nil + end ex_index = exercise_index_show(exercise,@course,@is_teacher_or,@current_user_) - json.extract! exercise, :id, :exercise_name,:is_public,:created_at,:time json.exercise_status ex_index[:ex_status] json.lock_status ex_index[:lock_icon] json.publish_time ex_index[:publish_time] # 试卷的发布时间 @@ -38,3 +24,22 @@ else json.exercises [] end +json.course_types do + json.course_status @course.is_end ? 1 : 0 #课堂的当前是否结束,如结束,则为1,否则为0 + json.course_end_time @course.end_date #课堂的截止时间 + json.course_is_public @course.is_public #判断课堂是否为公开,只有公开课才有设为公开的按钮 + json.user_permission @is_teacher_or # 当前用户存在且为课堂教师/管理员/超级管理员时为1 ,课堂成员为2,否则为0 +end + +json.exercises_counts do + json.exercises_total_counts @exercises_count #全部试卷数 + json.exercises_all_counts @exercises_select_count #选择后的全部试卷数 + json.exercises_unpublish_counts @exercises_unpublish_counts #未发布试卷数 + json.exercises_published_counts @exercises_published_counts #已发布试卷数 + # json.exercises_ended_counts @exercises_ended_counts #已截止试卷数 + json.left_banner_id @left_banner_id + json.left_banner_name @left_banner_name +end + + + diff --git a/app/views/exercises/review_exercise.json.jbuilder b/app/views/exercises/review_exercise.json.jbuilder index 5d2ac875d..638324256 100644 --- a/app/views/exercises/review_exercise.json.jbuilder +++ b/app/views/exercises/review_exercise.json.jbuilder @@ -8,5 +8,6 @@ json.partial! "exercises/user_exercise_info",locals:{exercise:@exercise, ex_sub_array:@ex_sub_array, exercise_questions:@exercise_questions, student_status:@student_status, - question_status:@question_status + question_status:@question_status, + ex_answer_status:@ex_answer_status } diff --git a/app/views/exercises/show.json.jbuilder b/app/views/exercises/show.json.jbuilder index 8f6517c2c..d92eebeab 100644 --- a/app/views/exercises/show.json.jbuilder +++ b/app/views/exercises/show.json.jbuilder @@ -18,7 +18,8 @@ json.exercise_questions do shixun_challenges: q.exercise_shixun_challenges, exercise_type:1, user_answer:[], - shixun_type:0 + shixun_type:0, + ques_position:nil end end diff --git a/app/views/exercises/start_answer.json.jbuilder b/app/views/exercises/start_answer.json.jbuilder index fb9916696..42d611712 100644 --- a/app/views/exercises/start_answer.json.jbuilder +++ b/app/views/exercises/start_answer.json.jbuilder @@ -36,12 +36,12 @@ json.partial! "exercises/exercise_scores" json.exercise_questions do json.array! @exercise_all_questions do |q| question = q[:question] - ques_position = q[:ques_number] #问题的序号,当问题为随机时,重新更新后的问题序号 + # ques_position = q[:ques_number] #问题的序号,当问题为随机时,重新更新后的问题序号 question_info = get_exercise_question_info(question,@exercise,@exercise_user_current,@ex_answerer.id) - json.q_position ques_position + # json.q_position q[:ques_number] #问题的序号,当问题为随机时,重新更新后的问题序号 if @t_user_exercise_status == 3 - this_answer_status = "0.0" - user_score = "0.0" + this_answer_status = 0 + user_score = nil if all_question_status.size > 0 this_ques_status = all_question_status.detect {|f| f[:q_id] == question.id} this_answer_status = this_ques_status[:stand_status] @@ -58,6 +58,7 @@ json.exercise_questions do user_answer: question_info[:answered_content], choices:question.exercise_choices, exercise_type:3, - shixun_type:question_info[:shixun_type] + shixun_type:question_info[:shixun_type], + ques_position: q[:ques_number] end end \ No newline at end of file diff --git a/app/views/exercises/students_exercises.json.jbuilder b/app/views/exercises/students_exercises.json.jbuilder deleted file mode 100644 index 25c85be88..000000000 --- a/app/views/exercises/students_exercises.json.jbuilder +++ /dev/null @@ -1,18 +0,0 @@ -json.total_counts @total_exercise_counts - -json.total_user_exercises do - json.array! @all_exercise_stu_array do |a| - json.student_exercise do - json.partial! "exercises/user_exercise_info",locals:{exercise:@exercise, - is_teacher_or:a[:is_teacher], - ex_answerer:a[:ex_answerer], - exercise_user:a[:ex_user], - ex_obj_array:a[:ex_obj_array], - ex_sub_array:a[:ex_sub_array], - exercise_questions:@exercise_questions, - student_status:@student_status, - question_status:@question_status - } - end - end -end diff --git a/app/views/files/index.json.jbuilder b/app/views/files/index.json.jbuilder index 03b4d4892..81fa406dd 100644 --- a/app/views/files/index.json.jbuilder +++ b/app/views/files/index.json.jbuilder @@ -3,8 +3,8 @@ json.data do json.id @category_id json.name @category_name json.total_count @total_count - json.public_count @public_count - json.private_count @private_count + json.publish_count @publish_count + json.unpublish_count @unpublish_count json.course_is_public @course.is_public? json.files do json.array! @attachments do |attachment| diff --git a/app/views/games/_testset_list.json.jbuilder b/app/views/games/_testset_list.json.jbuilder index 2111e3467..86bf2de1b 100644 --- a/app/views/games/_testset_list.json.jbuilder +++ b/app/views/games/_testset_list.json.jbuilder @@ -7,6 +7,8 @@ json.test_sets @qurey_test_sets do |test_set| json.actual_output evaluate_actual_output(test_set) end json.compile_success test_set.try(:compile_success) + json.ts_time test_set.try(:ts_time) + json.ts_mem test_set.try(:ts_mem) end json.allowed_unlock @shixun.test_set_permission diff --git a/app/views/games/check_test_sets.json.jbuilder b/app/views/games/check_test_sets.json.jbuilder index 017a75aea..ba1ed64a6 100644 --- a/app/views/games/check_test_sets.json.jbuilder +++ b/app/views/games/check_test_sets.json.jbuilder @@ -1,2 +1,10 @@ -json.status @status -json.message @message \ No newline at end of file +json.test_sets @qurey_test_sets do |test_set| + json.is_public test_set.is_public + json.result test_set.try(:result) + if test_set.is_public || @allowed_hidden_testset + json.input test_set.input + json.output test_set.output + json.actual_output evaluate_actual_output(test_set) + end + json.compile_success test_set.try(:compile_success) +end \ No newline at end of file diff --git a/app/views/games/get_answer_info.json.jbuilder b/app/views/games/get_answer_info.json.jbuilder index 7620a991a..0f150d500 100644 --- a/app/views/games/get_answer_info.json.jbuilder +++ b/app/views/games/get_answer_info.json.jbuilder @@ -1,5 +1,6 @@ index = 0 json.status 3 +# st: 0 实践题 1 选择题 json.message do json.array! @challenge_answers do |answer| index += 1 @@ -13,3 +14,5 @@ json.message do end end + + diff --git a/app/views/games/get_choose_answer.json.jbuilder b/app/views/games/get_choose_answer.json.jbuilder new file mode 100644 index 000000000..15586de13 --- /dev/null +++ b/app/views/games/get_choose_answer.json.jbuilder @@ -0,0 +1,6 @@ +json.choose_answers do + json.array! @challenge_chooses do |choose| + json.position choose.position + json.answer choose.answer.blank? ? choose.standard_answer : choose.answer + end +end diff --git a/app/views/games/picture_display.json.jbuilder b/app/views/games/picture_display.json.jbuilder index 0470a5c0b..541c478a9 100644 --- a/app/views/games/picture_display.json.jbuilder +++ b/app/views/games/picture_display.json.jbuilder @@ -19,7 +19,7 @@ if @type == "image" end elsif @type == "html" - json.iframe_src html_show_users_path(:path => "#{@user_path}/#{@user_picture[0]}") + json.iframe_src File.read("#{@user_path}/#{@user_picture[0]}")&.html_safe elsif @type == "txt" json.contents @contents.html_safe elsif @type =="qrcode" diff --git a/app/views/games/show.json.jbuilder b/app/views/games/show.json.jbuilder index acbc8c2ef..607a57a15 100644 --- a/app/views/games/show.json.jbuilder +++ b/app/views/games/show.json.jbuilder @@ -1,6 +1,9 @@ json.(@base_date, :st, :discusses_count, :game_count, :record_onsume_time, :prev_game, :next_game, :praise_count, :user_praise, :time_limit, :tomcat_url, :is_teacher, :myshixun_manager, :game, :challenge, :shixun, :myshixun) +if @shixun.vnc + json.vnc_url @vnc_url +end json.user do json.partial! 'users/user', user: @user json.identity @identity diff --git a/app/views/games/unlock_answer.json.jbuilder b/app/views/games/unlock_answer.json.jbuilder index 71018c7be..322536c2b 100644 --- a/app/views/games/unlock_answer.json.jbuilder +++ b/app/views/games/unlock_answer.json.jbuilder @@ -1 +1 @@ -json.contents @answer.contents \ No newline at end of file +json.contents @answer.contents diff --git a/app/views/games/unlock_choose_answer.json.jbuilder b/app/views/games/unlock_choose_answer.json.jbuilder new file mode 100644 index 000000000..15586de13 --- /dev/null +++ b/app/views/games/unlock_choose_answer.json.jbuilder @@ -0,0 +1,6 @@ +json.choose_answers do + json.array! @challenge_chooses do |choose| + json.position choose.position + json.answer choose.answer.blank? ? choose.standard_answer : choose.answer + end +end diff --git a/app/views/graduation_tasks/index.json.jbuilder b/app/views/graduation_tasks/index.json.jbuilder index 157bde672..a6540555d 100644 --- a/app/views/graduation_tasks/index.json.jbuilder +++ b/app/views/graduation_tasks/index.json.jbuilder @@ -1,21 +1,18 @@ json.course_identity @identity json.course_public @course.is_public == 1 json.is_end @course.is_end -json.all_count @all_count -json.published_count @published_count -json.unpublished_count @all_count - @published_count -json.task_count @task_count json.tasks @tasks.each do |task| - task_private = @identity > Course::STUDENT && !task.is_public + # task_private = @identity > Course::STUDENT && !task.is_public json.task_id task.id json.name task.name - json.private_icon task_private + json.private_icon !task.is_public json.task_status task.status #6.12 -hs - json.status task_curr_status(task, @course)[:status] - json.status_time task_curr_status(task, @course)[:time] + task_curr_status = task_curr_status(task, @course) + json.status task_curr_status[:status] + json.status_time task_curr_status[:time] - unless task_curr_status(task, @course)[:status].include?("未发布") + unless task_curr_status[:status].include?("未发布") json.commit_count grduationwork_count task, 1 json.uncommit_count grduationwork_count task, 0 end @@ -28,3 +25,7 @@ json.tasks @tasks.each do |task| end end +json.all_count @all_count +json.published_count @published_count +json.unpublished_count @all_count - @published_count +json.task_count @task_count diff --git a/app/views/graduation_tasks/tasks_list.json.jbuilder b/app/views/graduation_tasks/tasks_list.json.jbuilder index 5f1b8eb40..5a2d7e08a 100644 --- a/app/views/graduation_tasks/tasks_list.json.jbuilder +++ b/app/views/graduation_tasks/tasks_list.json.jbuilder @@ -1,6 +1,7 @@ json.partial! "public_navigation", locals: {graduation: @task, course: @course} json.user_course_identity @user_course_identity json.course_group_count @course.course_groups_count +json.cross_comment @task.cross_comment # 课程发布才有数据 if @task.published? || @user_course_identity < Course::STUDENT # 老师身份才有的分类信息 @@ -25,16 +26,27 @@ if @task.published? || @user_course_identity < Course::STUDENT # 是否具有分组 json.have_grouping @task.have_grouping? - json.work_count @work_count - json.all_work_count @all_work_count + # 是否关联项目 + json.have_project @task.have_grouping? && @task.base_on_project + + if @user_course_identity == Course::STUDENT + json.commit_count grduationwork_count @task, 1 + json.uncommit_count grduationwork_count @task, 0 + json.left_time task_left_time @task + else + json.work_count @work_count + json.all_work_count @all_work_count + end + # 学生数据 json.work_lists do json.array! @work_list do |work| json.id work.id json.user_id work.user.id - json.name work.user.full_name - json.student_id work.user.school_id - json.class_grouping_name work.class_grouping_name + json.name work.user.real_name + json.student_id work.user.student_id + json.class_grouping_name @students.select{|student| student.user_id == work.user_id}.first.try(:course_group_name) + json.ultimate_score work.ultimate_score if @task.have_grouping? json.grouping_name work.grouping_name if @task.base_on_project @@ -44,9 +56,14 @@ if @task.published? || @user_course_identity < Course::STUDENT json.status work.work_status json.update_time format_time work.update_time json.teacher_comment_score work.teacher_comment_score(@current_user, @user_course_identity) - json.cross_comment_score work.cross_comment_score(@current_user, @user_course_identity) + if @task.cross_comment + json.cross_comment_score work.cross_comment_score(@current_user, @user_course_identity) + json.cross_comment_num work.cross_comment_num + end + json.late_penalty work.late_penalty if @task.allow_late json.final_score work_final_score work, @current_user, @user_course_identity - json.assign work.assign_power?(@user_course_identity) + json.assign @assign_power + json.view_work @view_work || (@current_user.id == work.user_id && work.work_status != 0) end end end \ No newline at end of file diff --git a/app/views/graduation_tasks/tasks_list.xlsx.axlsx b/app/views/graduation_tasks/tasks_list.xlsx.axlsx index 1f4f76292..e34290498 100644 --- a/app/views/graduation_tasks/tasks_list.xlsx.axlsx +++ b/app/views/graduation_tasks/tasks_list.xlsx.axlsx @@ -5,10 +5,12 @@ wb.styles do |s| blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 20,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {:horizontal => :center} wb.add_worksheet(:name =>"学生成绩") do |sheet| - sheet.add_row table_columns, :style => blue_cell + sheet.add_row table_columns,:height =>20, :style => blue_cell sheet.column_info.first.width = 12 task_users.each do |user| - sheet.add_row user, :style => sz_all + sheet.add_row user, :height =>20, :style => sz_all end #each_widh_index + sheet.column_widths *([25]*sheet.column_info.count) + sheet.column_info.first.width = 12 end #add_worksheet end \ No newline at end of file diff --git a/app/views/graduation_topics/_topics.json.jbuilder b/app/views/graduation_topics/_topics.json.jbuilder index 7a37b666b..271531f85 100644 --- a/app/views/graduation_topics/_topics.json.jbuilder +++ b/app/views/graduation_topics/_topics.json.jbuilder @@ -1,6 +1,6 @@ json.array! topics do |topic| - task_private = course_identity > Course::STUDENT && !topic.is_public - json.private_icon task_private + # task_private = course_identity > Course::STUDENT && !topic.is_public + json.private_icon !topic.is_public json.(topic, :id, :name, :status) json.author topic.teacher.full_name json.user_topic_status topic.user_status(current_user) diff --git a/app/views/graduation_topics/export.xlsx.axlsx b/app/views/graduation_topics/export.xlsx.axlsx index f1d7e8e74..2da608f6a 100644 --- a/app/views/graduation_topics/export.xlsx.axlsx +++ b/app/views/graduation_topics/export.xlsx.axlsx @@ -1,5 +1,5 @@ wb = xlsx_package.workbook -wb.use_autowidth = false +# wb.use_autowidth = false wb.use_shared_strings = true wb.styles do |s| @@ -9,13 +9,13 @@ wb.styles do |s| bg_cc = s.add_style :bg_color=> "CCC1DA",:border => { :style => :thick, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center } bg_ff = s.add_style :bg_color=> "FFC000",:border => { :style => :thick, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center } bg_bb = s.add_style :bg_color=> "9BBB59",:border => { :style => :thick, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center } - bg_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 20,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center } + bg_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center } wb.add_worksheet(:name => "毕设选题情况汇总") do |sheet| sheet.sheet_view.show_grid_lines = false sheet_title = table_columns sheet_title_c = sheet_title.count - sheet.add_row sheet_title, :style => bg_cell + sheet.add_row sheet_title,:height => 32, :style => bg_cell sheet["J1:L1"].each { |c| c.style = bg_db } sheet["M1:O1"].each { |c| c.style = bg_cc } sheet["P1:Q1"].each { |c| c.style = bg_d2 } @@ -23,10 +23,10 @@ wb.styles do |s| sheet["U1:W1"].each { |c| c.style = bg_bb } if topic_users.count > 0 topic_users.each do |user| - sheet.add_row user, :style => sz_all + sheet.add_row user,:height => 18, :style => sz_all end #each_widh_index else - sheet.add_row ["--"]*sheet_title_c + sheet.add_row ["--"]*sheet_title_c,:height => 18 end sheet.column_widths *([15]*sheet.column_info.count) diff --git a/app/views/graduation_topics/show.json.jbuilder b/app/views/graduation_topics/show.json.jbuilder index 440dc776e..87fcc87aa 100644 --- a/app/views/graduation_topics/show.json.jbuilder +++ b/app/views/graduation_topics/show.json.jbuilder @@ -7,13 +7,8 @@ json.edit_url edit_course_graduation_topic_path(@course, graduation_topic_id: @g json.users_count @users_count json.course_identity @current_user.course_identity(@course) json.user_selected_topic @graduation_topic.user_status(current_user.id) - -json.group_list do - json.array! @group_list do |group| - json.course_group_id group.id - json.group_name group.name - end -end +json.group_list @course.teacher_group(current_user.id) +json.user_selected @user_selected # 列表数据 json.users_list do diff --git a/app/views/graduation_works/edit.json.jbuilder b/app/views/graduation_works/edit.json.jbuilder index 7fc3a9621..254579473 100644 --- a/app/views/graduation_works/edit.json.jbuilder +++ b/app/views/graduation_works/edit.json.jbuilder @@ -3,6 +3,8 @@ json.task_type @task.task_type json.work_id @work.id json.description @work.description json.user_name @task_user.real_name +json.max_num @task.max_num +json.min_num @task.min_num json.attachments @work.attachments do |atta| json.partial! "attachments/attachment_simple", locals: {attachment: atta, delete: @work.delete_atta(atta)} diff --git a/app/views/graduation_works/new.json.jbuilder b/app/views/graduation_works/new.json.jbuilder index 601ba02d3..26c046ab6 100644 --- a/app/views/graduation_works/new.json.jbuilder +++ b/app/views/graduation_works/new.json.jbuilder @@ -6,4 +6,6 @@ if @task.task_type == 2 json.user_id @user.id json.user_student_id @user.student_id json.group_name @course.course_member(@user.id).try(:course_group_name) + json.max_num @task.max_num + json.min_num @task.min_num end diff --git a/app/views/homework_commons/_homework_public_navigation.json.jbuilder b/app/views/homework_commons/_homework_public_navigation.json.jbuilder index 09dd076c0..243c6aecd 100644 --- a/app/views/homework_commons/_homework_public_navigation.json.jbuilder +++ b/app/views/homework_commons/_homework_public_navigation.json.jbuilder @@ -3,11 +3,13 @@ json.course_name course.name json.is_end course.is_end json.category homework.category_info member = course.course_members.find_by(user_id: user.id, is_active: 1) -json.homework_status homework_curr_status(homework, user.course_identity(course), course, member, member&.teacher_course_groups)[:status] -json.time_status homework_curr_status(homework, user.course_identity(course), course, member, member&.teacher_course_groups)[:time_status] +curr_status = homework_curr_status(homework, user.course_identity(course), course, member, member&.teacher_course_groups) +json.homework_status curr_status[:status] +json.time_status curr_status[:time_status] json.homework_name homework.name json.homework_id homework.id json.homework_type homework.homework_type if homework.homework_type == "practice" - json.shixun_identifier homework.shixuns.first.try(:identifier) + json.shixun_identifier homework.shixuns.take.try(:identifier) + json.shixun_id homework.shixuns.take.try(:id) end diff --git a/app/views/homework_commons/_student_btn_check.json.jbuilder b/app/views/homework_commons/_student_btn_check.json.jbuilder index efa89203d..7b34622fa 100644 --- a/app/views/homework_commons/_student_btn_check.json.jbuilder +++ b/app/views/homework_commons/_student_btn_check.json.jbuilder @@ -1,6 +1,8 @@ if identity == Course::STUDENT if homework.homework_type == "practice" - json.task_operation task_operation_url(work.try(:myshixun), homework.shixuns.take) + shixun = homework.shixuns.take + myshixun = work.try(:myshixun) ? work.myshixun : shixun.myshixuns.find_by(user_id: work.user_id) + json.task_operation task_operation_url(myshixun, shixun) json.view_report work.work_status > 0 json.commit_des commit_des_status(work, homework) else diff --git a/app/views/homework_commons/code_review_detail.json.jbuilder b/app/views/homework_commons/code_review_detail.json.jbuilder index 4ebabf20a..c33a906ec 100644 --- a/app/views/homework_commons/code_review_detail.json.jbuilder +++ b/app/views/homework_commons/code_review_detail.json.jbuilder @@ -2,18 +2,26 @@ json.course_id @course.id json.course_name @course.name json.homework_common_id @homework.id json.homework_common_name @homework.name +json.work_id @student_work.id json.work_name @student_work.name json.username @user.full_name json.user_id @user.id json.user_login @user.login json.work_score @student_work.work_score + if @student_work.ultimate_score json.adjust_score @student_work.work_score < 0 ? 0 : number_with_precision(@student_work.work_score, precision: 1) else json.final_score @student_work.final_score json.late_penalty @student_work.late_penalty json.score @student_work.work_score < 0 ? 0 : number_with_precision(@student_work.work_score, precision: 1) + if @homework.work_efficiency + json.eff_score_full number_with_precision @homework.eff_score, precision: 1 + json.eff_score number_with_precision @student_work.eff_score, precision: 1 + json.challenge_score_full number_with_precision (100 - @homework.eff_score), precision: 1 + json.challenge_score number_with_precision @student_work.final_score, precision: 1 + end end json.challenge_list do @@ -25,6 +33,7 @@ json.challenge_list do json.final_score challenge[:final_score] json.username challenge[:username] json.all_score challenge[:all_score] + json.copy_user_id challenge[:copy_user_id] json.copy_username challenge[:copy_username] json.copy_end_time challenge[:copy_end_time] json.code_rate challenge[:code_rate] diff --git a/app/views/homework_commons/group_list.json.jbuilder b/app/views/homework_commons/group_list.json.jbuilder index 1be1cdab6..b5fead17e 100644 --- a/app/views/homework_commons/group_list.json.jbuilder +++ b/app/views/homework_commons/group_list.json.jbuilder @@ -7,11 +7,14 @@ json.group_list do end end # 未分班展示情况放在最后 -if @course_groups.count > 0 && @course_groups.count < @limit.to_i - json.ungroup_list do - json.id 0 - json.name "未分班" - json.work_count homework_ungroup_works_count @homework, @ungroup_user_ids - json.last_review_time ungroup_last_review_time @homework +if @course_groups.count != (@page -1)*@limit.to_i && @course_groups.count < @limit.to_i + ungroup_work_count = homework_ungroup_works_count(@homework, @ungroup_user_ids) + if ungroup_work_count > 0 + json.ungroup_list do + json.id 0 + json.name "未分班" + json.work_count ungroup_work_count + json.last_review_time ungroup_last_review_time @homework + end end end \ No newline at end of file diff --git a/app/views/homework_commons/index.json.jbuilder b/app/views/homework_commons/index.json.jbuilder index 18e601871..9107c9634 100644 --- a/app/views/homework_commons/index.json.jbuilder +++ b/app/views/homework_commons/index.json.jbuilder @@ -2,40 +2,39 @@ json.course_identity @user_course_identity json.homework_type @homework_type json.course_public @course.is_public == 1 json.is_end @course.is_end -json.all_count @all_count -json.published_count @published_count -json.unpublished_count @all_count - @published_count -json.task_count @task_count json.main_category_id @main_category.try(:id) json.main_category_name @main_category.try(:module_name) json.category_id @category.try(:id) json.category_name @category.try(:name) json.homeworks @homework_commons.each do |homework| - homework_private = (@user_course_identity > Course::STUDENT) && !homework.is_public + # homework_private = (@user_course_identity > Course::STUDENT) && !homework.is_public + curr_status = homework_curr_status(homework, @user_course_identity, @course, @member, @member&.teacher_course_groups) json.homework_id homework.id json.name homework.name - json.private_icon homework_private - json.status homework_curr_status(homework, @user_course_identity, @course, @member, @member&.teacher_course_groups)[:status] - json.status_time homework_curr_status(homework, @user_course_identity, @course, @member, @member&.teacher_course_groups)[:time] - json.time_status homework_curr_status(homework, @user_course_identity, @course, @member, @member&.teacher_course_groups)[:time_status] + json.private_icon !homework.is_public + json.status curr_status[:status] + json.status_time curr_status[:time] + json.time_status curr_status[:time_status] json.allow_late homework.allow_late - unless homework_curr_status(homework, @user_course_identity, @course, @member, @member&.teacher_course_groups)[:status].include?("未发布") - json.commit_count studentwork_count homework, 1, @user.id - json.uncommit_count studentwork_count homework, 0, @user.id + unless curr_status[:status].include?("未发布") + json.commit_count studentwork_count homework, 1, @member + json.uncommit_count studentwork_count homework, 0, @member end if @user_course_identity < Course::STUDENT if homework.homework_type == "practice" - json.shixun_identifier homework.shixuns.first.try(:identifier) + json.shixun_identifier homework.shixuns.take.try(:identifier) end elsif @user_course_identity == Course::STUDENT if homework.homework_type == "practice" + shixun = homework.shixuns.take # json.challenge_count homework.shixuns.first.try(:challenges_count).to_i current_myshixun = homework.user_work(@user.id).try(:myshixun) + myshixun = current_myshixun ? current_myshixun : shixun.myshixuns.find_by(user_id: @user.id) # json.game_count current_myshixun ? current_myshixun.exec_count : 0 - json.task_operation task_operation_url(current_myshixun, homework.shixuns.first) + json.task_operation task_operation_url(myshixun, shixun) else work = homework.user_work(@user.id) json.work_id work.try(:id) @@ -45,3 +44,8 @@ json.homeworks @homework_commons.each do |homework| end end +json.all_count @all_count +json.published_count @published_count +json.unpublished_count @all_count - @published_count +json.task_count @task_count + diff --git a/app/views/homework_commons/shixuns.json.jbuilder b/app/views/homework_commons/shixuns.json.jbuilder index 129a0b6d3..bd97f5e8d 100644 --- a/app/views/homework_commons/shixuns.json.jbuilder +++ b/app/views/homework_commons/shixuns.json.jbuilder @@ -1,12 +1,30 @@ +# json.shixun_list @shixuns do |shixun| +# json.shixun_identifier shixun.identifier +# json.name shixun.name +# json.creator shixun.user&.full_name +# json.creator_login shixun.user&.login +# json.school shixun.user&.school_name +# json.myshixuns_count shixun.myshixuns_count +# json.level level_to_s(shixun.trainee) +# json.challenge_tags shixun.challenge_tags_name +# end + +json.shixun_list @shixuns do |shixun| + json.shixun_id shixun.id + json.identifier shixun.identifier + json.shixun_name shixun.name + json.myshixuns_count shixun.myshixuns_count + json.school shixun.user&.school_name + json.creator shixun.user&.full_name + json.level level_to_s(shixun.trainee) +end + json.tags @tags do |tag| json.tag_id tag.id json.tag_name tag.name end -json.shixun_list do - json.partial! 'shixuns/choose_shixun', locals: {shixuns: @shixuns} -end - -json.shixuns_count @shixuns_count +json.shixuns_count @total_count +json.search_tags @search_tags json.partial! 'homework_commons/second_category', locals: {main_catrgory: @main_catrgory, homework_category: @homework_category} \ No newline at end of file diff --git a/app/views/homework_commons/subjects.json.jbuilder b/app/views/homework_commons/subjects.json.jbuilder index ea63f2125..257fcc9d5 100644 --- a/app/views/homework_commons/subjects.json.jbuilder +++ b/app/views/homework_commons/subjects.json.jbuilder @@ -6,8 +6,12 @@ end json.subject_list @subjects do |subject| json.subject_id subject.id json.subject_name subject.name + json.challenge_tags subject.shixun_tags json.shixun_count subject.shixuns.unhidden.size json.myshixun_count subject.shixuns.pluck(:myshixuns_count).sum + json.creator subject.user&.full_name + json.creator_login subject.user&.login + json.school subject.user&.school_name end -json.subjects_count @subjects_count \ No newline at end of file +json.subjects_count @total_count \ 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 1d3110604..bbe71661a 100644 --- a/app/views/homework_commons/works_list.json.jbuilder +++ b/app/views/homework_commons/works_list.json.jbuilder @@ -13,48 +13,55 @@ 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 + json.calculation_time @homework.calculation_time if @homework.homework_type == "practice" # 教师身份的评阅、提交状态、分班过滤 if @homework.homework_type != "practice" json.teacher_comment teacher_comment @homework, @current_user.id end - json.task_status homework_status @homework, @current_user.id + json.task_status homework_status @homework, @member json.course_group_info course_group_info @course, @current_user.id elsif @user_course_identity == Course::STUDENT - json.commit_count studentwork_count @homework, 1, @current_user.id - json.uncommit_count studentwork_count @homework, 0, @current_user.id + json.commit_count studentwork_count @homework, 1, @member + json.uncommit_count studentwork_count @homework, 0, @member json.left_time left_time @homework, @current_user.id if @homework.homework_type == "practice" - json.(@work, :id, :work_status, :update_time, :late_penalty, :ultimate_score) - - json.cost_time @work.myshixun.try(:total_cost_time) - json.work_score work_score_format(@work.work_score, true, @homework.score_open) - json.final_score work_score_format(@work.final_score, true, @homework.score_open) - json.efficiency work_score_format(@work.efficiency, true, @homework.score_open) - json.eff_score work_score_format(@work.eff_score, true, @homework.score_open) + json.(@work, :id, :work_status, :update_time, :ultimate_score) + json.calculation_time @work.calculation_time + json.late_penalty @work.late_penalty if @homework.allow_late + json.cost_time @work.myshixun.try(:total_spend_time) + json.work_score work_score_format(@work.work_score, true, @score_open) + json.final_score work_score_format(@work.final_score, true, @score_open) + json.efficiency work_score_format(@work.efficiency, true, @score_open) + json.eff_score work_score_format(@work.eff_score, true, @score_open) json.complete_count @work.myshixun.try(:passed_count) else - json.(@work, :id, :work_status, :update_time, :late_penalty, :absence_penalty, :appeal_penalty, :ultimate_score) + json.(@work, :id, :work_status, :update_time, :ultimate_score) - json.work_score work_score_format(@work.work_score, true, @homework.score_open) - json.final_score work_score_format(@work.final_score, true, @homework.score_open) - json.teacher_score work_score_format(@work.teacher_score, true, @homework.score_open) - json.student_score work_score_format(@work.student_score, true, @homework.score_open) - json.teaching_asistant_score work_score_format(@work.teaching_asistant_score, true, @homework.score_open) + json.work_score work_score_format(@work.work_score, true, @score_open) + json.final_score work_score_format(@work.final_score, true, @score_open) + json.teacher_score work_score_format(@work.teacher_score, true, @score_open) + json.student_score work_score_format(@work.student_score, true, @score_open) + json.teaching_asistant_score work_score_format(@work.teaching_asistant_score, true, @score_open) json.ta_comment_count @work.ta_comment_count + json.late_penalty @work.late_penalty if @homework.allow_late + if @homework.anonymous_comment json.student_comment_count @work.student_comment_num + json.absence_penalty @work.absence_penalty end if @homework.anonymous_appeal json.appeal_all_count @work.appeal_all_count json.appeal_deal_count @work.appeal_deal_count + json.appeal_penalty @work.appeal_penalty end if @homework.homework_type == "group" @@ -76,40 +83,47 @@ if @homework.homework_type == "practice" json.work_efficiency @homework.work_efficiency json.student_works @student_works.each do |work| - json.(work, :id, :work_status, :update_time, :late_penalty, :ultimate_score) + json.(work, :id, :work_status, :update_time, :ultimate_score) - json.work_score work_score_format(work.work_score, @current_user == work.user, @homework.score_open) - json.final_score work_score_format(work.final_score, @current_user == work.user, @homework.score_open) - json.efficiency work_score_format(work.efficiency, @current_user == work.user, @homework.score_open) - json.eff_score work_score_format(work.eff_score, @current_user == work.user, @homework.score_open) + json.late_penalty work.late_penalty if @homework.allow_late + json.work_score work_score_format(work.work_score, @current_user == work.user, @score_open) + json.final_score work_score_format(work.final_score, @current_user == work.user, @score_open) + json.efficiency work_score_format(work.efficiency, @current_user == work.user, @score_open) + json.eff_score work_score_format(work.eff_score, @current_user == work.user, @score_open) - json.cost_time work.myshixun.try(:total_cost_time) + json.cost_time work.myshixun.try(:total_spend_time) json.complete_count work.myshixun.try(:passed_count) json.user_login work.user.try(:login) json.user_name work.user.try(:real_name) json.student_id work.user.try(:student_id) - json.group_name @course.course_student(work.user_id).try(:course_group_name) + json.group_name @students.select{|student| student.user_id == work.user_id}.first.try(:course_group_name) end elsif @homework.homework_type == "group" || @homework.homework_type == "normal" json.anonymous_comment @homework.anonymous_comment json.anonymous_appeal @homework.anonymous_appeal json.student_works @student_works.each do |work| - if @is_evaluation json.(work, :id, :work_status, :update_time) json.student_score work_score_format(anon_comments(@current_user, work.id).last.try(:score), false, true) # json.student_comment_count anon_comments(@current_user, work.id).count + + # 申诉条数 + if @homework.anonymous_appeal + json.appeal_all_count work.my_appeal_all_count @current_user.id + json.appeal_deal_count work.my_appeal_deal_count @current_user.id + end else json.(work, :id, :work_status, :update_time, :work_score, :final_score, :teacher_score, :student_score, - :teaching_asistant_score, :late_penalty, :absence_penalty, :appeal_penalty, :ultimate_score) + :teaching_asistant_score, :ultimate_score) - json.work_score work_score_format(work.work_score, @current_user == work.user, @homework.score_open) - json.final_score work_score_format(work.final_score, @current_user == work.user, @homework.score_open) - json.teacher_score work_score_format(work.teacher_score, @current_user == work.user, @homework.score_open) - json.student_score work_score_format(work.student_score, @current_user == work.user, @homework.score_open) - json.teaching_asistant_score work_score_format(work.teaching_asistant_score, @current_user == work.user, @homework.score_open) + json.late_penalty work.late_penalty if @homework.allow_late + json.work_score work_score_format(work.work_score, @current_user == work.user, @score_open) + json.final_score work_score_format(work.final_score, @current_user == work.user, @score_open) + json.teacher_score work_score_format(work.teacher_score, @current_user == work.user, @score_open) + json.student_score work_score_format(work.student_score, @current_user == work.user, @score_open) + json.teaching_asistant_score work_score_format(work.teaching_asistant_score, @current_user == work.user, @score_open) # 助教评分次数 json.ta_comment_count work.ta_comment_count @@ -117,22 +131,24 @@ elsif @homework.homework_type == "group" || @homework.homework_type == "normal" # 作品匿评条数 if @homework.anonymous_comment json.student_comment_count @homework_detail_manual.comment_status > 2 ? work.student_comment_num : 0 + json.absence_penalty work.absence_penalty end json.student_id work.user.try(:student_id) - json.group_name @course.course_student(work.user_id).try(:course_group_name) + json.group_name @students.select{|student| student.user_id == work.user_id}.first.try(:course_group_name) if @homework.homework_type == "group" if @homework.homework_detail_group.base_on_project json.project_info project_info work, @current_user, @user_course_identity end json.work_group work.work_group_name end - end - # 申诉条数 - if @homework.anonymous_appeal - json.appeal_all_count work.appeal_all_count - json.appeal_deal_count work.appeal_deal_count + # 申诉条数 + if @homework.anonymous_appeal + json.appeal_all_count work.appeal_all_count + json.appeal_deal_count work.appeal_deal_count + json.appeal_penalty work.appeal_penalty + end end json.user_login @is_evaluation ? "--" : work.user.try(:login) diff --git a/app/views/homework_commons/works_list.xlsx.axlsx b/app/views/homework_commons/works_list.xlsx.axlsx index 3809c6264..aab3ac057 100644 --- a/app/views/homework_commons/works_list.xlsx.axlsx +++ b/app/views/homework_commons/works_list.xlsx.axlsx @@ -1,5 +1,6 @@ wb = xlsx_package.workbook +# wb.use_autowidth = false wb.styles do |s| sz_all = s.add_style :border => { :style => :thin, :color =>"000000" },:alignment => {:horizontal => :center} blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 20,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {:horizontal => :center} @@ -8,7 +9,7 @@ wb.styles do |s| sheet.add_row table_columns, :style => blue_cell if task_users.count > 0 task_users.each do |user| - sheet.add_row user, :style => sz_all + sheet.add_row user, :height => 20,:style => sz_all end #each_widh_index end sheet.column_widths *([20]*sheet.column_info.count) diff --git a/app/views/messages/_message.json.jbuilder b/app/views/messages/_message.json.jbuilder index bff2413cd..c3ab6c6e3 100644 --- a/app/views/messages/_message.json.jbuilder +++ b/app/views/messages/_message.json.jbuilder @@ -1 +1,2 @@ -json.extract! message, :id, :parent_id, :subject, :created_on, :total_replies_count, :total_praises_count, :praises_count, :visits, :sticky, :is_hidden, :is_public +json.extract! message, :id, :parent_id, :subject, :created_on, :total_replies_count, :total_praises_count, + :is_md, :praises_count, :visits, :sticky, :is_hidden, :is_public diff --git a/app/views/messages/index.json.jbuilder b/app/views/messages/index.json.jbuilder index 026e193a6..3470ed485 100644 --- a/app/views/messages/index.json.jbuilder +++ b/app/views/messages/index.json.jbuilder @@ -6,7 +6,12 @@ json.data do json.total_count @messages.total_count json.messages do json.array! @messages do |message| - json.partial! "messages/message", message: message + json.extract! message, :id, :parent_id, :subject, :created_on, :total_replies_count, + :praises_count, :visits, :sticky, :is_hidden, :is_public + + json.total_praises_count @praises_count_map.fetch(message.id, 0) + + #json.partial! "messages/message", message: message json.author do json.partial! "users/user_simple", user: message.author end diff --git a/app/views/messages/reply_list.json.jbuilder b/app/views/messages/reply_list.json.jbuilder index 2b7ef7178..b5c1ce256 100644 --- a/app/views/messages/reply_list.json.jbuilder +++ b/app/views/messages/reply_list.json.jbuilder @@ -1,6 +1,6 @@ json.partial! "commons/success" json.data do - json.user_course_identity @current_user.course_identity(@message.board.course) + json.user_course_identity @user_course_identity json.id @message.id json.total_count @messages.total_count json.total_replies_count @message.total_replies_count diff --git a/app/views/myshixuns/update_file.json.jbuilder b/app/views/myshixuns/update_file.json.jbuilder index c647927c4..f15b07cf8 100644 --- a/app/views/myshixuns/update_file.json.jbuilder +++ b/app/views/myshixuns/update_file.json.jbuilder @@ -1,3 +1,4 @@ json.content @content json.resubmit "#{@resubmit}" -json.content_modified @hide_code ? false : @content_modified +json.sec_key "#{@sec_key}" +json.content_modified @hide_code ? 0 : @content_modified diff --git a/app/views/polls/commit_result.xlsx.axlsx b/app/views/polls/commit_result.xlsx.axlsx index ce1817f76..4391e0e8f 100644 --- a/app/views/polls/commit_result.xlsx.axlsx +++ b/app/views/polls/commit_result.xlsx.axlsx @@ -1,96 +1,39 @@ wb = xlsx_package.workbook -wb.use_autowidth = false +# wb.use_autowidth = false wb.styles do |s| - sz_all = s.add_style :sz => 10,:border => { :style => :thin, :color =>"000000"},:alignment => {:horizontal => :left} - blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 20,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {:horizontal => :left} + sz_all = s.add_style :sz => 10,:border => { :style => :thin, :color =>"000000"},:alignment => {wrap_text: true,:horizontal => :left} + blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 20,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :left} wb.add_worksheet(:name => "统计结果") do |sheet| 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?} + sub_commit = polls_user_commit[:sub_commit] + poll_user_info = polls_user_commit[:poll_users_info] + user_commit = polls_user_commit[:user_commit] - poll_ques_ids = poll_questions.pluck(:id).sort #问题的全部id - 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).count #该问题的有效填写量 - 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).count - 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) + if sub_commit&.size > 0 + sub_commit.each do |sub| + main_sub_title = sub[:sub_title] + main_sub_content = sub[:sub_user_votes] + sheet.add_row main_sub_title,:height =>15, :style => blue_cell + 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 sheet_row, :style => blue_cell - sheet.add_row sheet_answer_row, :style => sz_all - sheet.add_row sheet_answer_percent, :style => sz_all - sheet.add_row sheet_answer_useful, :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, :style => blue_cell - q.poll_votes.each do |v| #主观题的答案 - sheet.add_row ["",v.vote_text.present? ? v.vote_text : "--"], :style => sz_all - end - sheet.add_row [], :style => sz_all end - end #each_with_index + end - sheet.add_row poll_users_info, :style => blue_cell - @poll.poll_users.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] + sheet.add_row poll_user_info, :height =>15, :style => blue_cell + + if user_commit&.size > 0 + user_commit.each do |com| + sheet.add_row com, :height =>15,:style => sz_all end - all_user_cell = user_cell + user_answer_array - sheet.add_row all_user_cell, :style => sz_all end sheet.column_widths *([25]*sheet.column_info.count) - sheet.column_info.first.width = 10 + sheet.column_info.first.width = 15 + end #add_worksheet -end \ No newline at end of file +end diff --git a/app/views/polls/common_header.json.jbuilder b/app/views/polls/common_header.json.jbuilder index 39c4ef811..b0a3d7374 100644 --- a/app/views/polls/common_header.json.jbuilder +++ b/app/views/polls/common_header.json.jbuilder @@ -1,5 +1,6 @@ json.course_is_end @course.is_end # true表示已结束,false表示未结束 -json.extract! @poll, :id,:polls_name,:polls_description,:polls_status,:show_result +json.extract! @poll, :id,:polls_name,:polls_description,:show_result +json.polls_status @poll_status json.user_permission do json.is_teacher_or @is_teacher_or diff --git a/app/views/polls/index.json.jbuilder b/app/views/polls/index.json.jbuilder index b657da7a0..0face0966 100644 --- a/app/views/polls/index.json.jbuilder +++ b/app/views/polls/index.json.jbuilder @@ -1,18 +1,4 @@ - json.polls_counts do - json.polls_total_counts @polls_count #全部问卷数 - json.polls_all_counts @polls_select_count #选择后的问卷数 - json.polls_unpublish_counts @polls_unpublish_counts #未发布问卷数 - json.polls_published_counts @polls_published_counts #已发布问卷数 - # json.polls_ended_counts @polls_ended_counts #已截止问卷数 - json.left_banner_id @left_banner_id - json.left_banner_name @left_banner_name -end -json.course_types do - json.course_status @course_status # 课堂的当前是否结束,如结束,则为1,否则为0 - json.course_is_public @course_is_public #判断课堂是否为公开,只有公开课才有设为公开的按钮 - json.user_permission @is_teacher_or # 当前用户存在且为课堂教师/管理员/超级管理员时为1 ,课堂成员为2,否则为0 -end if @polls_count > 0 json.polls do @@ -32,3 +18,17 @@ else json.polls [] end +json.polls_counts do + json.polls_total_counts @polls_count #全部问卷数 + json.polls_all_counts @polls_select_count #选择后的问卷数 + json.polls_unpublish_counts @polls_unpublish_counts #未发布问卷数 + json.polls_published_counts @polls_published_counts #已发布问卷数 + json.left_banner_id @left_banner_id + json.left_banner_name @left_banner_name +end + +json.course_types do + json.course_status @course_status # 课堂的当前是否结束,如结束,则为1,否则为0 + json.course_is_public @course_is_public #判断课堂是否为公开,只有公开课才有设为公开的按钮 + json.user_permission @is_teacher_or # 当前用户存在且为课堂教师/管理员/超级管理员时为1 ,课堂成员为2,否则为0 +end diff --git a/app/views/polls/poll_lists.json.jbuilder b/app/views/polls/poll_lists.json.jbuilder index fef129599..1ebccffeb 100644 --- a/app/views/polls/poll_lists.json.jbuilder +++ b/app/views/polls/poll_lists.json.jbuilder @@ -1,7 +1,6 @@ json.course do json.partial! "polls/course_name",locals:{course:@course} end - json.poll_types do if @poll_current_user_status == 0 json.published_count @poll_publish_count @@ -16,6 +15,7 @@ json.poll_types do json.user_permission @poll_current_user_status #当前用户存在且为课堂教师/管理员/超级管理员时为0 ,其他否则为1 json.poll_id @poll.id json.poll_end_time @poll.end_time + json.groups_count @poll_group_counts end if @poll_current_user_status == 0 diff --git a/app/views/schools/school_list.json.jbuilder b/app/views/schools/school_list.json.jbuilder deleted file mode 100644 index 1e2c89897..000000000 --- a/app/views/schools/school_list.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.shools_name @schools \ No newline at end of file diff --git a/app/views/searchs/index.json.jbuilder b/app/views/searchs/index.json.jbuilder new file mode 100644 index 000000000..5fa0c2744 --- /dev/null +++ b/app/views/searchs/index.json.jbuilder @@ -0,0 +1,11 @@ +json.count @results.total_count +json.results do + json.array! @results.with_highlights(multiple: true) do |obj, highlights| + json.merge! obj.to_searchable_json + json.type obj.class.name.downcase + + json.title highlights.delete(:name)&.join('...') || obj.searchable_title + # json.description highlights.values[0,5].each { |arr| arr.is_a?(Array) ? arr.join('...') : arr }.join('
') + json.content highlights + end +end \ No newline at end of file diff --git a/app/views/shixuns/_commit.json.jbuilder b/app/views/shixuns/_commit.json.jbuilder index cd934baea..f6587c261 100644 --- a/app/views/shixuns/_commit.json.jbuilder +++ b/app/views/shixuns/_commit.json.jbuilder @@ -14,8 +14,9 @@ json.commits commits do |commit| json.author do json.id nil json.login nil + json.image_url "avatars/User/b" json.name commit["author_name"] - json.email commit["author_email"] + # json.email commit["author_email"] end end end diff --git a/app/views/shixuns/_shixun.json.jbuilder b/app/views/shixuns/_shixun.json.jbuilder index 6913c4745..e6dbd3115 100644 --- a/app/views/shixuns/_shixun.json.jbuilder +++ b/app/views/shixuns/_shixun.json.jbuilder @@ -13,9 +13,9 @@ json.array! shixuns do |shixun| json.identifier shixun.identifier json.name shixun.name json.status shixun.status - json.power (User.current.shixun_permission(shixun)) # 现在首页只显示已发布的实训 + json.power (current_user.shixun_permission(shixun)) # 现在首页只显示已发布的实训 # REDO: 局部缓存 - json.tag_name shixun.tag_repertoires.first.try(:name) + json.tag_name @tag_name_map&.fetch(shixun.id, nil) || shixun.tag_repertoires.first.try(:name) json.myshixuns_count shixun.myshixuns_count json.stu_num shixun.myshixuns_count json.score_info shixun.averge_star diff --git a/app/views/shixuns/_top.json.jbuilder b/app/views/shixuns/_top.json.jbuilder index 7c006cccf..ebb77ec74 100644 --- a/app/views/shixuns/_top.json.jbuilder +++ b/app/views/shixuns/_top.json.jbuilder @@ -1,4 +1,4 @@ -json.status shixun.status +json.shixun_status shixun.status # REDO:前端需要通过status来判断发布 json.task_operation task_operation_url(current_myshixun, shixun) @@ -13,7 +13,6 @@ json.name shixun.name json.stu_num shixun.myshixuns_count json.experience shixun.all_score json.diffcult diff_to_s(shixun.trainee) -json.score_info shixun.averge_star +json.score_info shixun.shixun_preference_info # todo: 这块可以改成只显示实训的平均分,不用每次都去取每种星的分数了。 # 用于是否显示导航栏中的'背景知识' -json.propaedeutics shixun.propaedeutics.present? ? true : false - +json.propaedeutics shixun.propaedeutics.present? diff --git a/app/views/shixuns/add_collaborators.json.jbuilder b/app/views/shixuns/add_collaborators.json.jbuilder index ab4716681..d20f0b318 100644 --- a/app/views/shixuns/add_collaborators.json.jbuilder +++ b/app/views/shixuns/add_collaborators.json.jbuilder @@ -1,7 +1,11 @@ #json.partial! "users/users_list", users: @users -json.array! @users do |user| - json.user_id user.id - json.identify user.identity - json.nickname user.nickname - json.school_name user.school_name -end \ No newline at end of file +json.user_count @user_count +json.users do + json.array! @users do |user| + json.user_id user.id + json.identify user.identity + json.nickname user.real_name + json.school_name user.school_name + end + +end diff --git a/app/views/shixuns/collaborators.json.jbuilder b/app/views/shixuns/collaborators.json.jbuilder index bd880c93e..0101f1e59 100644 --- a/app/views/shixuns/collaborators.json.jbuilder +++ b/app/views/shixuns/collaborators.json.jbuilder @@ -10,7 +10,7 @@ json.array! @members do |member| json.user do json.partial! 'users/user', locals: { user: member.user } json.user_shixuns_count member.user.shixuns.published.count - #json.fans_count member.user.followers.count + #json.fans_count member.user.fan_count json.brief_introduction member.user.user_extension.brief_introduction json.identity member.user.identity json.school_name member.user.school_name diff --git a/app/views/shixuns/index.json.jbuilder b/app/views/shixuns/index.json.jbuilder index 41da7120f..8e5d49a34 100644 --- a/app/views/shixuns/index.json.jbuilder +++ b/app/views/shixuns/index.json.jbuilder @@ -1,7 +1,8 @@ -if @fuzzy_searchs - json.keyword @fuzzy_searchs - json.total_count @fuzzy_searchs.blank? ? nil : @total_count -end +# if @fuzzy_searchs +# json.keyword @fuzzy_searchs +# json.total_count @fuzzy_searchs.blank? ? nil : @total_count +# end +json.total_count @total_count json.pagination @total_count > 16 ? true : false json.search_tags @search_tags json.shixuns do diff --git a/app/views/shixuns/send_to_course.json.jbuilder b/app/views/shixuns/send_to_course.json.jbuilder index dd087d3e2..b2e30f985 100644 --- a/app/views/shixuns/send_to_course.json.jbuilder +++ b/app/views/shixuns/send_to_course.json.jbuilder @@ -1,4 +1,3 @@ json.status 1 json.message "发送成功" -json.url course_homework_commons_path(@course.id, type: 4) -# json.url "#{Rails::configuration.educoder['old_edu_host']}/homework_common?course=#{@course.id}&homework_type=4" \ No newline at end of file +json.course_id @course.id \ No newline at end of file diff --git a/app/views/shixuns/settings.json.jbuilder b/app/views/shixuns/settings.json.jbuilder index e97331388..e81498058 100644 --- a/app/views/shixuns/settings.json.jbuilder +++ b/app/views/shixuns/settings.json.jbuilder @@ -22,13 +22,21 @@ json.shixun do json.hide_code @shixun.hide_code # 隐藏代码窗口 json.code_hidden @shixun.code_hidden # 代码目录隐藏 json.vnc @shixun.vnc - json.exec_time @shixun.exec_time + #json.exec_time @shixun.exec_time json.webssh @shixun.webssh json.multi_webssh @shixun.multi_webssh json.use_scope @shixun.use_scope json.scope_partment @shixun.schools.map(&:name) # 公开范围 json.opening_time @shixun.opening_time json.forbid_copy @shixun.forbid_copy + + # 实训服务配置 + json.shixun_service_configs do + json.array! @configs do |config| + json.name config.mirror_repository&.name + json.(config, :cpu_limit, :lower_cpu_limit, :memory_limit, :request_limit, :mirror_repository_id) + end + end end diff --git a/app/views/shixuns/show_right.json.jbuilder b/app/views/shixuns/show_right.json.jbuilder index 8f4679a37..fe3c5d0f5 100644 --- a/app/views/shixuns/show_right.json.jbuilder +++ b/app/views/shixuns/show_right.json.jbuilder @@ -1,6 +1,6 @@ json.partial! 'shixuns/right', locals: { shixun: @shixun } -#json.follow follow?(@shixun.owner, User.current) -#json.fans_count @fans_count -#json.followed_count @followed_count +json.follow follow?(@shixun.owner, User.current) +json.fans_count @fans_count +json.followed_count @followed_count json.user_shixuns_count @user_own_shixuns diff --git a/app/views/student_works/adjust_review_score.json.jbuilder b/app/views/student_works/adjust_review_score.json.jbuilder index e69de29bb..928806bd6 100644 --- a/app/views/student_works/adjust_review_score.json.jbuilder +++ b/app/views/student_works/adjust_review_score.json.jbuilder @@ -0,0 +1,4 @@ +json.status 0 +json.message "调分成功" +json.work_score number_with_precision @work.work_score, 1 +json.challenge_score number_with_precision @work.final_score, 1 \ No newline at end of file diff --git a/app/views/student_works/shixun_work.json.jbuilder b/app/views/student_works/shixun_work.json.jbuilder index 3b6b598cb..39e7eb1b3 100644 --- a/app/views/student_works/shixun_work.json.jbuilder +++ b/app/views/student_works/shixun_work.json.jbuilder @@ -15,13 +15,14 @@ json.efficiency number_with_precision @work.efficiency, precision: 2 json.max_efficiency number_with_precision @homework.max_efficiency, precision: 2 json.passed_time @myshixun.passed_time json.total_spend_time @myshixun.total_spend_time +json.user_score @myshixun.total_score # 关卡完成情况 index = 1 json.game_list @myshixun.games do |game| json.position index json.end_time game.end_time ? game.end_time : '--' - json.cost_time game.cost_time + json.cost_time (game_spend_time game.cost_time) json.score game.final_score json.complete_status game_status(game, @homework) index += 1 diff --git a/app/views/student_works/shixun_work_report.json.jbuilder b/app/views/student_works/shixun_work_report.json.jbuilder index 1c6ed5899..e24092f05 100644 --- a/app/views/student_works/shixun_work_report.json.jbuilder +++ b/app/views/student_works/shixun_work_report.json.jbuilder @@ -1,6 +1,7 @@ json.homework_common_id @homework.id json.category @homework.category_info json.course_name @course.name +json.work_id @work.id if @shixun json.shixun_name @shixun.name # 总体评价 @@ -8,9 +9,15 @@ if @shixun json.myself_experience @work.myshixun.try(:total_score) json.total_experience @shixun.all_score json.work_score number_with_precision @work.work_score, precision: 1 - json.all_work_score 100 + json.all_work_score number_with_precision 100, precision: 1 json.time_consuming @work.myshixun_consume json.evaluate_count @user_evaluate_count.to_i + if @homework.work_efficiency + json.eff_score_full number_with_precision @homework.eff_score, precision: 1 + json.eff_score number_with_precision @work.eff_score, precision: 1 + json.challenge_score_full number_with_precision (100 - @homework.eff_score), precision: 1 + json.challenge_score number_with_precision @work.final_score, precision: 1 + end # 阶段成绩 json.stage_list do @@ -24,6 +31,10 @@ if @shixun json.myself_experience game.final_score json.experience game.challenge.all_score json.complete_status game_status(game, @homework) + json.challenge_id game.challenge_id + challenge_score = @homework.challenge_score game.challenge_id + json.game_score_full challenge_score + json.game_score @work.work_challenge_score game, challenge_score end end diff --git a/app/views/user_mailer/register_email.html.erb b/app/views/user_mailer/register_email.html.erb index 24ae606b7..6f88177c5 100644 --- a/app/views/user_mailer/register_email.html.erb +++ b/app/views/user_mailer/register_email.html.erb @@ -28,7 +28,7 @@
diff --git a/app/views/users/_user.json.jbuilder b/app/views/users/_user.json.jbuilder index 1d26506f3..581072072 100644 --- a/app/views/users/_user.json.jbuilder +++ b/app/views/users/_user.json.jbuilder @@ -2,7 +2,7 @@ json.user_id user.id json.login user.login json.name user.full_name json.grade user.grade +json.identity user&.user_extension&.identity # json.email user.mail # 邮箱原则上不暴露的,如果实在需要的话只能对某些具体的接口公开 json.image_url url_to_avatar(user) -json.user_url user_path(user) json.school user.school_name \ No newline at end of file diff --git a/app/views/users/accounts/show.json.jbuilder b/app/views/users/accounts/show.json.jbuilder index fca883ea0..6b28bda55 100644 --- a/app/views/users/accounts/show.json.jbuilder +++ b/app/views/users/accounts/show.json.jbuilder @@ -21,5 +21,5 @@ json.school_name extension&.school&.name json.department_id extension&.department_id json.department_name extension&.department&.name -json.base_info_completed user.base_info_completed? +json.base_info_completed user.profile_completed? json.all_certified user.all_certified? diff --git a/app/views/users/courses/shared/_course.json.jbuilder b/app/views/users/courses/shared/_course.json.jbuilder index e5823212e..e917033da 100644 --- a/app/views/users/courses/shared/_course.json.jbuilder +++ b/app/views/users/courses/shared/_course.json.jbuilder @@ -1,10 +1,12 @@ json.id course.id json.name course.name -json.members_count course.members_count -json.homework_commons_count course.homework_commons_count +# json.members_count course.members_count +json.members_count course.course_members_count +# json.homework_commons_count course.homework_commons_count +json.homework_commons_count get_tasks_count course json.attachments_count course.attachments.count -json.first_category_url module_url(course.course_modules.where.not(module_type: "activity").where(hidden: 0).order(position: :desc).first, course) +json.first_category_url module_url(course.course_modules.where(hidden: 0).order(position: :desc).first, course) json.is_public course.is_public json.can_visited observed_logged_user? || course.can_visited? diff --git a/app/views/users/get_navigation_info.json.jbuilder b/app/views/users/get_navigation_info.json.jbuilder index 57a303cb6..96f54d3d0 100644 --- a/app/views/users/get_navigation_info.json.jbuilder +++ b/app/views/users/get_navigation_info.json.jbuilder @@ -10,9 +10,12 @@ json.top do json.new_project_url "#{@old_domain}/projects/new" json.join_course_url "#{@old_domain}/courses/join_course_multi_role" json.join_project_url "#{@old_domain}/applied_project/applied_project_info" - json.message_url "#{@user_url}/user_tidings" + json.message_url "#{@old_domain}#{@user_url}/user_tidings" json.new_message @new_message + json.moop_cases_url "#{@old_domain}/moop_cases" + json.crowdsourcing_url "#{@old_domain}/crowdsourcing" + json.career_url do json.array! @career.to_a do |c| if c[1].present? @@ -30,6 +33,7 @@ json.top do json.my_project_url "#{@user_url}?type=a_project" json.account_manager_url "#{@old_domain}/my/account" json.logout_url logout_accounts_path + json.college_identifier @user.college_identifier # 旧版的域名 json.old_url @old_domain end diff --git a/app/views/users/get_user_info.json.jbuilder b/app/views/users/get_user_info.json.jbuilder index 779d58e95..fbb9778e2 100644 --- a/app/views/users/get_user_info.json.jbuilder +++ b/app/views/users/get_user_info.json.jbuilder @@ -4,6 +4,7 @@ json.user_id @user.id json.image_url url_to_avatar(@user) json.admin @user.admin? json.is_teacher @user.user_extension&.teacher? +json.user_identity @user.identity json.tidding_count 0 json.user_phone_binded @user.phone.present? if @course diff --git a/app/views/users/homepage_info.json.jbuilder b/app/views/users/homepage_info.json.jbuilder index 3f985eab9..1621448f3 100644 --- a/app/views/users/homepage_info.json.jbuilder +++ b/app/views/users/homepage_info.json.jbuilder @@ -1,5 +1,5 @@ json.id @user.id -json.name @user.homepage_name +json.name @user.full_name json.avatar_url url_to_avatar(@user) json.is_logged_user @user.logged_user? json.experience @user.experience diff --git a/app/views/users/html_show.html.erb b/app/views/users/html_show.html.erb new file mode 100644 index 000000000..0fb51d1b8 --- /dev/null +++ b/app/views/users/html_show.html.erb @@ -0,0 +1 @@ +<%= @contents.html_safe %> \ No newline at end of file diff --git a/app/views/users/reply_message.json.jbuilder b/app/views/users/reply_message.json.jbuilder deleted file mode 100644 index 26052baa8..000000000 --- a/app/views/users/reply_message.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.id @message.id \ No newline at end of file diff --git a/app/views/users/shixuns/shared/_shixun.json.jbuilder b/app/views/users/shixuns/shared/_shixun.json.jbuilder index 13cc3a9ee..8427ead58 100644 --- a/app/views/users/shixuns/shared/_shixun.json.jbuilder +++ b/app/views/users/shixuns/shared/_shixun.json.jbuilder @@ -6,4 +6,4 @@ json.name shixun.name json.status shixun.status json.human_status shixun.human_status json.challenges_count shixun.challenges_count -json.finished_challenges_count shixun.finished_challenges_count(user) \ No newline at end of file +json.finished_challenges_count @finished_challenges_count_map&.fetch(shixun.id, 0) || shixun.finished_challenges_count(user) \ No newline at end of file diff --git a/config/application.rb b/config/application.rb index 8f1d3aebf..baa0011f2 100644 --- a/config/application.rb +++ b/config/application.rb @@ -17,7 +17,7 @@ module Educoderplus # the framework and any gems in your application. # # - config.educoder = config_for(:configuration) + # config.educoder = config_for(:configuration) config.active_record.default_timezone = :local config.time_zone = 'Beijing' diff --git a/config/environments/development.rb.example b/config/environments/development.rb.example new file mode 100644 index 000000000..0b31f5828 --- /dev/null +++ b/config/environments/development.rb.example @@ -0,0 +1,76 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + + config.cache_store = :file_store, "#{Rails.root }/files/cache_store/" + + # if Rails.root.join('tmp', 'caching-dev.txt').exist? + # config.action_controller.perform_caching = true + # + # config.cache_store = :memory_store + # config.public_file_server.headers = { + # 'Cache-Control' => "public, max-age=#{2.days.to_i}" + # } + # else + # config.action_controller.perform_caching = false + # + # config.cache_store = :null_store + # end + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + config.file_watcher = ActiveSupport::EventedFileUpdateChecker + + config.action_controller.perform_caching = true + + config.action_mailer.delivery_method = :smtp + config.action_mailer.smtp_settings = { + address: 'smtp.exmail.qq.com', + port: 25, + domain: 'smtp.qq.com', + user_name: 'educoder@trustie.org', + password: 'mAZc9EWbe2Kawaqo2', + authentication: 'login', + enable_starttls_auto: true } +end diff --git a/config/environments/production.rb b/config/environments/production.rb.example similarity index 95% rename from config/environments/production.rb rename to config/environments/production.rb.example index 38938b7e3..be2bdf3d7 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb.example @@ -96,6 +96,7 @@ Rails.application.configure do config.active_record.belongs_to_required_by_default = false # config.cache_store = :file_store, "#{Rails.root }/files/cache_store/" + #config.cache_store = :redis_store, 'redis://r-bp122bd1b710f274.redis.rds.aliyuncs.com:6379/0/cache', { expires_in: 90.minutes } config.cache_store = :redis_store, 'redis://10.9.72.102:6379/0/cache', { expires_in: 90.minutes } config.action_mailer.delivery_method = :smtp diff --git a/config/initializers/elasticsearch.rb b/config/initializers/elasticsearch.rb new file mode 100644 index 000000000..5ab7d3e62 --- /dev/null +++ b/config/initializers/elasticsearch.rb @@ -0,0 +1,2 @@ +redis_config = Rails.application.config_for(:elasticsearch) +ENV['ELASTICSEARCH_URL'] = redis_config['url'] diff --git a/config/initializers/pdfkit.rb b/config/initializers/pdfkit.rb index 168fc0c1e..0cd80c9c7 100644 --- a/config/initializers/pdfkit.rb +++ b/config/initializers/pdfkit.rb @@ -1,11 +1,14 @@ PDFKit.configure do |config| config.wkhtmltopdf = ENV["WKHTMLTOPDF_EXEC"] || 'wkhtmltopdf' + # config.wkhtmltopdf = ENV["WKHTMLTOPDF_EXEC"] || '/usr/bin/wkhtmltopdf' config.default_options = { + encoding: "UTF-8", page_size: 'A4', print_media_type: true, dpi: 300, debug_javascript: true, javascript_delay: 500, + # quiet: false stop_slow_scripts:false, no_stop_slow_scripts: true } diff --git a/config/locales/competitions/zh-CN.yml b/config/locales/competitions/zh-CN.yml new file mode 100644 index 000000000..9c3ff2f1e --- /dev/null +++ b/config/locales/competitions/zh-CN.yml @@ -0,0 +1,8 @@ +'zh-CN': + activerecord: + models: + competition_module_md_content: '' + attributes: + competition_module_md_content: + name: '标题' + content: '内容' diff --git a/config/locales/en.yml b/config/locales/en.yml index bb1bb3934..257c83750 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,4 +1,5 @@ en: error: record_not_found: Record not found - forbidden: Forbidden \ No newline at end of file + forbidden: Forbidden + unauthorized: Unauthorized \ No newline at end of file diff --git a/config/locales/forms/add_school_apply_form.zh-CN.yml b/config/locales/forms/add_school_apply_form.zh-CN.yml new file mode 100644 index 000000000..749578164 --- /dev/null +++ b/config/locales/forms/add_school_apply_form.zh-CN.yml @@ -0,0 +1,8 @@ +'zh-CN': + activemodel: + attributes: + add_school_apply_form: + name: 名称 + province: 省份 + city: 城市 + address: 详细地址 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/locales/forms/save_team_form.zh-CN.yml b/config/locales/forms/save_team_form.zh-CN.yml new file mode 100644 index 000000000..106527687 --- /dev/null +++ b/config/locales/forms/save_team_form.zh-CN.yml @@ -0,0 +1,25 @@ +'zh-CN': + activemodel: + attributes: + competitions/save_team_form: + competition: '' + name: '战队名称' + creator: '' + teacher_ids: '' + member_ids: '' + errors: + models: + competitions/save_team_form: + attributes: + creator: + teacher_enroll_forbidden: "本竞赛的参赛者限定为:学生" + member_enroll_forbidden: "本竞赛的参赛者限定为:教师" + teacher_ids: + enroll_forbidden: "本竞赛的参赛者限定为:学生" + invalid_count: "教师数量应为%{minimum}~%{maximum}人" + enrolled: "教师 ${names} 已加入其它战队了" + member_ids: + enroll_forbidden: "本竞赛的参赛者限定为:教师" + invalid_count: "队员数量应为%{minimum}~%{maximum}人" + enrolled: "队员 ${names} 已加入其它战队了" + diff --git a/config/locales/shixuns/en.yml b/config/locales/shixuns/en.yml index 0f1a9f695..10de1eaef 100644 --- a/config/locales/shixuns/en.yml +++ b/config/locales/shixuns/en.yml @@ -1,7 +1,7 @@ 'en': shixun: status: - 0: editing - 1: applying - 2: published - 3: closed + '0': editing + '1': applying + '2': published + '3': closed diff --git a/config/locales/shixuns/zh-CN.yml b/config/locales/shixuns/zh-CN.yml index c5ba574d8..d7ad5f7e2 100644 --- a/config/locales/shixuns/zh-CN.yml +++ b/config/locales/shixuns/zh-CN.yml @@ -1,7 +1,7 @@ 'zh-CN': shixun: status: - 0: 编辑中 - 1: 审核中 - 2: 已发布 - 3: 已关闭 + '0': 编辑中 + '1': 审核中 + '2': 已发布 + '3': 已关闭 diff --git a/config/locales/users/zh-CN.yml b/config/locales/users/zh-CN.yml index 5c4ad76a7..48b8ca075 100644 --- a/config/locales/users/zh-CN.yml +++ b/config/locales/users/zh-CN.yml @@ -1,4 +1,11 @@ 'zh-CN': + activerecord: + models: + user: '用户' + attributes: + user: + phone: '手机号' + mail: '邮箱' user: identity: teacher: 教师 diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 99d5ac843..71cdb02e9 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -1,4 +1,5 @@ 'zh-CN': error: record_not_found: 您访问的页面不存在或已被删除 - forbidden: 您没有权限进行该操作 \ No newline at end of file + forbidden: 您没有权限进行该操作 + unauthorized: 未登录 \ No newline at end of file diff --git a/config/redis.yml b/config/redis.yml deleted file mode 100644 index 71e61cfd9..000000000 --- a/config/redis.yml +++ /dev/null @@ -1,12 +0,0 @@ -defaults: &defaults - url: <%= ENV["REDIS_URL"] || "redis://localhost:6379/0" %> - -development: - <<: *defaults - -test: - <<: *defaults - -production: - <<: *defaults - url: redis://10.9.72.102:6379/0/job \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index e7fac7331..cabdcb18e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,10 +1,16 @@ Rails.application.routes.draw do + require 'sidekiq/web' + require 'admin_constraint' + mount Sidekiq::Web => '/sidekiq', :constraints => AdminConstraint.new + resources :edu_settings scope '/api' do get 'home/index' get 'home/search' + get 'search', to: 'searchs#index' + post 'praise_tread/like', to: 'praise_tread#like' delete 'praise_tread/unlike', to: 'praise_tread#unlike' @@ -52,6 +58,7 @@ Rails.application.routes.draw do post :unfollow get :get_user_info get :attachment_show + get :html_show get :get_navigation_info post :reply_message get :search_user_projects @@ -66,11 +73,16 @@ Rails.application.routes.draw do resources :tidings, only: [:index] scope module: :users do + resource :interest, only: [:create] + resources :accounts, only: [:show, :update] do resource :phone_bind, only: [:create] resource :email_bind, only: [:create] resource :password, only: [:update] resource :avatar, only: [:update] + resource :auth_attachment, only: [:create] + resource :authentication_apply, only: [:create] + resource :professional_auth_apply, only: [:create] end end end @@ -117,6 +129,9 @@ Rails.application.routes.draw do get :close_webssh get :get_answer_info get :unlock_answer + get :check_test_sets + get :unlock_choose_answer + get :get_choose_answer end collection do @@ -252,6 +267,7 @@ Rails.application.routes.draw do get :mine_with_course_and_project post :import post :upload + put :bulk_publish end member do get :histories @@ -283,6 +299,7 @@ Rails.application.routes.draw do get 'course_group_list' get 'add_teacher_popup' get 'teachers' + get 'apply_teachers' get 'graduation_group_list' get 'top_banner' get 'left_banner' @@ -303,6 +320,7 @@ Rails.application.routes.draw do post 'search_course_list' get 'board_list' get 'mine' + get 'search_slim' end resources :polls, only:[:index,:new,:create] do @@ -336,6 +354,8 @@ Rails.application.routes.draw do get :publish_groups get :end_groups post :alter_name + get :update_score + get :update_student_score end collection do @@ -572,9 +592,13 @@ Rails.application.routes.draw do resources :schools do member do + resources :departments, only: [] do + get :for_option, on: :collection + end end collection do - get "school_list" + get :school_list + get :for_option end scope module: :ecs do @@ -584,6 +608,8 @@ Rails.application.routes.draw do resources :ec_major_schools, only: [:index, :create, :destroy] end end + resources :add_school_applies, only: [:create] + resources :add_department_applies, only: [:create] # 为避免url过长以及层级过深,路由定义和controller继承都做了处理 scope module: :ecs do @@ -641,6 +667,21 @@ Rails.application.routes.draw do get :export_exercises end end + + resources :repertoires, only: [:index] + + scope module: :competitions do + resources :competitions, only: [:index, :show] do + resources :competition_modules, only: [:index, :show, :update] + resource :competition_staff + resources :competition_teams, only: [:index, :show] do + post :join, on: :collection + post :leave, on: :member + end + resources :teachers, only: [:index] + resources :students, only: [:index] + end + end end #git 认证回调 diff --git a/config/sidekiq.yml b/config/sidekiq.yml index a2b3fc0be..1c7a4e2cd 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -3,4 +3,5 @@ :logfile: log/sidekiq.log :queues: - [default, 3] + - [searchkick, 10] - [notify, 100] \ No newline at end of file diff --git a/db/migrate/20190309085449_migrate_course_members.rb b/db/migrate/20190309085449_migrate_course_members.rb index ef8741bfb..a6d049dd7 100644 --- a/db/migrate/20190309085449_migrate_course_members.rb +++ b/db/migrate/20190309085449_migrate_course_members.rb @@ -1,10 +1,10 @@ class MigrateCourseMembers < ActiveRecord::Migration[5.2] def change - add_column :course_groups, :position, :integer, default: 0 + # add_column :course_groups, :position, :integer, default: 0 Course.find_each do |course| position = 1 - course.course_groups.reorder("CONVERT(course_groups.name USING gbk) COLLATE gbk_chinese_ci ASC").find_each do |group| + course.course_groups.reorder("CONVERT(course_groups.name USING gbk) COLLATE gbk_chinese_ci ASC").each do |group| group.update_attribute(:position, position) position += 1 end @@ -19,15 +19,13 @@ class MigrateCourseMembers < ActiveRecord::Migration[5.2] ActiveRecord::Base.transaction do begin - Member.where("course_id != -1").find_each do |member| - if member.course && member.user - puts(member.course_id) - member.member_roles.each do |role| - course_member_role = role.role_id == 3 ? 1 : (role.role_id == 9 ? 2 : (role.role_id == 7 ? 3 : 4)) - member_group_id = role.role_id == 10 ? member.course_group_id : 0 - CourseMember.create!(course_id: member.course_id, user_id: member.user_id, course_group_id: member_group_id.to_i, - graduation_group_id: member.graduation_group_id.to_i, role: course_member_role, is_active: role.is_current) - end + Member.where("course_id != -1").includes(:member_roles).find_each(batch_size: 500) do |member| + puts(member.id) + member.member_roles.each do |role| + course_member_role = role.role_id == 3 ? 1 : (role.role_id == 9 ? 2 : (role.role_id == 7 ? 3 : 4)) + member_group_id = role.role_id == 10 ? member.course_group_id : 0 + CourseMember.create!(course_id: member.course_id, user_id: member.user_id, course_group_id: member_group_id, + graduation_group_id: member.graduation_group_id, role: course_member_role, is_active: role.is_current) end end rescue Exception => e diff --git a/db/migrate/20190328134047_sync_shixuninfo.rb b/db/migrate/20190328134047_sync_shixuninfo.rb deleted file mode 100644 index bb374dc29..000000000 --- a/db/migrate/20190328134047_sync_shixuninfo.rb +++ /dev/null @@ -1,8 +0,0 @@ -class SyncShixuninfo < ActiveRecord::Migration[5.2] - def change - Shixun.find_each do |shixun| - ShixunInfo.create!(propaedeutics: shixun.propaedeutics, description: shixun.description, - evaluate_script: shixun.evaluate_script, shixun_id: shixun.id) - end - end -end diff --git a/db/migrate/20190328152957_remove_column_for_shixun.rb b/db/migrate/20190328152957_remove_column_for_shixun.rb deleted file mode 100644 index 70131a4b2..000000000 --- a/db/migrate/20190328152957_remove_column_for_shixun.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RemoveColumnForShixun < ActiveRecord::Migration[5.2] - def change - remove_columns :shixuns, :description, :propaedeutics, :evaluate_script - end -end diff --git a/db/migrate/20190426010412_add_is_invalid_to_student_works_scores.rb b/db/migrate/20190426010412_add_is_invalid_to_student_works_scores.rb index 2d782f924..7b893db6d 100644 --- a/db/migrate/20190426010412_add_is_invalid_to_student_works_scores.rb +++ b/db/migrate/20190426010412_add_is_invalid_to_student_works_scores.rb @@ -1,6 +1,6 @@ class AddIsInvalidToStudentWorksScores < ActiveRecord::Migration[5.2] def change - add_column :student_works_scores, :is_invalid, :boolean, default: false + # add_column :student_works_scores, :is_invalid, :boolean, default: false StudentWorksScore.where("score is not null").order("id desc").find_each do |score| unless score.is_invalid diff --git a/db/migrate/20190505092009_delete_ivalid_data.rb b/db/migrate/20190505092009_delete_ivalid_data.rb deleted file mode 100644 index 98f13d9e4..000000000 --- a/db/migrate/20190505092009_delete_ivalid_data.rb +++ /dev/null @@ -1,34 +0,0 @@ -class DeleteIvalidData < ActiveRecord::Migration[5.2] - def change - users = User.find_by_sql("select count(*) as user_count, login from users group by login having user_count>1") - users.each do |user| - valid_users = User.where(login: user.login) - valid_users.each do |valid_user| - unless valid_user.lastname.present? - valid_user.delete - end - end - end - - mail_users = User.find_by_sql("select count(*) as user_count, mail from users where mail is not null group by mail having user_count>1") - mail_users.each do |mail_user| - valid_mail_users = User.where(mail: mail_user.mail) - valid_mail_users.each do |valid_mail_user| - unless valid_mail_user.lastname.present? - valid_mail_user.delete - end - end - end - - - phone_users = User.find_by_sql("select count(*) as user_count, phone from users where phone is not null group by phone having user_count>1") - phone_users.each do |phone_user| - valid_phone_users = User.where(phone: phone_user.phone) - valid_phone_users.each do |valid_phone_user| - unless valid_phone_user.lastname.present? - valid_phone_user.delete - end - end - end - end -end diff --git a/db/migrate/20190505093440_init_use_index.rb b/db/migrate/20190505093440_init_use_index.rb index d885c3a9d..b7c3101dd 100644 --- a/db/migrate/20190505093440_init_use_index.rb +++ b/db/migrate/20190505093440_init_use_index.rb @@ -2,8 +2,8 @@ class InitUseIndex < ActiveRecord::Migration[5.2] def change remove_index :users, name: :index_users_on_login if index_exists?(:users, :login, name: :index_users_on_login) remove_index :users, name: :index_users_on_mail if index_exists?(:users, :mail, name: :index_users_on_mail) - add_index :users, :login, unique: true - add_index :users, :mail, unique: true - add_index :users, :phone, unique: true + # add_index :users, :login, unique: true + # add_index :users, :mail, unique: true + # add_index :users, :phone, unique: true end end diff --git a/db/migrate/20190517080313_add_test_set_average_for_challenges.rb b/db/migrate/20190517080313_add_test_set_average_for_challenges.rb index 59fabec9d..cac1d80bc 100644 --- a/db/migrate/20190517080313_add_test_set_average_for_challenges.rb +++ b/db/migrate/20190517080313_add_test_set_average_for_challenges.rb @@ -1,5 +1,5 @@ class AddTestSetAverageForChallenges < ActiveRecord::Migration[5.2] def change - add_column :challenges, :test_set_average, :boolean, :default => false + add_column :challenges, :test_set_average, :boolean, :default => true end end diff --git a/db/migrate/20190517083326_change_test_set_averger_for_challenges.rb b/db/migrate/20190517083326_change_test_set_averger_for_challenges.rb deleted file mode 100644 index bf474245f..000000000 --- a/db/migrate/20190517083326_change_test_set_averger_for_challenges.rb +++ /dev/null @@ -1,5 +0,0 @@ -class ChangeTestSetAvergerForChallenges < ActiveRecord::Migration[5.2] - def change - change_column :challenges, :test_set_average, :boolean, :default => true - end -end diff --git a/db/migrate/20190621010002_change_default_to_max_num.rb b/db/migrate/20190621010002_change_default_to_max_num.rb new file mode 100644 index 000000000..435756cd8 --- /dev/null +++ b/db/migrate/20190621010002_change_default_to_max_num.rb @@ -0,0 +1,5 @@ +class ChangeDefaultToMaxNum < ActiveRecord::Migration[5.2] + def change + change_column :graduation_tasks, :max_num, :integer, default: 5 + end +end diff --git a/db/migrate/20190621062948_migrate_course_module_activity.rb b/db/migrate/20190621062948_migrate_course_module_activity.rb new file mode 100644 index 000000000..1fa1ea112 --- /dev/null +++ b/db/migrate/20190621062948_migrate_course_module_activity.rb @@ -0,0 +1,5 @@ +class MigrateCourseModuleActivity < ActiveRecord::Migration[5.2] + def change + CourseModule.where(module_type: 'activity').update_all(hidden: 1) + end +end \ No newline at end of file diff --git a/db/migrate/20190621083604_add_descendants_count_to_messages.rb b/db/migrate/20190621083604_add_descendants_count_to_messages.rb new file mode 100644 index 000000000..02b721583 --- /dev/null +++ b/db/migrate/20190621083604_add_descendants_count_to_messages.rb @@ -0,0 +1,5 @@ +class AddDescendantsCountToMessages < ActiveRecord::Migration[5.2] + def change + add_column :messages, :descendants_count, :integer, default: 0 + end +end diff --git a/db/migrate/20190621105144_sync_ivalid_users.rb b/db/migrate/20190621105144_sync_ivalid_users.rb new file mode 100644 index 000000000..f2875977f --- /dev/null +++ b/db/migrate/20190621105144_sync_ivalid_users.rb @@ -0,0 +1,34 @@ +class SyncIvalidUsers < ActiveRecord::Migration[5.2] + # def change + # users = User.where.not(id: 2).find_by_sql("select count(*) as user_count, login from users group by login having user_count>1") + # users.each do |user| + # valid_users = User.where(login: user.login) + # valid_users.each do |valid_user| + # unless valid_user.lastname.present? + # valid_user.delete + # end + # end + # end + # + # mail_users = User.where.not(id: 2).find_by_sql("select count(*) as user_count, mail from users where mail is not null group by mail having user_count>1") + # mail_users.each do |mail_user| + # valid_mail_users = User.where(mail: mail_user.mail) + # valid_mail_users.each do |valid_mail_user| + # unless valid_mail_user.lastname.present? + # valid_mail_user.delete + # end + # end + # end + # + # + # phone_users = User.where.not(id: 2).find_by_sql("select count(*) as user_count, phone from users where phone is not null group by phone having user_count>1") + # phone_users.each do |phone_user| + # valid_phone_users = User.where(phone: phone_user.phone) + # valid_phone_users.each do |valid_phone_user| + # unless valid_phone_user.lastname.present? + # valid_phone_user.delete + # end + # end + # end + # end +end diff --git a/db/migrate/20190605060799_modify_script_and_description_for_shixuninfo.rb b/db/migrate/20190622055449_modify_shixun_info_for_shixuns.rb similarity index 87% rename from db/migrate/20190605060799_modify_script_and_description_for_shixuninfo.rb rename to db/migrate/20190622055449_modify_shixun_info_for_shixuns.rb index 4b3318d56..1a3aa147b 100644 --- a/db/migrate/20190605060799_modify_script_and_description_for_shixuninfo.rb +++ b/db/migrate/20190622055449_modify_shixun_info_for_shixuns.rb @@ -1,15 +1,15 @@ -class ModifyScriptAndDescriptionForShixuninfo < ActiveRecord::Migration[5.2] - def change - Shixun.find_each do |shixun| - if shixun.shixun_info - shixun.shixun_info.update_attributes(propaedeutics: shixun[:propaedeutics], - description: shixun[:description], - evaluate_script: shixun[:evaluate_script], - shixun_id: shixun[:id]) - else - ShixunInfo.create!(propaedeutics: shixun[:propaedeutics], description: shixun[:description], - evaluate_script: shixun[:evaluate_script], shixun_id: shixun.id) - end - end - end -end +class ModifyShixunInfoForShixuns < ActiveRecord::Migration[5.2] + def change + Shixun.find_each do |shixun| + if shixun.shixun_info + shixun.shixun_info.update_attributes(propaedeutics: shixun[:propaedeutics], + description: shixun[:description], + evaluate_script: shixun[:evaluate_script], + shixun_id: shixun[:id]) + else + ShixunInfo.create!(propaedeutics: shixun[:propaedeutics], description: shixun[:description], + evaluate_script: shixun[:evaluate_script], shixun_id: shixun.id) + end + end + end +end diff --git a/db/migrate/20190622060005_remove_shixun_long_text_for_shixuns.rb b/db/migrate/20190622060005_remove_shixun_long_text_for_shixuns.rb new file mode 100644 index 000000000..4557c610f --- /dev/null +++ b/db/migrate/20190622060005_remove_shixun_long_text_for_shixuns.rb @@ -0,0 +1,7 @@ +class RemoveShixunLongTextForShixuns < ActiveRecord::Migration[5.2] + def change + if Shixun.first.has_attribute?(:description) + remove_columns :shixuns, :description, :propaedeutics, :evaluate_script + end + end +end diff --git a/db/migrate/20190624085120_add_uniq_index_to_homework_challenge_settings.rb b/db/migrate/20190624085120_add_uniq_index_to_homework_challenge_settings.rb new file mode 100644 index 000000000..49a385ad9 --- /dev/null +++ b/db/migrate/20190624085120_add_uniq_index_to_homework_challenge_settings.rb @@ -0,0 +1,10 @@ +class AddUniqIndexToHomeworkChallengeSettings < ActiveRecord::Migration[5.2] + def change + remove_index :homework_challenge_settings, [:homework_common_id, :challenge_id] if index_exists?(:homework_challenge_settings, [:homework_common_id, :challenge_id]) + sql = %Q(delete from homework_challenge_settings where (homework_common_id, challenge_id) in + (select * from (select homework_common_id, challenge_id from homework_challenge_settings group by homework_common_id, challenge_id having count(*) > 1) a) + and id not in (select * from (select max(id) from homework_challenge_settings group by homework_common_id, challenge_id having count(*) > 1 order by id) b)) + ActiveRecord::Base.connection.execute sql + add_index :homework_challenge_settings, [:homework_common_id, :challenge_id], unique: true, name: "index_on_homework_common_id_challenge_id" + end +end diff --git a/db/migrate/20190625012548_add_index_for_evaluate_record.rb b/db/migrate/20190625012548_add_index_for_evaluate_record.rb new file mode 100644 index 000000000..d67e33b1e --- /dev/null +++ b/db/migrate/20190625012548_add_index_for_evaluate_record.rb @@ -0,0 +1,6 @@ +class AddIndexForEvaluateRecord < ActiveRecord::Migration[5.2] + def change + # 增加evalute_records的索引,提高查询效率 + add_index :evaluate_records, :game_id + end +end diff --git a/db/migrate/20190627012118_modify_quotes_for_gtopic_banks.rb b/db/migrate/20190627012118_modify_quotes_for_gtopic_banks.rb new file mode 100644 index 000000000..a47157414 --- /dev/null +++ b/db/migrate/20190627012118_modify_quotes_for_gtopic_banks.rb @@ -0,0 +1,6 @@ +class ModifyQuotesForGtopicBanks < ActiveRecord::Migration[5.2] + def change + GtopicBank.where("quotes is null").update_all(:quotes => 0) + change_column :gtopic_banks, :quotes, :integer, :default => 0 + end +end diff --git a/db/migrate/20190701013243_add_calculation_time_to_homework.rb b/db/migrate/20190701013243_add_calculation_time_to_homework.rb new file mode 100644 index 000000000..4a622ee92 --- /dev/null +++ b/db/migrate/20190701013243_add_calculation_time_to_homework.rb @@ -0,0 +1,6 @@ +class AddCalculationTimeToHomework < ActiveRecord::Migration[5.2] + def change + add_column :homework_commons, :calculation_time, :datetime + add_column :student_works, :calculation_time, :datetime + end +end diff --git a/db/migrate/20190703072611_add_old_exercise_tiankong_choice_id.rb b/db/migrate/20190703072611_add_old_exercise_tiankong_choice_id.rb new file mode 100644 index 000000000..9ad1429e2 --- /dev/null +++ b/db/migrate/20190703072611_add_old_exercise_tiankong_choice_id.rb @@ -0,0 +1,23 @@ +class AddOldExerciseTiankongChoiceId < ActiveRecord::Migration[5.2] + + def up + #类型为3 的问题答案及标准答案更新exercise_choice_id 为1,即表示第一空 + exercise_question_ids = ExerciseQuestion.where("question_type = 3").pluck(:id) + ExerciseAnswer.where(exercise_question_id: exercise_question_ids,exercise_choice_id: nil).update_all(exercise_choice_id:1) + ExerciseStandardAnswer.where(exercise_question_id: exercise_question_ids,exercise_choice_id: nil).update_all(exercise_choice_id:1) + + exercise_bank_question_ids = ExerciseBankQuestion.where("question_type =3").pluck(:id) + ExerciseBankStandardAnswer.where(exercise_bank_question_id: exercise_bank_question_ids).update_all(exercise_bank_choice_id:1) + end + + def down + #类型为3 的问题答案及标准答案更新exercise_choice_id 为1,即表示第一空 + exercise_question_ids = ExerciseQuestion.where("question_type = 3").pluck(:id) + ExerciseAnswer.where(exercise_question_id: exercise_question_ids,exercise_choice_id: 1).update_all(exercise_choice_id:nil) + ExerciseStandardAnswer.where(exercise_question_id: exercise_question_ids,exercise_choice_id: 1).update_all(exercise_choice_id:nil) + + exercise_bank_question_ids = ExerciseBankQuestion.where("question_type =3").pluck(:id) + ExerciseBankStandardAnswer.where(exercise_bank_question_id: exercise_bank_question_ids).update_all(exercise_bank_choice_id:nil) + end + +end diff --git a/db/migrate/20190703090511_add_index_for_shixun_services.rb b/db/migrate/20190703090511_add_index_for_shixun_services.rb new file mode 100644 index 000000000..693add3e3 --- /dev/null +++ b/db/migrate/20190703090511_add_index_for_shixun_services.rb @@ -0,0 +1,9 @@ +class AddIndexForShixunServices < ActiveRecord::Migration[5.2] + def change + sql = %Q(delete from shixun_service_configs where (shixun_id, mirror_repository_id) in + (select * from (select shixun_id, mirror_repository_id from shixun_service_configs group by shixun_id, mirror_repository_id having count(*) > 1) a) + and id not in (select * from (select min(id) from shixun_service_configs group by shixun_id, mirror_repository_id having count(*) > 1 order by id) b)) + ActiveRecord::Base.connection.execute sql + add_index :shixun_service_configs, [:shixun_id, :mirror_repository_id], unique: true, name: "shixun_id_mirror_id_unique" + end +end diff --git a/db/migrate/20190705011739_add_praises_count_for_challenges.rb b/db/migrate/20190705011739_add_praises_count_for_challenges.rb new file mode 100644 index 000000000..6ae1d8420 --- /dev/null +++ b/db/migrate/20190705011739_add_praises_count_for_challenges.rb @@ -0,0 +1,5 @@ +class AddPraisesCountForChallenges < ActiveRecord::Migration[5.2] + def change + add_column :challenges, :praises_count, :integer, :default => 0 + end +end diff --git a/db/migrate/20190705013204_modify_praises_count_for_challenges.rb b/db/migrate/20190705013204_modify_praises_count_for_challenges.rb new file mode 100644 index 000000000..59aa6ca53 --- /dev/null +++ b/db/migrate/20190705013204_modify_praises_count_for_challenges.rb @@ -0,0 +1,9 @@ +class ModifyPraisesCountForChallenges < ActiveRecord::Migration[5.2] + def change + challenges = Challenge.where(nil).unscoped + challenges.find_each do |c| + praises_count = c.praise_treads.where(praise_or_tread: 1).count + c.update_column(:praises_count, praises_count) + end + end +end diff --git a/db/migrate/20190705022502_add_praises_count_for_discuess.rb b/db/migrate/20190705022502_add_praises_count_for_discuess.rb new file mode 100644 index 000000000..47fd5ec1a --- /dev/null +++ b/db/migrate/20190705022502_add_praises_count_for_discuess.rb @@ -0,0 +1,5 @@ +class AddPraisesCountForDiscuess < ActiveRecord::Migration[5.2] + def change + add_column :discusses, :praises_count, :integer, :default => 0 + end +end diff --git a/db/migrate/20190705022737_modify_praises_count_for_discuess.rb b/db/migrate/20190705022737_modify_praises_count_for_discuess.rb new file mode 100644 index 000000000..4d5b6ca97 --- /dev/null +++ b/db/migrate/20190705022737_modify_praises_count_for_discuess.rb @@ -0,0 +1,9 @@ +class ModifyPraisesCountForDiscuess < ActiveRecord::Migration[5.2] + def change + discusses = Discuss.includes(:praise_treads).unscoped + discusses.find_each do |d| + praises_count = d.praise_treads.liker.count + d.update_column(:praises_count, praises_count) + end + end +end diff --git a/db/migrate/20190705085829_add_sec_key_to_outputs.rb b/db/migrate/20190705085829_add_sec_key_to_outputs.rb new file mode 100644 index 000000000..1da2930ae --- /dev/null +++ b/db/migrate/20190705085829_add_sec_key_to_outputs.rb @@ -0,0 +1,7 @@ +class AddSecKeyToOutputs < ActiveRecord::Migration[5.2] + def change + #add_column :outputs, :sec_key, :string + # add_column :outputs, :ts_mem, :float + # add_column :outputs, :ts_time, :float + end +end diff --git a/db/migrate/20190706010307_create_user_interests.rb b/db/migrate/20190706010307_create_user_interests.rb new file mode 100644 index 000000000..d64a1c228 --- /dev/null +++ b/db/migrate/20190706010307_create_user_interests.rb @@ -0,0 +1,8 @@ +class CreateUserInterests < ActiveRecord::Migration[5.2] + def change + create_table :user_interests do |t| + t.references :user + t.references :repertoire + end + end +end diff --git a/db/migrate/20190708062910_add_index_for_run_code_message.rb b/db/migrate/20190708062910_add_index_for_run_code_message.rb new file mode 100644 index 000000000..4449d58a2 --- /dev/null +++ b/db/migrate/20190708062910_add_index_for_run_code_message.rb @@ -0,0 +1,5 @@ +class AddIndexForRunCodeMessage < ActiveRecord::Migration[5.2] + def change + add_index :run_code_messages, :game_id + end +end diff --git a/db/migrate/20190711062033_modify_challenge_id_for_discusses.rb b/db/migrate/20190711062033_modify_challenge_id_for_discusses.rb new file mode 100644 index 000000000..86052375b --- /dev/null +++ b/db/migrate/20190711062033_modify_challenge_id_for_discusses.rb @@ -0,0 +1,11 @@ +class ModifyChallengeIdForDiscusses < ActiveRecord::Migration[5.2] + def change + discusses = Discuss.where(challenge_id: nil) + discusses.each do |dis| + challenge_id = Shixun.find(dis.dis_id).challenges.first.id + dis.update_column(:challenge_id, challenge_id) + end + add_index :discusses, :challenge_id + + end +end diff --git a/db/migrate/20190713022300_modify_md_attachment_url_for_md_cotents.rb b/db/migrate/20190713022300_modify_md_attachment_url_for_md_cotents.rb new file mode 100644 index 000000000..10b821fc5 --- /dev/null +++ b/db/migrate/20190713022300_modify_md_attachment_url_for_md_cotents.rb @@ -0,0 +1,35 @@ +class ModifyMdAttachmentUrlForMdCotents < ActiveRecord::Migration[5.2] + def change + # 更新MarkDown图片的URL + homework_commons = HomeworkCommon.all + homework_commons.find_each do |hc| + hc.update_column(:description, hc.description.gsub("![](/attachments/download", "![](/api/attachments")) if hc.description.present? + end + + challenges = Challenge.all.unscoped + challenges.find_each do |c| + c.update_column(:task_pass, c.task_pass.gsub("![](/attachments/download", "![](/api/attachments")) if c.task_pass.present? + end + + challenge_answers = ChallengeAnswer.all.unscoped + challenge_answers.find_each do |ca| + ca.update_column(:contents, ca.contents.gsub("![](/attachments/download", "![](/api/attachments")) if ca.contents.present? + end + + shixun_infos = ShixunInfo.all + shixun_infos.find_each do |si| + si.update_column(:propaedeutics, si.propaedeutics.gsub("![](/attachments/download", "![](/api/attachments")) if si.propaedeutics.present? + si.update_column(:description, si.description.gsub("![](/attachments/download", "![](/api/attachments")) if si.description.present? + end + + subjects = Subject.all + subjects.find_each do |s| + s.update_column(:description, s.description.gsub("![](/attachments/download", "![](/api/attachments")) if s.description.present? + end + + plats = PlatformSample.where(samples_type: ['introduction', 'knowledge']) + plats.find_each do |p| + p.update_column(:contents, p.contents.gsub("![](/attachments/download", "![](/api/attachments")) if p.contents.present? + end + end +end diff --git a/db/migrate/20190716064225_add_max_mem_to_evaluate_records.rb b/db/migrate/20190716064225_add_max_mem_to_evaluate_records.rb new file mode 100644 index 000000000..86425262d --- /dev/null +++ b/db/migrate/20190716064225_add_max_mem_to_evaluate_records.rb @@ -0,0 +1,5 @@ +class AddMaxMemToEvaluateRecords < ActiveRecord::Migration[5.2] + def change + #add_column :evaluate_records, :max_mem, :float + end +end diff --git a/db/migrate/20190720025309_add_ts_mem_for_outputs.rb b/db/migrate/20190720025309_add_ts_mem_for_outputs.rb new file mode 100644 index 000000000..1cf3f3e6f --- /dev/null +++ b/db/migrate/20190720025309_add_ts_mem_for_outputs.rb @@ -0,0 +1,5 @@ +class AddTsMemForOutputs < ActiveRecord::Migration[5.2] + def change + add_column :outputs, :ts_mem, :float + end +end diff --git a/db/migrate/20190720025341_add_ts_time_for_outputs.rb b/db/migrate/20190720025341_add_ts_time_for_outputs.rb new file mode 100644 index 000000000..a5366fbd0 --- /dev/null +++ b/db/migrate/20190720025341_add_ts_time_for_outputs.rb @@ -0,0 +1,5 @@ +class AddTsTimeForOutputs < ActiveRecord::Migration[5.2] + def change + add_column :outputs, :ts_time, :float + end +end diff --git a/db/migrate/20190720121537_add_is_md_for_messages.rb b/db/migrate/20190720121537_add_is_md_for_messages.rb new file mode 100644 index 000000000..a801fb387 --- /dev/null +++ b/db/migrate/20190720121537_add_is_md_for_messages.rb @@ -0,0 +1,5 @@ +class AddIsMdForMessages < ActiveRecord::Migration[5.2] + def change + add_column :messages, :is_md, :boolean, :default => true + end +end diff --git a/db/migrate/20190720122123_modify_is_md_for_messages.rb b/db/migrate/20190720122123_modify_is_md_for_messages.rb new file mode 100644 index 000000000..4137fc8af --- /dev/null +++ b/db/migrate/20190720122123_modify_is_md_for_messages.rb @@ -0,0 +1,7 @@ +class ModifyIsMdForMessages < ActiveRecord::Migration[5.2] + def change + Message.find_each do |m| + m.update_column(:is_md, false) + end + end +end diff --git a/lib/educoder/sms.rb b/lib/educoder/sms.rb index 9d54a6df5..7fa1c0edb 100644 --- a/lib/educoder/sms.rb +++ b/lib/educoder/sms.rb @@ -21,13 +21,13 @@ 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 def self.sendYunpian(mobile, code, send_type, name, user_name, result) #修改为您的apikey.可在官网(http://www.yunpian.com)登录后用户中心首页看到 - apikey = EduSetting.find_by_name('sms_apikey').try(:value) + apikey = EduSetting.get('sms_apikey') #指定模板发送接口HTTP地址 send_tpl_sms_uri = URI.parse('https://sms.yunpian.com/v2/sms/single_send.json') @@ -36,7 +36,7 @@ module Educoder params['mobile'] = mobile params['text'] = "" if send_type.nil? - params['text'] = "【Edu实训】" + code + "(手机验证码)。如非本人操作,请忽略。" + params['text'] = "【Edu实训】" + code + "(手机验证码),有效期为10分钟。如非本人操作,请忽略。" elsif send_type == 'competition_start' params['text'] = "【Edu实训】亲爱的#{user_name},你参与的#{name}将于#{result}开始,请及时参赛" Rails.logger.info "#{params['text']}" @@ -70,6 +70,7 @@ module Educoder response = http.start { |http| http.request(request) } ActiveSupport::JSON.decode(response.body) rescue =>err + Rails.logger.error("#############sendYunpian_error: #{err.message}") return nil end end diff --git a/lib/educoder/tip_exception.rb b/lib/educoder/tip_exception.rb index 09f0228ac..08fd53ed6 100644 --- a/lib/educoder/tip_exception.rb +++ b/lib/educoder/tip_exception.rb @@ -13,7 +13,7 @@ module Educoder @status = status @message = message - Rails.logger.info("############# #{@status}, #{@message}") + Rails.logger.error("############# #{@status}, #{@message}") end def tip_json diff --git a/lib/gitcheck/myshixun_update.txt b/lib/gitcheck/myshixun_update.txt new file mode 100644 index 000000000..e69de29bb diff --git a/lib/gitcheck/myshixun_update_error.txt b/lib/gitcheck/myshixun_update_error.txt new file mode 100644 index 000000000..e69de29bb diff --git a/lib/gitcheck/readme_test.txt b/lib/gitcheck/readme_test.txt new file mode 100644 index 000000000..317af632c --- /dev/null +++ b/lib/gitcheck/readme_test.txt @@ -0,0 +1,51 @@ +# 新版Git测试说明 +统一: +参考实训:http://47.96.87.25:48080/shixuns/ca9fvobr/repository +请求方式:POST +参数{repo_path: "educoder/ca9fvobr.git"} +公共方法: +['add_repository', 'fork_repository', 'delete_repository', 'file_tree', 'update_file', + 'file_content', 'commits'] + +1、仓库目录接口 + 测试方法:模拟1000个用户同时去访问接口,访问方式 + http://121.199.19.206:9000/api/file_tree + 参数: + {repo_path: "educoder/ca9fvobr.git", path: ''} // 如:{path: 'step1'} + +2、创建版本库 + 访问地址:http://121.199.19.206:9000/api/add_repository + 参数: + {repo_path: 比如:"Hjqreturn/aaass1.git"} + +3、fork版本库 + http://121.199.19.206:9000/api/fork_repository + 参数: + {repo_path: 'Hjqreturn/aaass1.git', fork_repository_path: 'educoder/ca9fvobr.git'} + 说明:fork_repository_path是新项目的repo_path, repo_path是源项目的 + + +4、更新文件 + 测试方法: + 1、更新同一个文件,并发量可以不用很大,可以用同一个用户并发10-100 + 2、更新不同的文件:可以依据创建的版本库去更新 + 访问地址:http://121.199.19.206:9000/api/update_file + 参数: + {repo_path: "educoder/ca9fvobr.git", + file_path: 'step1/main.py', + message: 'commit by test', + content: 'afdjadsjfj1111', + author_name: 'guange', + author_email: '8863824@gmil.com'} + +5、获取文件内容 + 访问地址:http://121.199.19.206:9000/api/file_content + 参数: + {repo_path: "educoder/ca9fvobr.git", path: 'step1/main.py',} + +6、获取提交记录 + 访问地址:http://121.199.19.206:9000/api/commits + 参数: + {repo_path: 比如:"educoder/ca9fvobr.git"} + + diff --git a/lib/gitcheck/shixun_update.txt b/lib/gitcheck/shixun_update.txt new file mode 100644 index 000000000..ff5e54236 --- /dev/null +++ b/lib/gitcheck/shixun_update.txt @@ -0,0 +1,563 @@ +http://testbdgit2.educoder.net/educoder/mqex9s82.git +http://testbdgit2.educoder.net/educoder/nf9ja46l.git +http://testbdgit2.educoder.net/educoder/qmeb65oa.git +http://testbdgit2.educoder.net/educoder/748fkcya.git +http://testbdgit2.educoder.net/educoder/o7pr4f6v.git +http://testbdgit2.educoder.net/educoder/tjxnyuv6.git +http://testbdgit2.educoder.net/educoder/fp6cmstz.git +http://testbdgit2.educoder.net/educoder/eh5oxkm9.git +http://testbdgit2.educoder.net/educoder/uznmbg54.git +http://testbdgit2.educoder.net/educoder/i8utopmc.git +http://testbdgit2.educoder.net/educoder/f9ly35vz.git +http://testbdgit2.educoder.net/educoder/vnw2fg5r.git +http://testbdgit2.educoder.net/educoder/pcfhzue5.git +http://testbdgit2.educoder.net/educoder/zlg2nmcf.git +http://testbdgit2.educoder.net/educoder/klp26sqc.git +http://testbdgit2.educoder.net/educoder/y68uqmoe.git +http://testbdgit2.educoder.net/educoder/7zg5mi2r.git +http://testbdgit2.educoder.net/educoder/8g93nfvc.git +http://testbdgit2.educoder.net/educoder/mnj3srpe.git +http://testbdgit2.educoder.net/educoder/lrwsyhzc.git +http://testbdgit2.educoder.net/educoder/a2ct98o7.git +http://testbdgit2.educoder.net/educoder/hawxspqm.git +http://testbdgit2.educoder.net/educoder/pobfl4g8.git +http://testbdgit2.educoder.net/educoder/zg7e9o2y.git +http://testbdgit2.educoder.net/educoder/fsu7tkaw.git +http://testbdgit2.educoder.net/educoder/cmklt4f8.git +http://testbdgit2.educoder.net/educoder/2gt3yuen.git +http://testbdgit2.educoder.net/educoder/v3bksozu.git +http://testbdgit2.educoder.net/educoder/ku6lva8t.git +http://testbdgit2.educoder.net/educoder/g8w3nj6r.git +http://testbdgit2.educoder.net/educoder/pxlsuotc.git +http://testbdgit2.educoder.net/educoder/opv8xkjw.git +http://testbdgit2.educoder.net/educoder/stewl573.git +http://testbdgit2.educoder.net/educoder/nuj9lbwv.git +http://testbdgit2.educoder.net/educoder/r4vlju5x.git +http://testbdgit2.educoder.net/educoder/85fat9w3.git +http://testbdgit2.educoder.net/educoder/guzqi4nm.git +http://testbdgit2.educoder.net/educoder/obtfwj3e.git +http://testbdgit2.educoder.net/educoder/3ozvy5f8.git +http://testbdgit2.educoder.net/educoder/8bu9zmjy.git +http://testbdgit2.educoder.net/educoder/n489y7qt.git +http://testbdgit2.educoder.net/educoder/f3pwvrtk.git +http://testbdgit2.educoder.net/educoder/b6ljcet3.git +http://testbdgit2.educoder.net/educoder/uie9snqp.git +http://testbdgit2.educoder.net/educoder/xti6ueyf.git +http://testbdgit2.educoder.net/educoder/gwkc395l.git +http://testbdgit2.educoder.net/educoder/6a2qy98p.git +http://testbdgit2.educoder.net/educoder/2qffg3pu.git +http://testbdgit2.educoder.net/educoder/nfypjxhl.git +http://testbdgit2.educoder.net/educoder/9p4neovc.git +http://testbdgit2.educoder.net/educoder/k4wg9b32.git +http://testbdgit2.educoder.net/educoder/pw53ln4m.git +http://testbdgit2.educoder.net/educoder/cylj7vgb.git +http://testbdgit2.educoder.net/educoder/ftfzbw72.git +http://testbdgit2.educoder.net/educoder/qt78x4a5.git +http://testbdgit2.educoder.net/educoder/qsza57pj.git +http://testbdgit2.educoder.net/educoder/afvk9r35.git +http://testbdgit2.educoder.net/educoder/68rqajhy.git +http://testbdgit2.educoder.net/educoder/q4ixftoz.git +http://testbdgit2.educoder.net/educoder/pbmkl5vt.git +http://testbdgit2.educoder.net/educoder/ral8fjw9.git +http://testbdgit2.educoder.net/educoder/89zfsjbp.git +http://testbdgit2.educoder.net/educoder/no9uv3g2.git +http://testbdgit2.educoder.net/educoder/cztux23y.git +http://testbdgit2.educoder.net/educoder/4bflgcs8.git +http://testbdgit2.educoder.net/educoder/6w2xmtls.git +http://testbdgit2.educoder.net/educoder/o4xa93mc.git +http://testbdgit2.educoder.net/educoder/uctzevfx.git +http://testbdgit2.educoder.net/educoder/wokspmut.git +http://testbdgit2.educoder.net/educoder/ba56rk8v.git +http://testbdgit2.educoder.net/educoder/6w49utr2.git +http://testbdgit2.educoder.net/educoder/qnubm248.git +http://testbdgit2.educoder.net/educoder/itzexlbn.git +http://testbdgit2.educoder.net/educoder/e6o9pmz4.git +http://testbdgit2.educoder.net/educoder/qr9fhylp.git +http://testbdgit2.educoder.net/educoder/q2nya3cj.git +http://testbdgit2.educoder.net/educoder/58drwg63.git +http://testbdgit2.educoder.net/educoder/oiwsvgpf.git +http://testbdgit2.educoder.net/educoder/4uyn5ebp.git +http://testbdgit2.educoder.net/educoder/pebvjtk9.git +http://testbdgit2.educoder.net/educoder/uywljq4v.git +http://testbdgit2.educoder.net/educoder/zawfjtnm.git +http://testbdgit2.educoder.net/educoder/z5w3gbhk.git +http://testbdgit2.educoder.net/educoder/cz7yw3en.git +http://testbdgit2.educoder.net/educoder/p87sflg2.git +http://testbdgit2.educoder.net/educoder/w3vcokrg.git +http://testbdgit2.educoder.net/educoder/uc64f2qs.git +http://testbdgit2.educoder.net/educoder/vtnag4op.git +http://testbdgit2.educoder.net/educoder/mbgfitn6.git +http://testbdgit2.educoder.net/educoder/nwj4ua2k.git +http://testbdgit2.educoder.net/educoder/y8kfhtu6.git +http://testbdgit2.educoder.net/educoder/tmivlph2.git +http://testbdgit2.educoder.net/educoder/ziyft572.git +http://testbdgit2.educoder.net/educoder/k8u4nrj6.git +http://testbdgit2.educoder.net/educoder/wgfyrzhe.git +http://testbdgit2.educoder.net/educoder/a4ts237c.git +http://testbdgit2.educoder.net/educoder/cvw63y9e.git +http://testbdgit2.educoder.net/educoder/bxltfpa5.git +http://testbdgit2.educoder.net/educoder/x2anczf5.git +http://testbdgit2.educoder.net/educoder/m57iyhan.git +http://testbdgit2.educoder.net/educoder/iqrakwl2.git +http://testbdgit2.educoder.net/educoder/fagcx7yl.git +http://testbdgit2.educoder.net/educoder/oxlpy9uq.git +http://testbdgit2.educoder.net/educoder/6spm2y7k.git +http://testbdgit2.educoder.net/educoder/6fxzts5b.git +http://testbdgit2.educoder.net/eduforge/fhc7p56a.git +http://testbdgit2.educoder.net/eduforge/3aexl5my.git +http://testbdgit2.educoder.net/educoder/9mz7qn5t.git +http://testbdgit2.educoder.net/educoder/b9r8pon3.git +http://testbdgit2.educoder.net/educoder/ciz68os9.git +http://testbdgit2.educoder.net/educoder/2e4fuw87.git +http://testbdgit2.educoder.net/educoder/hwm9s64y.git +http://testbdgit2.educoder.net/educoder/owsik483.git +http://testbdgit2.educoder.net/educoder/pbt9cyfo.git +http://testbdgit2.educoder.net/educoder/8u4fvn9w.git +http://testbdgit2.educoder.net/educoder/5bpkg3e6.git +http://testbdgit2.educoder.net/educoder/ohkunqe2.git +http://testbdgit2.educoder.net/educoder/u3j28qe6.git +http://testbdgit2.educoder.net/educoder/yjo3t72c.git +http://testbdgit2.educoder.net/educoder/oy7prsxe.git +http://testbdgit2.educoder.net/educoder/q3ljmkn2.git +http://testbdgit2.educoder.net/educoder/gk6lhtrf.git +http://testbdgit2.educoder.net/eduforge/v6pa2kiz.git +http://testbdgit2.educoder.net/educoder/qpuobn24.git +http://testbdgit2.educoder.net/educoder/mkxfysza.git +http://testbdgit2.educoder.net/eduforge/hpr7ojgc.git +http://testbdgit2.educoder.net/educoder/2aef9wni.git +http://testbdgit2.educoder.net/eduforge/8texrqwj.git +http://testbdgit2.educoder.net/educoder/wle7zmxu.git +http://testbdgit2.educoder.net/eduforge/j7cx68b9.git +http://testbdgit2.educoder.net/educoder/ywrcjki2.git +http://testbdgit2.educoder.net/educoder/sauvl9px.git +http://testbdgit2.educoder.net/educoder/3pl6j2me.git +http://testbdgit2.educoder.net/eduforge/o53rjgsh.git +http://testbdgit2.educoder.net/educoder/g8znf6cy.git +http://testbdgit2.educoder.net/educoder/itk4hy6l.git +http://testbdgit2.educoder.net/eduforge/igbc4rtw.git +http://testbdgit2.educoder.net/educoder/mnkfuyvx.git +http://testbdgit2.educoder.net/educoder/oatsh64e.git +http://testbdgit2.educoder.net/educoder/2mgsyrnu.git +http://testbdgit2.educoder.net/educoder/69ulmat5.git +http://testbdgit2.educoder.net/eduforge/9z3k5i4f.git +http://testbdgit2.educoder.net/educoder/7bysthvr.git +http://testbdgit2.educoder.net/eduforge/z3wh7uex.git +http://testbdgit2.educoder.net/educoder/9o5h2rsf.git +http://testbdgit2.educoder.net/educoder/uf3gl2vq.git +http://testbdgit2.educoder.net/eduforge/jef9xvzb.git +http://testbdgit2.educoder.net/educoder/g94qce7p.git +http://testbdgit2.educoder.net/educoder/2a54vk8x.git +http://testbdgit2.educoder.net/educoder/sx5eukfq.git +http://testbdgit2.educoder.net/educoder/ivzjw793.git +http://testbdgit2.educoder.net/eduforge/aekgf6pz.git +http://testbdgit2.educoder.net/educoder/tzqbu6c4.git +http://testbdgit2.educoder.net/educoder/ovz3e6a7.git +http://testbdgit2.educoder.net/educoder/ujavffi2.git +http://testbdgit2.educoder.net/educoder/8jsxcfm5.git +http://testbdgit2.educoder.net/educoder/qgpycjvn.git +http://testbdgit2.educoder.net/educoder/rhasift3.git +http://testbdgit2.educoder.net/educoder/nfpla5jg.git +http://testbdgit2.educoder.net/educoder/bjo2x4c9.git +http://testbdgit2.educoder.net/educoder/3jawxy9g.git +http://testbdgit2.educoder.net/eduforge/h6gs8t7q.git +http://testbdgit2.educoder.net/educoder/ntexhzrl.git +http://testbdgit2.educoder.net/educoder/jft327sa.git +http://testbdgit2.educoder.net/educoder/7bvs54gw.git +http://testbdgit2.educoder.net/educoder/grunzcs3.git +http://testbdgit2.educoder.net/educoder/q4fowkfa.git +http://testbdgit2.educoder.net/educoder/fkmtrpsn.git +http://testbdgit2.educoder.net/educoder/2iubzxfh.git +http://testbdgit2.educoder.net/educoder/gbhwvrki.git +http://testbdgit2.educoder.net/educoder/kpxfs4b5.git +http://testbdgit2.educoder.net/educoder/h5f6wi7x.git +http://testbdgit2.educoder.net/educoder/c3lr2xjz.git +http://testbdgit2.educoder.net/educoder/q8bcyxz3.git +http://testbdgit2.educoder.net/educoder/qha5emif.git +http://testbdgit2.educoder.net/educoder/5jr4gzs7.git +http://testbdgit2.educoder.net/educoder/9ksg4up7.git +http://testbdgit2.educoder.net/educoder/4rcxvftu.git +http://testbdgit2.educoder.net/educoder/hvaf5txj.git +http://testbdgit2.educoder.net/educoder/b4vqe8uz.git +http://testbdgit2.educoder.net/educoder/pg6c2i5y.git +http://testbdgit2.educoder.net/educoder/fbtlw8ro.git +http://testbdgit2.educoder.net/educoder/86f92lri.git +http://testbdgit2.educoder.net/educoder/zvaup9yo.git +http://testbdgit2.educoder.net/educoder/exm3ffap.git +http://testbdgit2.educoder.net/educoder/owg63ezu.git +http://testbdgit2.educoder.net/educoder/c36opqaj.git +http://testbdgit2.educoder.net/educoder/xuyrc6qs.git +http://testbdgit2.educoder.net/educoder/xc9tj82p.git +http://testbdgit2.educoder.net/educoder/nmougtya.git +http://testbdgit2.educoder.net/educoder/8arufxzl.git +http://testbdgit2.educoder.net/educoder/m7nrf6zf.git +http://testbdgit2.educoder.net/educoder/zffu9j6v.git +http://testbdgit2.educoder.net/educoder/epmtoh6b.git +http://testbdgit2.educoder.net/educoder/ejab7vxn.git +http://testbdgit2.educoder.net/educoder/83lyhsen.git +http://testbdgit2.educoder.net/educoder/m4e6x573.git +http://testbdgit2.educoder.net/educoder/unfihtsv.git +http://testbdgit2.educoder.net/educoder/74ftapwb.git +http://testbdgit2.educoder.net/educoder/iu47m9qx.git +http://testbdgit2.educoder.net/educoder/8bh6mfu3.git +http://testbdgit2.educoder.net/educoder/sb26oath.git +http://testbdgit2.educoder.net/educoder/igvm3fsb.git +http://testbdgit2.educoder.net/educoder/gancv2yo.git +http://testbdgit2.educoder.net/educoder/kyp65jwu.git +http://testbdgit2.educoder.net/educoder/6ru2nbpj.git +http://testbdgit2.educoder.net/educoder/rfpwhsu5.git +http://testbdgit2.educoder.net/educoder/orem2wgc.git +http://testbdgit2.educoder.net/educoder/yuhmfliq.git +http://testbdgit2.educoder.net/educoder/m4c7jo6y.git +http://testbdgit2.educoder.net/educoder/5l6oufzc.git +http://testbdgit2.educoder.net/educoder/my7vcffx.git +http://testbdgit2.educoder.net/educoder/uvka63xs.git +http://testbdgit2.educoder.net/educoder/c9thq3li.git +http://testbdgit2.educoder.net/educoder/o45rn2sl.git +http://testbdgit2.educoder.net/educoder/sae3fyjc.git +http://testbdgit2.educoder.net/educoder/56orxtg3.git +http://testbdgit2.educoder.net/educoder/cqpzx47f.git +http://testbdgit2.educoder.net/educoder/2in3vcf7.git +http://testbdgit2.educoder.net/educoder/6isfgtun.git +http://testbdgit2.educoder.net/educoder/46woubzq.git +http://testbdgit2.educoder.net/educoder/6xwmi29f.git +http://testbdgit2.educoder.net/educoder/hk968fua.git +http://testbdgit2.educoder.net/educoder/ogb6ixjz.git +http://testbdgit2.educoder.net/educoder/va7cru64.git +http://testbdgit2.educoder.net/educoder/vqnk5tjo.git +http://testbdgit2.educoder.net/educoder/oqfsci8u.git +http://testbdgit2.educoder.net/educoder/qcosi4f8.git +http://testbdgit2.educoder.net/educoder/bsnk7wit.git +http://testbdgit2.educoder.net/educoder/ksvmtwql.git +http://testbdgit2.educoder.net/educoder/eigqpfua.git +http://testbdgit2.educoder.net/educoder/hqmwxztb.git +http://testbdgit2.educoder.net/educoder/jlgt9wfk.git +http://testbdgit2.educoder.net/educoder/hcuzqkgv.git +http://testbdgit2.educoder.net/educoder/hzw89pof.git +http://testbdgit2.educoder.net/educoder/xnft4fsm.git +http://testbdgit2.educoder.net/educoder/guj4ml8q.git +http://testbdgit2.educoder.net/educoder/l56jkwfn.git +http://testbdgit2.educoder.net/educoder/4jqry5gl.git +http://testbdgit2.educoder.net/educoder/65kiwb72.git +http://testbdgit2.educoder.net/educoder/xb39mzfr.git +http://testbdgit2.educoder.net/educoder/hyb5m38x.git +http://testbdgit2.educoder.net/educoder/p4f2jtkq.git +http://testbdgit2.educoder.net/educoder/4n3stcol.git +http://testbdgit2.educoder.net/educoder/6kjqar5e.git +http://testbdgit2.educoder.net/educoder/qhc2prk4.git +http://testbdgit2.educoder.net/educoder/ltw8b29i.git +http://testbdgit2.educoder.net/educoder/g5y8zcvl.git +http://testbdgit2.educoder.net/educoder/5et7zpra.git +http://testbdgit2.educoder.net/educoder/au97mpbr.git +http://testbdgit2.educoder.net/educoder/oxmt2zvc.git +http://testbdgit2.educoder.net/educoder/26chou4y.git +http://testbdgit2.educoder.net/educoder/lfmus7o2.git +http://testbdgit2.educoder.net/educoder/efbp7luz.git +http://testbdgit2.educoder.net/educoder/7lr8agws.git +http://testbdgit2.educoder.net/educoder/ak8tbjuv.git +http://testbdgit2.educoder.net/educoder/qu8a93ew.git +http://testbdgit2.educoder.net/educoder/zlgfiowe.git +http://testbdgit2.educoder.net/educoder/qmt4nfai.git +http://testbdgit2.educoder.net/educoder/u2s4v9ba.git +http://testbdgit2.educoder.net/educoder/2icxsunf.git +http://testbdgit2.educoder.net/educoder/fzmqjp6g.git +http://testbdgit2.educoder.net/educoder/7ir3vmzw.git +http://testbdgit2.educoder.net/educoder/xkfzg96o.git +http://testbdgit2.educoder.net/educoder/xvfl5sjz.git +http://testbdgit2.educoder.net/educoder/qnwuy7h3.git +http://testbdgit2.educoder.net/educoder/bhnspvmg.git +http://testbdgit2.educoder.net/educoder/ns7vh6ro.git +http://testbdgit2.educoder.net/eduforge/un3xoal7.git +http://testbdgit2.educoder.net/educoder/29am7wv4.git +http://testbdgit2.educoder.net/educoder/qlfn5hiu.git +http://testbdgit2.educoder.net/educoder/e4pvkhtj.git +http://testbdgit2.educoder.net/educoder/hfesmtuz.git +http://testbdgit2.educoder.net/educoder/6kjhil3m.git +http://testbdgit2.educoder.net/educoder/2igrh8c4.git +http://testbdgit2.educoder.net/educoder/e7yt3kmw.git +http://testbdgit2.educoder.net/educoder/a8zybrkt.git +http://testbdgit2.educoder.net/educoder/v2uzrasj.git +http://testbdgit2.educoder.net/educoder/rb83htif.git +http://testbdgit2.educoder.net/eduforge/jc3p2wto.git +http://testbdgit2.educoder.net/educoder/jtnlfgw2.git +http://testbdgit2.educoder.net/educoder/fa96xrti.git +http://testbdgit2.educoder.net/educoder/r6bjga3u.git +http://testbdgit2.educoder.net/educoder/fpmwzxqn.git +http://testbdgit2.educoder.net/educoder/rbpsw8ct.git +http://testbdgit2.educoder.net/educoder/4zuxembp.git +http://testbdgit2.educoder.net/educoder/3gxwrzaf.git +http://testbdgit2.educoder.net/educoder/wz6j5lpn.git +http://testbdgit2.educoder.net/educoder/izu9tf3j.git +http://testbdgit2.educoder.net/educoder/vhux4pa7.git +http://testbdgit2.educoder.net/educoder/s9wvroqn.git +http://testbdgit2.educoder.net/educoder/ruofj2xl.git +http://testbdgit2.educoder.net/educoder/qj4mlxoi.git +http://testbdgit2.educoder.net/educoder/34gzbolc.git +http://testbdgit2.educoder.net/educoder/at86wfsn.git +http://testbdgit2.educoder.net/educoder/j7fnwsrh.git +http://testbdgit2.educoder.net/educoder/zgsuk364.git +http://testbdgit2.educoder.net/educoder/nf3gv54x.git +http://testbdgit2.educoder.net/educoder/fnbuq957.git +http://testbdgit2.educoder.net/educoder/z4fp9o3e.git +http://testbdgit2.educoder.net/educoder/c3qh4p6f.git +http://testbdgit2.educoder.net/educoder/fszntcbw.git +http://testbdgit2.educoder.net/educoder/af968lnf.git +http://testbdgit2.educoder.net/educoder/kpc36fhn.git +http://testbdgit2.educoder.net/educoder/6c4wp5bu.git +http://testbdgit2.educoder.net/educoder/hzmikncs.git +http://testbdgit2.educoder.net/educoder/6ogr4bhj.git +http://testbdgit2.educoder.net/educoder/fu59rezf.git +http://testbdgit2.educoder.net/educoder/zef9gswv.git +http://testbdgit2.educoder.net/educoder/p9z4fxv8.git +http://testbdgit2.educoder.net/eduforge/hcxeuyfl.git +http://testbdgit2.educoder.net/educoder/4u2ebx89.git +http://testbdgit2.educoder.net/educoder/cikojzsb.git +http://testbdgit2.educoder.net/educoder/2rzomtx5.git +http://testbdgit2.educoder.net/educoder/wfvbhr2s.git +http://testbdgit2.educoder.net/educoder/q8mxg4zv.git +http://testbdgit2.educoder.net/educoder/q8fezi37.git +http://testbdgit2.educoder.net/educoder/nb7ha8te.git +http://testbdgit2.educoder.net/educoder/qxgfbyn9.git +http://testbdgit2.educoder.net/educoder/k8so9wa2.git +http://testbdgit2.educoder.net/educoder/zwc9ja5y.git +http://testbdgit2.educoder.net/educoder/89lwscfy.git +http://testbdgit2.educoder.net/educoder/ga26fy4f.git +http://testbdgit2.educoder.net/educoder/rgy4769i.git +http://testbdgit2.educoder.net/educoder/q3rnovik.git +http://testbdgit2.educoder.net/educoder/r5xsukn4.git +http://testbdgit2.educoder.net/educoder/yu6za47j.git +http://testbdgit2.educoder.net/educoder/fqvr56nm.git +http://testbdgit2.educoder.net/educoder/tq26m73o.git +http://testbdgit2.educoder.net/educoder/k2rmpuf6.git +http://testbdgit2.educoder.net/educoder/fzg87ip6.git +http://testbdgit2.educoder.net/educoder/qk3l64zi.git +http://testbdgit2.educoder.net/educoder/bcjpk93f.git +http://testbdgit2.educoder.net/educoder/rnjak48l.git +http://testbdgit2.educoder.net/educoder/hyzkq5vr.git +http://testbdgit2.educoder.net/educoder/tqnvbisr.git +http://testbdgit2.educoder.net/educoder/nfszy26f.git +http://testbdgit2.educoder.net/educoder/rfnhkvgo.git +http://testbdgit2.educoder.net/educoder/6omf2gbl.git +http://testbdgit2.educoder.net/educoder/x4qhb5k7.git +http://testbdgit2.educoder.net/educoder/jyz63ge5.git +http://testbdgit2.educoder.net/educoder/hfqwilp3.git +http://testbdgit2.educoder.net/educoder/aq9c4fy5.git +http://testbdgit2.educoder.net/educoder/tzshnbl8.git +http://testbdgit2.educoder.net/educoder/zm8qffrj.git +http://testbdgit2.educoder.net/educoder/szctor3e.git +http://testbdgit2.educoder.net/educoder/amcyzpvk.git +http://testbdgit2.educoder.net/educoder/fpy467o9.git +http://testbdgit2.educoder.net/educoder/w5nytxec.git +http://testbdgit2.educoder.net/educoder/icreqzu4.git +http://testbdgit2.educoder.net/educoder/2jf76xr5.git +http://testbdgit2.educoder.net/educoder/yl4a2qf5.git +http://testbdgit2.educoder.net/educoder/jgmcieqk.git +http://testbdgit2.educoder.net/educoder/hjtxy657.git +http://testbdgit2.educoder.net/educoder/47w6uyeh.git +http://testbdgit2.educoder.net/educoder/pr4vg7j5.git +http://testbdgit2.educoder.net/educoder/m6xn7z93.git +http://testbdgit2.educoder.net/educoder/f23fge9h.git +http://testbdgit2.educoder.net/educoder/cfo7lqhs.git +http://testbdgit2.educoder.net/educoder/4gnkqf3y.git +http://testbdgit2.educoder.net/educoder/k89bgonj.git +http://testbdgit2.educoder.net/educoder/k98qr7iw.git +http://testbdgit2.educoder.net/educoder/jel85v62.git +http://testbdgit2.educoder.net/educoder/zt2aqnb6.git +http://testbdgit2.educoder.net/educoder/7icqubfj.git +http://testbdgit2.educoder.net/educoder/2x59s3by.git +http://testbdgit2.educoder.net/educoder/mrvwxekj.git +http://testbdgit2.educoder.net/educoder/k5cruoyp.git +http://testbdgit2.educoder.net/educoder/rc6hw58u.git +http://testbdgit2.educoder.net/educoder/ygzf7v3k.git +http://testbdgit2.educoder.net/educoder/8ty6fgln.git +http://testbdgit2.educoder.net/educoder/wp5mbjg8.git +http://testbdgit2.educoder.net/educoder/oniuafxz.git +http://testbdgit2.educoder.net/educoder/aviljpmn.git +http://testbdgit2.educoder.net/educoder/iufg8573.git +http://testbdgit2.educoder.net/educoder/gc8xl2v9.git +http://testbdgit2.educoder.net/educoder/2wgmhvuk.git +http://testbdgit2.educoder.net/educoder/clx7ha6j.git +http://testbdgit2.educoder.net/educoder/bz9wxpvr.git +http://testbdgit2.educoder.net/educoder/uw95cg28.git +http://testbdgit2.educoder.net/educoder/4frpc7ix.git +http://testbdgit2.educoder.net/educoder/nas3v78t.git +http://testbdgit2.educoder.net/educoder/cbrys8f3.git +http://testbdgit2.educoder.net/educoder/ofj29enq.git +http://testbdgit2.educoder.net/educoder/btvk2w5h.git +http://testbdgit2.educoder.net/educoder/cztbjan5.git +http://testbdgit2.educoder.net/educoder/7atfm9vu.git +http://testbdgit2.educoder.net/educoder/cpxs3kfu.git +http://testbdgit2.educoder.net/educoder/5pfalzkh.git +http://testbdgit2.educoder.net/educoder/yf6covh2.git +http://testbdgit2.educoder.net/educoder/ocevha8x.git +http://testbdgit2.educoder.net/educoder/qtxkogfi.git +http://testbdgit2.educoder.net/educoder/pa8fh4m2.git +http://testbdgit2.educoder.net/educoder/n3ps8i4m.git +http://testbdgit2.educoder.net/educoder/5x9alvmc.git +http://testbdgit2.educoder.net/educoder/yl732ofk.git +http://testbdgit2.educoder.net/educoder/hvlgfjb7.git +http://testbdgit2.educoder.net/educoder/i9sfum58.git +http://testbdgit2.educoder.net/educoder/my9jcvio.git +http://testbdgit2.educoder.net/educoder/2myqxbce.git +http://testbdgit2.educoder.net/educoder/p4x9qmka.git +http://testbdgit2.educoder.net/educoder/aslcogwk.git +http://testbdgit2.educoder.net/educoder/eryg8fot.git +http://testbdgit2.educoder.net/educoder/ust5hgjm.git +http://testbdgit2.educoder.net/educoder/ypve8gbo.git +http://testbdgit2.educoder.net/educoder/ir768pfq.git +http://testbdgit2.educoder.net/educoder/ki98yelu.git +http://testbdgit2.educoder.net/educoder/i4nzvb7x.git +http://testbdgit2.educoder.net/educoder/58l7vb9f.git +http://testbdgit2.educoder.net/educoder/l859pqs3.git +http://testbdgit2.educoder.net/educoder/6rvpzn7x.git +http://testbdgit2.educoder.net/educoder/c5msxfe8.git +http://testbdgit2.educoder.net/educoder/cwa6igze.git +http://testbdgit2.educoder.net/educoder/vbnqglcw.git +http://testbdgit2.educoder.net/educoder/8bysvmcf.git +http://testbdgit2.educoder.net/educoder/u3ceh2xw.git +http://testbdgit2.educoder.net/educoder/heqtnza3.git +http://testbdgit2.educoder.net/educoder/uzoltjva.git +http://testbdgit2.educoder.net/educoder/mefykafs.git +http://testbdgit2.educoder.net/educoder/6jvypwgq.git +http://testbdgit2.educoder.net/educoder/h5wisac9.git +http://testbdgit2.educoder.net/educoder/52ufjw9m.git +http://testbdgit2.educoder.net/educoder/v2uxoifl.git +http://testbdgit2.educoder.net/educoder/an2ofy6k.git +http://testbdgit2.educoder.net/educoder/kao2rlf5.git +http://testbdgit2.educoder.net/educoder/uihap3wr.git +http://testbdgit2.educoder.net/educoder/wliam3nq.git +http://testbdgit2.educoder.net/educoder/7cpo6hel.git +http://testbdgit2.educoder.net/educoder/bmtlph7e.git +http://testbdgit2.educoder.net/educoder/b8n9twpf.git +http://testbdgit2.educoder.net/educoder/3cur5wz6.git +http://testbdgit2.educoder.net/educoder/h6ga29wv.git +http://testbdgit2.educoder.net/educoder/67kv4zmg.git +http://testbdgit2.educoder.net/educoder/buf6h8jf.git +http://testbdgit2.educoder.net/educoder/gce9ojqv.git +http://testbdgit2.educoder.net/educoder/jm2l6rwf.git +http://testbdgit2.educoder.net/educoder/4lwfjfrt.git +http://testbdgit2.educoder.net/educoder/5qsw32oj.git +http://testbdgit2.educoder.net/educoder/9yw36vxq.git +http://testbdgit2.educoder.net/educoder/93fivo6k.git +http://testbdgit2.educoder.net/educoder/nwy3x4t2.git +http://testbdgit2.educoder.net/educoder/ku9o2fcf.git +http://testbdgit2.educoder.net/educoder/s68uqlic.git +http://testbdgit2.educoder.net/educoder/4bajyohg.git +http://testbdgit2.educoder.net/educoder/qtfpscz8.git +http://testbdgit2.educoder.net/educoder/j5u7y6wn.git +http://testbdgit2.educoder.net/educoder/btku8vcx.git +http://testbdgit2.educoder.net/educoder/a9n8w2eu.git +http://testbdgit2.educoder.net/educoder/vze7ny25.git +http://testbdgit2.educoder.net/educoder/yz5aofe2.git +http://testbdgit2.educoder.net/educoder/r9nibvz4.git +http://testbdgit2.educoder.net/educoder/6cvxk3q8.git +http://testbdgit2.educoder.net/educoder/rmtuvk6z.git +http://testbdgit2.educoder.net/educoder/sbitr936.git +http://testbdgit2.educoder.net/educoder/sb6j4raf.git +http://testbdgit2.educoder.net/educoder/a7gfvh5s.git +http://testbdgit2.educoder.net/educoder/zsj6ao3c.git +http://testbdgit2.educoder.net/educoder/8x2epwk6.git +http://testbdgit2.educoder.net/educoder/cbnfxeiw.git +http://testbdgit2.educoder.net/educoder/ul47bqcn.git +http://testbdgit2.educoder.net/educoder/ltsnfy4x.git +http://testbdgit2.educoder.net/educoder/t53nvo8e.git +http://testbdgit2.educoder.net/educoder/yojwp2mb.git +http://testbdgit2.educoder.net/educoder/67nayvtg.git +http://testbdgit2.educoder.net/educoder/42fq3yx7.git +http://testbdgit2.educoder.net/educoder/f39hiscw.git +http://testbdgit2.educoder.net/educoder/jey9avks.git +http://testbdgit2.educoder.net/educoder/ascbpy86.git +http://testbdgit2.educoder.net/educoder/vagzfryl.git +http://testbdgit2.educoder.net/educoder/c6k5i82o.git +http://testbdgit2.educoder.net/educoder/utr8bp9a.git +http://testbdgit2.educoder.net/educoder/ul65ap4o.git +http://testbdgit2.educoder.net/educoder/bmulap4n.git +http://testbdgit2.educoder.net/educoder/nxj2sfvr.git +http://testbdgit2.educoder.net/educoder/vq5t9hea.git +http://testbdgit2.educoder.net/educoder/7g5l6kzr.git +http://testbdgit2.educoder.net/educoder/2y8t594n.git +http://testbdgit2.educoder.net/educoder/mlnpqx9r.git +http://testbdgit2.educoder.net/educoder/apgxmqs7.git +http://testbdgit2.educoder.net/educoder/vur567ha.git +http://testbdgit2.educoder.net/educoder/qwctfpjl.git +http://testbdgit2.educoder.net/educoder/5w6gh9m8.git +http://testbdgit2.educoder.net/educoder/fzhe4mpv.git +http://testbdgit2.educoder.net/educoder/vmygstfb.git +http://testbdgit2.educoder.net/educoder/uryh3e4i.git +http://testbdgit2.educoder.net/educoder/nbixuzkf.git +http://testbdgit2.educoder.net/educoder/zpkyj7bs.git +http://testbdgit2.educoder.net/educoder/79tpk5oy.git +http://testbdgit2.educoder.net/educoder/s93x58at.git +http://testbdgit2.educoder.net/educoder/6ymec92a.git +http://testbdgit2.educoder.net/educoder/7vqgbsfc.git +http://testbdgit2.educoder.net/educoder/fr5fom8n.git +http://testbdgit2.educoder.net/educoder/7uzyskn9.git +http://testbdgit2.educoder.net/educoder/g4fvywf6.git +http://testbdgit2.educoder.net/educoder/wa98h2ly.git +http://testbdgit2.educoder.net/educoder/u6i2o3qz.git +http://testbdgit2.educoder.net/educoder/enxbyiok.git +http://testbdgit2.educoder.net/educoder/2fuweqf8.git +http://testbdgit2.educoder.net/educoder/48flws5g.git +http://testbdgit2.educoder.net/educoder/yugrij4n.git +http://testbdgit2.educoder.net/educoder/gtbkvm58.git +http://testbdgit2.educoder.net/educoder/nes73wfv.git +http://testbdgit2.educoder.net/educoder/oztyjl4h.git +http://testbdgit2.educoder.net/educoder/f398leqr.git +http://testbdgit2.educoder.net/educoder/i3xutoze.git +http://testbdgit2.educoder.net/educoder/mfv6zrj7.git +http://testbdgit2.educoder.net/educoder/6ujfeqbh.git +http://testbdgit2.educoder.net/educoder/8x93tfqn.git +http://testbdgit2.educoder.net/educoder/fxv9bpcw.git +http://testbdgit2.educoder.net/eduforge/64xb9k2q.git +http://testbdgit2.educoder.net/educoder/5e4vcr7t.git +http://testbdgit2.educoder.net/educoder/qwaffs2p.git +http://testbdgit2.educoder.net/educoder/ose7482b.git +http://testbdgit2.educoder.net/educoder/wt2xfzny.git +http://testbdgit2.educoder.net/educoder/cuqnpzjv.git +http://testbdgit2.educoder.net/educoder/n3a8q9b2.git +http://testbdgit2.educoder.net/educoder/f9o4hpix.git +http://testbdgit2.educoder.net/educoder/bm9qr7ue.git +http://testbdgit2.educoder.net/educoder/nhlygi7p.git +http://testbdgit2.educoder.net/educoder/mf2vfngu.git +http://testbdgit2.educoder.net/educoder/x6tsevzy.git +http://testbdgit2.educoder.net/educoder/rjfbm74o.git +http://testbdgit2.educoder.net/educoder/ztbukf7e.git +http://testbdgit2.educoder.net/educoder/pf8yze9h.git +http://testbdgit2.educoder.net/educoder/nrug2mfz.git +http://testbdgit2.educoder.net/educoder/jswmzaxr.git +http://testbdgit2.educoder.net/educoder/wpxjzo3c.git +http://testbdgit2.educoder.net/educoder/zaohblre.git +http://testbdgit2.educoder.net/educoder/psx2h9kf.git +http://testbdgit2.educoder.net/educoder/ayju6fie.git +http://testbdgit2.educoder.net/educoder/5kp9guol.git +http://testbdgit2.educoder.net/educoder/c4ztkfb2.git +http://testbdgit2.educoder.net/educoder/kboupjtl.git +http://testbdgit2.educoder.net/educoder/bcvhs9u7.git +http://testbdgit2.educoder.net/educoder/26vljnb3.git +http://testbdgit2.educoder.net/educoder/zesqa3wi.git +http://testbdgit2.educoder.net/educoder/43phxgsf.git +http://testbdgit2.educoder.net/educoder/fbx6awcm.git +http://testbdgit2.educoder.net/educoder/i2s7jof5.git +http://testbdgit2.educoder.net/educoder/n2w4jrax.git +http://testbdgit2.educoder.net/educoder/4pou5tey.git +http://testbdgit2.educoder.net/eduforge/e9qr7cxi.git +http://testbdgit2.educoder.net/educoder/y6bg739q.git +http://testbdgit2.educoder.net/educoder/h32r58s7.git +http://testbdgit2.educoder.net/eduforge/hpr7ojgc-1.git +http://testbdgit2.educoder.net/educoder/c3j4hufp.git +http://testbdgit2.educoder.net/eduforge/o72clmi4.git +http://testbdgit2.educoder.net/educoder/qfz8o2r6.git +http://testbdgit2.educoder.net/educoder/rw3i8vf2.git +http://testbdgit2.educoder.net/educoder/shpwf3xf.git +http://testbdgit2.educoder.net/eduforge/vnw2fg5r.git +http://testbdgit2.educoder.net/innov/f2izon59.git +http://testbdgit2.educoder.net/innov/qlkpiusm.git +http://testbdgit2.educoder.net/innov/edu1547017399.git +http://testbdgit2.educoder.net/forge01/cermyt39.git +http://testbdgit2.educoder.net/innov/em3z8yn6.git +http://testbdgit2.educoder.net/innov/c8ynf526.git +http://testbdgit2.educoder.net/Hjqreturn/sx36oveq.git +http://testbdgit2.educoder.net/innov/t7sxkfab20190115135957.git +http://testbdgit2.educoder.net/innov/etlb3pn620190115140004.git +http://testbdgit2.educoder.net/innov/5jbomfrg20190115140011.git +http://testbdgit2.educoder.net/innov/6ecmbf7g20190115140015.git +http://testbdgit2.educoder.net/innov/f7jn8kex20190115140330.git diff --git a/lib/gitcheck/shixun_update_error.txt b/lib/gitcheck/shixun_update_error.txt new file mode 100644 index 000000000..ef9663c46 --- /dev/null +++ b/lib/gitcheck/shixun_update_error.txt @@ -0,0 +1,72 @@ +mbtclufr +9op3hs4j +96ctv7yr +rtmzxfke +ofqxthrf +czu9w4gj +9fpzj6et +pwhc865b +maozpx4l +y5wh2ofx +b5rzhpf3 +bs243nrl +47fn2yfb +kwotfxey +w5468sbp +fyekprio +q6ze5fih +b5hjq9zm +ky8pbqux +53phc7nq +b9j2yuix +9t3uphwk +iokm8ah2 +qlsy6xb4 +345bqhfi +v728fqia +4euftvf2 +f23sef5m +nhqis8m9 +qp72tb5x +gt3anszw +tng6heyf +nb9keawo +elgnbkp9 +4neslomg +lh35s6ma +xmc4rpay +qrpaxi6b +9fla2zry +efuibzrm +fzp3iu4w +pligsyn8 +glbksr29 +kfm7ghyc +p6hk3svf +p539gjhm +am5o73er +4x3qwrbe +fqosyl8g +of5z3fci +tb7hw62n +ie6zxg7r +4q2bmy9h +fpm3u5yb +nikx3ojt +vt82s9bq +ma59fefo +lxa39tfq +4gnockxf +nxwg84ey +fmie8nzb +w5nsr24v +4hn3efwc +h9ljfbq7 +nuv54t8b +2te9fmfq +vihnsayz +qhlyn82s +vw74kmfr +vcta36bz +henz425l +g529v38z diff --git a/lib/tasks/course_board_message_count.rake b/lib/tasks/course_board_message_count.rake new file mode 100644 index 000000000..dadd7c3d0 --- /dev/null +++ b/lib/tasks/course_board_message_count.rake @@ -0,0 +1,43 @@ +namespace :course_board do + desc 'transfer children message to root message board' + task children_message_transfer: :environment do + Board.find_each do |board| + Rails.logger.info("Current transfer board id: #{board.id} ~") + + root_subquery = board.messages.where(parent_id: nil).reorder(nil).pluck(:id) + if root_subquery.present? + children_subquery = Message.where(parent_id: root_subquery).reorder(nil).pluck(:id) + if children_subquery.present? + second_children_subquery = Message.where(parent_id: children_subquery).reorder(nil).pluck(:id) + + ids = children_subquery.concat(second_children_subquery).uniq + Message.where(id: ids).update_all(board_id: board.id) + end + end + + Board.reset_counters(board.id, :messages) + Rails.logger.info("transfer success ~") + end + end + + desc 'transfer root id && statistic descendants count' + task messages_descendants_count_transfer: :environment do + Message.root_nodes.find_each do |root| + Rails.logger.info("Current transfer root id: #{root.id} ~") + children_ids = root.children.pluck(:id) + next if children_ids.blank? + + second_children_ids = Message.where(parent_id: children_ids).pluck(:id) + + ids = children_ids.concat(second_children_ids).uniq + Message.where(id: ids).update_all(root_id: root.id) + + Message.reset_counters(root.id, :descendants) + Rails.logger.info("transfer success ~") + end + end + + # def logger(msg) + # puts msg + # end +end \ No newline at end of file diff --git a/lib/tasks/exercise_close_to_deadline_warn.rake b/lib/tasks/exercise_close_to_deadline_warn.rake index 598755db0..0212e138c 100644 --- a/lib/tasks/exercise_close_to_deadline_warn.rake +++ b/lib/tasks/exercise_close_to_deadline_warn.rake @@ -5,37 +5,41 @@ namespace :exercise_deadline_warn do task :deadline_warn => :environment do puts "--------------------------------exercise_nearly_end start" # 统一设置发布时间的测验 - exercises = Exercise.where("exercise_status = 2 and unified_setting = 1 and end_time <=? and end_time > ?", Time.now + 86400, Time.now + 82800) + exercises = Exercise.where("exercise_status = 2 and unified_setting = 1 and end_time <=? and end_time > ?", Time.now + 86400, Time.now + 84600) exercises.each do |exercise| - if exercise.tidings.where(:parent_container_type => "NearlyEnd").count == 0 + if exercise.tidings.where(parent_container_type: "NearlyEnd").count == 0 course = exercise.course tid_str = "" - exercise.exercise_users.where(:commit_status => 0).find_each do |student| + exercise.exercise_users.where(commit_status: 0).find_each do |student| tid_str += "," if tid_str != "" - tid_str += "(#{student.user_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'NearlyEnd', #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + tid_str += "(#{student.user_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'NearlyEnd', + #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" end if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str + tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, + parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str ActiveRecord::Base.connection.execute tid_sql end end end # 分组设置发布时间的测验 - exercise_group_settings = ExerciseGroupSetting.where("end_time <=? and end_time > ?", Time.now + 86400, Time.now + 82800) + exercise_group_settings = ExerciseGroupSetting.where("end_time <=? and end_time > ?", Time.now + 86400, Time.now + 84600) exercise_group_settings.each do |exercise_group| exercise = exercise_group.exercise if exercise.present? course = exercise.course - members = course.course_members.where(:course_group_id => exercise_group.course_group_id) - if exercise.tidings.where(:parent_container_type => "NearlyEnd", :user_id => members.map(&:user_id)).count == 0 + members = course.students.where(course_group_id: exercise_group.course_group_id) + if exercise.tidings.where(parent_container_type: "NearlyEnd", user_id: members.pluck(:user_id)).count == 0 tid_str = "" - exercise.exercise_users.where(:commit_status => 0, :user_id => members.map(&:user_id)).find_each do |member| + exercise.exercise_users.where(commit_status: 0, user_id: members.pluck(:user_id)).find_each do |member| tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id},#{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'NearlyEnd', #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + tid_str += "(#{member.user_id},#{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'NearlyEnd', + #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" end if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str + tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, + parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str ActiveRecord::Base.connection.execute tid_sql end end diff --git a/lib/tasks/exercise_publish.rake b/lib/tasks/exercise_publish.rake index 8a13154cc..a26de1499 100644 --- a/lib/tasks/exercise_publish.rake +++ b/lib/tasks/exercise_publish.rake @@ -1,211 +1,268 @@ -#coding=utf-8 - -namespace :exercise_publish do - desc "publish exercise and end exercise" - def get_mulscore(question, user) - ecs = ExerciseAnswer.where("user_id =? and exercise_question_id =?", user.id, question.id) - arr = [] - ecs.each do |ec| - arr << ec.exercise_choice.choice_position - end - #arr = arr.sort - str = arr.sort.join("") - return str - end - - def tran_base64_decode64 str - if str.blank? - str - else - s_size = str.size % 4 - if s_size != 0 - str += "=" * (4 - s_size) - end - Base64.decode64(str.tr("-_", "+/")).force_encoding("utf-8") - end - end - - # def calculate_student_score(exercise, user) - # score = 0 - # score1 = 0 - # score2 = 0 - # score3 = 0 - # score4 = 0 - # exercise_qustions = exercise.exercise_questions - # exercise_qustions.each do |question| - # if question.question_type != 5 - # answer = question.exercise_answers.where("#{ExerciseAnswer.table_name}.user_id = #{user.id}") - # if question.question_type == 3 - # standard_answer =[] - # question.exercise_standard_answers.each do |answer| - # standard_answer << answer.answer_text.strip.downcase - # end - # else - # standard_answer = question.exercise_standard_answers.first - # end - # - # unless answer.empty? - # # 问答题有多个答案 - # if question.question_type == 3 && !standard_answer.empty? - # if standard_answer.include?(answer.first.answer_text.strip.downcase) - # score1 = score1+ question.question_score unless question.question_score.nil? - # end - # elsif question.question_type == 1 && !standard_answer.nil? - # if answer.first.exercise_choice.choice_position == standard_answer.exercise_choice_id - # score2 = score2 + question.question_score unless question.question_score.nil? - # end - # elsif question.question_type == 2 && !standard_answer.nil? - # arr = get_mulscore(question, user) - # if arr.to_i == standard_answer.exercise_choice_id - # score3 = score3 + question.question_score unless question.question_score.nil? - # end - # end - # end - # else - # question.exercise_shixun_challenges.each do |exercise_cha| - # game = Game.where(:user_id => user.id, :challenge_id => exercise_cha.challenge_id).first - # if game.present? - # exercise_cha_score = 0 - # answer_status = 0 - # cha_path = exercise_cha.challenge.path.present? ? exercise_cha.challenge.path.split(";") : [] - # challeng_path = cha_path.reject(&:blank?)[0].try(:strip) - # if game.status == 2 && game.final_score >= 0 - # exercise_cha_score = exercise_cha.question_score - # answer_status = 1 - # end - # if exercise_cha.exercise_shixun_answers.where(:user_id => user.id).empty? - # if GameCode.where(:game_id => game.try(:id), :path => challeng_path).first.present? - # game_code = GameCode.where(:game_id => game.try(:id), :path => challeng_path).first - # code = game_code.try(:new_code) - # else - # begin - # g = Gitlab.client - # Rails.logger.info "commit_exercise_path---- #{challeng_path}" - # if game.present? - # code = g.files(game.myshixun.gpid, challeng_path, "master").try(:content) - # else - # code = g.files(question.shixun.gpid, challeng_path, "master").try(:content) - # end - # code = tran_base64_decode64(code) - # rescue Exception => e - # @error_messages = e.message - # Rails.logger.info "commit_exercise---- #{@error_messages}" - # end - # end - # ExerciseShixunAnswer.create(:exercise_question_id => question.id, :exercise_shixun_challenge_id => exercise_cha.id, :user_id => user.id, - # :score => exercise_cha_score, :answer_text => code, :status => answer_status) - # - # end - # score4 += exercise_cha_score - # end - # end - # end - # end - # score = score1 + score2 + score3 + score4 - # end - - task :publish => :environment do - Rails.logger.info("log--------------------------------exercise_publish start") - puts "--------------------------------exercise_publish start" - exercises = Exercise.where("publish_time is not null and exercise_status = 1 and publish_time <=?",Time.now) - exercises.each do |exercise| - exercise.update_column('exercise_status', 2) - course = exercise.course - tid_str = "" - course.teachers.find_each do |member| - tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if exercise.unified_setting - course.student.find_each do |student| - tid_str += "," if tid_str != "" - tid_str += "(#{student.student_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - end - if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str - ActiveRecord::Base.connection.execute tid_sql - end - - if exercise.exercise_users.count == 0 - str = "" - course.student.find_each do |student| - str += "," if str != "" - str += "(#{student.user_id}, #{exercise.id}, 0, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - - if str != "" - sql = "insert into exercise_users (user_id, exercise_id, commit_status, created_at, updated_at) values" + str - ActiveRecord::Base.connection.execute sql - end - end - - if exercise.course_acts.size == 0 - exercise.course_acts << CourseActivity.new(:user_id => exercise.user_id,:course_id => exercise.course_id) - end - end - - # 分组设置发布时间的测验 - exercise_group_settings = ExerciseGroupSetting.where("publish_time < ? and publish_time > ?", Time.now + 1800, Time.now - 1800) - exercise_group_settings.each do |exercise_group| - exercise = exercise_group.exercise - if exercise.present? - course = exercise.course - exercise.update_attributes(:exercise_status => 2) if exercise.exercise_status == 1 - tid_str = "" - members = course.students.where(:course_group_id => exercise_group.course_group_id) - members.find_each do |member| - tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id},#{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str - ActiveRecord::Base.connection.execute tid_sql - end - end - end - Rails.logger.info("log--------------------------------exercise_publish end") - puts "--------------------------------exercise_publish end" - end - - task :end => :environment do - exercises = Exercise.where("end_time <=? and exercise_status = 2",Time.now) - exercises.each do |exercise| - course = exercise.course - exercise.update_column('exercise_status', 3) - - exercise.exercise_users.each do |exercise_user| - if exercise_user.commit_status == 0 && !exercise_user.start_at.nil? - exercise_user.update_attributes(:commit_status => 1, :end_at => Time.now, :status => true) - - s_score = calculate_student_score(exercise, exercise_user.user)[:total_score] - exercise_user.update_attributes(:objective_score => s_score, :score => (s_score + (exercise_user.subjective_score && exercise_user.subjective_score > 0 ? exercise_user.subjective_score : 0))) - if exercise_user.user.exercise_answer.where(:exercise_question_id => exercise.exercise_questions.where(:question_type => 4).map(&:id)).empty? - exercise_user.update_attributes(:subjective_score => 0) - end - end - end - end - - all_exercises = Exercise.where("end_time > ? and exercise_status = 2",Time.now) - exercise_ids = all_exercises.blank? ? "(-1)" : "(" + all_exercises.map(&:id).join(",") + ")" - ExerciseGroupSetting.where("end_time <= '#{Time.now}' and exercise_id in #{exercise_ids}").each do |exercise_setting| - exercise = exercise_setting.exercise - - users = exercise.course.students.where(:course_group_id => exercise_setting.course_group_id) - exercise_users = exercise.exercise_users.where(:user_id => users.map(&:user_id)) - - exercise_users.each do |exercise_user| - if exercise_user.commit_status == 0 && !exercise_user.start_at.nil? - exercise_user.update_attributes(:commit_status => 1, :end_at => Time.now, :status => true) - - s_score = calculate_student_score(exercise, exercise_user.user)[:total_score] - exercise_user.update_attributes(:objective_score => s_score, :score => (s_score + (exercise_user.subjective_score && exercise_user.subjective_score > 0 ? exercise_user.subjective_score : 0))) - if exercise_user.user.exercise_answer.where(:exercise_question_id => exercise.exercise_questions.where(:question_type => 4).map(&:id)).empty? - exercise_user.update_attributes(:subjective_score => 0) - end - end - end - end - end -end +# #coding=utf-8 +# +# namespace :exercise_publish do +# desc "publish exercise and end exercise" +# def get_mulscore(question, user) +# ecs = ExerciseAnswer.where("user_id =? and exercise_question_id =?", user.id, question.id) +# arr = [] +# ecs.each do |ec| +# arr << ec.exercise_choice.choice_position +# end +# #arr = arr.sort +# str = arr.sort.join("") +# return str +# end +# +# def tran_base64_decode64 str +# if str.blank? +# str +# else +# s_size = str.size % 4 +# if s_size != 0 +# str += "=" * (4 - s_size) +# end +# Base64.decode64(str.tr("-_", "+/")).force_encoding("utf-8") +# end +# end +# +# #计算试卷的总分和试卷的答题状态 +# def calculate_student_score(exercise,user) +# score1 = 0.0 #选择题/判断题 +# score2 = 0.0 #填空题 +# score5 = 0.0 #实训题 +# ques_stand = [] #问题是否正确 +# exercise_questions = exercise.exercise_questions +# exercise_questions.each do |q| +# if q.question_type != 5 +# answers_content = q.exercise_answers.search_answer_users("user_id",user.id) #学生的答案 +# else +# answers_content = q.exercise_shixun_answers.search_shixun_answers("user_id",user.id) #学生的答案 +# end +# if q.question_type <= 2 #为选择题或判断题时 +# answer_choice_array = [] +# answers_content.each do |a| +# answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 +# end +# user_answer_content = answer_choice_array.sort +# standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个 +# if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 +# if standard_answer.count > 0 +# multi_each_score = (q.question_score / standard_answer.count) #当多选答案正确时,每个answer的分数均摊。 +# else +# multi_each_score = 0.0 +# end +# answers_content.update_all(:score => multi_each_score) +# score1 = score1 + q.question_score +# end +# elsif q.question_type == 3 #填空题 +# null_standard_answer = q.exercise_standard_answers +# standard_answer_array = null_standard_answer.select(:exercise_choice_id,:answer_text) +# standard_answer_ids = standard_answer_array.pluck(:exercise_choice_id).reject(&:blank?).uniq #标准答案的exercise_choice_id数组 +# standard_answer_count = standard_answer_ids.count +# if standard_answer_count > 0 #存在标准答案时才有分数 +# each_standard_score = (q.question_score.to_f / standard_answer_count).round(1) #每一空的得分 +# else +# each_standard_score = 0.0 +# end +# if q.is_ordered +# answers_content.each do |u| +# i_standard_answer = standard_answer_array.where(exercise_choice_id:u.exercise_choice_id).pluck(:answer_text).reject(&:blank?).map!(&:downcase) #该选项的全部标准答案 +# if i_standard_answer.include?(u.answer_text.downcase) #该空的标准答案包含用户的答案才有分数 +# u.update_attribute("score",each_standard_score) +# score2 = score2 + each_standard_score +# end +# end +# else +# st_answer_text = standard_answer_array.pluck(:answer_text).reject(&:blank?).map!(&:downcase) +# answers_content.each do |u| +# u_answer_text = u.answer_text.downcase +# if st_answer_text.include?(u_answer_text) #只要标准答案包含用户的答案,就有分数。同时,下一次循环时,就会删除该标准答案。防止用户的相同答案获分 +# u.update_attribute("score",each_standard_score) +# score2 = score2 + each_standard_score +# st_answer_text.delete(u_answer_text) +# end +# end +# end +# elsif 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 +# answer_status = 0 +# cha_path = exercise_cha.challenge.path.present? ? exercise_cha.challenge.path.split(";").reject(&:blank?) : [] +# if game.status == 2 && game.final_score >= 0 +# exercise_cha_score = game.real_score exercise_cha.question_score #每一关卡的得分 +# answer_status = 1 +# end +# if exercise_cha.exercise_shixun_answers.search_shixun_answers("user_id",user.id).blank? #把关卡的答案存入试卷的实训里 +# game_challenge = game.game_codes.search_challenge_path(cha_path).first +# if game_challenge.present? +# game_code = game_challenge +# code = game_code.try(:new_code) +# else +# begin +# content = GitService.file_content(repo_path: exercise_cha.shixun.repo_path, path: cha_path)["content"] +# decode_content = nil +# if content.present? +# content = Base64.decode64(content) +# cd = CharDet.detect(content) +# decode_content = +# if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8 +# content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '}) +# else +# content.force_encoding('UTF-8') +# end +# end +# decode_content +# rescue Exception => e +# uid_logger_error(e.message) +# raise Educoder::TipException.new("文档内容获取异常") +# end +# code = git_fle_content(exercise_cha.shixun.repo_path,cha_path) +# end +# sx_option = { +# :exercise_question_id => q.id, +# :exercise_shixun_challenge_id => exercise_cha.id, +# :user_id => user.id, +# :score => exercise_cha_score, +# :answer_text => code, +# :status => answer_status +# } +# ex_shixun_answer = ExerciseShixunAnswer.new(sx_option) +# ex_shixun_answer.save! +# end +# score5 += exercise_cha_score +# end +# end +# end +# user_scores = answers_content.score_reviewed.pluck(:score).sum +# if user_scores > 0 +# stand_answer = 1 +# else +# stand_answer = 0 +# end +# ques_option = { +# "q_id":q.id, #该问题的id +# "q_type":q.question_type, +# "q_position":q.question_number, #该问题的位置 +# "stand_status":stand_answer, #该问题是否正确,1为正确,0为错误 +# "user_score":user_scores #每个问题的总得分 +# } +# ques_stand.push(ques_option) +# end +# total_score = score1 + score2 + score5 +# { +# "total_score":total_score, +# "stand_status":ques_stand +# } +# end +# +# task :publish => :environment do +# Rails.logger.info("log--------------------------------exercise_publish start") +# puts "--------------------------------exercise_publish start" +# exercises = Exercise.where("publish_time is not null and exercise_status = 1 and publish_time <=?",Time.now) +# exercises.each do |exercise| +# exercise.update_column('exercise_status', 2) +# course = exercise.course +# tid_str = "" +# course.teachers.find_each do |member| +# tid_str += "," if tid_str != "" +# tid_str += "(#{member.user_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" +# end +# if exercise.unified_setting +# course.student.find_each do |student| +# tid_str += "," if tid_str != "" +# tid_str += "(#{student.student_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" +# end +# end +# if tid_str != "" +# tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str +# ActiveRecord::Base.connection.execute tid_sql +# end +# +# if exercise.exercise_users.count == 0 +# str = "" +# course.student.find_each do |student| +# str += "," if str != "" +# str += "(#{student.user_id}, #{exercise.id}, 0, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" +# end +# +# if str != "" +# sql = "insert into exercise_users (user_id, exercise_id, commit_status, created_at, updated_at) values" + str +# ActiveRecord::Base.connection.execute sql +# end +# end +# +# if exercise.course_acts.size == 0 +# exercise.course_acts << CourseActivity.new(:user_id => exercise.user_id,:course_id => exercise.course_id) +# end +# end +# +# # 分组设置发布时间的测验 +# exercise_group_settings = ExerciseGroupSetting.where("publish_time < ? and publish_time > ?", Time.now + 1800, Time.now - 1800) +# exercise_group_settings.each do |exercise_group| +# exercise = exercise_group.exercise +# if exercise.present? +# course = exercise.course +# exercise.update_attributes(:exercise_status => 2) if exercise.exercise_status == 1 +# tid_str = "" +# members = course.students.where(:course_group_id => exercise_group.course_group_id) +# members.find_each do |member| +# tid_str += "," if tid_str != "" +# tid_str += "(#{member.user_id},#{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" +# end +# if tid_str != "" +# tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str +# ActiveRecord::Base.connection.execute tid_sql +# end +# end +# end +# Rails.logger.info("log--------------------------------exercise_publish end") +# puts "--------------------------------exercise_publish end" +# end +# +# task :end => :environment do +# # include ExercisesHelper +# # include ApplicationController +# +# exercises = Exercise.where("end_time <=? and exercise_status = 2",Time.now) +# exercises.each do |exercise| +# course = exercise.course +# exercise.update_column('exercise_status', 3) +# +# exercise.exercise_users.each do |exercise_user| +# if exercise_user.commit_status == 0 && !exercise_user.start_at.nil? +# exercise_user.update_attributes(:commit_status => 1, :end_at => Time.now, :status => true) +# +# s_score = calculate_student_score(exercise, exercise_user.user)[:total_score] +# exercise_user.update_attributes(:objective_score => s_score, :score => (s_score + (exercise_user.subjective_score && exercise_user.subjective_score > 0 ? exercise_user.subjective_score : 0))) +# if exercise_user.user.exercise_answers.where(:exercise_question_id => exercise.exercise_questions.where(:question_type => 4).map(&:id)).empty? +# exercise_user.update_attributes(:subjective_score => 0) +# end +# end +# end +# end +# +# all_exercises = Exercise.where("end_time > ? and exercise_status = 2",Time.now) +# exercise_ids = all_exercises.blank? ? "(-1)" : "(" + all_exercises.map(&:id).join(",") + ")" +# ExerciseGroupSetting.where("end_time <= '#{Time.now}' and exercise_id in #{exercise_ids}").each do |exercise_setting| +# exercise = exercise_setting.exercise +# +# users = exercise.course.students.where(:course_group_id => exercise_setting.course_group_id) +# exercise_users = exercise.exercise_users.where(:user_id => users.map(&:user_id)) +# +# exercise_users.each do |exercise_user| +# if exercise_user.commit_status == 0 && !exercise_user.start_at.nil? +# exercise_user.update_attributes(:commit_status => 1, :end_at => Time.now, :status => true) +# +# s_score = calculate_student_score(exercise, exercise_user.user)[:total_score] +# exercise_user.update_attributes(:objective_score => s_score, :score => (s_score + (exercise_user.subjective_score && exercise_user.subjective_score > 0 ? exercise_user.subjective_score : 0))) +# if exercise_user.user.exercise_answers.where(:exercise_question_id => exercise.exercise_questions.where(:question_type => 4).map(&:id)).empty? +# exercise_user.update_attributes(:subjective_score => 0) +# end +# end +# end +# end +# Rails.logger.info("log--------------------------------exercise_end completed") +# end +# end diff --git a/lib/tasks/git_check.rake b/lib/tasks/git_check.rake new file mode 100644 index 000000000..a5e95eedc --- /dev/null +++ b/lib/tasks/git_check.rake @@ -0,0 +1,53 @@ +# 需要做的几件事: +# 1、检测两边(TPM\TPI)同步后有更新的仓库 +# + +namespace :git do + desc "检测是否TPM是否需要更新" + task :shixun_check_update => :environment do + g = Gitlab.client + file_txt = File.new("lib/gitcheck/shixun_update.txt", "r+") + file_error_txt = File.new("lib/gitcheck/shixun_update_error.txt", "r+") + host = EduSetting.find_by_name("git_address_domain").try(:value) + Shixun.find_each do |shixun| + begin + gitlab_commit = g.commits(shixun.gpid, :ref_name => 'master').first.try(:id) + repo_name = shixun.repo_name + git_commit = GitService.commits(repo_path: "#{repo_name}.git").first["id"] + git_url = host + "/" + repo_name + ".git\n" + if git_commit != gitlab_commit + file_txt.syswrite(git_url) + end + rescue + file_error_txt.syswrite("#{shixun.identifier}\n") + end + end + end + + desc "检测版本库是否有更新" + task :myshixuns_check_update => :environment do + g = Gitlab.client + file_txt = File.new("lib/gitcheck/myshixun_update.txt", "r+") + file_error_txt = File.new("lib/gitcheck/myshixun_update_error.txt", "r+") + host = EduSetting.find_by_name("git_address_domain").try(:value) + Myshixun.find_each do |myshixun| + begin + gitlab_commit = g.commits(myshixun.gpid, :ref_name => 'master').first.try(:id) + repo_name = myshixun.repo_name + git_commit = GitService.commits(repo_path: "#{repo_name}.git").first["id"] + git_url = host + "/" + repo_name + ".git\n" + if git_commit != gitlab_commit + file_txt.syswrite(git_url) + end + rescue + file_error_txt.syswrite("#{myshixun.identifier}\n") + end + end + end + + + # 检测TPI没有迁移过来的 + task :check => :environment do + + end +end diff --git a/lib/tasks/gitlab.rake b/lib/tasks/gitlab.rake index 396f197d3..0d872991b 100644 --- a/lib/tasks/gitlab.rake +++ b/lib/tasks/gitlab.rake @@ -10,7 +10,7 @@ namespace :sync do puts repo_name myshixun.update_column(:repo_name, repo_name) rescue Exception => e - Rails.logger.error("e.message") + Rails.logger.error("#{e.message}") end end end @@ -26,7 +26,27 @@ namespace :sync do puts repo_name shixun.update_column(:repo_name, repo_name) rescue Exception => e - Rails.logger.error("e.message") + Rails.logger.error("#{e.message}") + end + end + end + + + task :check => :environment do + g = Gitlab.client + shixuns = Shixun.where("repo_name is null and fork_from is not null") + shixuns.find_each do |shixun| + begin + puts shixun.identifier + original_shixun = Shixun.find(fork_from) + + gshixun = g.fork(original_shixun.gpid, shixun.owner.try(:gid)) + + repo_name = g.project(gshixun.id).path_with_namespace + puts repo_name + shixun.update_attributes(:repo_name => repo_name, :gpid => gshixun.id) + rescue Exception => e + Rails.logger.error("#{e.message}") end end end diff --git a/lib/tasks/graduation_task.rake b/lib/tasks/graduation_task.rake index dada0303d..58f7764d0 100644 --- a/lib/tasks/graduation_task.rake +++ b/lib/tasks/graduation_task.rake @@ -5,32 +5,14 @@ namespace :graduation_task do tasks = GraduationTask.where("publish_time is not null and publish_time <= '#{Time.now}' and status = 0") tasks.each do |task| task.update_attributes(status: 1) - course = task.course - members = course.course_members - if !course.nil? && !members.empty? - tid_str = "" - members.find_each do |member| - tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id}, #{task.user_id}, #{task.id}, 'GraduationTask', #{task.id}, 'TaskPublish', - #{course.id}, 'Course', 0, 'GraduationTask', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', - '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, - parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, - updated_at) values" + tid_str - ActiveRecord::Base.connection.execute tid_sql - end - end + GraduationTaskPublishNotifyJob.perform_later(task.id) - if task.course_acts.size == 0 - task.course_acts << CourseActivity.new(user_id: task.user_id, course_id: task.course_id) - end + task.course_acts << CourseActivity.new(user_id: task.user_id, course_id: task.course_id) if !task.course_acts.exists? end end task :nearly_end => :environment do - tasks = GraduationTask.where("end_time <=? and end_time > ?", Time.now + 86400, Time.now + 82800) + tasks = GraduationTask.where("end_time <=? and end_time > ?", Time.now + 86400, Time.now + 84600) tasks.each do |task| if task.tidings.where(parent_container_type: "NearlyEnd").count == 0 course = task.course @@ -62,37 +44,11 @@ namespace :graduation_task do tasks = GraduationTask.where("cross_comment = 1 and comment_time is not null and comment_time <= '#{Time.now}' and status = 2") tasks.each do |task| if task.comment_status == 4 - course = task.course - task.graduation_task_group_assignations.each do |assignation| - graduation_group = assignation.graduation_group - assign_group = assignation.assign_group - if graduation_group.present? && assign_group.present? - course_group_ids = course.teacher_course_groups.where(course_member_id: graduation_group.course_members.pluck(:id)).pluck(:course_group_id) - graduation_works = task.graduation_works.where(user_id: course.course_members.where(:course_group_id => course_group_ids).map(&:user_id), - work_status: [1, 2]) - if assign_group.course_members.count <= task.comment_num - graduation_works.each do |work| - assign_group.course_members.each do |member| - work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new( - graduation_group_id: assign_group.id, user_id: member.user_id, graduation_task_id: task.id) - end - end - else - member_user_ids = assign_group.course_members.pluck(:user_id) - count = 0 - graduation_works.each do |work| - for i in 1 .. task.comment_num - assign_user_id = member_user_ids[count % member_user_ids.size] - work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new( - graduation_group_id: assign_group.id, user_id: assign_user_id, graduation_task_id: task.id) - count += 1 - end - end - end - end - end + GraduationTaskCrossCommentJob.perform_later(task.id) end task.update_attributes(status: 3) + + # 给老师发消息 tid_str = "" task.course.teachers.find_each do |member| tid_str += "," if tid_str != "" diff --git a/lib/tasks/homework_endtime.rake b/lib/tasks/homework_endtime.rake index feba02670..555903980 100644 --- a/lib/tasks/homework_endtime.rake +++ b/lib/tasks/homework_endtime.rake @@ -4,7 +4,7 @@ namespace :homework_endtime do desc "send a message for Job deadline" task :message => :environment do # 统一设置发布时间的作业 - homeworks = HomeworkCommon.where("unified_setting = 1 and end_time <=? and end_time > ?", Time.now + 86400, Time.now + 82800) + homeworks = HomeworkCommon.includes(:course).where("unified_setting = 1 and end_time <=? and end_time > ?", Time.now + 86400, Time.now + 84600) homeworks.each do |homework| if homework.tidings.where(:parent_container_type => "NearlyEnd").count == 0 course = homework.course @@ -25,7 +25,7 @@ namespace :homework_endtime do end # 分组设置发布时间的作业 - homework_group_settings = HomeworkGroupSetting.where("end_time <=? and end_time > ?", Time.now + 86400, Time.now + 82800) + homework_group_settings = HomeworkGroupSetting.includes(:homework_common).where("end_time <=? and end_time > ?", Time.now + 86400, Time.now + 84600) homework_group_settings.each do |homework_group| homework = homework_group.homework_common if homework.present? @@ -52,8 +52,8 @@ namespace :homework_endtime do # 匿评截止时间快到了 task :evaluation_nearly_end => :environment do - homework_detail_manuals = HomeworkDetailManual.where("homework_detail_manuals.comment_status = 3 and evaluation_end <=? - and evaluation_end > ? ", Time.now + 86400, Time.now + 82800) + homework_detail_manuals = HomeworkDetailManual.includes(:homework_common).where("homework_detail_manuals.comment_status = 3 and evaluation_end <=? + and evaluation_end > ? ", Time.now + 86400, Time.now + 84600) homework_detail_manuals.each do |homework_detail_manual| homework_common = homework_detail_manual.homework_common if homework_common.present? @@ -85,7 +85,7 @@ namespace :homework_endtime do # 匿评申诉截止时间快到了 task :appeal_nearly_end => :environment do homework_detail_manuals = HomeworkDetailManual.where("homework_detail_manuals.comment_status = 4 and appeal_time <=? - and appeal_time > ?", Time.now + 86400, Time.now + 82800) + and appeal_time > ?", Time.now + 86400, Time.now + 84600) homework_detail_manuals.each do |homework_detail_manual| homework_common = homework_detail_manual.homework_common if homework_common.present? diff --git a/lib/tasks/homework_evaluation.rake b/lib/tasks/homework_evaluation.rake index 84c7c888f..757b07877 100644 --- a/lib/tasks/homework_evaluation.rake +++ b/lib/tasks/homework_evaluation.rake @@ -12,7 +12,7 @@ namespace :homework_evaluation do task :start_evaluation => :environment do Rails.logger.info("log--------------------------------start_evaluation start") puts "--------------------------------start_evaluation start" - homework_detail_manuals = HomeworkDetailManual.where("evaluation_start <= '#{Time.now}' and + homework_detail_manuals = HomeworkDetailManual.includes(homework_common: :course).where("evaluation_start <= '#{Time.now}' and (homework_detail_manuals.comment_status < 3)") homework_detail_manuals.each do |homework_detail_manual| homework_common = homework_detail_manual.homework_common @@ -23,59 +23,11 @@ namespace :homework_evaluation do else student_works = homework_common.student_works.has_committed end - if student_works.present? && student_works.length >= 2 - if homework_common.homework_type == "group" - student_work_projects = homework_common.student_works.where("work_status != 0").shuffle - student_work_projects.each_with_index do |pro_work, pro_index| - n = homework_detail_manual.evaluation_num - n = (n < student_works.size && n != -1) ? n : student_works.size - 1 - work_index = -1 - student_works.each_with_index do |stu_work, stu_index| - if stu_work.group_id.to_i == pro_work.group_id.to_i - work_index = stu_index - end - end - assigned_homeworks = get_assigned_homeworks(student_works, n, work_index) - assigned_homeworks.each do |h| - student_works_evaluation_distributions = StudentWorksEvaluationDistribution.new(user_id: pro_work.user_id, student_work_id: h.id) - student_works_evaluation_distributions.save - end - #更新CourseHomeworkStatistics中该学生的待匿评数 - # course_statistics = CourseHomeworkStatistics.find_by_course_id_and_user_id(homework_common.course_id, pro_work.user_id) - # course_statistics.update_attribute('un_evaluation_work_num', course_statistics.un_evaluation_work_num + n) if course_statistics - end - else - student_works = student_works.shuffle - student_works.each_with_index do |work, index| - user = work.user - n = homework_detail_manual.evaluation_num - n = (n < student_works.size && n != -1) ? n : student_works.size - 1 - assigned_homeworks = get_assigned_homeworks(student_works, n, index) - assigned_homeworks.each do |h| - student_works_evaluation_distributions = StudentWorksEvaluationDistribution.new(user_id: user.id, student_work_id: h.id) - student_works_evaluation_distributions.save - end + if student_works.present? && student_works.length >= 2 + HomeworkEvaluationCommentAssginJob.perform_later(homework_common.id) - #更新CourseHomeworkStatistics中该学生的待匿评数 - # course_statistics = CourseHomeworkStatistics.find_by_course_id_and_user_id(homework_common.course_id, user.id) - # course_statistics.update_attribute('un_evaluation_work_num', course_statistics.un_evaluation_work_num + n) if course_statistics - end - end homework_detail_manual.update_column('comment_status', 3) - # 匿评开启消息邮件通知,# 所有人 - str = "" - homework_common.course.course_members.pluck(:user_id).uniq.each do |user_id| - str += "," if str != "" - str += "('#{user_id}', '#{homework_common.user_id}', '#{homework_common.id}','HomeworkCommon','#{homework_common.id}', - 'AnonymousComment',#{homework_common.course_id},'Course',0,'HomeworkCommon', - '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if str != "" - sql = "insert into tidings (user_id,trigger_user_id,container_id, container_type, parent_container_id, - parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + str - ActiveRecord::Base.connection.execute sql - end else #作业数小于2,启动失败, 只给老师和助教发 extra = "作品数量低于两个,无法开启匿评" @@ -83,20 +35,8 @@ namespace :homework_evaluation do else extra = "存在尚未截止的分班,无法开启匿评" end + HomeworkEvaluationStartNotifyJob.perform_later(homework_common.id, extra) if extra.present? - str = '' - homework_common.course.teachers.each do |mem| - str += "," if str != "" - str += "('#{mem.user.id}', '#{homework_common.user_id}', '#{homework_common.id}','HomeworkCommon','#{homework_common.id}', - 'AnonymousCommentFail',#{homework_common.course_id},'Course',0,'System','#{extra}', - '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if str != "" - sql = "insert into tidings (user_id,trigger_user_id,container_id, container_type,parent_container_id, - parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, extra, created_at, - updated_at) values" + str - ActiveRecord::Base.connection.execute sql - end homework_detail_manual.update_attributes(:evaluation_start => nil, :evaluation_end => nil, :absence_penalty => 0, :evaluation_num => 0, :appeal_time => nil, :appeal_penalty => 0) homework_common.update_attributes(:anonymous_comment => 0, :anonymous_appeal => 0) @@ -110,67 +50,19 @@ namespace :homework_evaluation do #自动关闭匿评的任务 task :end_evaluation => :environment do - homework_detail_manuals = HomeworkDetailManual.where("evaluation_end <= '#{Time.now}' and homework_detail_manuals.comment_status = 3") + homework_detail_manuals = HomeworkDetailManual.includes(:homework_common).where("evaluation_end <= '#{Time.now}' and homework_detail_manuals.comment_status = 3") homework_detail_manuals.each do |homework_detail_manual| homework_common = homework_detail_manual.homework_common if homework_common.anonymous_comment #开启匿评状态才可关闭匿评 - #计算缺评扣分 参与匿评 - work_ids = "(" + homework_common.student_works.has_committed.map(&:id).join(",") + ")" - - homework_common.student_works.where("work_status != 0").each do |student_work| - absence_penalty_count = student_work.user.student_works_evaluation_distributions.where("student_work_id IN #{work_ids}").count - - student_work.user.student_works_scores.where("student_work_id IN #{work_ids} and reviewer_role = 3").count - - student_work.absence_penalty = absence_penalty_count > 0 ? absence_penalty_count * homework_detail_manual.absence_penalty : 0 - student_work.save - - #更新CourseHomeworkStatistics中该学生的待匿评数和缺评数 - # absence_penalty_count = absence_penalty_count > 0 ? absence_penalty_count : 0 - # course_statistics = CourseHomeworkStatistics.find_by_course_id_and_user_id(homework_common.course_id, student_work.user_id) - # course_statistics.update_attribute('un_evaluation_work_num', (course_statistics.un_evaluation_work_num - absence_penalty_count) < 0 ? 0 : - # (course_statistics.un_evaluation_work_num - absence_penalty_count)) if course_statistics - # course_statistics.update_attribute('absence_evaluation_work_num', course_statistics.absence_evaluation_work_num + absence_penalty_count) if course_statistics - end - - # 未参与匿评 - if homework_common.homework_detail_manual.no_anon_penalty == 0 - all_dis_eva = StudentWorksEvaluationDistribution.where("student_work_id IN #{work_ids}") - has_sw_count = all_dis_eva.select("distinct user_id").count - anon_count = all_dis_eva.count / has_sw_count - homework_common.student_works.where("work_status != 0").each do |student_work| - if student_work.user.student_works_evaluation_distributions.where("student_work_id IN #{work_ids}").count == 0 - student_work.absence_penalty = homework_detail_manual.absence_penalty * anon_count - student_work.save - end - end - end - if homework_common.anonymous_appeal homework_detail_manual.update_column('comment_status', 4) - # 申诉开启 - eva_distribution = StudentWorksEvaluationDistribution.where(:student_work_id => homework_common.student_works.pluck(:id)) - str = "" - eva_distribution.pluck(:user_id).uniq.each do |user_id| - str += "," if str != "" - str += "(#{user_id}, #{homework_common.user_id}, #{homework_common.id}, 'HomeworkCommon', #{homework_common.id}, - 'AnonymousAppeal', #{homework_common.course_id}, 'Course', 0, 'HomeworkCommon', - '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if str != "" - sql = "insert into tidings (user_id,trigger_user_id,container_id, container_type, parent_container_id, - parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + str - ActiveRecord::Base.connection.execute sql - end + # 申诉开启发送消息 + HomeworkAnonymousAppealStartNotifyJob.perform_later(homework_common.id) else homework_detail_manual.update_column('comment_status', 5) + # 没有申诉阶段则直接计算缺评扣分 否则申诉结束时才计算 + HomeworkAbsencePenaltyCalculationJob.perform_later(homework_common.id) end - # 匿评关闭消息通知 给所有人发 - # course = homework_common.course - # course.members.each do |m| - # homework_common.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => course.id, :viewed => false, :status => 3) - # end - # 邮件通知 - # Mailer.send_mail_anonymous_comment_close(homework_common).deliver end end end @@ -179,5 +71,8 @@ namespace :homework_evaluation do task :end_appeal => :environment do homework_detail_manuals = HomeworkDetailManual.where("appeal_time <= '#{Time.now}' and homework_detail_manuals.comment_status = 4") homework_detail_manuals.update_all(:comment_status => 5) + homework_detail_manuals.each do |homework_detail_manual| + HomeworkAbsencePenaltyCalculationJob.perform_later(homework_detail_manual.homework_common_id) + end end end diff --git a/lib/tasks/homework_publishtime.rake b/lib/tasks/homework_publishtime.rake index f6a4325cd..918e70a70 100644 --- a/lib/tasks/homework_publishtime.rake +++ b/lib/tasks/homework_publishtime.rake @@ -6,8 +6,8 @@ namespace :homework_publishtime do # 作业的分班设置时间 def homework_group_setting homework, group_id setting = nil - if homework.homework_group_settings.where(:course_group_id => group_id).first - setting = homework.homework_group_settings.where(:course_group_id => group_id).first + if homework.homework_group_settings.where(course_group_id: group_id).first + setting = homework.homework_group_settings.where(course_group_id: group_id).first else setting = homework end @@ -21,37 +21,31 @@ namespace :homework_publishtime do homework_commons.each do |homework| homework_detail_manual = homework.homework_detail_manual homework_detail_manual.update_column('comment_status', 1) - course = homework.course - students = course.students - if !course.nil? && !students.empty? + # 统一设置的作业在这发消息,非统一设置的只给有全部分班权限的老师发 + if homework.unified_setting + # HomeworkPublishUpdateWorkStatusJob.perform_later(nil, homework.id) + HomeworkCommonPushNotifyJob.perform_later(homework.id, nil) + else + course = homework.course + teachers = course.teachers.where.not(id: course.teacher_course_groups.select(:course_member_id)) + tid_str = "" - course.teachers.find_each do |member| + teachers.find_each do |member| tid_str += "," if tid_str != "" tid_str += "(#{member.user_id}, #{homework.user_id}, #{homework.id}, 'HomeworkCommon', #{homework.id}, 'HomeworkPublish', #{course.id}, 'Course', 0, 'HomeworkCommon', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" end - if homework.unified_setting - students.each do |student| - tid_str += "," if tid_str != "" - tid_str += "(#{student.user_id}, #{homework.user_id}, #{homework.id}, 'HomeworkCommon', #{homework.id}, - 'HomeworkPublish', #{course.id}, 'Course', 0, 'HomeworkCommon', - '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - HomeworkPublishUpdateWorkStatusJob.perform_now(nil, homework.id) - end if tid_str != "" tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str ActiveRecord::Base.connection.execute tid_sql end - end - - if homework.course_acts.size == 0 - homework.course_acts << CourseActivity.new(:user_id => homework.user_id,:course_id => homework.course_id) end + + homework.course_acts << CourseActivity.new(user_id: homework.user_id, course_id: homework.course_id) if !homework.course_acts.exists? end # 分组设置发布时间的作业 @@ -59,27 +53,8 @@ namespace :homework_publishtime do homework_group_settings.each do |homework_group| homework = homework_group.homework_common if homework.present? - course = homework.course - homework_detail_manual = homework.homework_detail_manual - homework_detail_manual.update_column('comment_status', 1) if homework_detail_manual.comment_status == 0 - - tid_str = "" - members = course.students.where(:course_group_id => homework_group.course_group_id) - members.find_each do |member| - tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id}, #{homework.user_id}, #{homework.id}, 'HomeworkCommon', #{homework.id}, 'HomeworkPublish', - #{course.id}, 'Course', 0, 'HomeworkCommon', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', - '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, - parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, - updated_at) values" + tid_str - ActiveRecord::Base.connection.execute tid_sql - end - - HomeworkPublishUpdateWorkStatusJob.perform_now([homework_group.id], homework.id) - + # HomeworkPublishUpdateWorkStatusJob.perform_now([homework_group.id], homework.id) + HomeworkCommonPushNotifyJob.perform_later(homework.id, [homework_group.course_group_id]) end end Rails.logger.info("log--------------------------------homework_publish end") @@ -98,11 +73,10 @@ namespace :homework_publishtime do student_works = homework.student_works.where("work_status != 0") # none_student_works = homework.student_works.where("work_status = 0") else - setting = homework.homework_group_settings.where(:end_time => homework.end_time) + setting = homework.homework_group_settings.where(end_time: homework.end_time) unless setting.blank? - users = homework.course.students.where(:course_group_id => setting.map(&:course_group_id)) - user_ids = users.blank? ? "(-1)" : "(" + users.map(&:user_id).join(",") + ")" - student_works = homework.student_works.where("work_status != 0 and user_id in #{user_ids}") + users = homework.course.students.where(course_group_id: setting.pluck(:course_group_id)) + student_works = homework.student_works.where("work_status != 0").where(user_id: users.pluck(:user_id)) # none_student_works = homework.student_works.where("work_status = 0 and user_id in #{user_ids}") end end @@ -110,7 +84,8 @@ namespace :homework_publishtime do student_works.joins(:myshixun).where("myshixuns.status != 1").update_all(late_penalty: homework.late_penalty) if student_works.present? else - HomeworksService.new.update_student_eff_score homework + HomeworkEndUpdateScoreJob.perform_later(homework.id) + # HomeworksService.new.update_student_eff_score homework end =begin @@ -172,8 +147,7 @@ namespace :homework_publishtime do # homework_challenge_settings = homework.homework_challenge_settings users = homework.course.students.where(:course_group_id => homework_setting.course_group_id) - user_ids = users.blank? ? "(-1)" : "(" + users.map(&:user_id).join(",") + ")" - student_works = homework.student_works.where("work_status != 0 and user_id in #{user_ids}") + student_works = homework.student_works.where("work_status != 0").where(user_id: users.pluck(:user_id)) student_works.joins(:myshixun).where("myshixuns.status != 1").update_all(late_penalty: homework.late_penalty) if student_works.present? else # HomeworksService.new.update_student_eff_score homework # 分班设置的不需要另外算效率分 @@ -233,7 +207,8 @@ namespace :homework_publishtime do homework_commons = HomeworkCommon.joins(:homework_detail_manual).where("homework_type = 4 and allow_late = 1 and late_time <= ? and late_time > ? and homework_detail_manuals.comment_status != 6", Time.now, Time.now - 900) homework_commons.each do |homework| - HomeworksService.new.update_student_eff_score homework + # HomeworksService.new.update_student_eff_score homework + HomeworkEndUpdateScoreJob.perform_later(homework.id) =begin homework_detail_manual = homework.homework_detail_manual diff --git a/lib/tasks/poll_publish.rake b/lib/tasks/poll_publish.rake index c33ad3afb..8cec43565 100644 --- a/lib/tasks/poll_publish.rake +++ b/lib/tasks/poll_publish.rake @@ -6,42 +6,25 @@ namespace :poll_publish do task :publish => :environment do puts "--------------------------------poll_publish start" # 统一设置发布时间的问卷 - polls = Poll.where("publish_time is not null and polls_status = 1 and publish_time <=?",Time.now) + polls = Poll.includes(:poll_users).where("publish_time is not null and polls_status = 1 and publish_time <=?",Time.now) polls.each do |poll| poll.update_attributes(:polls_status => 2) - course = poll.course - tid_str = "" - course.teachers.find_each do |member| - tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id}, #{poll.user_id}, #{poll.id}, 'Poll', #{poll.id}, 'PollPublish', #{course.id}, 'Course', 0, 'Poll', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end if poll.unified_setting - course.students.find_each do |student| + PollPublishNotifyJob.perform_later(poll.id, nil) + else + course = poll.course + teachers = course.teachers.where.not(id: course.teacher_course_groups.select(:course_member_id)) + tid_str = "" + teachers.find_each do |member| tid_str += "," if tid_str != "" - tid_str += "(#{student.user_id}, #{poll.user_id}, #{poll.id}, 'Poll', #{poll.id}, 'PollPublish', #{course.id}, 'Course', 0, 'Poll', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - end - if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str - ActiveRecord::Base.connection.execute tid_sql - end - - if poll.poll_users.count == 0 - str = "" - course.students.find_each do |student| - str += "," if str != "" - str += "(#{student.user_id},#{poll.id}, 0, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + tid_str += "(#{member.user_id}, #{poll.user_id}, #{poll.id}, 'Poll', #{poll.id}, 'PollPublish', #{course.id}, 'Course', 0, 'Poll', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" end - - if str != "" - sql = "insert into poll_users (user_id, poll_id, commit_status, created_at, updated_at) values" + str - ActiveRecord::Base.connection.execute sql + if tid_str != "" + tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str + ActiveRecord::Base.connection.execute tid_sql end end - - if poll.course_acts.size == 0 - poll.course_acts << CourseActivity.new(:user_id => poll.user_id,:course_id => poll.course_id) - end + poll.course_acts << CourseActivity.new(user_id: poll.user_id, course_id: poll.course_id) if !poll.course_acts.exists? end # 分组设置发布时间的问卷 @@ -49,19 +32,8 @@ namespace :poll_publish do poll_group_settings.each do |poll_group| poll = poll_group.poll if poll.present? - course = poll.course poll.update_attributes(:polls_status => 2) if poll.polls_status == 1 - - tid_str = "" - members = course.course_members.where(:course_group_id => poll_group.course_group_id) - members.find_each do |member| - tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id},#{poll.user_id}, #{poll.id}, 'Poll', #{poll.id}, 'PollPublish', #{course.id}, 'Course', 0, 'Poll', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str - ActiveRecord::Base.connection.execute tid_sql - end + PollPublishNotifyJob.perform_later(poll.id, [poll_group.course_group_id]) end end @@ -71,7 +43,7 @@ namespace :poll_publish do task :nearly_end => :environment do puts "--------------------------------poll_nearly_end start" # 统一设置发布时间的问卷 - polls = Poll.where("polls_status = 2 and unified_setting = 1 and end_time <=? and end_time > ?", Time.now + 86400, Time.now + 84600) + polls = Poll.includes(:poll_users).where("polls_status = 2 and unified_setting = 1 and end_time <=? and end_time > ?", Time.now + 86400, Time.now + 84600) polls.each do |poll| if poll.tidings.where(:parent_container_type => "NearlyEnd").count == 0 course = poll.course @@ -111,27 +83,44 @@ namespace :poll_publish do end task :end => :environment do - polls = Poll.where("polls_status = 2 and unified_setting = 1 and end_time <=?",Time.now) + + #1.统一设置的截止 + polls = Poll.includes(:poll_users).where("polls_status = 2 AND unified_setting = true AND end_time <=?",Time.now + 900) polls.each do |poll| - poll.update_attributes(:polls_status => 3) - poll.poll_users.each do |poll_user| - if poll_user.commit_status == 0 && !poll_user.start_at.nil? - poll_user.update_attributes(:commit_status => 1, :end_at => Time.now) - end - end + poll.update_column('polls_status', 3) + poll.poll_users.where("commit_status = 0 and start_at is not null").update_all(commit_status: 1, end_at: Time.now) end - PollGroupSetting.where("end_time < ? and end_time > ?", Time.now + 1800, Time.now - 1800).each do |poll_setting| + #2.分班设置的截止 + polls = Poll.includes(:poll_users).where("polls_status = 2 AND unified_setting = false AND end_time > ?",Time.now + 900) + poll_ids = polls.blank? ? "(-1)" : "(" + polls.map(&:id).join(",") + ")" + polls_group_settings = PollGroupSetting.where("end_time <= '#{Time.now}' and poll_id in #{poll_ids}") + polls_group_settings.each do |poll_setting| poll = poll_setting.poll - - users = poll.course.course_members.where(:course_group_id => poll_setting.course_group_id) - poll_users = poll.poll_users.where(:user_id => users.map(&:user_id)) - - poll_users.each do |poll_user| - if poll_user.commit_status == 0 && !poll_user.start_at.nil? - poll_user.update_attributes(:commit_status => 1, :end_at => Time.now) - end + if poll&.end_time <= Time.now + poll.update_column('polls_status', 3) end + users = poll.course.course_members.where(course_group_id: poll_setting.course_group_id) + poll.poll_users.where(user_id: users.pluck(:user_id)).where("commit_status = 0 and start_at is not null").update_all(commit_status: 1, end_at: Time.now) + # poll_users.each do |poll_user| + # if poll_user.commit_status == 0 && !poll_user.start_at.nil? + # poll_user.update_attributes(:commit_status => 1, :end_at => Time.now) + # end + # end end + + # PollGroupSetting.where("end_time < ? and end_time > ?", Time.now + 1800, Time.now - 1800).each do |poll_setting| + # poll = poll_setting.poll + # poll.update_column('polls_status',3) + # + # users = poll.course.course_members.where(:course_group_id => poll_setting.course_group_id) + # poll_users = poll.poll_users.where(:user_id => users.map(&:user_id)) + # + # poll_users.each do |poll_user| + # if poll_user.commit_status == 0 && !poll_user.start_at.nil? + # poll_user.update_attributes(:commit_status => 1, :end_at => Time.now) + # end + # end + # end end end diff --git a/lib/tasks/resource_publish.rake b/lib/tasks/resource_publish.rake index 7872a6ce4..f90718cfb 100644 --- a/lib/tasks/resource_publish.rake +++ b/lib/tasks/resource_publish.rake @@ -5,9 +5,7 @@ namespace :resource_publish do task :publish => :environment do Rails.logger.info("log--------------------------------resource_publish start") attachments = Attachment.where("publish_time < '#{Time.now}' and is_publish = 0") - attachments.each do |attachment| - attachment.update_attributes(:is_publish => 1) - end + attachments.update_all(is_publish: 1) Rails.logger.info("log--------------------------------resource_publish end") end end \ No newline at end of file diff --git a/public/react/src/modules/courses/coursesPublic/form/SchoolSelect.js b/public/react/src/modules/courses/coursesPublic/form/SchoolSelect.js index db62c50b6..e1a9062e3 100644 --- a/public/react/src/modules/courses/coursesPublic/form/SchoolSelect.js +++ b/public/react/src/modules/courses/coursesPublic/form/SchoolSelect.js @@ -34,9 +34,9 @@ class SchoolSelect extends Component{ } }) .then((response) => { - if (response.data.shools_name) { + if (response.data.school_names) { if (currentValue === value) { - callback(response.data.shools_name); + callback(response.data.school_names); } } }) diff --git a/spec/jobs/course_add_student_create_works_job_spec.rb b/spec/jobs/course_add_student_create_works_job_spec.rb new file mode 100644 index 000000000..5466f830c --- /dev/null +++ b/spec/jobs/course_add_student_create_works_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe CourseAddStudentCreateWorksJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/jobs/course_delete_student_delete_works_job_spec.rb b/spec/jobs/course_delete_student_delete_works_job_spec.rb new file mode 100644 index 000000000..71ad3b1dc --- /dev/null +++ b/spec/jobs/course_delete_student_delete_works_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe CourseDeleteStudentDeleteWorksJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/jobs/graduation_task_cross_comment_job_spec.rb b/spec/jobs/graduation_task_cross_comment_job_spec.rb new file mode 100644 index 000000000..d517d939b --- /dev/null +++ b/spec/jobs/graduation_task_cross_comment_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe GraduationTaskCrossCommentJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/jobs/graduation_task_publish_notify_job_spec.rb b/spec/jobs/graduation_task_publish_notify_job_spec.rb new file mode 100644 index 000000000..39f6046af --- /dev/null +++ b/spec/jobs/graduation_task_publish_notify_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe GraduationTaskPublishNotifyJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/jobs/homework_absence_penalty_calculation_job_spec.rb b/spec/jobs/homework_absence_penalty_calculation_job_spec.rb new file mode 100644 index 000000000..b347086ce --- /dev/null +++ b/spec/jobs/homework_absence_penalty_calculation_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe HomeworkAbsencePenaltyCalculationJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/jobs/homework_anonymous_appeal_start_notify_job_spec.rb b/spec/jobs/homework_anonymous_appeal_start_notify_job_spec.rb new file mode 100644 index 000000000..bd5db1e69 --- /dev/null +++ b/spec/jobs/homework_anonymous_appeal_start_notify_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe HomeworkAnonymousAppealStartNotifyJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/jobs/homework_end_update_score_job_spec.rb b/spec/jobs/homework_end_update_score_job_spec.rb new file mode 100644 index 000000000..492b35d43 --- /dev/null +++ b/spec/jobs/homework_end_update_score_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe HomeworkEndUpdateScoreJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/jobs/homework_evaluation_comment_assgin_job_spec.rb b/spec/jobs/homework_evaluation_comment_assgin_job_spec.rb new file mode 100644 index 000000000..7a31a825f --- /dev/null +++ b/spec/jobs/homework_evaluation_comment_assgin_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe HomeworkEvaluationCommentAssginJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/jobs/homework_evaluation_start_notify_job_spec.rb b/spec/jobs/homework_evaluation_start_notify_job_spec.rb new file mode 100644 index 000000000..b347ea1f5 --- /dev/null +++ b/spec/jobs/homework_evaluation_start_notify_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe HomeworkEvaluationStartNotifyJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/shixun_service_config_spec.rb b/spec/models/shixun_service_config_spec.rb new file mode 100644 index 000000000..d79cd19f7 --- /dev/null +++ b/spec/models/shixun_service_config_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ShixunServiceConfig, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/user_agent_spec.rb b/spec/models/user_agent_spec.rb new file mode 100644 index 000000000..2bd0f7bbc --- /dev/null +++ b/spec/models/user_agent_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe UserAgent, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end