dev_forum
cxt 5 years ago
commit d13cab8c3c

12
.gitignore vendored

@ -33,7 +33,6 @@
# Ignore react node_modules # Ignore react node_modules
/public/react/build /public/react/build
/public/react/build/ /public/react/build/
/public/react/.cache
/public/react/node_modules/ /public/react/node_modules/
/public/react/config/stats.json /public/react/config/stats.json
/public/react/stats.json /public/react/stats.json
@ -44,10 +43,12 @@
/public/images/avatars /public/images/avatars
/config/secrets.yml /config/secrets.yml
/files/archiveZip/* /config/redis.yml
/files/cache_store/* /config/elasticsearch.yml
public/upload.html public/upload.html
/config/configuration.yml /config/configuration.yml
/config/environments/production.rb
/config/initializers/gitlab_config.rb /config/initializers/gitlab_config.rb
/db/schema.rb /db/schema.rb
.vscode/ .vscode/
@ -55,3 +56,8 @@ vendor/bundle/
.ruby-version .ruby-version
.ruby-gemset .ruby-gemset
/files
/public/images/avatars
/public/files
/workspace
/log

@ -39,6 +39,8 @@ gem 'pdfkit'
gem 'wkhtmltopdf-binary' gem 'wkhtmltopdf-binary'
#gem 'iconv' #gem 'iconv'
# markdown 转html
gem 'redcarpet', '~> 3.4'
gem 'rqrcode', '~> 0.10.1' gem 'rqrcode', '~> 0.10.1'
gem 'rqrcode_png' gem 'rqrcode_png'
@ -46,11 +48,13 @@ gem 'rqrcode_png'
gem 'acts-as-taggable-on', '~> 6.0' gem 'acts-as-taggable-on', '~> 6.0'
group :development, :test do group :development, :test do
#group :'development.rb.example', :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'rspec-rails', '~> 3.8' gem 'rspec-rails', '~> 3.8'
end end
group :development do group :development do
#group :'development.rb.example' do
gem 'awesome_print' gem 'awesome_print'
gem 'web-console', '>= 3.3.0' gem 'web-console', '>= 3.3.0'
gem 'listen', '>= 3.0.5', '< 3.2' gem 'listen', '>= 3.0.5', '< 3.2'
@ -80,7 +84,10 @@ gem 'rails-i18n', '~> 5.1'
# job # job
gem 'sidekiq' gem 'sidekiq'
gem 'sinatra'
# batch insert # batch insert
gem 'bulk_insert' gem 'bulk_insert'
# elasticsearch
gem 'searchkick'

@ -90,6 +90,14 @@ GEM
connection_pool (2.2.2) connection_pool (2.2.2)
crass (1.0.4) crass (1.0.4)
diff-lcs (1.3) 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) erubi (1.7.1)
execjs (2.7.0) execjs (2.7.0)
faraday (0.15.4) faraday (0.15.4)
@ -100,6 +108,7 @@ GEM
grape-entity (0.7.1) grape-entity (0.7.1)
activesupport (>= 4.0) activesupport (>= 4.0)
multi_json (>= 1.3.2) multi_json (>= 1.3.2)
hashie (3.6.0)
htmlentities (4.3.4) htmlentities (4.3.4)
httparty (0.16.2) httparty (0.16.2)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
@ -142,6 +151,7 @@ GEM
multi_json (1.13.1) multi_json (1.13.1)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.0.0) multipart-post (2.0.0)
mustermann (1.0.3)
mysql2 (0.5.2) mysql2 (0.5.2)
nio4r (2.3.1) nio4r (2.3.1)
nokogiri (1.8.4) nokogiri (1.8.4)
@ -193,6 +203,7 @@ GEM
rb-inotify (0.9.10) rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2) ffi (>= 0.5.0, < 2)
rchardet (1.8.0) rchardet (1.8.0)
redcarpet (3.4.0)
redis (4.1.0) redis (4.1.0)
redis-actionpack (5.0.2) redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6) actionpack (>= 4.0, < 6)
@ -253,6 +264,10 @@ GEM
sprockets (>= 2.8, < 4.0) sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0) sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3) tilt (>= 1.1, < 3)
searchkick (3.1.3)
activemodel (>= 4.2)
elasticsearch (>= 5)
hashie
selenium-webdriver (3.14.0) selenium-webdriver (3.14.0)
childprocess (~> 0.5) childprocess (~> 0.5)
rubyzip (~> 1.2) rubyzip (~> 1.2)
@ -264,6 +279,11 @@ GEM
simple_xlsx_reader (1.0.4) simple_xlsx_reader (1.0.4)
nokogiri nokogiri
rubyzip rubyzip
sinatra (2.0.5)
mustermann (~> 1.0)
rack (~> 2.0)
rack-protection (= 2.0.5)
tilt (~> 2.0)
spreadsheet (1.2.3) spreadsheet (1.2.3)
ruby-ole (>= 1.0) ruby-ole (>= 1.0)
spring (2.0.2) spring (2.0.2)
@ -328,6 +348,7 @@ DEPENDENCIES
rails (~> 5.2.0) rails (~> 5.2.0)
rails-i18n (~> 5.1) rails-i18n (~> 5.1)
rchardet (~> 1.8) rchardet (~> 1.8)
redcarpet (~> 3.4)
redis-rails redis-rails
roo-xls roo-xls
rqrcode (~> 0.10.1) rqrcode (~> 0.10.1)
@ -336,9 +357,11 @@ DEPENDENCIES
ruby-ole ruby-ole
rubyzip rubyzip
sass-rails (~> 5.0) sass-rails (~> 5.0)
searchkick
selenium-webdriver selenium-webdriver
sidekiq sidekiq
simple_xlsx_reader simple_xlsx_reader
sinatra
spreadsheet spreadsheet
spring spring
spring-watcher-listen (~> 2.0.0) spring-watcher-listen (~> 2.0.0)

@ -62,3 +62,8 @@ testeduplus2.educoder.net/games/*
# 文件上传ActiveStorage # 文件上传ActiveStorage
# 新能bootsnap # 新能bootsnap
# 注意事项:
# 第一次部署需要执行一些rake任务
# 配置redis地址
# 配置gitlab/intializers/gitlab_config.yml

@ -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

@ -1,6 +1,5 @@
class AccountsController < ApplicationController class AccountsController < ApplicationController
include ErrorCommon
#skip_before_action :check_account, :only => [:logout] #skip_before_action :check_account, :only => [:logout]
def index def index
@ -31,20 +30,21 @@ class AccountsController < ApplicationController
phone = nil phone = nil
verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
end 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}") 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) # check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
unless check_code return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
tip_exception("验证码无效") return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
end
code = generate_identifier User, 8 code = generate_identifier User, 8
login = pre + code 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.password = params[:password]
# 现在因为是验证码,所以在注册的时候就可以激活 # 现在因为是验证码,所以在注册的时候就可以激活
@user.activate @user.activate
# 必须要用save操作密码的保存是在users中 # 必须要用save操作密码的保存是在users中
if @user.save! if @user.save!
# todo user_extension
UserExtension.create!(user_id: @user.id)
# 注册完成手机号或邮箱想可以奖励500金币 # 注册完成手机号或邮箱想可以奖励500金币
RewardGradeService.call( RewardGradeService.call(
@user, @user,
@ -52,6 +52,13 @@ class AccountsController < ApplicationController
container_type: pre == 'p' ? 'Phone' : 'Mail', container_type: pre == 'p' ? 'Phone' : 'Mail',
score: 500 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 end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
@ -62,6 +69,15 @@ class AccountsController < ApplicationController
# 用户登录 # 用户登录
def login def login
@user = User.try_to_login(params[:login], params[:password]) @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) @user.update_column(:last_login_on, Time.now)
successful_authentication(@user) successful_authentication(@user)
@ -83,20 +99,17 @@ class AccountsController < ApplicationController
email = params[:login] email = params[:login]
verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last
user = User.find_by_mail(email) #这里有问题应该是为email,而不是mail 6.13-hs 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 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] user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if user.save! if user.save!
sucess_status sucess_status
end end
# rescue Exception => e rescue Exception => e
# uid_logger_error(e.message) uid_logger_error(e.message)
# tip_exception("密码重置失败,请稍后再试") tip_exception("密码重置失败")
end end
end end
@ -107,7 +120,10 @@ class AccountsController < ApplicationController
# generate a key and set cookie if autologin # generate a key and set cookie if autologin
set_autologin_cookie(user) 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 end
def set_autologin_cookie(user) def set_autologin_cookie(user)
@ -127,7 +143,7 @@ class AccountsController < ApplicationController
end end
def logout 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 session[:user_id] = nil
logout_user logout_user
render :json => {status: 1, message: "退出成功!"} render :json => {status: 1, message: "退出成功!"}
@ -143,7 +159,7 @@ class AccountsController < ApplicationController
# params[:login] 手机号或者邮箱号 # params[:login] 手机号或者邮箱号
# params[:type]为事件通知类型 1用户注册注册 2忘记密码 3: 绑定手机 4: 绑定邮箱 # 如果有新的继续后面加 # params[:type]为事件通知类型 1用户注册注册 2忘记密码 3: 绑定手机 4: 绑定邮箱 # 如果有新的继续后面加
# 发送验证码send_type 1注册手机验证码 2找回密码手机验证码 3找回密码邮箱验证码 4绑定手机 5绑定邮箱 # 发送验证码send_type 1注册手机验证码 2找回密码手机验证码 3找回密码邮箱验证码 4绑定手机 5绑定邮箱
# 6手机验证码登录 7邮箱验证码登录 8邮箱注册验证码 # 6手机验证码登录 7邮箱验证码登录 8邮箱注册验证码 9: 验收手机号有效
def get_verification_code def get_verification_code
code = %W(0 1 2 3 4 5 6 7 8 9) code = %W(0 1 2 3 4 5 6 7 8 9)
value = params[:login] value = params[:login]
@ -152,6 +168,8 @@ class AccountsController < ApplicationController
send_type = verify_type(login_type, type) send_type = verify_type(login_type, type)
verification_code = code.sample(6).join 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) check_verification_code(verification_code, send_type, value)
sucess_status sucess_status

@ -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

@ -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

@ -5,6 +5,8 @@ class ApplicationController < ActionController::Base
include RenderExpand include RenderExpand
include RenderHelper include RenderHelper
include ControllerRescueHandler include ControllerRescueHandler
include GitHelper
include LoggerHelper
protect_from_forgery prepend: true, unless: -> { request.format.json? } protect_from_forgery prepend: true, unless: -> { request.format.json? }
@ -17,8 +19,19 @@ class ApplicationController < ActionController::Base
# 全局配置参数 # 全局配置参数
# 返回name对应的value # 返回name对应的value
def edu_setting name def edu_setting(name)
EduSetting.find_by_name(name).try(:value) 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 end
def user_course_identity def user_course_identity
@ -33,15 +46,16 @@ class ApplicationController < ActionController::Base
# 判断用户的邮箱或者手机是否可用 # 判断用户的邮箱或者手机是否可用
# params[:type] 1: 注册2忘记密码 # params[:type] 1: 注册2忘记密码
def check_mail_and_phone_valid login, type 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}$/ 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("请输入正确的手机号或邮箱") login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
tip_exception(-2, "请输入正确的手机号或邮箱")
end end
# 考虑到安全参数问题多一次查询去掉Union # 考虑到安全参数问题多一次查询去掉Union
user = User.where(phone: login).first || User.where(mail: login).first user = User.where(phone: login).first || User.where(mail: login).first
if type.to_i == 1 && !user.nil? if type.to_i == 1 && !user.nil?
tip_exception("该手机号码或邮箱已被注册") tip_exception(-2, "该手机号码或邮箱已被注册")
elsif type.to_i == 2 && user.nil? elsif type.to_i == 2 && user.nil?
tip_exception("该手机号码或邮箱未注册") tip_exception(-2, "该手机号码或邮箱未注册")
end end
sucess_status sucess_status
end end
@ -55,7 +69,7 @@ class ApplicationController < ActionController::Base
# 手机类型的发送 # 手机类型的发送
sigle_para = {phone: value} sigle_para = {phone: value}
status = Educoder::Sms.send(mobile: value, code: code) 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 when 8, 3, 5
# 邮箱类型的发送 # 邮箱类型的发送
sigle_para = {email: value} sigle_para = {email: value}
@ -63,8 +77,8 @@ class ApplicationController < ActionController::Base
UserMailer.register_email(value, code).deliver_now UserMailer.register_email(value, code).deliver_now
# Mailer.run.email_register(code, value) # Mailer.run.email_register(code, value)
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) logger_error(e)
tip_exception("邮件发送失败,请稍后重试") tip_exception(-2,"邮件发送失败,请稍后重试")
end end
end end
ver_params = {code_type: send_type, code: code}.merge(sigle_para) ver_params = {code_type: send_type, code: code}.merge(sigle_para)
@ -124,27 +138,26 @@ class ApplicationController < ActionController::Base
end end
end end
# 课堂教师、课堂管理员、超级管理员的权限(不包含助教)
def teacher_or_admin_allowed
unless current_user.course_identity(@course) < Course::ASSISTANT_PROFESSOR
normal_status(403, "")
end
end
def require_admin def require_admin
normal_status(403, "") unless User.current.admin? normal_status(403, "") unless User.current.admin?
end end
def require_business
normal_status(403, "") unless admin_or_business?
end
# 前端会捕捉401,弹登录弹框 # 前端会捕捉401,弹登录弹框
# 未授权的捕捉407弹试用申请弹框 # 未授权的捕捉407弹试用申请弹框
def require_login def require_login
#6.13 -hs #6.13 -hs
if User.current.logged? tip_exception(401, "..") unless 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
end end
# 异常提醒 # 异常提醒
@ -172,85 +185,18 @@ class ApplicationController < ActionController::Base
end end
# 系统全局认证 # 系统全局认证
#
def check_auth def check_auth
old_edu_host = edu_setting('old_edu_host') if current_user.certification != 1 && current_user.apply_actions.exists?(container_type: 'TrialAuthorization', status: 0)
ue = current_user.user_extension tip_exception(408, "您的试用申请正在审核中,请耐心等待")
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 }
elsif current_user.certification != 1 elsif current_user.certification != 1
day_cer = UserDayCertification.where(user_id: current_user.id).last day_cer = UserDayCertification.find_by(user_id: current_user.id)
unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400 tip_exception(407, "系统未授权") unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400
account_url = old_edu_host + "/my/account" elsif !current_user.profile_completed?
render :json => { status: 402, url: account_url } info_url = '/account/profile'
end tip_exception(402, info_url)
end end
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) def start_user_session(user)
session[:user_id] = user.id session[:user_id] = user.id
session[:ctime] = Time.now.utc.to_i session[:ctime] = Time.now.utc.to_i
@ -258,20 +204,26 @@ class ApplicationController < ActionController::Base
end end
def user_setup def user_setup
# reacct静态资源加载不需要走这一步
return if params[:controller] == "main"
# Find the current user # Find the current user
User.current = find_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? if !User.current.logged? && Rails.env.development?
User.current = User.find 12 User.current = User.find 12
end end
# User.current = User.find 81403
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除 if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
User.current = User.find 49610 User.current = User.find 81403
elsif params[:debug] == 'student' elsif params[:debug] == 'student'
User.current = User.find 8686 User.current = User.find 8686
elsif params[:debug] == 'admin' elsif params[:debug] == 'admin'
User.current = User.find 1 User.current = User.find 1
elsif params[:debug]
User.current = User.find_by_login params[:debug]
end end
end end
@ -289,6 +241,7 @@ class ApplicationController < ActionController::Base
# Returns the current user or nil if no user is logged in # Returns the current user or nil if no user is logged in
# and starts a session if needed # and starts a session if needed
def find_current_user def find_current_user
uid_logger("user setup start: session[:user_id] is #{session[:user_id]}")
if session[:user_id] if session[:user_id]
# existing session # existing session
(User.active.find(session[:user_id]) rescue nil) (User.active.find(session[:user_id]) rescue nil)
@ -330,16 +283,6 @@ class ApplicationController < ActionController::Base
end end
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) def error_status(message = nil)
@status = -1 @status = -1
@ -403,12 +346,6 @@ class ApplicationController < ActionController::Base
end end
end end
#实训题的关卡url初始化
def challenge_path(path)
cha_path = path.present? ? path.split("") : []
cha_path.reject(&:blank?)[0].try(:strip)
end
# 适用与已经用url_safe编码后回调字符串形式 # 适用与已经用url_safe编码后回调字符串形式
def tran_base64_decode64(str) def tran_base64_decode64(str)
s_size = str.size % 4 s_size = str.size % 4
@ -472,6 +409,24 @@ class ApplicationController < ActionController::Base
container.to_json container.to_json
end 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) def course_work(task, **option)
logger.info("#############{option}") logger.info("#############{option}")

@ -2,10 +2,9 @@
# #
# 文件上传 # 文件上传
class AttachmentsController < ApplicationController class AttachmentsController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :find_file, only: %i[show destroy] before_action :find_file, only: %i[show destroy]
include ErrorCommon
include ApplicationHelper include ApplicationHelper
def show def show
@ -15,7 +14,7 @@ class AttachmentsController < ApplicationController
update_downloads(@file) update_downloads(@file)
redirect_to @file.cloud_url and return redirect_to @file.cloud_url and return
end 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) update_downloads(@file)
end end
@ -25,51 +24,50 @@ class AttachmentsController < ApplicationController
# 2. 上传到云 # 2. 上传到云
upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称 upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}") uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
if upload_file raise "未上传文件" unless upload_file
folder = edu_setting('attachment_folder')
raise "存储目录未定义" unless folder.present?
month_folder = current_month_folder folder = edu_setting('attachment_folder')
save_path = File.join(folder, month_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}" # remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
logger.info "remote_path: #{remote_path}" 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? disk_filename = local_path[save_path.size + 1, local_path.size]
@attachment = Attachment.new #存数据库
@attachment.filename = upload_file.original_filename #
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size] @attachment = Attachment.where(disk_filename: disk_filename,
@attachment.filesize = upload_file.tempfile.size author_id: current_user.id,
@attachment.content_type = content_type cloud_url: remote_path).first
@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
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 else
raise "未上传文件" logger.info "文件已存在id = #{@attachment.id}, filename = #{@attachment.filename}"
end end
render_json
end end
def destroy def destroy

@ -1,54 +1,47 @@
class BoardsController < ApplicationController class BoardsController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :find_course, only: [:create] before_action :find_course, only: [:create]
before_action :set_board, except: [:create] before_action :set_board, except: [:create]
before_action :teacher_allowed before_action :teacher_or_admin_allowed
def index def index
@boards = @course.boards.includes(messages: [:last_reply, :author]); @boards = @course.boards.includes(messages: [:last_reply, :author])
end end
def show def show
end
def new
end end
def create def create
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin board = @course.course_board
board = @course.course_board new_board = Board.new(board_params)
new_board = Board.new(board_params) new_board.course_id = @course.id
new_board.course_id = @course.id new_board.project_id = -1
new_board.project_id = -1 new_board.parent_id = board.try(:id)
new_board.parent_id = board.try(:id) new_board.position = board.children.count + 1
new_board.position = board.children.count + 1 new_board.save!
new_board.save!
normal_status(0, "添加成功")
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end end
normal_status(0, "添加成功")
end end
# 子目录的拖动 # 子目录的拖动
def move_category def move_category
tip_exception("移动失败") if params[:position].blank? tip_exception("移动失败") if params[:position].blank?
unless params[:position].to_i == @board.position return normal_status(-1, "位置没有变化") if params[:position].to_i == @board.position
course_board = @course.course_board
course_board = @course.course_board
ActiveRecord::Base.transaction do
if params[:position].to_i < @board.position 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 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 end
@board.update_attributes(position: params[:position]) @board.update_attributes(position: params[:position])
normal_status(0, "移动成功")
else
normal_status(-1, "位置没有变化")
end end
normal_status(0, "移动成功")
end end
def destroy def destroy

@ -1,12 +1,14 @@
class ChallengesController < ApplicationController class ChallengesController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :find_shixun, only: [:new, :create, :index] before_action :find_shixun, only: [:new, :create, :index]
skip_before_action :verify_authenticity_token, only: [:create, :update, :create_choose_question, :crud_answer] 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, before_action :find_challenge, only: [:edit, :show, :update, :create_choose_question, :index_down, :index_up,
:edit_choose_question, :show_choose_question, :destroy_challenge_choose, :edit_choose_question, :show_choose_question, :destroy_challenge_choose,
:update_choose_question, :destroy, :crud_answer, :answer] :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 ShixunsHelper
include ChallengesHelper include ChallengesHelper
@ -136,7 +138,7 @@ class ChallengesController < ApplicationController
# tab 0,nil 过关任务, 1 评测设置, 2 参考答案 # tab 0,nil 过关任务, 1 评测设置, 2 参考答案
def edit def edit
@tab = params[:tab].to_i @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 challenge_num = Challenge.where(:shixun_id => @shixun).count
@position = @challenge.position @position = @challenge.position
@chooses = @challenge.challenge_chooses @chooses = @challenge.challenge_chooses
@ -148,16 +150,17 @@ class ChallengesController < ApplicationController
def index def index
uid_logger("identifier: #{params}") uid_logger("identifier: #{params}")
# 通过调试发现 这里includes(:games)性能会慢10倍
@challenges = @shixun.challenges.fields_for_list @challenges = Challenge.fields_for_list.where(shixun_id: @shixun.id)
@editable = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0
@editable = @shixun.status == 0 # before_action有判断权限如果没发布则肯定是管理人员
@user = current_user @user = current_user
end end
def show def show
@tab = params[:tab].nil? ? 1 : params[:tab].to_i @tab = params[:tab].nil? ? 1 : params[:tab].to_i
challenge_num = Challenge.where(shixun_id: @shixun).count challenge_num = @shixun.challenges_count
@power = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0 @power = @shixun.status == 0 # 之前验证走过了是不是管理员,因此这里只用判断是否发布
@position = @challenge.position @position = @challenge.position
if @position < challenge_num if @position < challenge_num
@next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first @next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first
@ -206,7 +209,7 @@ class ChallengesController < ApplicationController
end end
# 关卡评测执行文件如果被修改,需要修改脚本内容 # 关卡评测执行文件如果被修改,需要修改脚本内容
script = modify_shixun_script @shixun, @shixun.evaluate_script script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script) @shixun.shixun_info.update_column(:evaluate_script, script)
# TODO: # TODO:
# if path != params[:challenge][:path] # if path != params[:challenge][:path]
# shixun_modify_status_without_publish(@shixun, 1) # shixun_modify_status_without_publish(@shixun, 1)
@ -246,8 +249,7 @@ class ChallengesController < ApplicationController
next_challenge.update_attribute(:position, next_challenge.position - 1) next_challenge.update_attribute(:position, next_challenge.position - 1)
# 关卡位置被修改,需要修改脚本 # 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script) @shixun.shixun_info.update_column(:evaluate_script, script)
end end
def index_up def index_up
@ -257,7 +259,7 @@ class ChallengesController < ApplicationController
last_challenge.update_attribute(:position, last_challenge.position + 1) last_challenge.update_attribute(:position, last_challenge.position + 1)
# 关卡位置被修改,需要修改脚本 # 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script) @shixun.shixun_info.update_column(:evaluate_script, script)
end end
def destroy def destroy
@ -268,7 +270,7 @@ class ChallengesController < ApplicationController
@challenge.destroy @challenge.destroy
# 关卡位置被删除,需要修改脚本 # 关卡位置被删除,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script) @shixun.shixun_info.update_column(:evaluate_script, script)
end end
@ -287,7 +289,7 @@ class ChallengesController < ApplicationController
def challenge_params def challenge_params
params.require(:challenge).permit(:subject, :task_pass, :difficulty, :score, :st, :modify_time, :test_set_average, 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, :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 end
def chooce_params def chooce_params
@ -295,9 +297,8 @@ class ChallengesController < ApplicationController
:standard_answer, :score, :difficult) :standard_answer, :score, :difficult)
end end
def allowed def update_allowed
# 实训为发布前,除实训的管理者外,其他人都不人都不允许访问 unless current_user.manager_of_shixun?(@shixun)
if !current_user.manager_of_shixun?(@shixun) && (@shixun.status < 1 || @shixun.hidden == 1)
raise Educoder::TipException.new(403, "..") raise Educoder::TipException.new(403, "..")
end end
end end

@ -1,7 +1,7 @@
class CommonsController < ApplicationController class CommonsController < ApplicationController
OBJECT_TYPE = %W[message journals_for_message] OBJECT_TYPE = %W[message journals_for_message]
before_action :require_login before_action :require_login, :check_auth
before_action :validate_object_type before_action :validate_object_type
before_action :find_object before_action :find_object
before_action :validate_power before_action :validate_power
@ -42,7 +42,24 @@ class CommonsController < ApplicationController
end end
def validate_power 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 end
def action(flag) def action(flag)

@ -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

@ -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

@ -0,0 +1,4 @@
class Competitions::CompetitionStaffsController < Competitions::BaseController
def show
end
end

@ -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

@ -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

@ -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

@ -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

@ -2,6 +2,10 @@ module ControllerRescueHandler
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do 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 ActionView::MissingTemplate, with: :object_not_found
# rescue_from ActiveRecord::RecordNotFound, with: :object_not_found # rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
rescue_from Educoder::TipException, with: :tip_show rescue_from Educoder::TipException, with: :tip_show
@ -12,5 +16,8 @@ module ControllerRescueHandler
rescue_from ActiveModel::ValidationError do |ex| rescue_from ActiveModel::ValidationError do |ex|
render_error(ex.model.errors.full_messages.join(',')) render_error(ex.model.errors.full_messages.join(','))
end end
rescue_from ActiveRecord::RecordInvalid do |ex|
render_error(ex.record.errors.full_messages.join(','))
end
end end
end end

@ -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

@ -28,7 +28,6 @@ module GitCommon
end end
def file_content def file_content
logger.info("#################{@repo_path}, #{@path}")
@content = git_fle_content @repo_path, @path @content = git_fle_content @repo_path, @path
end end

@ -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

@ -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

@ -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

@ -16,4 +16,8 @@ module RenderHelper
render json: { status: 403, message: message } render json: { status: 403, message: message }
# render status: 403, json: { errors: errors } # render status: 403, json: { errors: errors }
end end
def render_unauthorized(message = I18n.t('error.unauthorized'))
render json: { status: 401, message: message }
end
end end

@ -1,8 +1,8 @@
class CourseGroupsController < ApplicationController class CourseGroupsController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :set_group, except: [:create] before_action :set_group, except: [:create]
before_action :find_course, only: [:create] before_action :find_course, only: [:create]
before_action :teacher_allowed before_action :teacher_or_admin_allowed
def create def create
tip_exception("分班名称不能为空") if params[:name].blank? tip_exception("分班名称不能为空") if params[:name].blank?

@ -1,8 +1,8 @@
class CourseModulesController < ApplicationController class CourseModulesController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :set_module, except: [:unhidden_modules] before_action :set_module, except: [:unhidden_modules]
before_action :find_course, only: [:unhidden_modules] before_action :find_course, only: [:unhidden_modules]
before_action :teacher_allowed before_action :teacher_or_admin_allowed
# 模块置顶 # 模块置顶
def sticky_module def sticky_module
@ -16,6 +16,7 @@ class CourseModulesController < ApplicationController
# 模块隐藏 # 模块隐藏
def hidden_module 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) @course_module.update_attributes(hidden: 1)
normal_status(0, "更新成功") normal_status(0, "更新成功")
end end

@ -1,7 +1,7 @@
class CourseSecondCategoriesController < ApplicationController class CourseSecondCategoriesController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :set_category before_action :set_category
before_action :teacher_allowed before_action :teacher_or_admin_allowed
# 目录重命名 # 目录重命名
def rename_category def rename_category

@ -2,8 +2,6 @@ class CoursesController < ApplicationController
include MessagesHelper include MessagesHelper
include ExportHelper include ExportHelper
rescue_from ::ActionView::MissingTemplate, with: :missing_template
rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
# model validation error # model validation error
rescue_from ActiveRecord::RecordInvalid do |ex| rescue_from ActiveRecord::RecordInvalid do |ex|
render_error(ex.record.errors.full_messages.join(',')) render_error(ex.record.errors.full_messages.join(','))
@ -13,9 +11,9 @@ class CoursesController < ApplicationController
render_error(ex.model.errors.full_messages.join(',')) render_error(ex.model.errors.full_messages.join(','))
end 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, 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, :top_banner, :left_banner, :add_teacher_popup, :add_teacher,
:graduation_group_list, :create_graduation_group, :join_graduation_group, :graduation_group_list, :create_graduation_group, :join_graduation_group,
:course_group_list, :set_course_group, :change_course_admin, :change_course_teacher, :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, before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate,
:transfer_to_course_group, :delete_from_course, :transfer_to_course_group, :delete_from_course,
:search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup, :add_teacher] :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, before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin,
:set_course_group, :change_course_admin, :change_course_teacher, :set_course_group, :delete_course_teacher, :create_group_by_importing_file]
:delete_course_teacher, :teacher_application_review, :create_group_by_importing_file]
before_action :teacher_or_admin_allowed, only: [:graduation_group_list, :create_graduation_group, :join_graduation_group, 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 :validate_course_name, only: [:create, :update]
before_action :find_board, only: :board_list before_action :find_board, only: :board_list
before_action :validate_page_size, only: :mine before_action :validate_page_size, only: :mine
@ -49,47 +47,55 @@ class CoursesController < ApplicationController
@order = params[:order].present? ? params[:order] : "all" @order = params[:order].present? ? params[:order] : "all"
order_str = @order != "course_members_count" && @order != "created_at" ? "updated_at" : @order order_str = @order != "course_members_count" && @order != "created_at" ? "updated_at" : @order
if @order == "all" # 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 # @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),
# courses c, users u, user_extensions ue, schools s where c.is_delete=0 and c.tea_id=u.id and # u.login), s.name from courses c, users u, user_extensions ue, schools s where c.is_delete=0 and
# u.id=ue.user_id and ue.school_id=s.id limit 10;") # 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 = Course.where(is_delete: 0, is_hidden: 0)
courses.is_public, courses.is_end, courses.visits, courses.course_members_count,courses.homework_commons_count,(SELECT MAX(created_at) # .order("courses.id = 1309 desc, courses.created_at desc")
FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a")
.order("courses.id = 1309 desc, a desc") # @courses = Course.where(is_delete: 0, is_hidden: 0).select("courses.id, courses.tea_id, courses.name, courses.exercises_count, courses.polls_count,
elsif @order == "mine" # 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) @courses = Course.joins(:course_members)
.where("is_delete = 0 AND is_hidden = 0 AND course_members.user_id = ?", @user.id) .where("is_delete = 0 AND is_hidden = 0 AND course_members.user_id = ?", @user.id).distinct
.order("courses.id = 1309 DESC, courses.#{order_str} DESC")
elsif @order == "created_at" elsif @order == "created_at"
# REDO:Extension # REDO:Extension
@courses = Course.joins(teacher: :user_extension) @courses = Course.where(is_delete: 0, is_hidden: 0, is_end: 0).distinct
.where(is_delete: 0, is_hidden: 0, is_end: 0)
.order("courses.id = 1309 DESC, courses.#{order_str} DESC")
else else
# REDO:Extension # REDO:Extension
@courses = Course.joins(teacher: :user_extension) @courses = Course.where(is_delete: 0, is_hidden: 0).distinct
.where(is_delete: 0, is_hidden: 0)
.order("courses.id = 1309 DESC, courses.#{order_str} DESC")
end end
# 根据搜索关键字进一步筛选 # 根据搜索关键字进一步筛选
if params[:search].present? if params[:search].present?
# REDO:Extension # REDO:Extension
user_ids = User.includes(user_extension: :school).where("schools.name like ?", "%#{params[:search]}%").pluck(:id) #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) #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]}%") # and CONCAT(users.lastname, users.firstname) like ?", @courses.map(&:id), "%#{params[:search]}%")
.pluck(:course_id) # .pluck(:course_id)
@courses = @courses.where("name like ?", "%#{params[:search]}%").or(@courses.where(tea_id: user_ids)).or(@courses.where(id: course_ids)) #@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 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 page = params[:page] || 1
limit = params[:limit] || 16 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 end
def visits_plus_one def visits_plus_one
@ -101,6 +107,7 @@ class CoursesController < ApplicationController
# GET /courses/1 # GET /courses/1
# GET /courses/1.json # GET /courses/1.json
def show def show
# render :json => {first_category_url: module_url(course.course_modules.where.not(module_type: "activity").where(hidden: 0).first, course)}
end end
# GET /courses/new # GET /courses/new
@ -241,44 +248,52 @@ class CoursesController < ApplicationController
if @course.try(:id) != 1309 || current_user.admin? || current_user.try(:id) == 15582 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) @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 else
@teacher_list = @course.course_members.joins(:user).where("(course_members.role in (1, 3) or (course_members.user_id = #{current_user.id} @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)) and course_members.role = 2)) and LOWER(concat(users.lastname, users.firstname))
LIKE '%#{@search_str}%'") LIKE ?", "%#{@search_str}%")
end end
@teacher_list_size = @teacher_list.size @teacher_list_size = @teacher_list.size
@has_graduation_design = @course.course_modules.graduation_module_not_hidden.any? @has_graduation_design = @course.course_modules.graduation_module_not_hidden.any?
sort = params[:sort] || "desc"
@order = params[:order].to_i @order = params[:order].to_i
if @order.present? if @order.present?
case @order case @order
when 1 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 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 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 else
@teacher_list = @teacher_list.order("created_at") @teacher_list = @teacher_list.order("role #{sort}")
end end
else else
if @has_graduation_design @teacher_list = @teacher_list.order("role #{sort}")
@teacher_list = @teacher_list.includes(:course, :graduation_group).order("graduation_groups.name")
else
@teacher_list = @teacher_list.order("created_at")
end
end 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 page = params[:page] || 1
limit = params[:limit] || 20 limit = params[:limit] || 20
@teacher_list = @teacher_list.page(page).per(limit) @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 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_teacher = CourseMember.find_by(user_id: current_user.id, role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR], course_id: @course.id)
course_student.destroy! course_student.destroy!
course_teacher.update_attributes(is_active: 1) if course_teacher.present? && !course_teacher.is_active 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, "退出成功") normal_status(0, "退出成功")
end end
@ -566,6 +582,18 @@ class CoursesController < ApplicationController
end end
new_teacher.save! 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 elsif approval == 2
course_message.reject! course_message.reject!
else else
@ -625,7 +653,8 @@ class CoursesController < ApplicationController
page = params[:page] || 1 page = params[:page] || 1
limit = params[:limit] || 20 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 end
# 获取当前课程所有分班 # 获取当前课程所有分班
@ -674,11 +703,16 @@ class CoursesController < ApplicationController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
students = params[:students] students = params[:students]
student_ids = []
students.each do |student| students.each do |student|
course_member = CourseMember.find_by!(id: student[:course_member_id].to_i, course_id: @course.id) course_member = CourseMember.find_by(id: student[:course_member_id].to_i, course_id: @course.id)
course_member.destroy! if course_member.present?
student_ids << course_member.user_id
course_member.destroy!
end
end end
CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, student_ids) if student_ids.present?
normal_status(0, "操作成功") normal_status(0, "操作成功")
rescue => e rescue => e
uid_logger(e.message) uid_logger(e.message)
@ -701,7 +735,7 @@ class CoursesController < ApplicationController
student_ids = [] student_ids = []
user_ids.each do |user_id| 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) 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? if existing_course_member.present?
@ -710,6 +744,7 @@ class CoursesController < ApplicationController
else else
new_student.is_active = 0 if existing_course_member.is_active new_student.is_active = 0 if existing_course_member.is_active
new_student.save! new_student.save!
student_ids << user_id
end end
else else
new_student.save! new_student.save!
@ -717,6 +752,7 @@ class CoursesController < ApplicationController
end end
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? TeacherInviteJoinCourseNotifyJob.perform_later(current_user.id, @course.id, 10, student_ids) if student_ids.present?
normal_status(0, "添加成功") normal_status(0, "添加成功")
rescue => e rescue => e
@ -727,11 +763,11 @@ class CoursesController < ApplicationController
end end
end end
# 获取历史课堂,即用户管理的所有课堂以及课堂下的分班 # 获取历史课堂,即用户管理的所有课堂以及课堂下的分班(去除当前课堂)
def get_historical_courses def get_historical_courses
user_id = current_user.id @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(tea_id: user_id, is_delete: 0) # @courses = Course.includes(:course_groups).where(id: current_user.course_members, is_delete: 0)
end end
# 根据历史课堂的课堂id和分班id获取所有学生 # 根据历史课堂的课堂id和分班id获取所有学生
@ -744,6 +780,7 @@ class CoursesController < ApplicationController
@students = @students.where(course_group_id: course_group_id) @students = @students.where(course_group_id: course_group_id)
end end
@students = @students.includes(user: [user_extension: :school])
@students_count = @students.size @students_count = @students.size
end end
@ -765,7 +802,7 @@ class CoursesController < ApplicationController
name = attachment.disk_filename name = attachment.disk_filename
if name.split(".").last == "xls" if name.split(".").last == "xls"
begin begin
attachment_folder = Rails.configuration.educoder['attachment_folder'] attachment_folder = edu_setting('attachment_folder')
full_path = "#{attachment_folder}/#{path}/#{name}" full_path = "#{attachment_folder}/#{path}/#{name}"
xls = Roo::Spreadsheet.open(full_path, extension: :xls) xls = Roo::Spreadsheet.open(full_path, extension: :xls)
worksheet = xls.sheet(0) worksheet = xls.sheet(0)
@ -788,6 +825,8 @@ class CoursesController < ApplicationController
uid_logger_error(e.message) uid_logger_error(e.message)
normal_status(-1, "无法完成导入,原因:文件内容无法读取") normal_status(-1, "无法完成导入,原因:文件内容无法读取")
end end
else
normal_status(-1, "只支持xls文件的导入")
end end
end end
end end
@ -841,6 +880,13 @@ class CoursesController < ApplicationController
return normal_status(-1, "同一课堂不允许申请多个教师身份") return normal_status(-1, "同一课堂不允许申请多个教师身份")
end 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? if params[:student].present?
existing_student = CourseMember.find_by(course_id: course.id, role: %i[STUDENT], user_id: current_user.id) 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.course_group_id = course_group.id if course_group.present?
new_student.save! new_student.save!
CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id])
StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id) StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id)
end end
end end
@ -895,15 +942,15 @@ class CoursesController < ApplicationController
def top_banner def top_banner
@user = current_user @user = current_user
@is_teacher = @user.teacher_of_course?(@course) @is_teacher = @user_course_identity < Course::STUDENT
@is_student = @course.course_members.where(user_id: @user.id, role: 4, is_active: 1).present? @is_student = @user_course_identity == Course::STUDENT
@course.increment!(:visits) @course.increment!(:visits)
end end
def left_banner def left_banner
@user = current_user @user = current_user
@is_teacher = @user.teacher_of_course?(@course) @is_teacher = @user_course_identity < Course::ASSISTANT_PROFESSOR
@course_modules = @course.course_modules.where.not(module_type: "activity").where(hidden: 0) @course_modules = @course.course_modules.where(hidden: 0)
@hidden_modules = @course.course_modules.where(hidden: 1) @hidden_modules = @course.course_modules.where(hidden: 1)
@second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group"] @second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group"]
end end
@ -930,7 +977,7 @@ class CoursesController < ApplicationController
@page = params[:page] || 1 @page = params[:page] || 1
@page_size = params[:page_size] || 15 @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 # @total_count = @courses.count
# offset = 0 # offset = 0
@ -946,34 +993,33 @@ class CoursesController < ApplicationController
def export_member_scores_excel def export_member_scores_excel
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
name = params[:name] ? "#{params[:name].strip}" : "" #用户名或学生学号id搜索 search = params[:search] ? "#{params[:search].strip}" : "" #用户名或学生学号id搜索
group_id = params[:group_id] #分班的班级id group_id = params[:group_id] #分班的班级id
if group_id && group_id != "0" && group_id != "-1" # if group_id && group_id != "0" && group_id != "-1"
@all_members = @course.students.course_find_by_ids("course_group_id",group_id) # @all_members = @course.students.course_find_by_ids("course_group_id",group_id)
elsif group_id && group_id == "0" # 未分班 # elsif group_id && group_id == "0" # 未分班
@all_members = @course.course_members.ungroup_students # @all_members = @course.course_members.ungroup_students
else # else
@all_members = @course.students # @all_members = @course.students
end # end
if name.present? # if name.present?
nick_name_search = @all_members.joins(:user).where("nickname like ?","%#{name}%") # @all_members = @all_members.joins(user: [:user_extension]).where('concat(users.lastname, users.firstname) like ? or user_extensions.student_id like ?',"%#{name}%","%#{name}%")
if nick_name_search.present? # end
@all_members = nick_name_search
else @all_members = student_act_score group_id, search
@all_members = @all_members.joins(user: [:user_extension]).where('user_extensions.student_id like ? OR user_extensions.student_realname like ?',"%#{name}%","%#{name}%")
end @c_homeworks = @course.homework_commons.homework_published.order("homework_commons.publish_time asc, homework_commons.created_at asc")
end @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_homeworks = @course.homework_commons.homework_published.order("publish_time asc, created_at asc") @c_tasks = @course.graduation_tasks.task_published.order("graduation_tasks.publish_time asc, graduation_tasks.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 @user_course_identity > Course::ASSISTANT_PROFESSOR if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作") tip_exception(403,"无权限操作")
elsif @all_members.size == 0
normal_status(-1,"课堂暂时没有学生")
else else
member_to_xlsx(@course,@all_members,@c_homeworks,@c_exercises,@c_tasks,@c_polls) member_to_xlsx(@course, @all_members, @c_homeworks, @c_exercises, @c_tasks)
filename = current_user.real_name + "_" + @course.name + "_全部成绩" + Time.now.strftime('%Y%m%d_%H%M%S') filename_ = "#{current_user.real_name}_#{@course.name}_全部成绩"
render xlsx: "#{filename.strip.first(30)}",template: "courses/export_member_scores_excel.xlsx.axlsx", 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, locals: {course_info:@course_info, activity_level:@user_activity_level,
course_scores:@course_user_scores,shixun_works:@shixun_work_arrays, 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, common_works:@common_work_arrays,group_works:@group_work_arrays,task_works:@task_work_arrays,
@ -981,12 +1027,26 @@ class CoursesController < ApplicationController
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("没有权限") tip_exception(e.message)
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end 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 private
# Use callbacks to share common setup or constraints between actions. # 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]) && tip_exception("课堂名称应以课程名称开头命名") unless params[:course][:name].index(params[:course_list_name]) &&
params[:course][:name].index(params[:course_list_name]) == 0 params[:course][:name].index(params[:course_list_name]) == 0
tip_exception("课堂所属单位不能为空!") if params[:school].blank? tip_exception("课堂所属单位不能为空!") if params[:school].blank?
tip_exception("请至少添加一个课堂模块") if params[:course_module_types].blank?
@school = School.find_by!(name: params[:school].strip) @school = School.find_by!(name: params[:school].strip)
end end
@ -1029,16 +1090,72 @@ class CoursesController < ApplicationController
end end
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) + ["总得分"] 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_titles = common_homeworks.pluck(:name)+ ["总得分"]
common_homeworks = common_homeworks&.includes(score_student_works: :user)
group_homeworks = homeworks.search_homework_type(3) #全部分组作业 group_homeworks = homeworks.search_homework_type(3) #全部分组作业
group_titles = group_homeworks.pluck(:name)+ ["总得分"] group_titles = group_homeworks.pluck(:name)+ ["总得分"]
task_titles = tasks.pluck(:name)+ ["总得分"] group_homeworks = group_homeworks&.includes(score_student_works: :user)
exercise_titles = exercises.pluck(:exercise_name)+ ["总得分"]
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 = [] #学生总成绩集合 total_user_score_array = [] #学生总成绩集合
#课堂信息 #课堂信息
@ -1047,13 +1164,13 @@ class CoursesController < ApplicationController
course_id = course.id course_id = course.id
course_name = course.name course_name = course.name
course_list_name = course.course_list.present? ? course.course_list.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 = course.teachers
course_assistants_count = course_assistants&.count course_assistants_count = course_assistants&.size
course_assistants_name = course_assistants_count > 0 ? course_assistants.map{|m| m.user.real_name}.join('、') : "--" 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_member = course.course_members.course_user_role(%i[CREATOR])
course_teacher = course_teacher_member.present? ? course_teacher_member.first.user.real_name : "--" course_teacher = course_teacher_member.present? ? course_teacher_member.first.user.real_name : "--"
course_class_counts = course.course_groups_count course_class_counts = course.course_groups_count
course_students_count = course.students.count course_students_count = course.students.size
course_1 = ["课堂编号",course_id] course_1 = ["课堂编号",course_id]
course_2 = ["课程名称",course_list_name] course_2 = ["课程名称",course_list_name]
course_3 = ["课堂名称",course_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_main_info = [course_1,course_2,course_3,course_4,course_5,course_6,course_7]
course_group_info_head = %w(序号 分班名称 邀请码 学生数量) course_group_info_head = %w(序号 分班名称 邀请码 学生数量)
course_group_info_body = [] 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| course.course_groups.each_with_index do |group, index|
group_index = (index+1) group_index = (index+none_group_index)
group_name = group.name group_name = group.name
group_code = group.invite_code group_code = group.invite_code
group_count = group.course_members_count group_count = group.course_members_count
group_array = [group_index,group_name,group_code,group_count] group_array = [group_index,group_name,group_code,group_count]
course_group_info_body.push(group_array) course_group_info_body.push(group_array)
end end
end end
course_group_info = [course_group_info_head,course_group_info_body] course_group_info = [course_group_info_head,course_group_info_body]
@course_info += [course_info_title,course_main_info,course_group_info] @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 = [] @user_activity_level = []
course_user_level = [] course_user_level = []
course_activity_title = "课堂活跃度统计" course_activity_title = "课堂活跃度统计"
@ -1093,27 +1217,26 @@ class CoursesController < ApplicationController
user_login = user.login user_login = user.login
user_name = user.real_name user_name = user.real_name
user_mail = user.mail 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_course_group = u.course_group_name
user_info_array = [user_login,user_name,user_mail,user_stu_id,user_course_group] #用户的信息集合 user_info_array = [user_login,user_name,user_mail,user_stu_id,user_course_group] #用户的信息集合
user_work_scores = [] user_work_scores = []
#课堂活跃度统计 #课堂活跃度统计
user_homeworks_num = user.student_works.find_by_homework(course_homework_ids).has_committed.count #完成的作业数 user_homeworks_num = u.homework_num.to_i #完成的作业数
user_graduate_num = user.graduation_works.find_by_task(course_graduate_task_ids).has_committed.count #毕业任务完成数 user_graduate_num = u.graduation_num.to_i #毕业任务完成数
user_exercise_num = user.exercise_users.search_by_exercise(course_exercise_ids).commit_exercise_by_status(1).count #根据试卷的id来查找 user_exercise_num = u.exercise_num.to_i #根据试卷的id来查找
user_poll_num = user.poll_users.search_by_poll(course_poll_ids).commit_by_status(1).count #已完成问卷 user_poll_num = u.poll_num.to_i #已完成问卷
user_file_num = user.attachments.search_by_container(course.id).count user_file_num = u.resource_num.to_i
user_messages = user.messages user_messages_num = u.message_num.to_i #帖子发布数
user_messages_num = user_messages.root_nodes.find_by_boards(course_board_ids).count #帖子发布数 user_reply_num = u.message_reply_num.to_i #帖子回复数
user_reply_num = user_messages.reply_nodes.find_by_boards(course_board_ids).count #帖子回复数 user_work_reply_num = u.homework_journal_num.to_i #作业回复数的数量
user_work_reply_num = user.journals_for_messages.search_by_jour_type("HomeworkCommon",course_homework_ids).count #作业回复数的数量
c_works_num = (user_homeworks_num + user_graduate_num)*10 c_works_num = (user_homeworks_num + user_graduate_num)*10
c_exercise_num = user_exercise_num*10 c_exercise_num = user_exercise_num*10
c_poll_num = user_poll_num*7 c_poll_num = user_poll_num*7
c_file_num = user_file_num*5 c_file_num = user_file_num*5
c_message_num = user_messages_num*2 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_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 = { user_ac_level = {
u_1: user_name, u_1: user_name,
@ -1145,14 +1268,13 @@ class CoursesController < ApplicationController
exercise_score_array = [] exercise_score_array = []
#实训作业 #实训作业
if shixun_homeworks.count > 0 if shixun_homeworks.size > 0
shixun_homeworks.each do |s| shixun_homeworks.each do |s|
user_student_work = s.student_works.homework_by_user(user.id) #当前用户的对该作业的回答 user_student_work = s.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
if user_student_work.blank? if user_student_work.nil?
h_score = 0.0 #该作业的得分为0 h_score = 0.0 #该作业的得分为0
else else
user_stu_work = user_student_work.first h_score = user_student_work.work_score.nil? ? 0.0 : user_student_work.work_score #用户对该作业的分数
h_score = user_stu_work.work_score.nil? ? 0.0 : user_stu_work.work_score #用户对该作业的分数
end end
shixun_score_array.push(h_score) shixun_score_array.push(h_score)
end end
@ -1162,14 +1284,13 @@ class CoursesController < ApplicationController
user_work_scores += user_info_array + shixun_score_array #单个用户的实训作业得分信息 user_work_scores += user_info_array + shixun_score_array #单个用户的实训作业得分信息
#普通作业 #普通作业
if common_homeworks.count > 0 if common_homeworks.size > 0
common_homeworks.each do |c| common_homeworks.each do |c|
user_student_work_1 = c.student_works.homework_by_user(user.id) #当前用户的对该作业的回答 user_student_work_1 = c.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
if user_student_work_1.blank? if user_student_work_1.nil?
h_score_1 = 0.0 #该作业的得分为0 h_score_1 = 0.0 #该作业的得分为0
else else
user_stu_work_1 = user_student_work_1.first h_score_1 = user_student_work_1.work_score.nil? ? 0.0 : user_student_work_1.work_score #用户对该作业的分数
h_score_1 = user_stu_work_1.work_score.nil? ? 0.0 : user_stu_work_1.work_score #用户对该作业的分数
end end
common_score_array.push(h_score_1) common_score_array.push(h_score_1)
end end
@ -1179,14 +1300,13 @@ class CoursesController < ApplicationController
user_work_scores += common_score_array #单个用户的普通作业得分信息 user_work_scores += common_score_array #单个用户的普通作业得分信息
#分组作业 #分组作业
if group_homeworks.count > 0 if group_homeworks.size > 0
group_homeworks.each do |g| group_homeworks.each do |g|
user_student_work_3 = g.student_works.homework_by_user(user.id) #当前用户的对该作业的回答 user_student_work_3 = g.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
if user_student_work_3.blank? if user_student_work_3.nil?
h_score_3 = 0.0 #该作业的得分为0 h_score_3 = 0.0 #该作业的得分为0
else else
user_stu_work_3 = user_student_work_3.first h_score_3 = user_student_work_3.work_score.nil? ? 0.0 : user_student_work_3.work_score #用户对该作业的分数
h_score_3 = user_stu_work_3.work_score.nil? ? 0.0 : user_stu_work_3.work_score #用户对该作业的分数
end end
group_score_array.push(h_score_3) group_score_array.push(h_score_3)
end end
@ -1196,13 +1316,13 @@ class CoursesController < ApplicationController
user_work_scores += group_score_array #单个用户的分组作业得分信息 user_work_scores += group_score_array #单个用户的分组作业得分信息
#毕设作业 #毕设作业
if tasks.count > 0 if tasks.size > 0
tasks.each do |task| tasks.each do |task|
graduation_works = task.graduation_works.find_by_task_user(user.id) graduation_work = task.score_graduation_works.select{|work| work.user_id == user.id}.first
if graduation_works.empty? if graduation_work.nil?
t_score = 0.0 t_score = 0.0
else 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 end
task_score_array.push(t_score) task_score_array.push(t_score)
end end
@ -1212,13 +1332,13 @@ class CoursesController < ApplicationController
user_work_scores += task_score_array #单个用户的分组作业得分信息 user_work_scores += task_score_array #单个用户的分组作业得分信息
#试卷 #试卷
if exercises.count > 0 if exercises.size > 0
exercises.each do |ex| exercises.each do |ex|
exercise_works = ex.exercise_users.exercise_commit_users(user.id) exercise_work = ex.score_exercise_users.select{|work| work.user_id == user.id}.first
if exercise_works.empty? if exercise_work.nil?
e_score = 0.0 e_score = 0.0
else 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 end
exercise_score_array.push(e_score) exercise_score_array.push(e_score)
end end
@ -1250,73 +1370,60 @@ class CoursesController < ApplicationController
@common_work_arrays = [] @common_work_arrays = []
@task_work_arrays = [] @task_work_arrays = []
@exercise_work_arrays = [] @exercise_work_arrays = []
count_1 = shixun_homeworks.count count_1 = shixun_homeworks.size
count_2 = common_homeworks.count count_2 = common_homeworks.size
count_3 = group_homeworks.count count_3 = group_homeworks.size
count_4 = tasks.count count_4 = tasks.size
count_5 = exercises.count
#实训作业 #实训作业
if count_1 > 0 shixun_homeworks.each_with_index do |s,index|
shixun_homeworks.each_with_index do |s,index| all_student_works = s.score_student_works #该实训题的全部用户回答
all_student_works = s.student_works.has_committed.order("work_score desc") #该实训题的全部用户回答 title_no = index.to_i + 1
title_no = index.to_i + 1 student_work_to_xlsx(all_student_works,s)
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_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_content = [shixun_work_display_name,@work_head_cells,@work_cells_column] @shixun_work_arrays.push(shixun_work_content)
@shixun_work_arrays.push(shixun_work_content)
end
end end
#普通作业 #普通作业
if count_2 > 0 common_homeworks.each_with_index do |c,index|
common_homeworks.each_with_index do |c,index| all_student_works = c.score_student_works #当前用户的对该作业的回答
all_student_works = c.student_works.has_committed.order("work_score desc") #当前用户的对该作业的回答 title_no = count_1 + index.to_i + 1
title_no = count_1 + index.to_i + 1 student_work_to_xlsx(all_student_works,c)
student_work_to_xlsx(all_student_works,c)
work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30)
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,@work_head_cells,@work_cells_column] @common_work_arrays.push(work_content)
@common_work_arrays.push(work_content) title_no
title_no
end
end end
#分组作业 #分组作业
if count_3 > 0 group_homeworks.each_with_index do |c,index|
group_homeworks.each_with_index do |c,index| all_student_works = c.score_student_works #当前用户的对该作业的回答
all_student_works = c.student_works.has_committed.order("work_score desc") #当前用户的对该作业的回答 title_no = count_1 + count_2 + index.to_i + 1
title_no = count_1 + count_2 + index.to_i + 1 student_work_to_xlsx(all_student_works,c)
student_work_to_xlsx(all_student_works,c) work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30)
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,@work_head_cells,@work_cells_column] @group_work_arrays.push(work_content)
@group_work_arrays.push(work_content)
end
end end
#毕设任务 #毕设任务
if count_4 > 0 tasks.each_with_index do |c,index|
tasks.each_with_index do |c,index| all_student_works = c.score_graduation_works #当前用户的对该作业的回答
all_student_works = c.graduation_works.has_committed.order("work_score desc") #当前用户的对该作业的回答 title_no = count_1 + count_2 + count_3 + index.to_i + 1
title_no = count_1 + count_2 + count_3 + index.to_i + 1 graduation_work_to_xlsx(all_student_works,c,current_user)
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_name = (title_no.to_s + "." + c.name).strip.first(30) work_content = [work_name,@head_cells_column,@task_cells_column]
# work_content = [work_name,@work_head_cells,@work_cells_column] @task_work_arrays.push(work_content)
work_content = [work_name,@head_cells_column,@task_cells_column]
@task_work_arrays.push(work_content)
end
end end
#试卷的导出 #试卷的导出
if count_5 > 0 exercises.each_with_index do |c,index|
exercises.each_with_index do |c,index| all_student_works = c.score_exercise_users #当前用户的对该作业的回答
all_student_works = c.exercise_users.exercise_user_committed #当前用户的对该作业的回答 title_no = count_1 + count_2 + count_3 + count_4 + index.to_i + 1
title_no = count_1 + count_2 + count_3 + count_4 + index.to_i + 1 get_export_users(c,course,all_student_works)
get_export_users(c,course,all_student_works) work_name = format_sheet_name (title_no.to_s + "." + c.exercise_name).strip.first(30)
work_name = (title_no.to_s + "." + c.exercise_name).strip.first(30) work_content = [work_name,@table_columns,@user_columns]
# work_content = [work_name,@work_head_cells,@work_cells_column] @exercise_work_arrays.push(work_content)
work_content = [work_name,@table_columns,@user_columns]
@exercise_work_arrays.push(work_content)
end
end end
end end
end end

@ -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

@ -7,9 +7,24 @@ class DiscussesController < ApplicationController
page = params[:page].to_i page = params[:page].to_i
offset = page * LIMIT offset = page * LIMIT
# 总数,分页使用 # 总数,分页使用
@disscuss_count = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil).count if current_user.admin?
@discusses = Discuss.limit(LIMIT).where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil). @disscuss_count = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil).count
includes(:user, :praise_tread).offset(offset) 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 @current_user = current_user
end end
@ -23,8 +38,10 @@ class DiscussesController < ApplicationController
def create def create
begin begin
@discuss = Discuss.create!(:dis_id => params[:container_id], :dis_type => params[:container_type], :content => params[:content].gsub("&nbsp\;", "").strip, @discuss = Discuss.create!(:dis_id => params[:container_id], :dis_type => params[:container_type],
:user_id => current_user.id, :praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id]) :content => params[:content].gsub("&nbsp\;", "").strip, :user_id => current_user.id,
:praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id],
:hidden => !current_user.admin?) # 管理员回复的能够显示
rescue Exception => e rescue Exception => e
uid_logger_error("create discuss failed : #{e.message}") uid_logger_error("create discuss failed : #{e.message}")
raise Educoder::TipException.new("评论异常") raise Educoder::TipException.new("评论异常")

@ -1,15 +1,6 @@
class Ecs::BaseController < ApplicationController class Ecs::BaseController < ApplicationController
# model validation error before_action :require_login, :check_auth
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 :check_user_permission! before_action :check_user_permission!
helper_method :current_user, :current_school helper_method :current_user, :current_school

@ -1,6 +1,7 @@
class ExerciseAnswersController < ApplicationController class ExerciseAnswersController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :get_exercise_question before_action :get_exercise_question
include ExercisesHelper
def create #每一次答案的点击,请求一次,实训题不在这里回答 def create #每一次答案的点击,请求一次,实训题不在这里回答
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@ -8,11 +9,11 @@ class ExerciseAnswersController < ApplicationController
q_type = @exercise_question.question_type #试卷的类型 q_type = @exercise_question.question_type #试卷的类型
choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : "" choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : ""
answer_text = params[:answer_text].present? ? params[:answer_text] : "" #为字符串 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,"请选择序号") normal_status(-1,"请选择序号")
else else
ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案 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 ea_choice = ea.search_exercise_answer("exercise_choice_id",choice_id).first
answer_option = { answer_option = {
:user_id => current_user.id, :user_id => current_user.id,
@ -29,8 +30,9 @@ class ExerciseAnswersController < ApplicationController
ex_a = ExerciseAnswer.new(answer_option) ex_a = ExerciseAnswer.new(answer_option)
ex_a.save! ex_a.save!
end end
elsif q_type == 1 #多选题的 elsif q_type == Exercise::MULTIPLE #多选题的
choice_ids = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : [] choice_ids = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : []
ea_ids = ea.pluck(:exercise_choice_id) ea_ids = ea.pluck(:exercise_choice_id)
common_answer_ids = choice_ids & ea_ids #已经存在的试卷选项id common_answer_ids = choice_ids & ea_ids #已经存在的试卷选项id
new_ids = choice_ids - common_answer_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 = ea.search_answer_users("exercise_choice_id",old_ids)
ea_answer.destroy_all ea_answer.destroy_all
end end
elsif q_type == 3 #填空题 elsif q_type == Exercise::COMPLETION #填空题
answer_option = { answer_option = {
:user_id => current_user.id, :user_id => current_user.id,
:exercise_question_id => @exercise_question.id, :exercise_question_id => @exercise_question.id,
@ -65,7 +67,7 @@ class ExerciseAnswersController < ApplicationController
ex_new = ExerciseAnswer.new(answer_option) ex_new = ExerciseAnswer.new(answer_option)
ex_new.save! ex_new.save!
end end
elsif q_type == 4 #简答题 elsif q_type == Exercise::SUBJECTIVE #简答题
answer_option = { answer_option = {
:user_id => current_user.id, :user_id => current_user.id,
:exercise_question_id => @exercise_question.id :exercise_question_id => @exercise_question.id
@ -92,9 +94,10 @@ class ExerciseAnswersController < ApplicationController
def get_exercise_question def get_exercise_question
@exercise_question = ExerciseQuestion.find_by_id(params[:exercise_question_id]) @exercise_question = ExerciseQuestion.find_by_id(params[:exercise_question_id])
@exercise = @exercise_question.exercise @exercise = @exercise_question&.exercise
@course = @exercise.course @course = @exercise&.course
@exercise_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first #当前用户 @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? if @exercise_question.blank?
normal_status(-1,"试卷问题不存在!") normal_status(-1,"试卷问题不存在!")
@ -102,15 +105,28 @@ class ExerciseAnswersController < ApplicationController
normal_status(-1,"试卷不存在!") normal_status(-1,"试卷不存在!")
elsif @course.blank? elsif @course.blank?
normal_status(-1,"该课堂不存在!") 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,"已提交/已结束的试卷不允许修改!") normal_status(-1,"已提交/已结束的试卷不允许修改!")
elsif @exercise.time > 0 else
user_start_at = @exercise.exercise_users.exercise_commit_users(current_user.id).first.start_at 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))
exercise_time = @exercise.time.to_i objective_score = calculate_student_score(@exercise,current_user)[:total_score]
if (user_start_at + exercise_time.minutes) < Time.now subjective_score = @exercise_user.subjective_score < 0.0 ? 0.0 : @exercise_user.subjective_score
normal_status(-1,"限时试卷已结束!") 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
end end
end end

@ -1,5 +1,5 @@
class ExerciseQuestionsController < ApplicationController class ExerciseQuestionsController < ApplicationController
before_action :require_login #用户需登陆 before_action :require_login, :check_auth #用户需登陆
before_action :get_exercise,only:[:new,:create] #获取试卷 before_action :get_exercise,only:[:new,:create] #获取试卷
before_action :get_exercise_question,except: [:new,:create] #获取试卷的问题及试卷 before_action :get_exercise_question,except: [:new,:create] #获取试卷的问题及试卷
before_action :is_course_teacher #是否为老师 before_action :is_course_teacher #是否为老师
@ -47,7 +47,7 @@ class ExerciseQuestionsController < ApplicationController
if @exercise_question.save if @exercise_question.save
#为选择题(包括单选和多选)的时候,创建问题选项 #为选择题(包括单选和多选)的时候,创建问题选项
ques_type = @exercise_question.question_type ques_type = @exercise_question.question_type
if ques_type <= 1 if ques_type <= Exercise::MULTIPLE
choices_array = params[:question_choices] choices_array = params[:question_choices]
choices_count= choices_array.count choices_count= choices_array.count
standard_answer = params[:standard_answers] #为数组格式,因为可能会有单选和多选,标准答案,已提前判断不能为空, standard_answer = params[:standard_answers] #为数组格式,因为可能会有单选和多选,标准答案,已提前判断不能为空,
@ -70,13 +70,13 @@ class ExerciseQuestionsController < ApplicationController
} }
question_standard_answer = ExerciseStandardAnswer.new(standard_option) question_standard_answer = ExerciseStandardAnswer.new(standard_option)
question_standard_answer.save question_standard_answer.save
if standard_answer.count > 1 && ques_type == 0 #当标准答案数大于1且不为多选时修改为多选 if standard_answer.count > 1 && ques_type == Exercise::SINGLE #当标准答案数大于1且不为多选时修改为多选
@exercise_question.update_attribute("question_type",1) @exercise_question.update_attribute("question_type",Exercise::MULTIPLE)
elsif standard_answer.count == 1 && ques_type == 1 elsif standard_answer.count == 1 && ques_type == Exercise::MULTIPLE
@exercise_question.update_attribute("question_type",0) @exercise_question.update_attribute("question_type",Exercise::SINGLE)
end end
end end
elsif ques_type == 2 #这个为判断题 elsif ques_type == Exercise::JUDGMENT #这个为判断题
choices_array = params[:question_choices] #判断的选项,对/错等等 choices_array = params[:question_choices] #判断的选项,对/错等等
choices_count= choices_array.count choices_count= choices_array.count
(1..choices_count).each do |c| (1..choices_count).each do |c|
@ -95,7 +95,7 @@ class ExerciseQuestionsController < ApplicationController
} }
question_standard_answer = ExerciseStandardAnswer.new(standard_option) question_standard_answer = ExerciseStandardAnswer.new(standard_option)
question_standard_answer.save question_standard_answer.save
elsif ques_type == 3 #填空题,每空的参考答案有多个,那么以位置对应 elsif ques_type == Exercise::COMPLETION #填空题,每空的参考答案有多个,那么以位置对应
standard_answer = params[:standard_answers] standard_answer = params[:standard_answers]
standard_answer.each do |a| standard_answer.each do |a|
null_choice_id = a[:choice_id] null_choice_id = a[:choice_id]
@ -110,7 +110,7 @@ class ExerciseQuestionsController < ApplicationController
question_standard_answer.save question_standard_answer.save
end end
end end
elsif ques_type == 4 #简答题 elsif ques_type == Exercise::SUBJECTIVE #简答题
if params[:standard_answers].present? && params[:standard_answers].reject(&:blank?).count > 0 if params[:standard_answers].present? && params[:standard_answers].reject(&:blank?).count > 0
standard_answer = params[:standard_answers] standard_answer = params[:standard_answers]
standard_answer.each do |a| standard_answer.each do |a|
@ -122,12 +122,12 @@ class ExerciseQuestionsController < ApplicationController
question_standard_answer.save question_standard_answer.save
end end
end end
elsif ques_type == 5 #实训题 elsif ques_type == Exercise::PRACTICAL #实训题
shixun = Shixun.find_by(id: params[:shixun_id]) shixun = Shixun.find_by(id: params[:shixun_id])
shixun_scores = params[:question_scores] #试卷有多个的分值有多个分数表,所以为分数的数组 shixun_scores = params[:question_scores] #试卷有多个的分值有多个分数表,所以为分数的数组
shixun_name = params[:shixun_name] || shixun.name shixun_name = params[:shixun_name] || shixun.name
question_score = 0 question_score = 0
shixun.challenges.each_with_index do |challenge,index| shixun.challenges.try(:each_with_index) do |challenge,index|
shixun_option = { shixun_option = {
:challenge_id => challenge.id, :challenge_id => challenge.id,
:shixun_id => shixun.id, :shixun_id => shixun.id,
@ -223,16 +223,14 @@ class ExerciseQuestionsController < ApplicationController
end end
end end
#试卷未发布时,当标准答案存在时,可修改标准答案内容,可增删标准答案,否则只能修改标准答案,不能增删标准答案 #试卷未发布时,当标准答案存在时,可修改标准答案内容,可增删标准答案,否则只能修改标准答案,不能增删标准答案
st_count = 0
@exercise_answers_array = @exercise_question.exercise_standard_answers #问卷的全部标准答案 @exercise_answers_array = @exercise_question.exercise_standard_answers #问卷的全部标准答案
if standard_answer.present? 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) #问题以前的全部标准答案选项位置 exercise_standard_choices = @exercise_answers_array.pluck(:exercise_choice_id) #问题以前的全部标准答案选项位置
common_standard_choices = standard_answer & exercise_standard_choices # 传入的标准答案的选项位置和以前的并集,即表示不用做更改的 common_standard_choices = standard_answer & exercise_standard_choices # 传入的标准答案的选项位置和以前的并集,即表示不用做更改的
old_left_standard_choices = exercise_standard_choices - common_standard_choices # 以前的差集共同的,剩余的表示需要删掉 old_left_standard_choices = exercise_standard_choices - common_standard_choices # 以前的差集共同的,剩余的表示需要删掉
new_left_standard_choices = standard_answer - common_standard_choices # 传入的标准答案差集共同的,剩余的表示需要新建 new_left_standard_choices = standard_answer - common_standard_choices # 传入的标准答案差集共同的,剩余的表示需要新建
if old_left_standard_choices.count > 0 if old_left_standard_choices.count > 0
st_count += 1
@exercise_answers_array.standard_by_ids(old_left_standard_choices).destroy_all @exercise_answers_array.standard_by_ids(old_left_standard_choices).destroy_all
end end
if new_left_standard_choices.count > 0 #新建标准答案 if new_left_standard_choices.count > 0 #新建标准答案
@ -246,19 +244,18 @@ class ExerciseQuestionsController < ApplicationController
end end
end end
if standard_answer.count > 1 && @exercise_question.question_type == 0 #当标准答案数大于1且不为多选时修改为多选 if standard_answer.count > 1 && @exercise_question.question_type == Exercise::SINGLE #当标准答案数大于1且不为多选时修改为多选
@exercise_question.update_attribute("question_type",1) @exercise_question.update_attribute("question_type",Exercise::MULTIPLE)
elsif standard_answer.count == 1 && @exercise_question.question_type == 1 elsif standard_answer.count == 1 && @exercise_question.question_type == Exercise::MULTIPLE
@exercise_question.update_attribute("question_type",0) @exercise_question.update_attribute("question_type",Exercise::SINGLE)
end 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 = @exercise_question.exercise_standard_answers #当前问题的全部标准答案
old_ex_answer_choice_ids = old_ex_answer.pluck(:exercise_choice_id).uniq #全部的答案数组序号 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 #新传入的答案数组序号 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 #有减少的填空 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 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 old_ex_answer.standard_by_ids(delete_ex_answer_choice_ids).destroy_all
end end
@ -284,7 +281,6 @@ class ExerciseQuestionsController < ApplicationController
ex_answer_pre[n-1].update(standard_option) ex_answer_pre[n-1].update(standard_option)
end end
if new_add_choice.count > 0 #表示有新增的 if new_add_choice.count > 0 #表示有新增的
st_count += 1
new_add_choice.each do |i| new_add_choice.each do |i|
standard_option = { standard_option = {
:exercise_question_id => @exercise_question.id, :exercise_question_id => @exercise_question.id,
@ -306,7 +302,6 @@ class ExerciseQuestionsController < ApplicationController
ex_answer_pre[index].update(standard_option) ex_answer_pre[index].update(standard_option)
end end
if new_delete_choice.count > 0 #表示填空题的答案有删减的 if new_delete_choice.count > 0 #表示填空题的答案有删减的
st_count += 1
new_delete_choice.each do |d| new_delete_choice.each do |d|
ex_answer_pre[d-1].destroy ex_answer_pre[d-1].destroy
end end
@ -326,7 +321,7 @@ class ExerciseQuestionsController < ApplicationController
end end
end 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 main_standard_answer = standard_answer.present? ? standard_answer.first : nil
if @exercise_answers_array.present? if @exercise_answers_array.present?
@exercise_answers_array.first.update_attribute("answer_text",main_standard_answer) @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 = ExerciseStandardAnswer.new(standard_option)
question_standard_answer.save question_standard_answer.save
end end
elsif @exercise_question.question_type == 5 elsif @exercise_question.question_type == Exercise::PRACTICAL
question_score = 0 question_score = 0
shixun_name = params[:shixun_name] || @exercise_question.shixun_name shixun_name = params[:shixun_name] || @exercise_question.shixun_name
@exercise_question.exercise_shixun_challenges.each_with_index do |challenge, index| @exercise_question.exercise_shixun_challenges.each_with_index do |challenge, index|
@ -350,8 +345,9 @@ class ExerciseQuestionsController < ApplicationController
@exercise_question.shixun_name = shixun_name @exercise_question.shixun_name = shixun_name
end end
#当标准答案修改时,如有已提交的学生,需重新计算分数 #当试卷已发布时(试卷的总状态),当标准答案修改时,如有已提交的学生,需重新计算分数.
if st_count > 0
if @exercise.exercise_status == Exercise::PUBLISHED
ex_users_committed = @exercise.exercise_users.exercise_user_committed ex_users_committed = @exercise.exercise_users.exercise_user_committed
if ex_users_committed.size > 0 if ex_users_committed.size > 0
ex_users_committed.each do |ex_user| ex_users_committed.each do |ex_user|
@ -364,12 +360,7 @@ class ExerciseQuestionsController < ApplicationController
end end
end end
end end
normal_status(0,"试卷更新成功!")
if @exercise_question.save
normal_status(0,"试卷更新成功!")
else
normal_status(-1,"试卷更新失败!")
end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("页面调用失败!") tip_exception("页面调用失败!")
@ -384,24 +375,22 @@ class ExerciseQuestionsController < ApplicationController
begin begin
opr = params[:opr] opr = params[:opr]
current_q_p = @exercise_question.question_number.to_i #问题的当前位置 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 # 当前问题的前一个问题 if @exercise.exercise_status.to_i == Exercise::UNPUBLISHED
# 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 opr.present? if opr.present?
if opr.to_s == "up" if opr.to_s == "up"
last_q_p = @exercise.exercise_questions.find_by(question_number: (current_q_p - 1)) # 当前问题的前一个问题
if last_q_p.present? if last_q_p.present?
@exercise_question.update_attribute('question_number', (current_q_p - 1)) @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, "问题上移成功!") normal_status(0, "问题上移成功!")
else else
normal_status(-1, "移动失败,已经是第一个问题了!") normal_status(-1, "移动失败,已经是第一个问题了!")
end end
elsif opr.to_s == "down" elsif opr.to_s == "down"
next_q_p = @exercise.exercise_questions.find_by(question_number: (current_q_p + 1)) # 当前问题的前一个问题
if next_q_p.present? if next_q_p.present?
@exercise_question.update_attribute('question_number', (current_q_p + 1)) @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, "问题下移成功!") normal_status(0, "问题下移成功!")
else else
normal_status(-1, "移动失败,已经是最后一个问题了!") normal_status(-1, "移动失败,已经是最后一个问题了!")
@ -426,14 +415,9 @@ class ExerciseQuestionsController < ApplicationController
begin begin
choice_d_id = params[:choice_no].to_i # 选项的当前位置 choice_d_id = params[:choice_no].to_i # 选项的当前位置
question_choices = @exercise_question.exercise_choices question_choices = @exercise_question.exercise_choices
delete_answer = question_choices.find_choice_custom("choice_position",choice_d_id).first delete_answer = question_choices.find_by(choice_position: choice_d_id)
left_choice = question_choices.left_choice_choose("choice_position",choice_d_id) left_choices = question_choices.where("choice_position > ? ",choice_d_id)
if left_choice.present? left_choices.update_all("choice_position = choice_position - 1") if left_choices
left_choice.each do |p|
p.choice_position -= 1
p.save
end
end
if delete_answer.destroy if delete_answer.destroy
normal_status(0, "答案删除成功!") normal_status(0, "答案删除成功!")
else else
@ -452,13 +436,8 @@ class ExerciseQuestionsController < ApplicationController
begin begin
question_d_id = @exercise_question.question_number.to_i #问题的当前位置 question_d_id = @exercise_question.question_number.to_i #问题的当前位置
exercise_questions = @exercise.exercise_questions exercise_questions = @exercise.exercise_questions
left_question = exercise_questions.left_question_choose("question_number",question_d_id) left_questions = exercise_questions.where("question_number > ?", question_d_id)
if left_question.present? left_questions.update_all("question_number = question_number - 1") if left_questions
left_question.each do |q|
q.question_number -= 1
q.save
end
end
if @exercise_question.destroy if @exercise_question.destroy
normal_status(0, "问题删除成功!") normal_status(0, "问题删除成功!")
else else
@ -478,9 +457,9 @@ class ExerciseQuestionsController < ApplicationController
ex_obj_score = @exercise_current_user.objective_score #全部客观题得分 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_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) #当前用户答案的得分 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 #每一关的得分总和 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 new_obj_score = ex_obj_score - ex_answer_old + @c_score
total_scores = new_obj_score + ex_subj_score total_scores = new_obj_score + ex_subj_score
ex_scores = { ex_scores = {
@ -489,8 +468,8 @@ class ExerciseQuestionsController < ApplicationController
} }
@exercise_current_user.update_attributes(ex_scores) @exercise_current_user.update_attributes(ex_scores)
ex_answers.update_all(:score => each_right_score) #所有的正确选项需重新更新 ex_answers.update_all(:score => each_right_score) #所有的正确选项需重新更新
elsif @exercise_question.question_type == 4 #当为主观题时 elsif @exercise_question.question_type == Exercise::SUBJECTIVE #当为主观题时
if ex_answers.present? if ex_answers.exists?
ex_answers_old_score = ex_answers.first.score > 0.0 ? ex_answers.first.score : 0.0 #原分数小于0取0 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 #原全部主观题总分减去原该主观题得分再加调分后的分数,即为当前全部主观题得分 new_sub_score = ex_subj_score - ex_answers_old_score + @c_score #原全部主观题总分减去原该主观题得分再加调分后的分数,即为当前全部主观题得分
ex_answers.first.update_attribute("score",@c_score) ex_answers.first.update_attribute("score",@c_score)
@ -502,7 +481,7 @@ class ExerciseQuestionsController < ApplicationController
:answer_text => "" :answer_text => ""
} }
ExerciseAnswer.create(answer_option) ExerciseAnswer.create(answer_option)
new_sub_score = @c_score new_sub_score = ex_subj_score + @c_score
end end
total_scores = ex_obj_score + new_sub_score total_scores = ex_obj_score + new_sub_score
ex_scores = { ex_scores = {
@ -511,8 +490,7 @@ class ExerciseQuestionsController < ApplicationController
} }
@exercise_current_user.update_attributes(ex_scores) @exercise_current_user.update_attributes(ex_scores)
elsif @exercise_question.question_type == 5 elsif @exercise_question.question_type == Exercise::PRACTICAL
# ex_answers = @exercise_question.exercise_shixun_answers.search_shixun_answers("user_id",@user_id).search_shixun_answers("exercise_shixun_challenge_id",@shixun_a_id)
ex_answers = @exercise_question.exercise_shixun_answers.where(user_id:@user_id,exercise_shixun_challenge_id:@shixun_a_id) ex_answers = @exercise_question.exercise_shixun_answers.where(user_id:@user_id,exercise_shixun_challenge_id:@shixun_a_id)
if ex_answers.present? #当为实训题时 if ex_answers.present? #当为实训题时
@ -599,23 +577,23 @@ class ExerciseQuestionsController < ApplicationController
if @exercise_question.present? if @exercise_question.present?
@exercise = @exercise_question.exercise @exercise = @exercise_question.exercise
if @exercise.blank? if @exercise.blank?
tip_exception(404) tip_exception(404,"试卷不存在")
else else
@course = @exercise.course @course = @exercise.course
if @course.blank? if @course.blank?
tip_exception(404) tip_exception(404,"课堂不存在")
end end
end end
else else
tip_exception(404) tip_exception(404,"试卷问题不存在")
end end
end end
def validate_params 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_type].blank?
normal_status(-1,"分值不允许为空!" ) if params[:question_score].blank? && params[:question_scores].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") 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)) 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分") 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个选项不能为空 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个") 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 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 elsif params[:question_type].to_i == 3 && (params[:standard_answers].blank? || params[:standard_answers].count > 5 ) #填空题选项最多为5个,且如果为1个的话不允许修改is_ordered
normal_status(-1,"填空题标准答案不能为空/不能超过5个") normal_status(-1,"填空题标准答案不能为空/不能超过5个")
elsif params[:question_type].to_i == 4 && params[:standard_answers].count > 2 #简单题参考答案最多为1个 elsif params[:question_type].to_i == 4 && params[:standard_answers].count > 2 #简单题参考答案最多为1个
@ -643,16 +621,16 @@ class ExerciseQuestionsController < ApplicationController
end end
def check_exercise_status def check_exercise_status
normal_status(-1,"不能更改试卷问题!") if @exercise.exercise_status != 1 normal_status(-1,"不能更改试卷问题!") if @exercise.exercise_status != Exercise::UNPUBLISHED
end end
#更新时不能修改的内容 #更新时不能修改的内容
def cannot_change_column def cannot_change_column
#已发布的/已截止的/评阅中的状态时,不能修改分数,不能增删问题和答案,不能修改标准答案,可以修改选项内容/题目内容,这里仅指单个问题 #已发布的/已截止的/评阅中的状态时,不能修改分数,不能增删问题和答案,不能修改标准答案,可以修改选项内容/题目内容,这里仅指单个问题
if @exercise.exercise_status != 1 if @exercise.exercise_status != Exercise::UNPUBLISHED
question_score = @exercise_question.question_score #原来的分数 question_score = @exercise_question.question_score #原来的分数
update_question_score = params[:question_score].to_f.round(1) #传入的分数 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 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 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 #传入的选项个数 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 #选项个数有修改 elsif update_choices_count != choices_count #选项个数有修改
normal_status(-1,"已发布/已截止,不允许增删答案!") normal_status(-1,"已发布/已截止,不允许增删答案!")
elsif standard_answer.present? 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 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) unless (standard_answer.count == exercise_choice_ids.count) && (standard_answers_text.count == exercise_answers_text.count)
normal_status(-1,"已发布/已截止,不允许增删标准答案!") normal_status(-1,"已发布/已截止,不允许增删标准答案!")
end end
elsif @exercise_question.question_type == 4 elsif @exercise_question.question_type == Exercise::SUBJECTIVE
unless standard_answers_text.count == standard_answer.count unless standard_answers_text.count == standard_answer.count
normal_status(-1,"已发布/已截止,不允许增删标准答案!") normal_status(-1,"已发布/已截止,不允许增删标准答案!")
end end
@ -677,20 +655,20 @@ class ExerciseQuestionsController < ApplicationController
end end
def check_adjust_score def check_adjust_score
@c_score = params[:score].to_f.round(1) #调分后的分数 @c_score = params[:score].to_f #调分后的分数
@user_id = params[:user_id] @user_id = params[:user_id]
@exercise_current_user = @exercise.exercise_users.exercise_commit_users(@user_id).first #当前试卷用户的答案内容 @exercise_current_user = @exercise.exercise_users.exercise_commit_users(@user_id).first #当前试卷用户的答案内容
if @exercise_current_user.blank? if @exercise_current_user.blank?
normal_status(-1,"用户不存在!") normal_status(-1,"用户不存在!")
elsif @c_score.blank? elsif @c_score.blank?
normal_status(-1,"分数不能为空!") normal_status(-1,"分数不能为空!")
elsif @exercise_question.question_type <= 1 || @exercise_question.question_type == 2 elsif @exercise_question.question_type <= Exercise::JUDGMENT
normal_status(-1,"选择题/判断题不能调分!") normal_status(-1,"选择题/判断题不能调分!")
elsif params[:comment].present? && params[:comment].length > 100 elsif params[:comment].present? && params[:comment].length > 100
normal_status(-1,"评语不能超过100个字符!") normal_status(-1,"评语不能超过100个字符!")
else else
@shixun_a_id = params[:shixun_challenge_id] @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) @shixun_challenge = @exercise_question.exercise_shixun_challenges.cha_id_find(@shixun_a_id)
if @shixun_challenge.present? if @shixun_challenge.present?
@old_ques_score = @shixun_challenge.first.question_score @old_ques_score = @shixun_challenge.first.question_score

File diff suppressed because it is too large Load Diff

@ -1,9 +1,9 @@
class FilesController < ApplicationController class FilesController < ApplicationController
include MessagesHelper 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_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 :file_validate_sort_type, only: :index
before_action :validate_send_message_to_course_params, only: :bulk_send 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] 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 = params[:sort] || 0 # 0: 降序1: 升序
sort_type = params[:sort_type] || 'created_on' # created_on时间排序 downloads下载次数排序; quotes: 引用次数排序 sort_type = params[:sort_type] || 'created_on' # created_on时间排序 downloads下载次数排序; quotes: 引用次数排序
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
@user = current_user || nil @user = current_user
@attachments = @course.attachments.by_keywords(params[:search]) @attachments = @course.attachments.by_course_second_category_id(course_second_category_id)
.includes(attachment_group_settings: :course_group, author: [:user_extension, :course_members]) .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) .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 @total_count = @attachments.size
@public_count = @attachments.publiced.size @publish_count = @attachments.published.size
@private_count = @total_count - @public_count @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) @attachments = @attachments.page(@page).per(@page_size)
end 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 def bulk_delete
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@ -180,6 +187,8 @@ class FilesController < ApplicationController
attach_copied_obj.created_on = Time.now attach_copied_obj.created_on = Time.now
attach_copied_obj.author = current_user attach_copied_obj.author = current_user
attach_copied_obj.is_public = 0 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.course_second_category_id = course_second_category_id
attach_copied_obj.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from attach_copied_obj.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from
if attach_copied_obj.attachtype == nil if attach_copied_obj.attachtype == nil
@ -197,7 +206,7 @@ class FilesController < ApplicationController
# 资源设置 # 资源设置
def update 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] is_unified_setting = params[:is_unified_setting]
publish_time = params[:publish_time] publish_time = params[:publish_time]

@ -1,5 +1,5 @@
class GamesController < ApplicationController class GamesController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :find_game before_action :find_game
before_action :find_shixun, only: [:show, :answer, :rep_content, :choose_build, :game_build, :game_status] 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? 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) 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) next_game = @game.next_of_current_game(@shixun.id, @game.myshixun_id, game_challenge.position)
# 关卡点赞数, praise_or_tread = 1则表示赞过 # 关卡点赞数, praise_or_tread = 1则表示赞过
praise_count = PraiseTread.where(praise_tread_object_id: game_challenge.id, praise_tread_object_type: "Challenge", praise_count = game_challenge.praises_count
praise_or_tread: 1).count user_praise = game_challenge.praise_treads.exists?(user_id:current_user.id, praise_or_tread: 1)
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
# 实训的最大评测次数,这个值是为了优化查询,每次只取最新的最新一次评测的结果集 # 实训的最大评测次数,这个值是为了优化查询,每次只取最新的最新一次评测的结果集
max_query_index = @game.query_index.to_i 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判断用户是否有权限查看隐藏测试集(TPM管理员平台认证的老师花费金币查看者)
# myshixun_manager myshixun_manager = @identity < User::EDU_GAME_MANAGER
myshixun_manager = current_user.manager_of_shixun?(@shixun) || (current_user.is_teacher? && current_user.pro_certification?)
# 选择题和编程题公共部分 # 选择题和编程题公共部分
@base_date = {st: @st, discusses_count: discusses_count, game_count: game_count, myshixun: @myshixun, @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, praise_count: praise_count, user_praise: user_praise, time_limit: time_limit,
tomcat_url: edu_setting('cloud_tomcat_php'), is_teacher: is_teacher, tomcat_url: edu_setting('cloud_tomcat_php'), is_teacher: is_teacher,
myshixun_manager: myshixun_manager} 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
# 区分选择题和编程题st0编程题 # 区分选择题和编程题st0编程题
if @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 game_challenge.answer = nil
mirror_name = @shixun.mirror_name mirror_name = @shixun.mirror_name
@ -75,7 +90,7 @@ class GamesController < ApplicationController
rescue rescue
uid_logger("实训平台繁忙繁忙等级81") uid_logger("实训平台繁忙繁忙等级81")
end 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} @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 @result = challenge.st == 0 ? challenge.try(:answer) : challenge.choose_answer
end end
# 获取答案 # 获取实践题答案
# GET: /tasks/:identifier/get_answer_info # GET: /tasks/:identifier/get_answer_info
# 0 直接查看答案, 1 查看答案弹框, 2 答案详情弹框 # 0 直接查看答案, 1 查看答案弹框, 2 答案详情弹框
def get_answer_info def get_answer_info
challenge = @game.challenge @challenge = @game.challenge
@challenge_answers = challenge.challenge_answers @challenge_answers = @challenge.challenge_answers
# 平台已认证的老师需要控制 # 平台已认证的老师需要控制
@power = (@identity < User::EDU_GAME_MANAGER) @power = (@identity < User::EDU_GAME_MANAGER)
if !@power if !@power
@ -229,16 +244,29 @@ class GamesController < ApplicationController
end end
end 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 end
# 解锁答案 # 解锁实践题答案
# GET: /tasks/:identifier/get_answer_info?answer_id=? # GET: /tasks/:identifier/get_answer_info?answer_id=?
def unlock_answer def unlock_answer
@challenge = @game.challenge
@answer = ChallengeAnswer.find(params[:answer_id]) @answer = ChallengeAnswer.find(params[:answer_id])
challenge = @answer.challenge 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 deduct_score = ((points / 100.0) * challenge.score).to_i
uid_logger("############金币数目: #{current_user.grade}") uid_logger("############金币数目: #{current_user.grade}")
unless current_user.grade.to_i - deduct_score > 0 unless current_user.grade.to_i - deduct_score > 0
@ -249,13 +277,16 @@ class GamesController < ApplicationController
begin begin
# 积分消耗情况记录 # 积分消耗情况记录
score = challenge.st.zero? ? -deduct_score : -challenge.choose_score.to_i 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 if @game.status == 2
@game.update_attributes!(:answer_open => @answer.level) @game.update_attributes!(:answer_open =>answer_open)
else 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 end
rescue Exception => e rescue Exception => e
@ -263,7 +294,32 @@ class GamesController < ApplicationController
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
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 end
# 查看答案需要扣取金币 # 查看答案需要扣取金币
@ -327,11 +383,10 @@ class GamesController < ApplicationController
@game.update_attribute(:test_sets_view, true) @game.update_attribute(:test_sets_view, true)
# 扣分记录 # 扣分记录
Grade.create(:user_id => current_user.id, :container_id => @game.id, :score => -@minus_grade, :container_type => "testSet") Grade.create(:user_id => current_user.id, :container_id => @game.id, :score => -@minus_grade, :container_type => "testSet")
@status = 0 max_query_index = @game.query_index.to_i
@message = "解锁成功!" testset_detail max_query_index, challenge
else else
@status = -1 tip_exception(-1, "本操作需要扣除#{ @minus_grade }金币,您的金币不够了")
@message = "本操作需要扣除#{ @minus_grade }金币,您的金币不够了"
end end
end end
@ -411,12 +466,12 @@ class GamesController < ApplicationController
game_code = GameCode.where(:game_id => @game.try(:id), :path => path).first game_code = GameCode.where(:game_id => @game.try(:id), :path => path).first
if game_code.present? if game_code.present?
content = game_code.try(:new_code) content = game_code.try(:new_code)
@content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && content.present? # @content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && content.present?
content.gsub(/\t/, ' ') # content.gsub(/\t/, ' ')
else # else
content # content
end # end
update_file_content(@content, @myshixun.repo_path, path, current_user.mail, current_user.full_name, "game passed reset") update_file_content(content, @myshixun.repo_path, path, current_user.mail, current_user.full_name, "game passed reset")
else else
tip_exception("代码重置失败,代码为空") tip_exception("代码重置失败,代码为空")
end end
@ -425,7 +480,7 @@ class GamesController < ApplicationController
# 获取版本库文件内容 # 获取版本库文件内容
# 注如果本身path传错内容肯定也为空fork成功后可能短时间内也获取不到版本库内容 # 注如果本身path传错内容肯定也为空fork成功后可能短时间内也获取不到版本库内容
# params[:status] 1: 目录树点击的请求 0正常自动加载 # params[:status] 1: 目录树点击的请求 0正常自动加载
# 返回参数status -3 需要重试带retry参数-1 给出提示 # 返回参数status -1 系统统一报错提示;-3 需要轮训重试带retry参数-4 立即重试
def rep_content def rep_content
challenge_path = @game.challenge.try(:path) challenge_path = @game.challenge.try(:path)
if challenge_path.blank? if challenge_path.blank?
@ -437,22 +492,19 @@ class GamesController < ApplicationController
path = path.try(:strip) path = path.try(:strip)
uid_logger("--rep_content: path is #{path}") uid_logger("--rep_content: path is #{path}")
begin begin
@content = git_fle_content(@myshixun.repo_path, path) || "" if @myshixun.repo_name.nil?
rescue g = Gitlab.client
if params[:retry].present? repo_name = g.project(@myshixun.gpid).path_with_namespace
begin @myshixun.update_column(:repo_name, repo_name)
begin @content = git_fle_content("#{repo_name}.git", path) || ""
# 检测TPM对应的路径代码是否正常 else
git_fle_content(@myshixun.shixun.repo_path, path) @content = git_fle_content(@myshixun.repo_path, path) || ""
rescue Exception => e end
uid_logger_error("#{e.message}")
if @myshixun.shixun.try(:status) < 2
tip_exception("代码获取异常,请检查实训模板的评测设置是否正确")
else
tip_exception("代码获取异常,请联系系统管理员")
end
end
rescue Exception => e
# 思路: 异常首先应该考虑去恢复
if params[:retry].to_i == 1
begin
# 如果模板没有问题,则通过中间层检测实训仓库是否异常 # 如果模板没有问题,则通过中间层检测实训仓库是否异常
# 监测版本库HEAD是否存在不存在则取最新的HEAD # 监测版本库HEAD是否存在不存在则取最新的HEAD
gitUrl = repo_url @myshixun.repo_path gitUrl = repo_url @myshixun.repo_path
@ -462,30 +514,41 @@ class GamesController < ApplicationController
# 监测版本库HEAD是否存在不存在则取最新的HEAD # 监测版本库HEAD是否存在不存在则取最新的HEAD
uri = "#{shixun_tomcat}/bridge/game/check" uri = "#{shixun_tomcat}/bridge/game/check"
res = uri_post uri, rep_params res = uri_post uri, rep_params
uid_logger("repo_content to bridge: res is #{res}")
# res值0 表示正常;-1表示有错误-2表示代码版本库没了 # res值0 表示正常;-1表示有错误-2表示代码版本库没了
if status == 0 && res && (res['code'] == -2 || res['code'] == -1) #
# 删除不需要的仓库 if status == 0 && res
begin # 版本库报错,修复不了
GitService.delete_repository(repo_path: @myshixun.repo_path) if res['code'] == -1 || res['code'] == -2
rescue Exception => e begin
uid_logger_error("#{e.message}") # 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 end
# fork一个新的仓库
project_fork(@myshixun, @shixun.repo_path, current_user.login)
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) 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
end end
tip_exception(-3, "#{e.message}") # 有异常版本库获取不到代码前端轮训30S后调用retry == 1
tip_exception(0, e.message)
end end
end end
# 编程题评测 # 编程题评测
def game_build 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)) @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}", br_params = {:tpiID => "#{@myshixun.id}", :tpiGitURL => "#{gitUrl}", :buildID => "#{@game.id}",
:instanceChallenge => "#{step}", :testCases => "#{testCases}", :resubmit => "#{resubmit}", :instanceChallenge => "#{step}", :testCases => "#{testCases}", :resubmit => "#{resubmit}",
:times => params[:first].to_i, :podType => @shixun.webssh, :content_modified => content_modified, :times => params[:first].to_i, :podType => @shixun.webssh, :content_modified => content_modified,
:containers => "#{Base64.urlsafe_encode64(container_limit(@shixun.mirror_repositories))}", :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}",
:persistenceName => @shixun.identifier, :tpmScript => "#{tpmScript}", :persistenceName => @shixun.identifier, :tpmScript => "#{tpmScript}", :sec_key => sec_key,
:timeLimit => "#{@shixun.exec_time}", :isPublished => (@shixun.status < 2 ? 0 : 1) } :timeLimit => game_challenge.exec_time, :isPublished => (@shixun.status < 2 ? 0 : 1) }
# 评测有文件输出的需要特殊传字段 path表示文件存储的位置 # 评测有文件输出的需要特殊传字段 path表示文件存储的位置
br_params['file'] = Base64.urlsafe_encode64({path: "#{game_challenge.picture_path}"}.to_json) if game_challenge.picture_path.present? 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虽然是传的数组,但是可能存在多选择提的情况.
user_answer_tran = user_answer[index].size > 1 ? user_answer[index].split("").sort.join("") : user_answer[index] 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 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? if str.present?
str += "," str += ","
end end
@ -597,13 +660,10 @@ class GamesController < ApplicationController
end 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 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 ActiveRecord::Base.connection.execute sql
had_done = @game.had_done
@myshixun.update_attribute(:status, 1) if had_done == 1
# 没通关或者查看了答案通关的时候经验为0 # 没通关或者查看了答案通关的时候经验为0
# 通关但是查看了答案评测的时候金币显示0避免用户以为重复扣除但是在关卡列表中金币显示负数 # 通关但是查看了答案评测的时候金币显示0避免用户以为重复扣除但是在关卡列表中金币显示负数
experience = 0 experience = 0
@ -613,7 +673,8 @@ class GamesController < ApplicationController
if had_passed && !@game.had_passed? if had_passed && !@game.had_passed?
@game.update_attributes(:status => 2, :end_time => Time.now) @game.update_attributes(:status => 2, :end_time => Time.now)
# TPM实训已发布并且没有查看答案 # TPM实训已发布并且没有查看答案
if @shixun.is_published? && !@game.answer_open if @shixun.is_published? && @game.answer_open == 0
uid_logger("@@@@@@@@@@@@@@@@@chooice score: #{score}")
# 查看答案的时候处理final_scor和扣分记录 # 查看答案的时候处理final_scor和扣分记录
experience = score experience = score
reward_attrs = { container_id: @game.id, container_type: 'Game', score: score } reward_attrs = { container_id: @game.id, container_type: 'Game', score: score }
@ -622,6 +683,8 @@ class GamesController < ApplicationController
final_score = score final_score = score
RewardExperienceService.call(@myshixun.owner, reward_attrs) RewardExperienceService.call(@myshixun.owner, reward_attrs)
end end
had_done = @game.had_done
@myshixun.update_attribute(:status, 1) if had_done == 1
end end
grade = @myshixun.owner.try(:grade) grade = @myshixun.owner.try(:grade)
@ -660,6 +723,7 @@ class GamesController < ApplicationController
uid_logger("################params[:resubmit]: #{params[:resubmit]}") uid_logger("################params[:resubmit]: #{params[:resubmit]}")
uid_logger("################resubmit_identifier: #{resubmit_identifier}") uid_logger("################resubmit_identifier: #{resubmit_identifier}")
uid_logger("################time_out: #{params[:time_out]}") 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? && if (params[:time_out] == "false") && ((params[:resubmit].blank? && @game.status == 1) || (params[:resubmit].present? &&
(params[:resubmit] != resubmit_identifier))) (params[:resubmit] != resubmit_identifier)))
# 代码评测的信息 # 代码评测的信息
@ -688,14 +752,14 @@ class GamesController < ApplicationController
end end
else # 重新评测 else # 重新评测
# 如果满足前面的条件,进入此处只可能是结果已返回并存入了数据库 # 如果满足前面的条件,进入此处只可能是结果已返回并存入了数据库
if params[:resubmit] == resubmit_identifier # 本次重新评测结果已经返回并存入数据库 if params[:resubmit] == resubmit_identifier # 本次重新评测结果已经返回并存入数据库
game_status = (@game.retry_status == 2 ? 2 : 0) # retry_status是判断重新评测的通关情况。2表示通关 game_status = (@game.retry_status == 2 ? 2 : 0) # retry_status是判断重新评测的通关情况。2表示通关
end end
end end
# 实训的最大评测次数,这个值是为了优化查询,每次只取最新的最新一次评测的结果集 # 实训的最大评测次数,这个值是为了优化查询,每次只取最新的最新一次评测的结果集
max_query_index = @game.query_index 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 testset_detail max_query_index.to_i, game_challenge
@ -705,9 +769,10 @@ class GamesController < ApplicationController
web_route = game_challenge.try(:web_route) web_route = game_challenge.try(:web_route)
mirror_name = @shixun.mirror_name mirror_name = @shixun.mirror_name
e_record = EvaluateRecord.where(:identifier => sec_key).first
# 轮询结束,更新评测统计耗时 # 轮询结束,更新评测统计耗时
if game_status == 0 || game_status == 2 if game_status == 0 || game_status == 2
e_record = EvaluateRecord.where(:game_id => @game.id).first
if e_record if e_record
front_js = format("%.3f", (Time.now.to_f - e_record.try(:updated_at).to_f)).to_f 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 consume_time = format("%.3f", (Time.now - e_record.created_at)).to_f
@ -715,9 +780,10 @@ class GamesController < ApplicationController
end end
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 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, @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, 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, 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 end
# 记录实训花费的时间 # 记录实训花费的时间
@ -796,11 +862,11 @@ class GamesController < ApplicationController
# 评测测试机封装 # 评测测试机封装
def testset_detail max_query_index, challenge def testset_detail max_query_index, challenge
# 是否允许查看隐藏的测试集以前的power # 是否允许查看隐藏的测试集以前的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 if max_query_index > 0
uid_logger("max_query_index is #{max_query_index} game id is #{@game.id}, challenge_id is #{challenge.id}") 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, 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} 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 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 end
@last_compile_output = @qurey_test_sets.first['out_put'].gsub(/\n/, '<br/>').gsub(/\t/, "&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;") if @qurey_test_sets.first['out_put'].present? @last_compile_output = @qurey_test_sets.first['out_put'].gsub(/\n/, '<br/>').gsub(/\t/, "&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;") if @qurey_test_sets.first['out_put'].present?
else else
# 没有评测过,第一次进来后的呈现方式
@qurey_test_sets = TestSet.find_by_sql("SELECT t.is_public, t.input, t.output, t.position @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
end end
@ -849,7 +916,7 @@ class GamesController < ApplicationController
end end
# actual_output为空表示暂时没有评测答题不允许查看 # actual_output为空表示暂时没有评测答题不允许查看
actual_output = output.try(:actual_output).try(:strip) 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替代 # 标准答案处理,错误的不让用户查看,用-1替代
standard_answer = (actual_output.blank? || !output.try(:result)) ? -1 : choose.standard_answer standard_answer = (actual_output.blank? || !output.try(:result)) ? -1 : choose.standard_answer
result = output.try(:result) result = output.try(:result)
@ -860,7 +927,7 @@ class GamesController < ApplicationController
@chooses << sin_choose @chooses << sin_choose
test_sets << sin_test_set test_sets << sin_test_set
end end
@has_answer = has_answer.present? @has_answer = true # 选择题永远都有答案
@choose_test_cases = {:had_submmit => had_submmit, :challenge_chooses_count => challenge_chooses_count, @choose_test_cases = {:had_submmit => had_submmit, :challenge_chooses_count => challenge_chooses_count,
:choose_correct_num => choose_correct_num, :test_sets => test_sets} :choose_correct_num => choose_correct_num, :test_sets => test_sets}
end end

@ -1,10 +1,15 @@
class GitsController < ApplicationController class GitsController < ApplicationController
#供git-workhorse反向调用认证 # 说明:
# 以下Git认证只针对新版gitGitlab的Git认证不走该控制器
# 思路:
# 1、用户通过Git客户端推送代码的时候这个时候Git客户端肯定会强制用户输入邮箱的
# 2、通过web端版本库界面更新代码如果用户邮箱不存在则用系统备用邮箱
# 供 git-workhorse反向调用认证
def auth def auth
# HTTP_AUTHORIZATION: "Basic 这里base64编码的的密码(user:passwd)" # HTTP_AUTHORIZATION: "Basic 这里base64编码的的密码(user:passwd)"
logger.info("11111112222223333#{request.env["HTTP_AUTHORIZATION"]}") logger.info("11111112222223333 HTTP_AUTHORIZATION: #{request.env["HTTP_AUTHORIZATION"]}")
#logger.info("#########-----request_env: #{request.env}") # logger.info("#########-----request_env: #{request.env}")
# {"service"=>"git-receive-pack", "controller"=>"gits", "action"=>"auth", # {"service"=>"git-receive-pack", "controller"=>"gits", "action"=>"auth",
# "url"=>"forge01/cermyt39.git/info/refs"} # "url"=>"forge01/cermyt39.git/info/refs"}
# #
@ -18,15 +23,16 @@ class GitsController < ApplicationController
input_password = username_password.split(":")[1].strip() input_password = username_password.split(":")[1].strip()
uid_logger("git start auth: input_username is #{input_username}") uid_logger("git start auth: input_username is #{input_username}")
# Git 超级权限用户 # Git 超级权限用户
if input_username == gituser && input_password == gitpassword if input_username.strip == gituser.strip && input_password.strip == gitpassword.strip
result = true result = true
else else
# 用户是否对对象拥有权限 # 用户是否对对象拥有权限
system_user = User.find_by_login(input_username) || User.find_by_mail(input_username) || User.find_by_phone(input_username) 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") uid_logger_error("git start: password is wrong")
result = false result = false
else else
@ -43,12 +49,13 @@ class GitsController < ApplicationController
if system_user.present? && system_user.manager_of_shixun?(shixun) if system_user.present? && system_user.manager_of_shixun?(shixun)
result = true result = true
else else
logger.info("git411 start") uid_logger_error("gituser is not shixun manager")
result = false result = false
end end
else else
render :json => { :status => 404 } uid_logger_error("shixun is not exist")
result = false # result = false
result = true # 为了测试跳出
end end
end end
end end

@ -1,5 +1,5 @@
class GraduationTasksController < ApplicationController 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_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 :find_task, only: [:edit, :update, :settings, :update_settings, :tasks_list, :show, :show_comment]
before_action :user_course_identity before_action :user_course_identity
@ -37,7 +37,7 @@ class GraduationTasksController < ApplicationController
@all_count = @course.graduation_tasks.size @all_count = @course.graduation_tasks.size
@published_count = @course.graduation_tasks.where("publish_time <= '#{Time.now}'").size @published_count = @course.graduation_tasks.where("publish_time <= '#{Time.now}'").size
@task_count = @tasks.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 end
# 任务问答 # 任务问答
@ -55,30 +55,33 @@ class GraduationTasksController < ApplicationController
page = params[:page] || 1 page = params[:page] || 1
limit = params[:limit] || 20 limit = params[:limit] || 20
@work = @task.graduation_works.where(user_id: current_user.id) @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 #end_time @task.allow_late ? @task.late_time : @task.end_time
# 任务发布的情况下: 是老师身份或者任务已截止的情况下公开任务了作品设置的学生也能查看其他人的作品 # 任务发布的情况下: 是老师身份或者任务已截止的情况下公开任务了作品设置的学生也能查看其他人的作品
if @task.published? && (@user_course_identity < Course::STUDENT || if @task.published? && (@user_course_identity < Course::STUDENT ||
(@user_course_identity == Course::STUDENT && @work.present? && @work.take.work_status > 0 && (@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 = user_ids =
if @user_course_identity < Course::STUDENT if @user_course_identity < Course::STUDENT
@course.teacher_group_user_ids(current_user.id) @course.teacher_group_user_ids(current_user.id)
else else
course_group_id = @course.course_member(current_user.id).course_group_id 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 end
@work_list = @task.graduation_works.where(user_id: user_ids).includes(user: [:user_extension]) @work_list = @task.graduation_works.where(user_id: user_ids).includes(user: [:user_extension])
@all_work_count = @work_list.count @all_work_count = @work_list.count
@teachers = @course.teachers @teachers = @course.teachers.where.not(user_id: current_user.id).includes(:user)
# 教师评阅搜索 0: 未评, 1 已评 # 教师评阅搜索 0: 未评, 1 已评
unless params[:teacher_comment].blank? unless params[:teacher_comment].blank?
graduation_work_ids = GraduationWorkScore.where(graduation_work_id: @work_list.map(&:id)).pluck(:graduation_work_id) graduation_work_ids = GraduationWorkScore.where(graduation_work_id: @work_list.map(&:id)).pluck(:graduation_work_id)
if params[:teacher_comment] == 0 if params[:teacher_comment].to_i == 0
@work_list = @work_list.where.not(id: graduation_work_ids) @work_list = @work_list.where("work_status != 0")
elsif params[:teacher_comment] == 1 elsif params[:teacher_comment].to_i == 1
@work_list = @work_list.where(id: graduation_work_ids).where.not(work_status: 0) @work_list = @work_list.where("work_status != 0").where(id: graduation_work_ids)
end end
end end
@ -89,7 +92,7 @@ class GraduationTasksController < ApplicationController
# 分班情况 # 分班情况
unless params[:course_group].blank? 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) @work_list = @work_list.where(user_id: group_user_ids)
end end
@ -98,7 +101,7 @@ class GraduationTasksController < ApplicationController
unless params[:cross_comment].blank? unless params[:cross_comment].blank?
graduation_work_id = @task.graduation_work_comment_assignations.where(:user_id =>current_user.id) 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 .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 end
# 输入姓名和学号搜索 # 输入姓名和学号搜索
@ -109,57 +112,61 @@ class GraduationTasksController < ApplicationController
end end
# 排序 # 排序
rorder = params[:order] || "updated_at" rorder = params[:order].blank? ? "update_time" : params[:order]
b_order = params[:b_order] || "desc" b_order = params[:b_order].blank? ? "desc" : params[:b_order]
if rorder == "created_at" || rorder == "work_score" if rorder == "update_time" || rorder == "work_score"
@work_list = @work_list.order("graduation_works.#{rorder} #{b_order}") @work_list = @work_list.order("graduation_works.#{rorder} #{b_order}")
elsif rorder == "student_id" elsif rorder == "student_id"
@work_list = @work_list.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}") @work_list = @work_list.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}")
end end
@view_work = @task.open_work || @user_course_identity < Course::STUDENT
@work_count = @work_list.count @work_count = @work_list.count
@work_excel = @work_list @work_excel = @work_list
@work_list = @work_list.page(page).limit(limit) @work_list = @work_list.page(page).per(limit)
respond_to do |format|
format.json if params[:format] == "xlsx"
format.xlsx{ complete_works = @work_excel.where("work_status > 0").size
if @user_course_identity >= Course::STUDENT if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作") tip_exception(403, "无权限操作")
else elsif complete_works == 0
graduation_work_to_xlsx(@work_excel,@task,current_user) normal_status(-1,"暂无用户提交")
exercise_export_name = current_user.real_name + "_" + @course.name + "_" + @task.name + "_" + Time.now.strftime('%Y%m%d_%H%M%S') else
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} 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 end
} end
format.zip{ elsif params[:format] == "zip"
if @user_course_identity >= Course::STUDENT if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作") tip_exception(403, "无权限操作")
else else
zip_works = @work_excel.where("work_status > 0") zip_works = @work_excel.where("work_status > 0")
status = checkfileSize(zip_works) status = checkfileSize(zip_works)
if status == 0 if status == 0
zipfile = zip_homework_common @task, zip_works respond_to do |format|
file = decode64(zipfile[0][:base64file]) format.zip{
send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip' zipfile = zip_homework_common @task, zip_works
else file = decode64(zipfile[0][:base64file])
tip_exception(status == -1 ? "文件大小超过500M请通过微信或者QQ联系管理员辅助您打包下载" : "无附件可下载") send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
}
end end
else
normal_status(status,status == -2 ? "500M" : "无附件可下载")
end end
} end
end end
else else
@work_list = @work @work_list = @work
@view_work = false
@work_count = @work_list.count @work_count = @work_list.count
@all_work_count = @work_list.count @all_work_count = @work_list.count
respond_to do |format| if params[:format] == "xlsx" || params[:format] == "zip"
format.json normal_status(-1,"毕设任务未发布")
format.xlsx{
normal_status(-1,"作业未发布")
}
format.zip{
normal_status(-1,"作业未发布")
}
end end
end end
end end

@ -1,9 +1,9 @@
class GraduationTopicsController < ApplicationController class GraduationTopicsController < ApplicationController
before_action :require_login, except: [:index] before_action :require_login, :check_auth, except: [:index]
before_action :find_course before_action :find_course
before_action :teacher_allowed, only: [:new, :create, :update, :edit, :destroys, :set_public, before_action :teacher_allowed, only: [:new, :create, :update, :edit, :destroys, :set_public,
:refuse_student_topic, :accept_student_topic, :export] :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 :find_course_teachers, only: [:new, :edit]
before_action :user_course_identity, only: [:index, :show, :show_detail, :show_comment] before_action :user_course_identity, only: [:index, :show, :show_detail, :show_comment]
@ -24,9 +24,7 @@ class GraduationTopicsController < ApplicationController
end end
# 当前用户是否已经选过题 # 当前用户是否已经选过题
# @user_selected = StudentGraduationTopic.where(graduation_topic_id: @graduation_topic, user_id: current_user.id).count > 0 @user_selected = @course.student_graduation_topics.where(user_id: current_user.id, status: [0, 1]).count > 0 #6.12 -hs
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
## 分页参数 ## 分页参数
page = params[:page] || 1 page = params[:page] || 1
limit = params[:limit] || 15 limit = params[:limit] || 15
@ -45,16 +43,9 @@ class GraduationTopicsController < ApplicationController
end end
## 分页参数 ## 分页参数
@current_user = current_user @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 user_graduation_topics = @course.student_graduation_topics.where(user_id: current_user.id,
#6.11 -hs status: [0, 1])
if course_group_ids.present? @user_selected = user_graduation_topics.size > 0
if course_group_ids.include?(0)
course_group_ids = @course.course_groups.pluck(:id)
end
end
@group_list = CourseGroup.where(id: course_group_ids)
page = params[:page] || 1 page = params[:page] || 1
limit = params[:limit] || 50 limit = params[:limit] || 50
@users_count = @student_graduation_topics.try(:count).to_i @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 member = @course.course_members.where(:user_id => @graduation_topic.tea_id).first
tip_exception("分班名称不能为空") if params[:course_group_name].blank? tip_exception("分班名称不能为空") if params[:course_group_name].blank?
course_group = CourseGroup.create(:name => params[:course_group_name], :course_id => @course.id) 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, :user_id => @graduation_topic.tea_id,
:course_group_id => course_group.try(:id)) :course_group_id => course_group.try(:id))
end end
@ -202,8 +193,8 @@ class GraduationTopicsController < ApplicationController
def student_select_topic def student_select_topic
user_unaccept_topics = @course.student_graduation_topics.where(user_id: current_user.id, status: [0, 1]) user_unaccept_topics = @course.student_graduation_topics.where(user_id: current_user.id, status: [0, 1])
if user_unaccept_topics.size == 0 if user_unaccept_topics.size == 0
member_id = @course.course_members.find_by_user_id(current_user.id) member = @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, 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_id: @graduation_topic.id)
@graduation_topic.update_attribute(:status, 1) @graduation_topic.update_attribute(:status, 1)
normal_status("选题成功") normal_status("选题成功")
@ -231,7 +222,7 @@ class GraduationTopicsController < ApplicationController
# 已加入的更新,未加入的新建 # 已加入的更新,未加入的新建
if topic_bank.present? 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_source: topic.topic_source,
topic_property_first: topic.topic_property_first, topic_property_first: topic.topic_property_first,
topic_property_second: topic.topic_property_second, topic_property_second: topic.topic_property_second,
@ -242,7 +233,7 @@ class GraduationTopicsController < ApplicationController
course_list_id: @course.course_list_id) course_list_id: @course.course_list_id)
topic_bank.attachments.destroy_all topic_bank.attachments.destroy_all
else 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_source: topic.topic_source,
topic_property_first: topic.topic_property_first, topic_property_first: topic.topic_property_first,
topic_property_second: topic.topic_property_second, topic_property_second: topic.topic_property_second,
@ -275,11 +266,16 @@ class GraduationTopicsController < ApplicationController
# 导出功能 # 导出功能
def export def export
course = @course begin
students = course.students.joins(user: :user_extension).order("user_extensions.student_id") course = @course
graduation_topic_to_xlsx(students,course) students = course.students.joins(user: :user_extension).order("user_extensions.student_id")
exercise_export_name = current_user.real_name + "_" + course.name + "_毕设选题" + "_" + Time.now.strftime('%Y%m%d_%H%M%S') graduation_topic_to_xlsx(students,course)
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} 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 end
private private

@ -1,5 +1,5 @@
class GraduationWorksController < ApplicationController 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, before_action :find_task, only: [:new, :create, :search_member_list, :check_project, :relate_project,
:cancel_relate_project] :cancel_relate_project]
before_action :find_work, only: [:show, :edit, :update, :revise_attachment, :supply_attachments, :comment_list, 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, before_action :published_task, only: [:new, :create, :edit, :update, :search_member_list, :relate_project,
:cancel_relate_project, :revise_attachment] :cancel_relate_project, :revise_attachment]
before_action :edit_duration, only: [:edit, :update] before_action :edit_duration, only: [:edit, :update]
before_action :open_work, only: [:show, :supply_attachments, :comment_list]
def new def new
if @task.task_type == 2 && @task.base_on_project if @task.task_type == 2 && @task.base_on_project
@ -432,11 +433,11 @@ class GraduationWorksController < ApplicationController
# 交叉评阅分配老师 # 交叉评阅分配老师
def assign_teacher def assign_teacher
tip_exception(-1, "user_id不能为空") if params[:user_id].nil? 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: 已经是答辩组的需要 将答辩组清空 # 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 else
@work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new(graduation_task_id: @task.id, @work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new(graduation_task_id: @task.id,
user_id: params[:user_id], user_id: params[:user_id],
@ -489,6 +490,11 @@ class GraduationWorksController < ApplicationController
tip_exception("已过了修改时间") if @task.end_time && @task.end_time < Time.now tip_exception("已过了修改时间") if @task.end_time && @task.end_time < Time.now
end 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 def update_check work
tip_exception("作品描述不能为空") if params[:description].blank? tip_exception("作品描述不能为空") if params[:description].blank?
if @task.task_type == 2 if @task.task_type == 2

@ -3,16 +3,17 @@ class HomeworkCommonsController < ApplicationController
include ApplicationHelper include ApplicationHelper
include ExportHelper 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, 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, :end_homework, :set_public, :choose_category, :move_to_category, :choose_category,
:create_subject_homework, :multi_destroy, :add_to_homework_bank] :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, 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, :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 :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, 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, :publish_homework, :end_homework, :set_public, :choose_category, :move_to_category,
:choose_category, :create_subject_homework, :multi_destroy, :group_list, :homework_code_repeat, :choose_category, :create_subject_homework, :multi_destroy, :group_list, :homework_code_repeat,
@ -81,23 +82,17 @@ class HomeworkCommonsController < ApplicationController
end end
@homework_commons = @homework_commons.joins(:homework_detail_manual).where(sql_str) @homework_commons = @homework_commons.joins(:homework_detail_manual).where(sql_str)
end 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 @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 @homework_type == 4
if @user_course_identity == Course::STUDENT @homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings, :shixuns)
@homework_commons = @homework_commons.includes(:homework_detail_manual, :homework_group_settings, :shixuns, elsif @homework_type == 3
student_works: [myshixun: [:games]]) @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, :shixuns, :student_works)
end
else else
@homework_commons = @homework_commons.includes(:homework_detail_manual, :homework_group_settings, :homework_detail_group, @homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings)
:student_works)
end end
end end
@ -108,45 +103,43 @@ class HomeworkCommonsController < ApplicationController
@shixun = @homework.shixuns.take if @homework.homework_type == "practice" @shixun = @homework.shixuns.take if @homework.homework_type == "practice"
student_works = @homework.all_works student_works = @homework.all_works
@all_member_count = student_works.count @all_member_count = student_works.size
if @homework.publish_time.nil? || @homework.publish_time > Time.now
if @homework.publish_time.blank? || (@homework.publish_time > Time.now)
@student_works = [] @student_works = []
respond_to do |format| if (params[:format] == "xlsx") || (params[:format] == "zip")
format.json normal_status(-1,"作业未发布")
format.xlsx{
normal_status(-1,"作业未发布")
}
format.zip{
normal_status(-1,"作业未发布")
}
end end
else else
if @user_course_identity == Course::STUDENT if @user_course_identity == Course::STUDENT
@work = @homework.user_work(current_user.id) @work = @homework.user_work(current_user.id)
# 学生已提交作品且补交(提交)已截止、作品公开、非匿评阶段 # 学生已提交作品且补交(提交)已截止、作品公开、非匿评阶段
if @work.work_status > 0 && @homework.work_public && 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.anonymous_comment && @homework.end_or_late) || (@homework_detail_manual.comment_status > 4 && @homework.end_or_late))
@student_works = student_works.where("user_id != #{@work.id}") @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 @is_evaluation = true
@student_works = student_works.joins(:student_works_evaluation_distributions).where( @student_works = student_works.joins(:student_works_evaluation_distributions).where(
"student_works_evaluation_distributions.user_id = #{@current_user.id}") "student_works_evaluation_distributions.user_id = #{@current_user.id}")
else else
@student_works = [] @student_works = []
end end
@score_open = @homework.score_open && @work&.work_status.to_i > 0
elsif @user_course_identity < Course::STUDENT elsif @user_course_identity < Course::STUDENT
@student_works = @homework.teacher_works(@current_user.id) @student_works = @homework.teacher_works(@member)
@all_member_count = @student_works.count @all_member_count = @student_works.size
@score_open = true
elsif @user_course_identity > Course::STUDENT && @homework.work_public elsif @user_course_identity > Course::STUDENT && @homework.work_public
@student_works = student_works @student_works = student_works
@score_open = false
else else
@student_works = [] @student_works = []
end end
unless @student_works.size == 0 if @student_works.size > 0
# 教师评阅搜索 0: 未评, 1 已评 # 教师评阅搜索 0: 未评, 1 已评
unless params[:teacher_comment].blank? unless params[:teacher_comment].blank?
student_work_ids = StudentWorksScore.where(student_work_id: @student_works.map(&:id)).pluck(:student_work_id) 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]}%") or student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end end
@work_count = @student_works.size
@work_excel = @student_works.where("work_status > 0")
# 排序 # 排序
rorder = params[:order] || "update_time" rorder = params[:order].blank? ? "update_time" : params[:order]
b_order = params[:b_order] || "desc" b_order = params[:b_order].blank? ? "desc" : params[:b_order]
if rorder == "update_time" || rorder == "work_score" if rorder == "update_time" || rorder == "work_score"
@student_works = @student_works.order("student_works.#{rorder} #{b_order}") @student_works = @student_works.order("student_works.#{rorder} #{b_order}")
elsif rorder == "student_id" elsif rorder == "student_id"
@student_works = @student_works.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}") @student_works = @student_works.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}")
end end
@work_count = @student_works.size
@work_excel = @student_works
# 分页参数 # 分页参数
page = params[:page] || 1 page = params[:page] || 1
limit = params[:limit] || 20 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" 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 else
@student_works = @student_works.includes(:student_works_scores, :project, user: :user_extension) @student_works = @student_works.includes(:student_works_scores, :project, user: :user_extension)
end end
end end
respond_to do |format|
format.json if params[:format] == "xlsx"
format.xlsx{ if @user_course_identity >= Course::STUDENT
if @user_course_identity >= Course::STUDENT tip_exception(403, "无权限操作")
tip_exception(403, "无权限操作") elsif @work_excel.blank? || @work_excel.size == 0
else normal_status(-1,"暂无用户提交!")
student_work_to_xlsx(@work_excel,@homework) else
exercise_export_name = current_user.real_name + "_" + @course.name + "_" + @homework.name + "_" + Time.now.strftime('%Y%m%d_%H%M%S') respond_to do |format|
render xlsx: "#{exercise_export_name.strip.first(30)}",template: "homework_commons/works_list.xlsx.axlsx",locals: format.xlsx{
{table_columns: @work_head_cells,task_users: @work_cells_column} 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 end
} end
format.zip{ elsif params[:format] == "zip"
if @user_course_identity >= Course::STUDENT if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作") tip_exception(403, "无权限操作")
else else
zip_works = @work_excel.where("work_status > 0") if @work_excel.present?
zip_works = @work_excel&.where("work_status > 0")
status = checkfileSize(zip_works) status = checkfileSize(zip_works)
if status == 0 else
zipfile = zip_homework_common @homework, zip_works status = -1
file = decode64(zipfile[0][:base64file]) end
send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
else if status == 0
tip_exception(status == -1 ? "文件大小超过500M请通过微信或者QQ联系管理员辅助您打包下载" : "无附件可下载") 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 end
else
normal_status(status, status == -2 ? "500M" : "无附件可下载")
end 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 end
end end
@ -347,10 +406,8 @@ class HomeworkCommonsController < ApplicationController
homework_detail_group = @homework.homework_detail_group homework_detail_group = @homework.homework_detail_group
param_min = params[:min_num].to_i param_min = params[:min_num].to_i
param_max = params[:max_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 : homework_detail_group.min_num = @homework.has_commit_work ? [param_min, homework_detail_group.min_num].min : param_min
param_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.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.base_on_project = params[:base_on_project] unless @homework.has_relate_project homework_detail_group.base_on_project = params[:base_on_project] unless @homework.has_relate_project
homework_detail_group.save! homework_detail_group.save!
end 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[: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[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
tip_exception("截止时间不能早于发布时间") if params[:publish_time] > params[:end_time] 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.unified_setting = 1
@homework.homework_group_settings.destroy_all @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[:publish_time] <= strf_time(Time.now)
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[: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] 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 if @homework.end_time > Time.now && @homework.unified_setting
tip_exception("截止时间不能为空") if params[:end_time].blank? 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) tip_exception("截止时间不能于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
@homework.end_time = params[:end_time] @homework.end_time = params[:end_time]
@ -457,11 +514,11 @@ class HomeworkCommonsController < ApplicationController
tip_exception("发布时间不能为空") if setting[:publish_time].blank? tip_exception("发布时间不能为空") if setting[:publish_time].blank?
tip_exception("截止时间不能为空") if setting[:end_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[: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_published.update_all(publish_time: setting[:publish_time])
group_settings.none_end.update_all(end_time: setting[:end_time]) group_settings.none_end.update_all(end_time: setting[:end_time])
@ -529,7 +586,7 @@ class HomeworkCommonsController < ApplicationController
if setting && setting.score != score if setting && setting.score != score
score_change = true score_change = true
setting.update_attributes(score: score) setting.update_attributes(score: score)
else elsif setting.blank?
score_change = true score_change = true
HomeworkChallengeSetting.create!(homework_common_id: @homework.id, challenge_id: challenge[:challenge_id], HomeworkChallengeSetting.create!(homework_common_id: @homework.id, challenge_id: challenge[:challenge_id],
shixun_id: @homework.homework_commons_shixun.try(:shixun_id), score: score) 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.score_open = params[:score_open]
@homework.save! @homework.save!
if score_change # if score_change
@homework.student_works.has_committed.each do |student_work| # @homework.student_works.has_committed.each do |student_work|
HomeworksService.new.set_shixun_final_score student_work # HomeworksService.new.set_shixun_final_score student_work
end # end
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) HomeworksService.new.update_student_eff_score HomeworkCommon.find_by(id: @homework.id)
end end
@ -584,9 +641,9 @@ class HomeworkCommonsController < ApplicationController
# anonymous_comment :true 是启用false 是不启用 # anonymous_comment :true 是启用false 是不启用
if params[:anonymous_comment] if params[:anonymous_comment]
tip_exception("匿评开启时间不能为空") if params[:evaluation_start].blank? 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].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] > tip_exception("匿评截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:evaluation_end] >
strf_time(@course.end_date.end_of_day) strf_time(@course.end_date.end_of_day)
tip_exception("匿评数必须为正整数") if params[:evaluation_num].blank? || params[:evaluation_num].to_i < 1 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 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].blank?
tip_exception("匿评截止时间不能早于匿评开启时间") if @homework.anonymous_comment && tip_exception("匿评截止时间必须晚于匿评开启时间") if @homework.anonymous_comment &&
params[:evaluation_end] <= params[:evaluation_start] params[:evaluation_end] <= strf_time(@homework_detail_manual.evaluation_start)
tip_exception("匿评截止时间不能晚于课堂结束时间") if @homework.anonymous_comment && tip_exception("匿评截止时间不能晚于课堂结束时间") if @homework.anonymous_comment &&
@course.end_date.present? && params[:evaluation_end] > strf_time(@course.end_date.end_of_day) @course.end_date.present? && params[:evaluation_end] > strf_time(@course.end_date.end_of_day)
@ -758,6 +815,9 @@ class HomeworkCommonsController < ApplicationController
# 选用实训 # 选用实训
def shixuns def shixuns
@main_catrgory = @course.course_modules.where(module_type: "shixun_homework")
@homework_category = @main_catrgory.take.course_second_categories
search = params[:search] search = params[:search]
type = params[:type] type = params[:type]
# 超级管理员用户显示所有未隐藏的实训、非管理员显示所有已发布的实训(对本单位公开且未隐藏未关闭) # 超级管理员用户显示所有未隐藏的实训、非管理员显示所有已发布的实训(对本单位公开且未隐藏未关闭)
@ -774,22 +834,82 @@ class HomeworkCommonsController < ApplicationController
if params[:search] && params[:search].strip != "" if params[:search] && params[:search].strip != ""
@shixuns = @shixuns.joins(:user).where("shixuns.name like ? or concat(users.lastname, users.firstname) like ?", @shixuns = @shixuns.joins(:user).where("shixuns.name like ? or concat(users.lastname, users.firstname) like ?",
"%#{search}%", "%#{search}%").distinct "%#{search}%", "%#{search}%").distinct
end end
unless type.blank? || type == "all" unless type.blank? || type == "all"
@shixuns = @shixuns.joins(:shixun_tag_repertoires).where(shixun_tag_repertoires: {tag_repertoire_id: type}).distinct @shixuns = @shixuns.joins(:shixun_tag_repertoires).where(shixun_tag_repertoires: {tag_repertoire_id: type}).distinct
end end
@shixuns = @shixuns.select([:id, :name, :status, :myshixuns_count, :identifier]).reorder("shixuns.created_at desc") @shixuns = @shixuns.select([:id, :name, :status, :myshixuns_count, :identifier, :user_id, :trainee])
@shixuns_count = @shixuns.size @total_count = @shixuns.size
## 分页参数 ## 分页参数
page = params[:page] || 1 page = params[:page] || 1
@shixuns = @shixuns.page(page).per(10) @shixuns = @shixuns.reorder("shixuns.created_at desc").includes(:challenges, user: [user_extension: :school]).page(page).per(10)
@main_catrgory = @course.course_modules.where(module_type: "shixun_homework") # 新版用下面的代码
@homework_category = @main_catrgory.take.course_second_categories # ## 我的实训
# @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 end
def create_shixun_homework def create_shixun_homework
@ -815,30 +935,69 @@ class HomeworkCommonsController < ApplicationController
# 选用实训课程 # 选用实训课程
def subjects 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] 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 ?", if select && select != "all"
"%#{search}%", "%#{search}%") @subjects = @subjects.where(repertoire_id: select)
end end
unless type.blank? || type == "all" if search.present?
@subjects = @subjects.where(repertoire_id: type) @subjects = @subjects.where("name like ?", "%#{search}%")
end end
@subjects = @subjects.reorder("subjects.created_at desc") # 排序
@subjects_count = @subjects.size order_str = "updated_at #{sort}"
@subjects = @subjects.reorder(order_str)
end
## 分页参数 @total_count = @subjects.size
page = params[:page] || 1
@subjects = @subjects.page(page).per(10)
@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 end
def create_subject_homework def create_subject_homework
@ -889,7 +1048,8 @@ class HomeworkCommonsController < ApplicationController
def publish_homework def publish_homework
tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0 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].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 = @course.homework_commons.where(id: params[:homework_ids])
homeworks = homeworks.includes(:homework_group_settings, :homework_detail_manual) 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 if @course.course_groups.where(id: publish_groups).size == @course.course_groups.size
homework.homework_group_settings.destroy_all homework.homework_group_settings.destroy_all
homework.unified_setting = true homework.unified_setting = true
homework.end_time = params[:end_time]
else else
homework.unified_setting = false homework.unified_setting = false
# 创建作业分班设置homework_group_setting # 创建作业分班设置homework_group_setting
create_homework_group_settings(homework) 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).update_all(publish_time: Time.now,
homework.homework_group_settings.where(course_group_id: publish_groups, end_time: nil). end_time: params[:end_time])
update_all(end_time: params[:end_time])
# 发消息 # 发消息
tiding_group_ids = publish_groups tiding_group_ids = publish_groups
end end
@ -927,7 +1087,7 @@ class HomeworkCommonsController < ApplicationController
homework.publish_time = Time.now homework.publish_time = Time.now
# 截止时间不为空的保持原状,为空的改为一个月后, 非统一设置的更新为最大分班截止时间 # 截止时间的处理
if homework.end_time.nil? if homework.end_time.nil?
homework.end_time = params[:end_time] homework.end_time = params[:end_time]
elsif homework.max_group_end_time elsif homework.max_group_end_time
@ -938,14 +1098,13 @@ class HomeworkCommonsController < ApplicationController
if homework.course_acts.size == 0 if homework.course_acts.size == 0
homework.course_acts << CourseActivity.new(user_id: homework.user_id, course_id: homework.course_id) homework.course_acts << CourseActivity.new(user_id: homework.user_id, course_id: homework.course_id)
end end
# 发消息
HomeworkCommonPushNotifyJob.perform_later(homework.id, tiding_group_ids) HomeworkCommonPushNotifyJob.perform_later(homework.id, tiding_group_ids)
else else
create_homework_group_settings(homework) create_homework_group_settings(homework)
none_publish_settings = homework.homework_group_settings.where(course_group_id: publish_groups).none_published 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.update_all(publish_time: Time.now, end_time: params[:end_time])
none_publish_settings.where(end_time: nil).update_all(end_time: params[:end_time])
if homework.max_group_end_time if homework.max_group_end_time
homework.end_time = homework.max_group_end_time homework.end_time = homework.max_group_end_time
end end
@ -960,7 +1119,8 @@ class HomeworkCommonsController < ApplicationController
homework.save! homework.save!
HomeworkPublishUpdateWorkStatusJob.perform_later(tiding_group_ids, homework.id) # 更新学生状态及成绩(手动点击计算)
# HomeworkPublishUpdateWorkStatusJob.perform_later(tiding_group_ids, homework.id)
end end
normal_status(0, "发布成功") normal_status(0, "发布成功")
rescue Exception => e rescue Exception => e
@ -1060,7 +1220,7 @@ class HomeworkCommonsController < ApplicationController
=end =end
# 更新所有学生的效率分(重新取homework确保是更新后的) # 更新所有学生的效率分(重新取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
end end
homework.save! homework.save!
@ -1259,7 +1419,7 @@ class HomeworkCommonsController < ApplicationController
.where(:user_id => user_ids).joins(user: :user_extension) .where(:user_id => user_ids).joins(user: :user_extension)
# 按学号和姓名搜索 # 按学号和姓名搜索
if params[:search] 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 end
# 抄袭作品数 # 抄袭作品数
@copy_reviews_count = @users_reviews.count @copy_reviews_count = @users_reviews.count
@ -1279,7 +1439,7 @@ class HomeworkCommonsController < ApplicationController
end end
# 代码查重详情 # 代码查重代码的详情
def code_review_detail def code_review_detail
@student_work = @homework.student_works.find_by(user_id: params[:user_id]) @student_work = @homework.student_works.find_by(user_id: params[:user_id])
@user = @student_work.user @user = @student_work.user
@ -1292,7 +1452,7 @@ class HomeworkCommonsController < ApplicationController
if results.status == 0 if results.status == 0
code_info = results.code_info code_info = results.code_info
homework_challenge_settings = @homework.homework_challenge_settings 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 =
@challenges.map do |challenge| @challenges.map do |challenge|
code_rate = 0 code_rate = 0
@ -1306,24 +1466,8 @@ class HomeworkCommonsController < ApplicationController
game = challenge.games.find_by(user_id: @user.id) game = challenge.games.find_by(user_id: @user.id)
end_time = game.end_time end_time = game.end_time
# 用户关卡的得分 # 用户关卡的得分
all_score = homework_challenge_settings.find_by(challenge_id: challenge.id).try(:score) all_score = homework_challenge_settings.find_by(challenge_id: challenge.id).try(:score).to_f
final_score = final_score = @student_work.work_challenge_score game, all_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
# 抄袭用户 # 抄袭用户
copy_user = User.find_by_id(game_codes[0].target_user_id) 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? copy_end_time = copy_user.games.find_by(challenge_id: challenge.id).try(:end_time) if copy_user.present?

@ -3,7 +3,7 @@ class MessagesController < ApplicationController
SORT_TYPE = %w[time hot] 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_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 :find_message, only: [:update, :destroy, :sticky_top, :reply_list, :destroy, :reply]
before_action :validate_delete_params, only: %i[bulk_delete bulk_public] before_action :validate_delete_params, only: %i[bulk_delete bulk_public]
@ -17,17 +17,25 @@ class MessagesController < ApplicationController
@page = params[:page] || 1 @page = params[:page] || 1
@page_size = params[:page_size] || 15 @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_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 = @board.messages.root_nodes.by_keywords(params[:search])
@messages = @messages.ordered(sort: sort, sort_type: sort_type)
@messages = sort_by_all_replies(sort, sort_type, @messages)
@messages = sort_by_sticky(@messages) messages = messages.reorder('(sticky = 1) DESC') # 置顶
@messages = Kaminari.paginate_array(@messages).page(@page).per(@page_size)
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 end
def reply_list def reply_list
@ -35,41 +43,31 @@ class MessagesController < ApplicationController
@page_size = params[:page_size] || 10 @page_size = params[:page_size] || 10
@current_user = current_user || nil @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? @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) @messages = @messages.page(@page).per(@page_size)
end end
def reply def reply
return normal_status(2, "回复内容不能为空") if params[:content].blank? return normal_status(2, "回复内容不能为空") if params[:content].blank?
begin @reply = Message.create!(board: @message.board, root_id: @message.root_id || @message.id,
@reply = Message.create!(board: @message.board, author: current_user, parent: @message,
author: current_user, message_detail_attributes: {
parent: @message,
message_detail_attributes: {
content: params[:content] content: params[:content]
} })
)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end end
def sticky_top def sticky_top
return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@message.board.course) return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@message.board.course)
ActiveRecord::Base.transaction do @message.update_attributes(:sticky => @message.sticky == 1 ? 0 : 1)
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
end end
def bulk_delete def bulk_delete
@ -89,7 +87,10 @@ class MessagesController < ApplicationController
end end
def show 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? return normal_status(-2, "ID为#{params[:id]}的帖子不存在") if @message.nil?
@attachment_size = @message.attachments.size @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) return normal_status(403, "您没有权限进行该操作") if current_user != @message.author && !current_user.teacher_of_course?(@message.board.course)
begin 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) Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
@message.update_content(params[:content]) @message.update_content(params[:content])
rescue Exception => e rescue Exception => e
@ -130,7 +133,7 @@ class MessagesController < ApplicationController
def destroy def destroy
begin 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! @message.destroy!
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
@ -170,15 +173,9 @@ class MessagesController < ApplicationController
def bulk_move 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])
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
end end
def bulk_public def bulk_public

@ -1,7 +1,7 @@
class MyshixunsController < ApplicationController class MyshixunsController < ApplicationController
before_action :require_login, :except => [:training_task_status, :code_runinng_message] before_action :require_login, :check_auth, :except => [:training_task_status, :code_runinng_message]
before_action :find_myshixun, :except => [:training_task_status] before_action :find_myshixun, :except => [:training_task_status, :code_runinng_message]
before_action :find_repo_name, :except => [:training_task_status] before_action :find_repo_name, :except => [:training_task_status, :code_runinng_message]
skip_before_action :verify_authenticity_token, :only => [:html_content] skip_before_action :verify_authenticity_token, :only => [:html_content]
## TPI关卡列表 ## TPI关卡列表
@ -15,7 +15,6 @@ class MyshixunsController < ApplicationController
# For Admin # For Admin
# 强制重置实训 # 强制重置实训
# REDO等删除是否可以做成异步
# 前段需要按照操作过程提示 # 前段需要按照操作过程提示
def reset_my_game def reset_my_game
unless (current_user.admin? || current_user.id == @myshixun.user_id) unless (current_user.admin? || current_user.id == @myshixun.user_id)
@ -34,8 +33,11 @@ class MyshixunsController < ApplicationController
uid_logger_error("版本库删除异常,详情:#{e.message}") uid_logger_error("版本库删除异常,详情:#{e.message}")
end 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 rescue Exception => e
uid_logger_error("myshixun reset failed #{e}") uid_logger_error("myshixun reset failed #{e}")
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
@ -44,6 +46,7 @@ class MyshixunsController < ApplicationController
end end
# 代码运行中的信息接口 # 代码运行中的信息接口
# 这个方法是中间层主动调用的点击评测后中间层会发送参数过来告诉目前Pod的启动情况一次评测会调用两次请求
def code_runinng_message def code_runinng_message
begin begin
jsonTestDetails = JSON.parse(params[:jsonTestDetails]) 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"}' # "createPod":"1.610","evaluateAllTime":2820,"evaluateStart":"2017-11-24 11:04:35","execute":"0.294"}'
# params[:pics] = "a.png,b.png,c.png" # params[:pics] = "a.png,b.png,c.png"
def training_task_status def training_task_status
logger.info("123################{params[:jsonTestDetails]}")
logger.info("456################{params[:timeCost]}")
logger.info("666###############{params}")
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@ -99,13 +99,16 @@ class MyshixunsController < ApplicationController
return_back_time = format("%.3f", ( t1.to_f - brige_end_time.to_f)).to_f return_back_time = format("%.3f", ( t1.to_f - brige_end_time.to_f)).to_f
status = jsonTestDetails['status'] status = jsonTestDetails['status']
game_id = jsonTestDetails['buildID'] 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")}") logger.info("training_task_status start#1**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
resubmit = jsonTestDetails['resubmit'] resubmit = jsonTestDetails['resubmit']
outPut = tran_base64_decode64(jsonTestDetails['outPut']) outPut = tran_base64_decode64(jsonTestDetails['outPut'])
jenkins_testsets = jsonTestDetails['msg'] jenkins_testsets = jsonTestDetails['msg']
compile_success = jsonTestDetails['compileSuccess'] compile_success = jsonTestDetails['compileSuccess']
# message = Base64.decode64(params[:msg]) unless params[:msg].blank? # message = Base64.decode64(params[:msg]) unless params[:msg].blank?
logger.info(outPut)
game = Game.find(game_id) game = Game.find(game_id)
myshixun = game.myshixun myshixun = game.myshixun
challenge = game.challenge challenge = game.challenge
@ -122,11 +125,16 @@ class MyshixunsController < ApplicationController
jenkins_testsets.each_with_index do |j_test_set, i| jenkins_testsets.each_with_index do |j_test_set, i|
logger.info("j_test_set: ############## #{j_test_set}") logger.info("j_test_set: ############## #{j_test_set}")
actual_output = tran_base64_decode64(j_test_set['output']) 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) # is_public = test_sets.where(:position => j_test_set['caseId']).first.try(:is_public)
logger.info "actual_output:################################################# #{actual_output}" 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'], 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, :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 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 test_set_score += challenge.test_sets.where(:position => j_test_set['caseId']).pluck(:score).first
@ -134,14 +142,14 @@ class MyshixunsController < ApplicationController
end end
end end
uid_logger("#############status: #{status}") uid_logger("#############status: #{status}")
uid_logger("#############resubmit: #{resubmit}") record = EvaluateRecord.where(:identifier => sec_key).first
record = EvaluateRecord.where(:game_id => game_id).first
logger.info("training_task_status start#3**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") 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_percentage = (100 - game.answer_deduction) / 100.to_f # 查看答案后剩余分数的百分比.
# answer_deduction是查看答案的扣分比例 # answer_deduction是查看答案的扣分比例
# status0表示评测成功 # status0表示评测成功
if status == "0" if status == "0"
if resubmit.present? if resubmit.present?
uid_logger("#############resubmitdaiao: #{resubmit}")
game.update_attributes!(:retry_status => 2, :resubmit_identifier => resubmit) game.update_attributes!(:retry_status => 2, :resubmit_identifier => resubmit)
challenge.path.split("").each do |path| challenge.path.split("").each do |path|
game_passed_code(path.try(:strip), myshixun, game_id) game_passed_code(path.try(:strip), myshixun, game_id)
@ -167,7 +175,7 @@ class MyshixunsController < ApplicationController
end end
# 更新实训关联的作品分数 TODO: 更新作品分数 # 更新实训关联的作品分数 TODO: 更新作品分数
HomeworksService.new.update_myshixun_work_score myshixun # HomeworksService.new.update_myshixun_work_score myshixun
end end
# 如果过关了下一关的状态是3为开启则需要把状态改成1已开启 # 如果过关了下一关的状态是3为开启则需要把状态改成1已开启
# next_game = game.next_game # next_game = game.next_game
@ -182,14 +190,21 @@ class MyshixunsController < ApplicationController
test_set_percentage = test_set_score / 100.to_f # 测试集得分比 test_set_percentage = test_set_score / 100.to_f # 测试集得分比
score = (challenge.score * test_set_percentage * answer_deduction_percentage).to_i 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
end end
test_cases_time = format("%.3f", (Time.now.to_f - t1.to_f)).to_f test_cases_time = format("%.3f", (Time.now.to_f - t1.to_f)).to_f
if record.present? if record.present?
consume_time = format("%.3f", (Time.now - record.created_at)).to_f 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) :brige => timeCost['evaluateAllTime'], :return_back => return_back_time)
end end
uid_logger("training_task_status start#4**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") 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') shixun_tomcat = edu_setting('tomcat_webssh')
uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo" uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo"
params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), 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 res = uri_post uri, params
if res && res['code'].to_i != 0 if res && res['code'].to_i != 0
tip_exception("实训云平台繁忙繁忙等级92") tip_exception("实训云平台繁忙繁忙等级92")
@ -237,55 +252,58 @@ class MyshixunsController < ApplicationController
# -----Repository # -----Repository
# TODO: 之类需要一个resubmit参数,但是是关于games. # TODO: 之类需要一个resubmit参数,但是是关于games.
def update_file def update_file
@hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first begin
tip_exception("技术平台为空!") if @myshixun.mirror_name.blank? @hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first
path = params[:path].strip unless params[:path].blank? tip_exception("技术平台为空!") if @myshixun.mirror_name.blank?
game_id = params[:game_id] path = params[:path].strip unless params[:path].blank?
game = Game.find(game_id) game_id = params[:game_id]
@content_modified = 0 game = Game.find(game_id)
# params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过 @content_modified = 0
# 自动保存的时候evaluate为0点评测的时候为1
if params[:evaluate] == 1 # params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id) # 自动保存的时候evaluate为0点评测的时候为1
uid_logger("-- game is #{game_id}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") if params[:evaluate] == 1
student_work_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f @sec_key = generate_identifier(EvaluateRecord, 12)
record.update_attributes!(:student_work => student_work_time) record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id,
end :identifier => @sec_key)
unless @hide_code 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")}")
# 远程版本库文件内容
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}")
end 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 author_name = current_user.real_name
@resubmit = Time.now.to_i author_email = current_user.git_mail
end 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 game.status == 2
if record.present? @resubmit = Time.now.to_i
consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f end
record.update_attributes!(:file_update => consume_time)
# 评测时间记录
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
end end

@ -1,5 +1,5 @@
class PollQuestionsController < ApplicationController class PollQuestionsController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :get_poll,only:[:new,:create] before_action :get_poll,only:[:new,:create]
before_action :get_poll_question,except: [:new,:create] before_action :get_poll_question,except: [:new,:create]
before_action :is_course_teacher before_action :is_course_teacher
@ -156,14 +156,10 @@ class PollQuestionsController < ApplicationController
begin begin
answer_d_id = params[:answer_no].to_i # 答案的当前位置 answer_d_id = params[:answer_no].to_i # 答案的当前位置
poll_answers = @poll_question.poll_answers poll_answers = @poll_question.poll_answers
delete_answer = poll_answers.find_answer_by_custom("answer_position",answer_d_id).first delete_answer = poll_answers.find_by(answer_position: answer_d_id)
left_answer = poll_answers.left_answer_choose("answer_position",answer_d_id) left_answers = poll_answers.where("answer_position > ?",answer_d_id)
if left_answer.present? left_answers.update_all("answer_position = answer_position - 1") if left_answers
left_answer.each do |p|
p.answer_position -= 1
p.save
end
end
if delete_answer.destroy if delete_answer.destroy
normal_status(0, "答案删除成功!") normal_status(0, "答案删除成功!")
else else
@ -197,22 +193,23 @@ class PollQuestionsController < ApplicationController
begin begin
opr = params[:opr] opr = params[:opr]
current_q_p = @poll_question.question_number.to_i #问题的当前位置 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 @poll.polls_status.to_i == 1
if opr.present? if opr.present?
if opr.to_s == "up" if opr.to_s == "up"
last_q_p = @poll.poll_questions.find_by(question_number: (current_q_p-1)) #当前问题的前一个问题
if last_q_p.present? if last_q_p.present?
@poll_question.update_attribute(:question_number, (current_q_p - 1)) @poll_question.update_attribute("question_number", (current_q_p - 1))
last_q_p.update_attribute(:question_number, (@poll_question.question_number.to_i + 1)) # 重新获取当前问题的位置 last_q_p.update_attribute("question_number", current_q_p) # 重新获取当前问题的位置
normal_status(0, "问题上移成功!") normal_status(0, "问题上移成功!")
else else
normal_status(-1, "移动失败,已经是第一个问题了!") normal_status(-1, "移动失败,已经是第一个问题了!")
end end
elsif opr.to_s == "down" elsif opr.to_s == "down"
next_q_p = @poll.poll_questions.find_by(question_number: (current_q_p+1)) #当前问题的后一个问题
if next_q_p.present? if next_q_p.present?
@poll_question.update_attribute(:question_number, (current_q_p + 1)) @poll_question.update_attribute("question_number", (current_q_p + 1))
next_q_p.update_attribute(:question_number, (@poll_question.question_number.to_i - 1)) next_q_p.update_attribute("question_number", current_q_p)
normal_status(0, "问题下移成功!") normal_status(0, "问题下移成功!")
else else
normal_status(-1, "移动失败,已经是最后一个问题了!") normal_status(-1, "移动失败,已经是最后一个问题了!")

@ -1,9 +1,8 @@
class PollVotesController < ApplicationController class PollVotesController < ApplicationController
#在开始回答和提交问卷的时候,已经做了判断用户的身份权限 #在开始回答和提交问卷的时候,已经做了判断用户的身份权限
before_action :require_login before_action :require_login, :check_auth
before_action :get_poll_question before_action :get_poll_question
before_action :check_answer_in_question,only: [:create] before_action :check_answer_in_question
before_action :check_multi_answers
def create #每一次答案的点击,请求一次 def create #每一次答案的点击,请求一次
@ -31,11 +30,13 @@ class PollVotesController < ApplicationController
if question_type == 1 if question_type == 1
if user_votes.present? #用户曾经回答过的,答案选择不一样,否则新建 if user_votes.present? #用户曾经回答过的,答案选择不一样,否则新建
current_user_answer = user_votes.first 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 current_user_answer.destroy
PollVote.create(vote_answer_params) PollVote.create(vote_answer_params)
else else
if question_answer_text.present? if question_answer_text.present?
current_user_answer.update_attribute("vote_text", question_answer_text) current_user_answer.update_attribute("vote_text", question_answer_text)
end end
end end
@ -98,9 +99,10 @@ class PollVotesController < ApplicationController
@current_question_necessary = @poll_question.is_necessary @current_question_necessary = @poll_question.is_necessary
#问答记录存在,且有值,才会有返回值。 #问答记录存在,且有值,才会有返回值。
@current_question_status = 0 @current_question_status = 0
if user_votes.present? new_user_votes = question_votes.where(user_id: current_user.id)
vote_answer_id = user_votes.pluck(:poll_answer_id).reject(&:blank?).size if new_user_votes.present?
vote_text_count = user_votes.pluck(:vote_text).reject(&:blank?).size 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 if vote_text_count > 0 || vote_answer_id > 0
@current_question_status = 1 @current_question_status = 1
end end
@ -129,29 +131,28 @@ class PollVotesController < ApplicationController
normal_status(-1,"课堂不存在!") normal_status(-1,"课堂不存在!")
end end
end end
end end
def check_answer_in_question def check_answer_in_question
poll_answer_ids = @poll_question.poll_answers.pluck(:id) poll_user_status = @poll.get_poll_status(current_user)
if @poll_question.question_type == 1 #单选题/多选题 poll_user = @poll.poll_users.find_by(user_id: current_user.id) #当前用户
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
def check_multi_answers question_type = @poll_question&.question_type
if @poll_question.question_type == 2 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 user_vote_count = params[:poll_answer_id].size
if @poll_question.max_choices.present? if @poll_question.max_choices.present?
question_max_choices = @poll_question.max_choices question_max_choices = @poll_question.max_choices
else else
question_max_choices = 0 question_max_choices = 0
end 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,"多选题答案超过最大限制!") normal_status(-1,"多选题答案超过最大限制!")
end end
elsif (poll_user.present? && poll_user.commit_status == 1) || poll_user_status == 3
normal_status(-1,"已提交/已结束的问卷不允许修改!")
end end
end end
end end

@ -1,6 +1,6 @@
class PollsController < ApplicationController class PollsController < ApplicationController
# before_action :check_poll_status 问卷的发消息和定时任务没有做 # 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, 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] :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, 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_user_id_start_answer,only: [:start_answer]
before_action :check_poll_question_complete,only: [:commit_poll] #问卷提交前来判断问题是否完成 before_action :check_poll_question_complete,only: [:commit_poll] #问卷提交前来判断问题是否完成
before_action :check_poll_commit_result,only: [:commit_result] 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] before_action :get_left_banner_id, only:[:common_header,:start_answer,:new,:edit,:index]
include PollsHelper include PollsHelper
@ -31,50 +31,48 @@ class PollsController < ApplicationController
@current_user_ = current_user @current_user_ = current_user
@course_status = @course.is_end ? 0 : 1 # 课堂是否结束 @course_status = @course.is_end ? 0 : 1 # 课堂是否结束
@course_is_public = @course.is_public @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 = @course.students #当前课堂的全部学生
@course_all_members_count = @course_all_members.count #当前课堂的学生数
@current_student = @course_all_members.find_by(user_id: current_user.id) #当前用户是否为课堂的学生 @current_student = @course_all_members.find_by(user_id: current_user.id) #当前用户是否为课堂的学生
# polls的不同用户群体的显示 # polls的不同用户群体的显示
if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教 if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教
@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 #老师能看到全部的问卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同) @polls = @polls_all #老师能看到全部的问卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同)
elsif @user_course_identity == Course::STUDENT # 2为课堂成员能看到统一设置的和自己班级的 elsif @user_course_identity == Course::STUDENT # 2为课堂成员能看到统一设置的和自己班级的
@is_teacher_or = 2 @is_teacher_or = 2
member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id默认为0 @member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id默认为0
if member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的) if @member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的)
@polls = member_show_polls.size > 0 ? member_show_polls.public_or_unset : [] @polls = member_show_polls.size > 0 ? member_show_polls.public_or_unset : []
else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷 else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷
# 已发布 当前用户班级分组的 试卷id # 已发布 当前用户班级分组的 试卷id
poll_settings_ids = @course.poll_group_settings.where(course_group_id: member_group_id).poll_group_published.pluck(:poll_id).uniq # 选择成员的班级id等于课堂问卷设置的班级id 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.present? ? member_show_polls.public_or_unset.or(member_show_polls.where(id: poll_settings_ids)) : [] @polls = member_show_polls.where.not(id: not_poll_ids)
end end
else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁 else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁
@is_teacher_or = 0 @is_teacher_or = 0
@polls = member_show_polls.size > 0 ? member_show_polls.public_or_unset : [] @polls = member_show_polls.public_or_unset
end end
if @polls.count > 0 if @polls.count > 0
if params[:type].present? if params[:type].present?
choose_type = params[:type] choose_type = params[:type]
member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id默认为0 poll_setting_ids = []
if @is_teacher_or == 2 && member_group_id > 0 if @is_teacher_or != 2
poll_groups_sets = @course.poll_group_settings.where(course_group_id: member_group_id).poll_group_published @polls = @polls.where("polls_status = #{choose_type}")
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
else 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
end end
@ -90,11 +88,16 @@ class PollsController < ApplicationController
@limit = params[:limit] || 15 @limit = params[:limit] || 15
@polls = @polls.page(@page).per(@limit) @polls = @polls.page(@page).per(@limit)
@polls = @polls.includes(:poll_users,:poll_questions,:poll_group_settings) @polls = @polls&.includes(:published_settings)
else else
@polls = [] @polls = []
end 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 rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception(e.message) tip_exception(e.message)
@ -146,7 +149,7 @@ class PollsController < ApplicationController
def edit def edit
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@poll_questions = @poll.poll_questions.order("question_number ASC")
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("页面请求失败!") tip_exception("页面请求失败!")
@ -183,7 +186,7 @@ class PollsController < ApplicationController
else else
@is_teacher_or = 0 @is_teacher_or = 0
end end
@poll_questions = @poll.poll_questions.order("question_number ASC")
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("没有权限") tip_exception("没有权限")
@ -202,15 +205,15 @@ class PollsController < ApplicationController
@is_teacher_or = 1 @is_teacher_or = 1
@user_poll_answer = 3 #教师页面 @user_poll_answer = 3 #教师页面
end end
poll_status = @poll.get_poll_status(current_user.id) @poll_status = @poll.get_poll_status(current_user)
poll_id_array = [@poll.id] poll_id_array = [@poll.id]
@poll_publish_count = get_user_permission_course(poll_id_array,2).count #是否存在已发布的 @poll_publish_count = get_user_permission_course(poll_id_array,2).count #是否存在已发布的
@poll_unpublish_count = get_user_permission_course(poll_id_array,1).count #是否存在未发布的 @poll_unpublish_count = get_user_permission_course(poll_id_array,1).count #是否存在未发布的
if (@poll_publish_count == 0) && (@poll_unpublish_count == 0) #即表示没有分班 if (@poll_publish_count == 0) && (@poll_unpublish_count == 0) #即表示没有分班
if poll_status == 1 if @poll_status == 1
@poll_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候 @poll_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候
elsif poll_status == 2 elsif @poll_status == 2
@poll_publish_count = 1 #试卷未发布,且课堂没有分班的时候 @poll_publish_count = 1 #试卷未发布,且课堂没有分班的时候
end end
end end
@ -241,10 +244,13 @@ class PollsController < ApplicationController
end end
#首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。 #首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。
def publish 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 ActiveRecord::Base.transaction do
begin begin
check_ids = Poll.where(id: params[:check_ids]) 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| check_ids.each do |poll|
if poll.unified_setting if poll.unified_setting
pl_status = poll.polls_status #则为试卷的状态 pl_status = poll.polls_status #则为试卷的状态
@ -254,16 +260,11 @@ class PollsController < ApplicationController
if pl_status == 1 #如果问卷存在已发布的,或者是已截止的,那么则直接跳过 if pl_status == 1 #如果问卷存在已发布的,或者是已截止的,那么则直接跳过
g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数那么poll的统一设置需修改 g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数那么poll的统一设置需修改
if g_course if g_course
course_groups = @course.teacher_course_groups.get_user_groups(current_user.id) user_course_groups = @course.charge_group_ids(current_user)
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
if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则问卷不用分组,且问卷设定为统一设置,否则则分组设置 if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则问卷不用分组,且问卷设定为统一设置,否则则分组设置
poll.poll_group_settings.destroy_all poll.poll_group_settings.destroy_all
poll_unified = true poll_unified = true
notify_student_ids = @course.students.pluck(:user_id) e_time = ex_end_time
else else
poll_unified = false poll_unified = false
g_course.each do |i| g_course.each do |i|
@ -282,20 +283,13 @@ class PollsController < ApplicationController
new_poll_group.save new_poll_group.save
end end
end end
e_time = poll.poll_group_settings.end_time_present.map(&:end_time).max
notify_student_ids = @course.students.where(course_group_id: params[:group_ids]).pluck(:user_id) # group_ids = params[:group_ids]
end end
else else
poll.poll_group_settings.destroy_all poll.poll_group_settings.destroy_all
poll_unified = true poll_unified = true
notify_student_ids = @course.students.pluck(:user_id)
end
if poll.end_time.blank?
e_time = ex_end_time 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 end
poll_status = set_poll_status(Time.now,e_time) poll_status = set_poll_status(Time.now,e_time)
@ -309,7 +303,7 @@ class PollsController < ApplicationController
if poll.course_acts.size == 0 if poll.course_acts.size == 0
poll.course_acts << CourseActivity.new(:user_id => poll.user_id,:course_id => poll.course_id) poll.course_acts << CourseActivity.new(:user_id => poll.user_id,:course_id => poll.course_id)
end end
PollPublishNotifyJob.perform_later(poll.id, notify_student_ids) PollPublishNotifyJob.perform_later(poll.id, g_course)
end end
end end
normal_status(0, "问卷发布成功!") normal_status(0, "问卷发布成功!")
@ -347,7 +341,7 @@ class PollsController < ApplicationController
begin begin
check_ids = Poll.where(id: params[:check_ids]) check_ids = Poll.where(id: params[:check_ids])
check_ids.each do |poll| 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 #跳过已截止的或未发布的 if poll_status == 2 #跳过已截止的或未发布的
g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数那么poll的统一设置需修改poll_group_settings g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数那么poll的统一设置需修改poll_group_settings
if g_course 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) @user_published_setting = @poll.poll_group_settings.find_in_poll_group("course_group_id",@being_setting_course_ids)
poll_ids = [@poll.id] poll_ids = [@poll.id]
@poll_publish_count = get_user_permission_course(poll_ids,2).count @poll_publish_count = get_user_permission_course(poll_ids,2).count
## 需添加发送消息的接口,稍后添加
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("页面调用失败!") tip_exception("页面调用失败!")
@ -688,10 +682,10 @@ class PollsController < ApplicationController
begin begin
error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。 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) poll_status = @poll.get_poll_status(current_user)
if poll_status == 1 && (course_group_ids - [0]).count > 0 # 问卷未发布且老师的分班大于1 才可以修改统一设置否则按poll默认的来处理 if poll_status == 1 && course_group_ids.size > 0 # 问卷未发布且老师的分班大于1 才可以修改统一设置否则按poll默认的来处理
unified_setting = params[:unified_setting] unified_setting = params[:unified_setting]
else else
unified_setting = @poll.unified_setting unified_setting = @poll.unified_setting
@ -849,8 +843,8 @@ class PollsController < ApplicationController
def start_answer def start_answer
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
poll_user_current = @poll.poll_users.find_by_group_ids(@poll_current_user_id).first #查找当前用户是否有过答题 poll_user_current = PollUser.where(user_id:@poll_current_user_id,poll_id:@poll.id)&.first #查找当前用户是否有过答题
@poll_status = @poll.get_poll_status(current_user.id) @poll_status = @poll.get_poll_status(current_user)
if poll_user_current.blank? if poll_user_current.blank?
if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候不创建poll_user表理论上老师是不能进入答题的 if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候不创建poll_user表理论上老师是不能进入答题的
poll_user_params = { poll_user_params = {
@ -871,7 +865,6 @@ class PollsController < ApplicationController
@user_poll_status = 0 #可编辑 @user_poll_status = 0 #可编辑
end end
# @answer_user = User.find_by(id:@poll_current_user_id)
@answer_status = [] @answer_status = []
question_answered = 0 question_answered = 0
@ -923,21 +916,26 @@ class PollsController < ApplicationController
def commit_result def commit_result
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin 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 @page = params[:page] || 1
@limit = params[:limit] || 10 @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) @poll_questions = @poll_questions.page(@page).per(@limit)
respond_to do |format| if params[:format] == "xlsx"
format.json if @user_course_identity > Course::ASSISTANT_PROFESSOR
format.xlsx{ tip_exception(403,"无权限操作")
if @user_course_identity > Course::ASSISTANT_PROFESSOR elsif (@poll.polls_status == 1) || (@poll_export_questions.size == 0) || (@poll_commit_ids.size == 0)
tip_exception(403,"无权限操作") normal_status(-1,"暂无用户提交")
else else
polls_export_name = current_user.real_name + "_" + @course.name + "_" + @poll.polls_name + "_" + Time.now.strftime('%Y%m%d_%H%M%S') respond_to do |format|
render xlsx: "#{polls_export_name.strip.first(30)}",template: "polls/commit_result.xlsx.axlsx",locals: {poll_questions:@poll_export_questions} 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
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
@ -951,17 +949,17 @@ class PollsController < ApplicationController
def poll_lists def poll_lists
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin 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_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_publish_count = get_user_permission_course(poll_ids,2).count
@poll_unpublish_count = get_user_permission_course(poll_ids,1).count @poll_unpublish_count = get_user_permission_course(poll_ids,1).count
@course_all_members = @course.students @course_all_members = @course.students
@poll_group_counts = @course.course_groups_count
if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的问卷 if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的问卷
@poll_current_user_status = 0 @poll_current_user_status = 0
@poll_users_list = @poll.all_poll_users(current_user.id).distinct #该老师分班的全部学生 @poll_users_list = @poll.all_poll_users(current_user.id) #该老师分班的全部学生
get_poll_answers(@poll_users_list) get_poll_answers(@poll_users_list, @poll_list_status)
if @poll_list_status == 1 if @poll_list_status == 1
@poll_course_groups =[] @poll_course_groups =[]
else else
@ -973,7 +971,7 @@ class PollsController < ApplicationController
end end
elsif @user_course_identity > Course::ASSISTANT_PROFESSOR elsif @user_course_identity > Course::ASSISTANT_PROFESSOR
@poll_all_users = @poll.get_poll_exercise_users @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_course_groups = [] #当为学生的时候,不显示分班情况
@poll_current_user_status = 1 #当前用户的状态,为学生 @poll_current_user_status = 1 #当前用户的状态,为学生
poll_current_user = @poll_all_users.find_by_group_ids(current_user.id) #当前用户是否开始做问卷(提交/未提交/没做) poll_current_user = @poll_all_users.find_by_group_ids(current_user.id) #当前用户是否开始做问卷(提交/未提交/没做)
@ -984,7 +982,7 @@ class PollsController < ApplicationController
end end
else else
@poll_all_users = @poll.get_poll_exercise_users @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_current_user_status = 2 #当前用户非课堂成员
@poll_users_list = [] @poll_users_list = []
end end
@ -1007,14 +1005,8 @@ class PollsController < ApplicationController
search_content = params[:search] search_content = params[:search]
if @poll_users_list.present? && @poll_users_list.count > 0 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? if choose_type.present?
@poll_users_list = @poll_users_list.commit_by_status(choose_type) @poll_users_list = @poll_users_list.commit_by_status(choose_type)
end end
@ -1028,20 +1020,23 @@ class PollsController < ApplicationController
#搜索 #搜索
if search_content.present? if search_content.present?
#搜索用户的nickname,如果存在则返回,否则继续查询用户的真实姓名或学生号 @poll_users_list = @poll_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{search_content}%", "%#{search_content}%")
nick_name_search = @poll_users_list.where(user_id: User.where('CONCAT(users.lastname, users.firstname) like ?',"%#{search_content}%")) end
if nick_name_search.present?
@poll_users_list = nick_name_search poll_users_joins = @poll_users_list.joins(user: :user_extension)
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}%") if order == "student_id"
end @poll_users_list = poll_users_joins.order("user_extensions.student_id DESC")
else
@poll_users_list = poll_users_joins.order("end_at DESC")
end end
@poll_users_size = @poll_users_list.count @poll_users_size = @poll_users_list.count
# 分页 # 分页
@page = params[:page] || 1 page = params[:page] || 1
@limit = params[:limit] || 20 limit = params[:limit] || 20
@poll_users_list = @poll_users_list.page(@page).per(@limit) @poll_users_list = @poll_users_list.page(page).per(limit)
else else
@poll_users_list = [] @poll_users_list = []
@poll_users_size = 0 @poll_users_size = 0
@ -1103,7 +1098,7 @@ class PollsController < ApplicationController
## 判断开始答题页面的用户权限 ## 判断开始答题页面的用户权限
def check_user_on_answer 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 #问卷未发布,且当前用户不为老师/管理员 if @user_course_identity == Course::STUDENT && poll_status == 1 #问卷未发布,且当前用户不为老师/管理员
normal_status(-1, "未发布问卷!") normal_status(-1, "未发布问卷!")
elsif @user_course_identity > Course::STUDENT && (!@poll.is_public || (@poll.is_public && !@poll.unified_setting)) ##不为课堂成员,且问卷不为公开的,或问卷公开,但是不是统一设置的 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 def get_questions_count
@poll_questions = @poll.poll_questions.order("question_number ASC") @poll_questions = @poll.poll_questions.order("question_number ASC")
@poll_questions_count = @poll_questions.count # 全部的题目数 @poll_questions_count = @poll_questions&.size # 全部的题目数
@poll_question_singles = @poll_questions.ques_count(1).all.count # 单选题 @poll_question_singles = @poll_questions.ques_count(1).size # 单选题
@poll_question_doubles = @poll_questions.ques_count(2).all.count # 多选题 @poll_question_doubles = @poll_questions.ques_count(2).size # 多选题
@poll_question_mains = @poll_questions.ques_count(3).all.count #主观题 @poll_question_mains = @poll_questions.ques_count(3).size #主观题
@poll_questions = @poll_questions&.includes(:poll_answers,:poll_votes).distinct
end end
def check_poll_question_complete #commit_poll 的权限 def check_poll_question_complete #commit_poll 的权限
poll_user_current = @poll.poll_users.find_by_group_ids(current_user.id).first 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) if @user_course_identity < Course::STUDENT || (poll_status == 3) || (poll_user_current.present? && poll_user_current.commit_status == 1)
normal_status(-1,"用户没有权限!") #老师/管理员在提交时没有权限 normal_status(-1,"用户没有权限!") #老师/管理员在提交时没有权限
else else
@ -1181,9 +1177,9 @@ class PollsController < ApplicationController
end end
def check_poll_commit_result 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) #当前用户已提交问卷的 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,"没有权限!") #当前为老师/问卷公开统计,且问卷已截止,且用户有过回答的 normal_status(-1,"没有权限!") #当前为老师/问卷公开统计,且问卷已截止,且用户有过回答的
end end
end end
@ -1213,17 +1209,12 @@ class PollsController < ApplicationController
def get_user_permission_course(poll_ids,status) #获取用户权限范围内的已发布/未发布 def get_user_permission_course(poll_ids,status) #获取用户权限范围内的已发布/未发布
poll_status = status.to_i poll_status = status.to_i
unpublish_group = [] unpublish_group = []
g_course_ids = @course.teacher_course_groups.get_user_groups(current_user.id).pluck(:course_group_id).reject(&:blank?).uniq user_groups_id = @course.charge_group_ids(current_user)
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
all_polls = Poll.where(id:poll_ids) all_polls = Poll.where(id:poll_ids)
all_polls.each do |poll| all_polls.each do |poll|
if poll.present? if poll.present?
if poll.unified_setting 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 #未发布的情况 if poll_user_status == poll_status || poll_status == 3 #未发布的情况
unpublish_group = unpublish_group + user_groups_id unpublish_group = unpublish_group + user_groups_id
else else
@ -1282,8 +1273,6 @@ class PollsController < ApplicationController
else else
normal_status(-1,"请选择分班!") normal_status(-1,"请选择分班!")
end end
# elsif (@poll.poll_status != 1) && (params[:publish_time].to_time != @poll.publish_time) && (@user_course_identity > Course::CREATOR)
# normal_status(-1,"已发布/已截止的不能修发布时间!") #课堂管理员和超级管理员才有权限
end end
end end
@ -1297,4 +1286,99 @@ class PollsController < ApplicationController
end end
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 end

@ -1,6 +1,6 @@
class PraiseTreadController < ApplicationController class PraiseTreadController < ApplicationController
include MessagesHelper include MessagesHelper
before_action :require_login before_action :require_login, :check_auth
before_action :validate_params, only: [:like, :unlike] before_action :validate_params, only: [:like, :unlike]
before_action :find_object before_action :find_object

@ -1,5 +1,5 @@
class QuestionBanksController < ApplicationController class QuestionBanksController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :params_filter before_action :params_filter
# 题库选用列表 # 题库选用列表
@ -178,6 +178,7 @@ class QuestionBanksController < ApplicationController
:question_type => q.question_type || 1, :question_type => q.question_type || 1,
:question_number => q.question_number, :question_number => q.question_number,
:question_score => q.question_score, :question_score => q.question_score,
:shixun_name => q.shixun_name,
:shixun_id => q.shixun_id :shixun_id => q.shixun_id
} }
exercise_question = new_exercise.exercise_questions.new option exercise_question = new_exercise.exercise_questions.new option
@ -240,8 +241,9 @@ class QuestionBanksController < ApplicationController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
new_task = GraduationTask.new new_task = GraduationTask.new
new_task.attributes = task.attributes.dup.except("id", "course_id", "user_id", "quotes", "graduation_task_id", 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.course_id = course.id
new_task.gtask_bank_id = task.id
new_task.user_id = current_user.id new_task.user_id = current_user.id
if new_task.save! if new_task.save!
new_task.create_work_list new_task.create_work_list
@ -264,9 +266,12 @@ class QuestionBanksController < ApplicationController
def quote_gtopic_bank topic, course def quote_gtopic_bank topic, course
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
new_topic = GraduationTopic.new 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.course_id = course.id
new_topic.gtopic_bank_id = topic.id
new_topic.user_id = current_user.id new_topic.user_id = current_user.id
new_topic.tea_id = current_user.id
new_topic.save new_topic.save
topic.attachments.each.try(:each) do |attachment| topic.attachments.each.try(:each) do |attachment|

@ -0,0 +1,5 @@
class RepertoiresController < ApplicationController
def index
render_ok(repertoires: Repertoire.cache_data)
end
end

@ -1,8 +1,16 @@
class SchoolsController < ApplicationController 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 render_ok(school_names: schools.pluck(:name))
q = params[:search] ? params[:search].strip : "" end
@schools = School.where("name like ?", "%#{q}%").pluck(:name)
def for_option
render_ok(schools: School.cached_names_data)
end end
end end

@ -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

@ -1,9 +1,13 @@
class ShixunsController < ApplicationController class ShixunsController < ApplicationController
before_action :require_login, except: [:download_file, :index] include ShixunsHelper
# before_action :check_auth, except: [:download_file, :index] include ApplicationHelper
before_action :find_shixun, except: [:index, :new, :create, :menus, :get_recommend_shixuns, :propaedeutics, before_action :require_login, :check_auth, except: [:download_file, :index, :menus]
:departments, :apply_shixun_mirror, :get_mirror_script, :download_file] 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 :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy]
before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish, 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] before_action :special_allowed, only: [:send_to_course, :search_user_courses]
include ShixunsHelper
include ApplicationHelper
## 获取课程列表 ## 获取课程列表
def index def index
## 我的实训 ## 我的实训
@shixuns = @shixuns =
if params[:order_by] == 'mine' if params[:order_by] == 'mine'
tip_exception(401, "..") unless current_user.logged?
current_user.my_shixuns current_user.my_shixuns
else else
Shixun.unhidden Shixun.unhidden
@ -43,11 +45,12 @@ class ShixunsController < ApplicationController
## 搜索关键字 匹配关卡名, 用户名, 实训名 和 空格多搜索 ## 搜索关键字 匹配关卡名, 用户名, 实训名 和 空格多搜索
if params[:keyword].present? if params[:keyword].present?
keyword = params[:keyword].strip keyword = params[:keyword].strip
@shixuns = @shixuns.joins(:users, challenges: :challenge_tags). @shixuns = @shixuns.joins(:user, challenges: :challenge_tags).
where("challenge_tags.name like '%#{keyword}%' where("challenge_tags.name like :keyword
or challenges.subject like '%#{keyword}%' or challenges.subject like :keyword
or concat(lastname, firstname) like '%#{keyword}%' or concat(lastname, firstname) like :keyword
or shixuns.name like '%#{keyword.split(" ").join("%")}%'") or shixuns.name like :name",
keyword: "%#{keyword}%", name: "%#{keyword.split(" ").join("%")}%").distinct
end end
## 筛选 状态 ## 筛选 状态
@ -67,21 +70,27 @@ class ShixunsController < ApplicationController
when 'new' when 'new'
@shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.created_at #{bsort}") @shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.created_at #{bsort}")
when 'hot' 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' when 'mine'
@shixuns = @shixuns.order("shixuns.created_at #{bsort}") @shixuns = @shixuns.order("shixuns.created_at #{bsort}")
else else
@shixuns = @shixuns.order("shixuns.status = 2 desc, publish_time #{bsort}") @shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.publish_time #{bsort}")
end end
# 用id计数会快10+MS左右,对于搜索的内容随着数据的增加,性能会提升一些。
@total_count = @shixuns.count @total_count = @shixuns.count("shixuns.id")
## 分页参数 ## 分页参数
page = params[:page] || 1 page = params[:page] || 1
limit = params[:limit] || 16 limit = params[:limit] || 16
@shixuns = @shixuns.includes(:tag_repertoires, :challenges).page(page).per(limit) @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 end
## 获取顶部菜单 ## 获取顶部菜单
@ -115,8 +124,8 @@ class ShixunsController < ApplicationController
def show_right def show_right
owner = @shixun.owner owner = @shixun.owner
#@fans_count = owner.followers.count #@fans_count = owner.fan_count
#@followed_count = owner.followed_users.count #@followed_count = owner.follow_count
@user_own_shixuns = owner.shixuns.published.count @user_own_shixuns = owner.shixuns.published.count
end end
@ -127,7 +136,7 @@ class ShixunsController < ApplicationController
select m.user_id, u.login, u.lastname, m.updated_at, 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(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 (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 order by score desc, time asc limit 10
" "
@myshixuns = Myshixun.find_by_sql(sql) @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) ShixunTagRepertoire.create!(:tag_repertoire_id => str.tag_repertoire_id, :shixun_id => @new_shixun.id)
end 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版本库 # fork版本库
logger.info("###########fork_repo_path: ######{@repo_path}") logger.info("###########fork_repo_path: ######{@repo_path}")
project_fork(@new_shixun, @repo_path, current_user.login) 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.user_id = User.current.id
new_challenge.shixun_id = @new_shixun.id new_challenge.shixun_id = @new_shixun.id
new_challenge.save! 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.st == 0 # 评测题
# 同步测试集 # 同步测试集
if challenge.test_sets.present? if challenge.test_sets.present?
@ -269,7 +296,6 @@ class ShixunsController < ApplicationController
@small_type = shixun_small_type @small_type = shixun_small_type
end end
# 注意这里传参都应该使用params[:shixun]['name']这种格式
def create def create
# 评测脚本的一些操作 # 评测脚本的一些操作
main_type, sub_type = params[:main_type], params[:small_type] 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? 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? if sub_type.present?
sub_type.each do |mirror| sub_type.each do |mirror|
ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
# 实训子镜像服务配置
ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
end end
end end
@ -362,11 +392,6 @@ class ShixunsController < ApplicationController
end end
def update 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 ActiveRecord::Base.transaction do
begin begin
@shixun.shixun_mirror_repositories.destroy_all @shixun.shixun_mirror_repositories.destroy_all
@ -378,9 +403,8 @@ class ShixunsController < ApplicationController
ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror) ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
end end
end end
@shixun.update_attributes(shixun_params)
@shixun.update_attributes(s_params) @shixun.shixun_info.update_attributes(shixun_info_params)
@shixun.shixun_info.update_attributes(description: params[:description], evaluate_script: params[:evaluate_script])
@shixun.shixun_schools.delete_all @shixun.shixun_schools.delete_all
if params[:scope_partment].present? && params[:user_scope].to_i == 1 if params[:scope_partment].present? && params[:user_scope].to_i == 1
arr = [] arr = []
@ -394,6 +418,11 @@ class ShixunsController < ApplicationController
use_scope = 0 use_scope = 0
end end
@shixun.update_attributes!(:use_scope => use_scope) @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 rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("实训保存失败") tip_exception("实训保存失败")
@ -409,12 +438,12 @@ class ShixunsController < ApplicationController
end end
def propaedeutics def propaedeutics
@content = Shixun.where(identifier: params[:identifier]).pluck(:propaedeutics) @content = Shixun.find_by_identifier!(params[:identifier]).propaedeutics
end end
# 更新背景知识 # 更新背景知识
def update_propaedeutics def update_propaedeutics
@shixun.update_column(:propaedeutics, params[:content]) @shixun.shixun_info.update_column(:propaedeutics, params[:content])
end end
# 获取推荐实训接口 2个热门实训 + 2个最新实训 # 获取推荐实训接口 2个热门实训 + 2个最新实训
@ -429,6 +458,7 @@ class ShixunsController < ApplicationController
@choice_small_type = @shixun.small_mirror_id @choice_small_type = @shixun.small_mirror_id
@main_type = shixun_main_type @main_type = shixun_main_type
@small_type = shixun_small_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 #@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 # @shixun_main_mirror = @shixun.show_shixun_mirror
# @script_type = @shixun.script_tag.try(:script_type) || "无" # @script_type = @shixun.script_tag.try(:script_type) || "无"
@ -472,8 +502,8 @@ class ShixunsController < ApplicationController
# TODO: 目前实训只做软删除. # TODO: 目前实训只做软删除.
def destroy def destroy
# apply_records = ApplyAction.where(container_id: @shixun.id, container_type: "ApplyShixun") apply_records = ApplyAction.where(container_id: @shixun.id, container_type: "ApplyShixun")
# apply_records.delete_all if apply_records apply_records.delete_all if apply_records
# HomeworkCommonShixuns.where(shixun_id: @shixun).delete_all # HomeworkCommonShixuns.where(shixun_id: @shixun).delete_all
# @shixun.destroy # @shixun.destroy
@shixun.update_column(:status, -1) @shixun.update_column(:status, -1)
@ -484,21 +514,46 @@ class ShixunsController < ApplicationController
# 中间需要一个过渡动画 # 中间需要一个过渡动画
# TODO: 第一次开启实训都会去判断是否是纯选择题类型,感觉做成在创建关卡的时候就判断该实训是否是纯选择题更加合适 # TODO: 第一次开启实训都会去判断是否是纯选择题类型,感觉做成在创建关卡的时候就判断该实训是否是纯选择题更加合适
def shixun_exec def shixun_exec
current_myshixun = @shixun.current_myshixun(current_user.id) if is_shixun_opening?
if @shixun.opening_time.present? && @shixun.opening_time > Time.now && current_user.shixun_identity(@shixun) > User::EDU_SHIXUN_MEMBER
tip_show_exception(-3, "#{@shixun.opening_time.strftime('%Y-%m-%d %H:%M:%S')}") tip_show_exception(-3, "#{@shixun.opening_time.strftime('%Y-%m-%d %H:%M:%S')}")
end end
current_myshixun = @shixun.current_myshixun(current_user.id)
min_challenges = @shixun.challenges.pluck(:id , :st)
if current_myshixun Rails.logger.info("11111111112#{current_myshixun.try(:id)}")
# 如果TPM和TPI的管卡数不相等或者关卡顺序错了说明实训被极大的改动需要重置 Rails.logger.info("111111111102#{params[:reset] != 1}")
if current_myshixun.games.count != @shixun.challenges_count || current_myshixun.games.map(&:challenge_id).sort != Challenge.where(shixun_id: @shixun.id).pluck(:id).sort
# 因为读写分离有延迟所以如果是重置来的请求可以先跳过重置过来的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. # 这里页面弹框要收到 当前用户myshixun的identifier.
tip_show_exception("/myshixuns/#{current_myshixun.try(:identifier)}/reset_my_game") tip_show_exception("/myshixuns/#{current_myshixun.try(:identifier)}/reset_my_game")
end 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 else
# 如果未创建关卡一定不能开启实训否则TPI没法找到当前的关卡 # 如果未创建关卡一定不能开启实训否则TPI没法找到当前的关卡
if @shixun.challenges_count == 0 if @shixun.challenges_count == 0
@ -506,10 +561,10 @@ class ShixunsController < ApplicationController
end 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 if !is_choice_type
commit = GitService.commits(repo_path: @repo_path).try(:first) 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? tip_exception("开启实战前请先在版本库中提交代码") if commit.blank?
commit_id = commit["id"] commit_id = commit["id"]
end end
@ -523,6 +578,21 @@ class ShixunsController < ApplicationController
onclick_time: Time.now, commit_id: commit_id) onclick_time: Time.now, commit_id: commit_id)
uid_logger("myshixun_id is #{myshixun.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仓库以及中间层的相关操作了 # 如果实训是纯选择题则不需要去fork仓库以及中间层的相关操作了
unless is_choice_type unless is_choice_type
# fork仓库 # fork仓库
@ -534,22 +604,10 @@ class ShixunsController < ApplicationController
logger.info("end openGameInstance") logger.info("end openGameInstance")
params = {tpiID: "#{myshixun.id}", tpmGitURL:rep_url, tpiRepoName: myshixun.repo_name.split("/").last} params = {tpiID: "#{myshixun.id}", tpmGitURL:rep_url, tpiRepoName: myshixun.repo_name.split("/").last}
uid_logger("openGameInstance params is #{params}") uid_logger("openGameInstance params is #{params}")
# res = interface_post uri, params, 83, "实训云平台繁忙繁忙等级83" 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)
end end
# REDO:开启实训时更新关联作品的状态 @current_task = myshixun.current_task(myshixun.games)
HomeworksService.new.update_myshixun_work_status myshixun
@current_task = myshixun.current_task
uid_logger("## shixun exec: myshixun id is #{myshixun.id}") uid_logger("## shixun exec: myshixun id is #{myshixun.id}")
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
@ -558,10 +616,8 @@ class ShixunsController < ApplicationController
end end
end end
end end
end end
# gameID 及实训ID # gameID 及实训ID
# status: 0 , 1 申请过, 2实训关卡路径未填 3 实训标签未填, 4 实训未创建关卡 # status: 0 , 1 申请过, 2实训关卡路径未填 3 实训标签未填, 4 实训未创建关卡
def publish def publish
@ -611,16 +667,27 @@ class ShixunsController < ApplicationController
def update_file def update_file
content = params[:content] content = params[:content]
author_name = current_user.full_name 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" @content = update_file_content content, @repo_path, @path, author_email, author_name, "Edit by browser"
end end
def add_collaborators def add_collaborators
raise("搜索内容不能为空") unless params[:search] member_ids = "(" + @shixun.shixun_members.map(&:user_id).join(',') + ")"
member_ids = "(" + @shixun.shixun_members.map(&:user_id).join(',') + ")" user_name = "%#{params[:user_name].to_s.strip}%"
condition = "%#{params[:search].strip}%".gsub(" ","") school_name = "%#{params[:school_name].to_s.strip}%"
@users = User.where("id not in #{member_ids} and status = 1 and LOWER(concat(lastname, firstname, login, mail, nickname)) LIKE '#{condition}'") if user_name.present? || school_name.present?
end @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 def shixun_members_added
raise("user_ids 不能为空!") if params[:user_ids].blank? raise("user_ids 不能为空!") if params[:user_ids].blank?
@ -661,14 +728,14 @@ class ShixunsController < ApplicationController
limit = params[:limit] || 20 limit = params[:limit] || 20
if params[:search] if params[:search]
search = "%#{params[:search].to_s.strip.downcase}%" search = "%#{params[:search].to_s.strip.downcase}%"
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, members m, member_roles mr course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m
WHERE m.course_id = c.id AND m.id=mr.member_id AND mr.role_id in (3,7,9) 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 m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0
AND c.name like '#{search}' ").map(&:id) AND c.name like '#{search}' ").map(&:id)
else else
course_ids = Course.find_by_sql("SELECT c.id, c.name FROM courses c, members m, member_roles mr 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.id=mr.member_id AND mr.role_id in (3,7,9) 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) AND m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0").map(&:id)
end end
@ -680,7 +747,7 @@ class ShixunsController < ApplicationController
# 将实训发送到课程 # 将实训发送到课程
def send_to_course def send_to_course
@course = Course.find(params[:course_id]) @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 end
# 二维码扫描下载 # 二维码扫描下载
@ -693,32 +760,40 @@ class ShixunsController < ApplicationController
# 撤销发布 # 撤销发布
def cancel_publish def cancel_publish
tip_exception("实训已经发布,无法撤销") if @shixun.status == 2
apply = ApplyAction.where(:container_type => "ApplyShixun", :container_id => @shixun.id).order("created_at desc").first apply = ApplyAction.where(:container_type => "ApplyShixun", :container_id => @shixun.id).order("created_at desc").first
if apply && apply.status == 0 if apply && apply.status == 0
apply.update_attribute(:status, 3) apply.update_attribute(:status, 3)
apply.tidings.destroy_all apply.tidings.destroy_all
@shixun.update_column('status', 0)
end end
@shixun.update_column(:status, 0)
end end
private private
def shixun_params 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, 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 end
def find_shixun def find_shixun
@shixun = Shixun.find_by_identifier(params[:identifier]) @shixun = Shixun.find_by_identifier(params[:identifier])
shixun = Shixun.where(identifier: params[:identifier]).first
if @shixun.blank? if @shixun.blank?
normal_status(404, "...") normal_status(404, "...")
return return
end end
if !current_user.shixun_permission(@shixun) || (@shixun.status == -1 && !current_user.admin?)
tip_exception(403, "..")
end
end end
def find_repo_name def find_repo_name
@ -743,4 +818,20 @@ private
tip_exception(403, "..") tip_exception(403, "..")
end end
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 end

@ -1,5 +1,5 @@
class StagesController < ApplicationController class StagesController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :find_subject, only: [:create, :index] before_action :find_subject, only: [:create, :index]
before_action :find_stage, only: [:update, :destroy, :edit, :up_position, :down_position] before_action :find_stage, only: [:update, :destroy, :edit, :up_position, :down_position]
before_action :allowed, except: [:index] before_action :allowed, except: [:index]

@ -2,7 +2,7 @@ class StudentWorksController < ApplicationController
include HomeworkCommonsHelper include HomeworkCommonsHelper
include StudentWorksHelper 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, before_action :find_homework, only: [:new, :create, :search_member_list, :check_project, :relate_project,
:cancel_relate_project] :cancel_relate_project]
before_action :find_work, only: [:shixun_work_report, :adjust_review_score, :shixun_work, :commit_des, :update_des, 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 :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 def new
uid_logger("#######new current_user : 1111") uid_logger("#######new current_user : 1111")
@ -41,14 +41,16 @@ class StudentWorksController < ApplicationController
# 搜索课堂学生 # 搜索课堂学生
def search_member_list def search_member_list
unless params[:search].blank? # 统一设置的作业取所有学生,否则取已发布的分班学生
@members = @course.students.joins(:user).where("user_id != #{current_user.id} and students = @homework.unified_setting? ? @course.students : @course.students.where(course_group_id: @homework.published_settings.pluck(:course_group_id))
concat(users.lastname, users.firstname) like ?", "%#{params[:search]}%") 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 else
# 没有搜索条件时搜索课堂所有未提交的学生 # 没有搜索条件时搜索课堂所有未提交的学生
user_ids = @homework.student_works.where("work_status = 0").pluck(:user_id) - [current_user.id] 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 end
page = params[:page] ? params[:page].to_i : 1 page = params[:page] ? params[:page].to_i : 1
@ -332,8 +334,9 @@ class StudentWorksController < ApplicationController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
# 没传score则取上次评分成绩 # 没传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 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.score = params[:score].blank? ? score.try(:score) : params[:score].to_f
new_score.comment = params[:comment] if params[:comment] && params[:comment].strip != "" new_score.comment = params[:comment] if params[:comment] && params[:comment].strip != ""
new_score.user_id = current_user.id 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" @work.update_attributes(group_id: @homework.max_group_id) if @homework.homework_type == "group"
end 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! if new_score.save!
Attachment.associate_container(params[:attachment_ids], new_score.id, new_score.class) Attachment.associate_container(params[:attachment_ids], new_score.id, new_score.class)
@ -379,7 +382,7 @@ class StudentWorksController < ApplicationController
when 3 #学生评分 学生评分显示平均分 when 3 #学生评分 学生评分显示平均分
# 匿评分 # 匿评分
@work.student_score = new_score.stu_score(@work.id) @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 add_score_to_member @work, @homework, new_score
end end
@ -427,10 +430,17 @@ class StudentWorksController < ApplicationController
def shixun_work_report def shixun_work_report
@user = @work.user @user = @work.user
@shixun = @homework.shixuns.take @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) @echart_data = student_efficiency(@homework, @work)
end end
@ -438,17 +448,17 @@ class StudentWorksController < ApplicationController
def export_shixun_work_report def export_shixun_work_report
@user = @work.user @user = @work.user
@shixun = @homework.shixuns.take @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) @echart_data = student_efficiency(@homework, @work)
@myself_eff = @echart_data[:efficiency_list].find { |item| item.last == @user.id } @myself_eff = @echart_data[:efficiency_list].find { |item| item.last == @user.id }
@myself_consume = @echart_data[:consume_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) stylesheets = %w(shixun_work/shixun_work.css shared/codemirror.css)
render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets
end end
@ -580,6 +590,9 @@ class StudentWorksController < ApplicationController
score_appeal.tidings.update_all(status: 1) score_appeal.tidings.update_all(status: 1)
if params[:status].to_i == 3 if params[:status].to_i == 3
# 申诉成功后该评分失效
score.update_attributes(is_invalid: 1)
# 申诉成功后 扣匿评学生的违规匿评扣分 # 申诉成功后 扣匿评学生的违规匿评扣分
sw = @homework.student_works.find_by(user_id: score.user_id) 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? 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 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不能为空") 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 end
copy_user = User.find params[:copy_user_id] challenge_setting = @homework.homework_challenge_settings.find_by(challenge_id: params[:challenge_id])
comment = "代码查重结果显示与#{copy_user.try(:show_real_name)}的代码相似度#{params[:code_rate]}%" challenge = challenge_setting&.challenge
@work.challenge_work_scores.create(challenge_id: params[:challenge_id], user_id: current_user.id, score: params[:score], tip_exception("不能小于零") if params[:score] < 0
comment: comment) tip_exception("不能大于关卡分值:#{challenge_setting.score}") if challenge_setting.score < params[:score]
HomeworksService.new.set_shixun_final_score(@work)
@work_score = @homework.student_works.find_by(id: @work.id).try(:work_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
end end
@ -692,6 +724,11 @@ class StudentWorksController < ApplicationController
[3, 4].include?(@homework.homework_detail_manual.comment_status) [3, 4].include?(@homework.homework_detail_manual.comment_status)
end 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 def allow_add_score
# 老师始终有评阅权限,匿评阶段内,学生对分配给该学生的作品有评阅权限 # 老师始终有评阅权限,匿评阶段内,学生对分配给该学生的作品有评阅权限
tip_exception(403, "没有权限") unless allow_score(@homework, @user_course_identity, current_user.id, @work) 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| student_works.each do |st_work|
st_score = StudentWorksScore.new(user_id: new_score.user_id, score: new_score.score, st_score = StudentWorksScore.new(user_id: new_score.user_id, score: new_score.score,
reviewer_role: new_score.reviewer_role, comment: new_score.comment) 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? 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 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 elsif new_score.reviewer_role == 2
if homework.homework_detail_manual.ta_mode == 1 if homework.homework_detail_manual.ta_mode == 1
st_work.teaching_asistant_score = new_score.ta_score st_work.id st_work.teaching_asistant_score = new_score.ta_score st_work.id
else else
st_work.teaching_asistant_score = new_score.score st_work.teaching_asistant_score = new_score.score if new_score.score.present?
end end
else else
st_work.student_score = student_work.student_score st_work.student_score = student_work.student_score

@ -1,5 +1,5 @@
class SubjectsController < ApplicationController 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 :check_auth, except: [:index]
before_action :find_subject, except: [:index, :create, :append_to_stage] before_action :find_subject, except: [:index, :create, :append_to_stage]
before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish, 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 reorder == "myshixun_count"
if select if select
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_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 subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
WHERE myshixuns.shixun_id = stage_shixuns.shixun_id AND stage_shixuns.subject_id = subjects.id on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
AND `subjects`.`hidden` = 0 AND `subjects`.`status` = 2 AND `subjects`.`name` like '%#{search}%' 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") AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_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 subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
WHERE myshixuns.shixun_id = stage_shixuns.shixun_id AND stage_shixuns.subject_id = subjects.id on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
AND `subjects`.`hidden` = 0 AND `subjects`.`status` = 2 AND `subjects`.`name` like '%#{search}%' subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
GROUP BY subjects.id ORDER BY myshixun_member_count DESC") GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
end end
else else
# 我的路径 # 我的路径
if reorder == "mine" 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 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) (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) manage_subject_id = SubjectMember.where(user_id: current_user.id).pluck(:subject_id)
@ -65,9 +67,12 @@ class SubjectsController < ApplicationController
@total_count = @subjects.size @total_count = @subjects.size
if reorder != "myshixun_count" if reorder != "myshixun_count"
@subjects = @subjects.page(page).per(limit).includes(:shixuns) @subjects = @subjects.page(page).per(limit).includes(:shixuns, :repertoire)
else else
@subjects = @subjects[offset, limit] @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
end end
@ -81,6 +86,9 @@ class SubjectsController < ApplicationController
@tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq @tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq
# 用户获取的实训标签 # 用户获取的实训标签
@user_tags = @subject.shixuns.map(&:user_tags_name).flatten.uniq @user_tags = @subject.shixuns.map(&:user_tags_name).flatten.uniq
# 访问数变更
@subject.increment!(:visits)
end end
def create def create
@ -131,7 +139,7 @@ class SubjectsController < ApplicationController
if current_user.admin? if current_user.admin?
@shixuns = Shixun.select([:id, :name, :status, :myshixuns_count, :identifier]).where(hidden: 0) @shixuns = Shixun.select([:id, :name, :status, :myshixuns_count, :identifier]).where(hidden: 0)
else 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) @shixuns = Shixun.select([:id, :name, :status, :myshixuns_count, :identifier]).where.not(id: none_shixun_ids).where(hidden: 0)
end end
@ -164,11 +172,11 @@ class SubjectsController < ApplicationController
end end
def choose_course def choose_course
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, members m, member_roles mr course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m
WHERE m.course_id = c.id AND m.id=mr.member_id AND mr.role_id in (3,7,9) 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) 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) @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 end
def send_to_course def send_to_course

@ -1,4 +1,5 @@
class TrialAppliesController < ApplicationController class TrialAppliesController < ApplicationController
before_action :require_user_login
def create def create
Users::ApplyTrailService.call(current_user, create_params) Users::ApplyTrailService.call(current_user, create_params)
@ -12,4 +13,10 @@ class TrialAppliesController < ApplicationController
def create_params def create_params
params.permit(:phone, :code, :reason).merge(remote_ip: request.remote_ip) params.permit(:phone, :code, :reason).merge(remote_ip: request.remote_ip)
end end
def require_user_login
return if User.current.logged?
render_unauthorized
end
end end

@ -1,4 +1,4 @@
class Users::AccountsController < Users::BaseController class Users::AccountsController < Users::BaseAccountController
before_action :private_user_resources! before_action :private_user_resources!
def show def show

@ -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

@ -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

@ -28,6 +28,6 @@ class Users::AvatarsController < Users::BaseAccountController
end end
def avatar_url 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
end end

@ -4,4 +4,5 @@ class Users::BaseAccountController < Users::BaseController
def observed_user def observed_user
@_observed_user ||= (User.find_by_id(params[:account_id]) || User.find_by_login(params[:account_id])) @_observed_user ||= (User.find_by_id(params[:account_id]) || User.find_by_login(params[:account_id]))
end end
end end

@ -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

@ -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

@ -4,6 +4,10 @@ class Users::ShixunsController < Users::BaseController
@count = shixuns.count @count = shixuns.count
@shixuns = paginate(shixuns.includes(:first_tag_repertoire), special: true) @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 end
private private

@ -1,5 +1,5 @@
class Users::WatchesController < Users::BaseController class Users::WatchesController < Users::BaseController
before_action :require_login before_action :require_login, :check_auth
def create def create
if observed_logged_user? if observed_logged_user?

@ -9,10 +9,6 @@ class UsersController < ApplicationController
@user = User.find params[:id] @user = User.find params[:id]
@user.update!(user_params) @user.update!(user_params)
render_ok render_ok
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end end
# 贴吧获取用户信接口 # 贴吧获取用户信接口
@ -41,6 +37,7 @@ class UsersController < ApplicationController
end end
@course_identity = current_user.course_identity(@course) if @course @course_identity = current_user.course_identity(@course) if @course
rescue Exception => e rescue Exception => e
uid_logger_error(e.message)
missing_template missing_template
end end
@ -54,6 +51,13 @@ class UsersController < ApplicationController
:disposition => 'attachment' #inline can open in browser :disposition => 'attachment' #inline can open in browser
end end
def html_show
@contents = File.read("#{params[:path]}")
respond_to do |format|
format.html {render :layout => false}
end
end
# Redo: 消息总数缓存 # Redo: 消息总数缓存
def get_navigation_info def get_navigation_info
@old_domain = edu_setting('old_edu_host') @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 @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) @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
ec_user = EcSchoolUser.where(:user_id => current_user.id).first ec_user = EcSchoolUser.where(:user_id => current_user.id).first
@auth = ec_user ? "#{@old_domain}/ecs/department?school_id=#{ec_user.school_id}" : nil @auth = ec_user ? "#{@old_domain}/ecs/department?school_id=#{ec_user.school_id}" : nil
@ -69,21 +73,24 @@ class UsersController < ApplicationController
# 用户回复功能 # 用户回复功能
def reply_message def reply_message
@message = JournalsForMessage.new(reply_message_params) message = JournalsForMessage.new(reply_message_params)
@message.user_id = current_user.id message.user_id = current_user.id
@message.save! message.save!
#normal_status("回复成功")
render_ok(id: message.id)
end end
# 搜索用户具有管理员角色的项目 # 搜索用户具有管理员角色的项目
def search_user_projects def search_user_projects
condition = '%%' projects = Project.where.not(status: 9)
condition = "%#{params[:search].strip}%".gsub(" ","") if !params[:search].blank?
project_ids = Project.find_by_sql("SELECT p.id FROM projects p, members m, member_roles mr WHERE m.project_id = p.id projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
AND m.id=mr.member_id AND mr.role_id = 3 AND m.user_id=#{current_user.id} AND p.status != 9 and projects = projects.where(members: { user_id: current_user.id })
p.name like '#{condition}'")
@projects = Project.where(id: project_ids.pluck(:id)) search = params[:search].to_s.strip
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
@projects = projects.select(:id, :name)
end end
# 个人主页信息 # 个人主页信息
@ -91,10 +98,6 @@ class UsersController < ApplicationController
def brief_introduction def brief_introduction
content = params[:content].to_s.strip content = params[:content].to_s.strip
if content.blank?
render_error('内容不能为空')
return
end
current_user.user_extension.update!(brief_introduction: content) current_user.user_extension.update!(brief_introduction: content)

@ -1,26 +1,24 @@
class ZipsController < ApplicationController class ZipsController < ApplicationController
before_action :require_login before_action :require_login, :check_auth
before_action :load_homework, only: [:shixun_report] before_action :load_homework, only: [:shixun_report]
before_action :get_exercise, only: [:export_exercises] before_action :get_exercise, only: [:export_exercises]
before_action :require_admin_or_teacher before_action :require_admin_or_teacher
def shixun_report def shixun_report
student_work_ids = Array.wrap(params[:student_work_ids]) service = BatchExportShixunReportService.new(@homework, @all_student_works)
filename_ = filename_for_content_disposition(service.filename)
service = BatchExportShixunReportService.new(@homework, student_work_ids) send_file service.zip, filename: filename_, type: 'application/zip'
filename = filename_for_content_disposition(service.filename)
send_file service.zip, filename: filename, type: 'application/zip'
rescue BatchExportShixunReportService::Error => ex rescue BatchExportShixunReportService::Error => ex
normal_status(-1, ex.message) normal_status(-1, ex.message)
end end
def export_exercises 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) file_name_ = filename_for_content_disposition(exercises.filename)
send_file exercises.ex_zip, filename: file_name, type: 'application/zip' send_file exercises.ex_zip, filename: file_name_, type: 'application/zip'
rescue Exception => e rescue Exception => e
normal_status(-1, e.message) normal_status(-1, e.message)
end end
@ -39,27 +37,53 @@ class ZipsController < ApplicationController
def get_exercise def get_exercise
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin 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] group_id = params[:exercise_group_id]
if @exercise.blank? if @exercise.blank?
normal_status(-1,"试卷不存在") normal_status(-1,"试卷不存在")
elsif @exercise_status == 1
normal_status(-1,"试卷未发布")
else else
@course = @exercise.course @course = @exercise.course
default_ex_users = @exercise.all_exercise_users(current_user.id).exercise_user_committed 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 #仅导出已提交的,截止后则是全部为提交的。 @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? if group_id.present?
exercise_students = @course.students.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数 exercise_students = @course.students.where(course_group_id: group_id) # 试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?) user_ids = exercise_students.pluck(:user_id).reject(&:blank?).uniq
@ex_users = @ex_users.exercise_commit_users(user_ids) @ex_users = @ex_users.where(user_id: user_ids)
end end
# @ex_users = @ex_users.first(200)
if default_ex_users_size == 0 #搜索
normal_status(-1,"导出失败,暂时没有已提交的学生") if params[:search].present?
elsif default_ex_users_size > 200 @ex_users = @ex_users.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
normal_status(-1,"导出数量超过200,请分班导出或联系网站管理员导出") 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
end end
rescue Exception => e rescue Exception => e
@ -71,6 +95,40 @@ class ZipsController < ApplicationController
def load_homework def load_homework
@homework = HomeworkCommon.find(params[:homework_common_id]) @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
end end

@ -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

@ -0,0 +1,6 @@
module CompetitionDecorator
extend ApplicationDecorator
display_time_method :start_time, :end_time, :enroll_end_time
end

@ -0,0 +1,5 @@
module CompetitionStageSectionDecorator
extend ApplicationDecorator
display_time_method :start_time, :end_time
end

@ -1,8 +1,4 @@
module ShixunDecorator 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 def human_status
I18n.t("shixun.status.#{status}") I18n.t("shixun.status.#{status}")
end end

@ -12,48 +12,6 @@ module UserDecorator
logged_user? ? real_name : full_name logged_user? ? real_name : full_name
end 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 def authentication_status
if authentication? if authentication?
@ -74,16 +32,4 @@ module UserDecorator
'uncertified' 'uncertified'
end end
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 end

@ -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

@ -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

@ -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

@ -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

@ -10,9 +10,9 @@ class Users::UpdateAccountForm
validates :gender, presence: true, numericality: { only_integer: true }, inclusion: { in: [0, 1] } validates :gender, presence: true, numericality: { only_integer: true }, inclusion: { in: [0, 1] }
validates :location, presence: true validates :location, presence: true
validates :location_city, presence: true validates :location_city, presence: true
validates :identity, presence: true, numericality: { only_integer: true }, inclusion: { in: [0, 1, 2] } validates :identity, presence: true, inclusion: { in: %w[teacher student professional ] }
validates :technical_title, presence: true, unless: -> { identity == 1 } validates :technical_title, presence: true, unless: -> { identity.to_s == 'student' }
validates :student_id, presence: true, if: -> { identity == 1 } validates :student_id, presence: true, if: -> { identity.to_s == 'student' }
validates :school_id, presence: true validates :school_id, presence: true
validate :check_school_exist validate :check_school_exist

@ -1,6 +1,7 @@
# 所有的方法请按首字母的顺序依次列出 # 所有的方法请按首字母的顺序依次列出
module ApplicationHelper module ApplicationHelper
include Educoder::I18n include Educoder::I18n
include GitHelper
ONE_MINUTE = 60 * 1000 ONE_MINUTE = 60 * 1000
ONE_HOUR = 60 * ONE_MINUTE ONE_HOUR = 60 * ONE_MINUTE
@ -11,7 +12,7 @@ module ApplicationHelper
# 全局参数配置 # 全局参数配置
def edu_setting name def edu_setting name
EduSetting.find_by_name(name).try(:value) EduSetting.get(name)
end end
def graduation_navigation graduation def graduation_navigation graduation
@ -29,8 +30,9 @@ module ApplicationHelper
end end
# git用户 # git用户
# git用户命名规则login+"@educoder.net"
def git_username(email) def git_username(email)
User.find_by_mail(email) User.find_by_mail(email) || User.find_by_login(email.split("@").first)
end end
# 不同的类型扩展不同的目录 # 不同的类型扩展不同的目录
@ -109,7 +111,7 @@ module ApplicationHelper
# 计算到结束还有多长时间 **天**小时**分 # 计算到结束还有多长时间 **天**小时**分
def how_much_time(time) def how_much_time(time)
if time.nil? if time.nil? || time < Time.now #6.21 -hs 增加小于time.now
'' ''
else else
result = ((time - Time.now.to_i).to_i / (24*60*60)).to_s + "" 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' if source.class.to_s == 'User'
File.join(relative_path, ["#{source.class}", "#{source.id}"]) File.join(relative_path, ["#{source.class}", "#{source.id}"])
else else
File.join("/images/avatars", ["#{source.class}", "#{source.id}"]) File.join("images/avatars", ["#{source.class}", "#{source.id}"])
end end
elsif source.class.to_s == 'User' elsif source.class.to_s == 'User'
str = source.user_extension.try(:gender).to_i == 0 ? "b" : "g" 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}") File.join(storage_path, "#{source_type}", "#{source_id}")
end 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) def shixun_url_to_avatar(shixun)
if File.exist?(disk_filename(shixun.class, shixun.id)) 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 else
File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg") File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg")
end end
@ -332,6 +346,24 @@ module ApplicationHelper
raw arr.join('') raw arr.join('')
end 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 end

@ -232,7 +232,7 @@ module CoursesHelper
course.course_groups.includes(:course_members) course.course_groups.includes(:course_members)
end end
group_info = [] group_info = []
if course_groups.count > 0 if !course_groups.blank?
course_groups.each do |group| course_groups.each do |group|
group_info << {course_group_id: group.id, group_group_name: group.name, count: group.course_members_count} group_info << {course_group_id: group.id, group_group_name: group.name, count: group.course_members_count}
end end
@ -246,15 +246,18 @@ module CoursesHelper
def left_group_info course def left_group_info course
group_info = [] group_info = []
course.course_groups.each do |course_group| if course.course_groups_count > 0
group_info << {category_id: course_group.id, category_name: course_group.name, position: course_group.position, none_group_count = course.students.where(course_group_id: 0).size
category_count: course_group.course_members_count, category_type: false, group_info << {category_id: 0, category_name: "未分班", position: course.course_groups.pluck(:position).max.to_i + 1,
second_category_url: "/courses/#{@course.id}/course_groups/#{course_group.id}"} 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 end
none_group_count = course.students.where(course_group_id: 0).size group_info
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"}
end end
end end

@ -32,7 +32,7 @@ module ExerciseQuestionsHelper
def shixun_game_scores(challenge,ex_answerer,shixun_type,question_id) def shixun_game_scores(challenge,ex_answerer,shixun_type,question_id)
game_score = challenge.question_score 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? #试卷已截止,用户才可以查看答案 if shixun_type == 2 && game_answers.present? #试卷已截止,用户才可以查看答案
s_score = game_answers.first.score s_score = game_answers.first.score
else else

@ -1,19 +1,42 @@
module ExercisesHelper module ExercisesHelper
# include GitHelper
#获取每个学生对每个题的答案状态 #获取每个学生对每个题的答案状态
def get_each_student_exercise(exercise_id,exercise_questions,user_id) 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 exercise_obj_status = exercise_questions.find_objective_questions
@ex_obj_array = [] @ex_obj_array = []
exercise_obj_status.each do |q| exercise_obj_status.each do |q|
if q.question_type == 5 q_type = q.question_type
ques_score = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id).pluck(:score).sum if q_type == Exercise::PRACTICAL
answers_content = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id)
else 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 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 stand_answer = 1
elsif ques_score > 0.0 #部分作答 elsif ques_score > 0.0 #部分作答
stand_answer = 2 stand_answer = 2
@ -30,21 +53,21 @@ module ExercisesHelper
} }
@ex_obj_array.push(ques_option) @ex_obj_array.push(ques_option)
end 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 = [] #主观题的已答/未答 @ex_sub_array = [] #主观题的已答/未答
exercise_sub_status.each do |s| exercise_sub_status.each do |s|
sub_answer = s.exercise_answers.search_answer_users("user_id",user_id) #主观题只有一个回答 sub_answer = s.exercise_answers.search_answer_users("user_id",user_id) #主观题只有一个回答
if sub_answer.present? && sub_answer.first.score >= 0.0 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 stand_status = 1
else else
stand_status = 2 stand_status = 2
end end
# stand_status = 1
sub_answer_score = sub_answer.first.score sub_answer_score = sub_answer.first.score
else else
stand_status = 0 stand_status = 0
sub_answer_score = 0.0 sub_answer_score = nil
end end
sub_score = { sub_score = {
@ -52,65 +75,87 @@ module ExercisesHelper
"q_type":s.question_type, "q_type":s.question_type,
"q_position":s.question_number, "q_position":s.question_number,
"stand_status":stand_status, "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) @ex_sub_array.push(sub_score)
end end
@ex_obj_array.sort_by {|k| k[:q_position]} @ex_obj_array = @ex_obj_array.sort_by {|k| k[:q_position]}
@ex_sub_array.sort_by {|k| k[:q_position]} @ex_sub_array = @ex_sub_array.sort_by {|k| k[:q_position]}
end end
#试卷的统计结果页面计算各题的 #试卷的统计结果页面计算各题的
def exercise_commit_result(questions,user_ids) def exercise_commit_result(questions,user_ids)
question_infos = [] question_infos = []
questions.each do |ex| percent = 0.0
ex_total_score = user_ids.count * ex&.question_score #该试卷的已回答的总分 questions.includes(:exercise_choices).each do |ex|
ex_answers = ex.exercise_answers ex_total_score = user_ids.count * ex&.question_score.to_f #该试卷的已回答的总分
if ex.question_type != 5 # ex_answers = ex.exercise_answers
if ex.question_type != Exercise::PRACTICAL
ques_title = ex.question_title ques_title = ex.question_title
ques_less_title = nil ques_less_title = nil
ex_answers = ex.exercise_answers
effictive_users = ex_answers.search_answer_users("user_id",user_ids) effictive_users = ex_answers.search_answer_users("user_id",user_ids)
else else
ques_title = ex.shixun.name ques_title = ex.shixun.name
ques_less_title = ex.question_title 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 end
effictive_users_count = effictive_users.count #有效回答数可能有重复的用户id这里仅统计是否回答这个问题的全部人数
ex_answered_scores = effictive_users.score_reviewed.pluck(:score).sum #该问题的全部得分 effictive_users_count = effictive_users.size #有效回答数可能有重复的用户id这里仅统计是否回答这个问题的全部人数
if ex_total_score == 0.0
percent = 0.0 if ex.question_type > Exercise::COMPLETION #当为主观题和实训题时,
else ex_answered_scores = effictive_users.score_reviewed.pluck(:score).sum #该问题的全部得分
percent = (ex_answered_scores / ex_total_score.to_f).round(3) * 100 #正确率 percent = (ex_total_score == 0.0 ? 0.0 : (ex_answered_scores / ex_total_score.to_f).round(3) * 100) #正确率
end end
question_answer_infos = [] question_answer_infos = []
if ex.question_type <= 2 #单选题 if ex.question_type <= Exercise::JUDGMENT #选择题和判断题
standard_answer = ex.exercise_standard_answers.pluck(:exercise_choice_id) #标准答案的位置 ex_choices = ex.exercise_choices
ex.exercise_choices.each do |c| standard_answer = ex.exercise_standard_answers.pluck(:exercise_choice_id).sort #标准答案的位置
if standard_answer.include?(c.choice_position) #选项的标准答案为选项的位置 right_users_count = 0
right_answer = true #该问题的正确率
else if ex.question_type == Exercise::MULTIPLE #多选题
right_answer = false right_user_ids = user_ids
end standard_answer.each do |choice_position|
answer_this_choice = effictive_users.search_exercise_answer("exercise_choice_id",c.id) standard_answer_choice_id = ex_choices.select{|ec| ec.choice_position == choice_position}.first&.id
answer_users_count = answer_this_choice.count right_user_ids = right_user_ids & effictive_users.select{|answer| answer.exercise_choice_id == standard_answer_choice_id}.pluck(:user_id)
if effictive_users_count == 0
answer_percent = 0.0
else
answer_percent = (answer_users_count / effictive_users_count.to_f ).round(3)
end 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 = { answer_option = {
:choice_position => c.choice_position, :choice_position => c.choice_position,
:choice_text => c.choice_text, :choice_text => c.choice_text,
:choice_users_count => answer_users_count, :choice_users_count => answer_users_count,
:choice_percent => answer_percent.round(1), :choice_percent => answer_percent.round(1).to_s,
:right_answer => right_answer :right_answer => right_answer
} }
question_answer_infos.push(answer_option) question_answer_infos.push(answer_option)
end end
elsif ex.question_type == 3 #填空题 elsif ex.question_type == Exercise::COMPLETION #填空题
ex_ordered = ex.is_ordered ex_ordered = ex.is_ordered
null_standard_answer = ex.exercise_standard_answers 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) null_stand_text = null_standard_answer.pluck(:answer_text)
standard_answer_count = 0 standard_answer_count = 0
all_user_count = 0 all_user_count = 0
@ -118,33 +163,24 @@ module ExercisesHelper
user_count = 0 user_count = 0
s_choice_text = null_stand_text[index] s_choice_text = null_stand_text[index]
if ex_ordered #有序排列 if ex_ordered #有序排列
user_ids.each do |u| user_count = user_count + effictive_users.select{|answer| answer.exercise_choice_id == s && answer.answer_text == s_choice_text}.size
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
else else
user_count = user_count + effictive_users.search_exercise_answer("answer_text",s_choice_text).count #回答了标准答案的用户 user_count = user_count + effictive_users.select{|answer| answer.answer_text == s_choice_text }.size #回答了标准答案的用户
end
if effictive_users_count == 0
answer_percent = 0.0
else
answer_percent = (user_count / effictive_users_count.to_f ).round(3)
end end
answer_percent = ((effictive_users_count == 0) ? 0.0 : (user_count / effictive_users_count.to_f ).round(3))
answer_option = { answer_option = {
:choice_position => index+1, :choice_position => index+1,
:choice_text => s_choice_text, :choice_text => s_choice_text,
:choice_users_count => user_count, :choice_users_count => user_count,
:choice_percent => answer_percent.round(1), :choice_percent => answer_percent.round(1).to_s,
:right_answer => true :right_answer => true
} }
question_answer_infos.push(answer_option) question_answer_infos.push(answer_option)
all_user_count += user_count all_user_count += user_count
standard_answer_count += 1 standard_answer_count += 1
end 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 ) user_wrong_count = (effictive_users_count - all_user_count )
if effictive_users_count > 0 && user_wrong_count >= 0 if effictive_users_count > 0 && user_wrong_count >= 0
@ -156,25 +192,22 @@ module ExercisesHelper
:choice_position => (standard_answer_count + 1), :choice_position => (standard_answer_count + 1),
:choice_text => "wrong", :choice_text => "wrong",
:choice_users_count => user_wrong_count, :choice_users_count => user_wrong_count,
:choice_percent => wrong_percent.round(1), :choice_percent => wrong_percent.round(1).to_s,
:right_answer => false :right_answer => false
} }
question_answer_infos.push(wrong_answer_position) question_answer_infos.push(wrong_answer_position)
elsif ex.question_type == 4 #主观题 elsif ex.question_type == Exercise::SUBJECTIVE #主观题
ex_score = ex&.question_score ex_score = ex&.question_score
full_scores = effictive_users.search_exercise_answer("score",ex_score).count #满分人数 full_scores = effictive_users.search_exercise_answer("score",ex_score).size #满分人数
no_full_scores = effictive_users.exercise_no_full_scores(ex_score).count #部分分数人数 no_full_scores = effictive_users.exercise_no_full_scores(ex_score).size #部分分数人数
all_zero_scores = effictive_users.search_exercise_answer("score",0.0).count #包含为0分的及未评阅的 zero_scores = effictive_users.search_exercise_answer("score",0.0).size #包含为0分的及未评阅的
review_scores = ex.exercise_answer_comments.count #主观题的评阅数量 un_review_scores = effictive_users_count - full_scores - no_full_scores - zero_scores #未评阅数
un_review_scores = effictive_users_count - review_scores #未评阅数 if un_review_scores < 0
zero_scores = all_zero_scores - 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 = [full_scores,no_full_scores,zero_scores,un_review_scores]
main_scores_array.each_with_index do |s,index| main_scores_array.each_with_index do |s,index|
if index == 0 right_answer = (index == 0)
right_answer = true
else
right_answer = false
end
if effictive_users_count == 0 || s < 0 if effictive_users_count == 0 || s < 0
s = 0 s = 0
score_percent = 0.0 score_percent = 0.0
@ -185,37 +218,33 @@ module ExercisesHelper
:choice_position => index+1, :choice_position => index+1,
:choice_text => index+1, :choice_text => index+1,
:choice_users_count => s, :choice_users_count => s,
:choice_percent => score_percent.round(1), :choice_percent => score_percent.round(1).to_s,
:right_answer => right_answer :right_answer => right_answer
} }
question_answer_infos.push(answer_option) question_answer_infos.push(answer_option)
end end
elsif ex.question_type == 5 #实训题 elsif ex.question_type == Exercise::PRACTICAL #实训题
ex.exercise_shixun_challenges.each do |c| ex.exercise_shixun_challenges.each do |c|
cha_score = c&.question_score cha_score = c&.question_score
cha_shixun_answer = effictive_users.search_shixun_keys("exercise_shixun_challenge_id",c.id) cha_shixun_answer = effictive_users.search_shixun_keys("exercise_shixun_challenge_id",c.id)
effictive_users_count = cha_shixun_answer.count #实训题的每个关卡的有效填写量 effictive_users_count = cha_shixun_answer.size #实训题的每个关卡的有效填写量
full_scores = cha_shixun_answer.search_shixun_keys("score",cha_score).count #满分人数 full_scores = cha_shixun_answer.search_shixun_keys("score",cha_score).size #满分人数
no_full_scores = cha_shixun_answer.shixun_no_full_scores(cha_score).count #部分分数人数c 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).count #满分人数 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_score_array = [full_scores,no_full_scores,all_zero_scores]
shixun_chas = [] shixun_chas = []
shixun_score_array.each_with_index do |s,index| shixun_score_array.each_with_index do |s,index|
if index == 0 right_answer = (index == 0)
right_answer = true score_percent = (effictive_users_count == 0 ? 0.0 : (s.to_i / effictive_users_count.to_f ).round(3))
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
answer_option = { answer_option = {
:choice_position => index+1, :choice_position => index+1,
:choice_text => index+1, :choice_text => index+1,
:choice_users_count => s, :choice_users_count => s,
:choice_percent => score_percent.round(1), :choice_percent => score_percent.round(1).to_s,
:right_answer => right_answer :right_answer => right_answer
} }
shixun_chas.push(answer_option) shixun_chas.push(answer_option)
@ -224,7 +253,8 @@ module ExercisesHelper
:cha_id => c.challenge_id, :cha_id => c.challenge_id,
:cha_name => c.challenge.subject, :cha_name => c.challenge.subject,
:cha_position => c.position, :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) question_answer_infos.push(shixun_new_chas)
end end
@ -244,16 +274,18 @@ module ExercisesHelper
end end
#获取试卷的已答/未答人数 #获取试卷的已答/未答人数
def get_exercise_answers(ex_users) def get_exercise_answers(ex_users, status)
@commit_ex_users = ex_users.commit_exercise_by_status(1) #当前老师的全部学生中已提交的 @exercise_answers = 0
@exercise_unanswers = 0
@exercise_answers = @commit_ex_users.present? ? @commit_ex_users.size : 0 #表示已经提交了的用户 unless status == Exercise::UNPUBLISHED
course_all_members_count = ex_users.present? ? ex_users.size : 0 @exercise_answers = ex_users.commit_exercise_by_status(1).size #表示已经提交了的用户
@exercise_unanswers = (course_all_members_count - @exercise_answers) course_all_members_count = ex_users.size
@exercise_unanswers = (course_all_members_count - @exercise_answers)
end
end end
def exercise_index_show(exercise,course,is_teacher_or,user) def exercise_index_show(exercise,course,is_teacher_or,user)
# exercise_all_users = exercise.exercise_users # lock_icon 0出现锁1不出现锁
ex_show_text = [] ex_show_text = []
if course.is_end #课堂停止后,试卷显示为已结束 if course.is_end #课堂停止后,试卷显示为已结束
@ -261,7 +293,7 @@ module ExercisesHelper
elsif is_teacher_or == 1 #当前为老师的时候,显示的是老师身份的对应试卷的状态,因为该试卷,可能对应老师的多个分班 elsif is_teacher_or == 1 #当前为老师的时候,显示的是老师身份的对应试卷的状态,因为该试卷,可能对应老师的多个分班
exercise_status = exercise.exercise_status exercise_status = exercise.exercise_status
else else
exercise_status = exercise.get_exercise_status(user.id) #当前用户查看的试卷的发布状态 exercise_status = exercise.get_exercise_status(user) #当前用户查看的试卷的发布状态
end end
case exercise_status case exercise_status
@ -274,15 +306,16 @@ module ExercisesHelper
else else
ex_show_text ex_show_text
end end
if is_teacher_or == 1 if is_teacher_or == 1
exercise_users_list = exercise.all_exercise_users(user.id) #当前老师所在班级的全部学生 exercise_users_list = exercise.all_exercise_users(user.id) #当前老师所在班级的全部学生
unreview_count = exercise_users_list.exercise_unreview.size unreview_count = exercise_status == 1 ? 0 : exercise_users_list.exercise_unreview.size
get_exercise_answers(exercise_users_list) get_exercise_answers(exercise_users_list, exercise_status)
ex_pb_time = exercise.get_exercise_times(user.id,true) ex_pb_time = exercise.get_exercise_times(user.id,true)
exercise_publish_time = ex_pb_time[:publish_time] exercise_publish_time = ex_pb_time[:publish_time]
exercise_end_time = ex_pb_time[:end_time] exercise_end_time = ex_pb_time[:end_time]
current_status = 3 current_status = 3
lock_icon = 1 #不显示锁图标 lock_icon = 0
if exercise_status == 1 if exercise_status == 1
ex_show_text.push("未发布") ex_show_text.push("未发布")
elsif exercise_status == 3 elsif exercise_status == 3
@ -290,34 +323,38 @@ module ExercisesHelper
end end
elsif is_teacher_or == 2 elsif is_teacher_or == 2
exercise_users_list = exercise.get_stu_exercise_users exercise_users_list = exercise.get_stu_exercise_users
get_exercise_answers(exercise_users_list) # 未答和已答的 get_exercise_answers(exercise_users_list, exercise_status) # 未答和已答的
unreview_count = exercise_users_list.exercise_unreview.size unreview_count = exercise_status == 1 ? 0 : exercise_users_list.exercise_unreview.size
ex_pb_time = exercise.get_exercise_times(user.id,false) ex_pb_time = exercise.get_exercise_times(user.id,false)
exercise_publish_time = ex_pb_time[:publish_time] exercise_publish_time = ex_pb_time[:publish_time]
exercise_end_time = ex_pb_time[:end_time] exercise_end_time = ex_pb_time[:end_time]
current_status = exercise.check_user_answer_status(user) current_status = exercise.check_user_answer_status(user)
lock_icon = 1 #不显示锁图标 lock_icon = 0
if current_status == 4 if current_status == 4
ex_show_text.push("未提交") ex_show_text.push("未提交")
end end
else else
exercise_users_list = exercise.get_stu_exercise_users 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_publish_time = exercise.publish_time
exercise_end_time = exercise.end_time exercise_end_time = exercise.end_time
unreview_count = nil unreview_count = nil
if exercise.is_public if exercise.is_public
current_status = exercise.check_user_answer_status(user) current_status = exercise.check_user_answer_status(user)
lock_icon = 1 #非课堂成员,但是试卷为公开的,不加 lock_icon = 1 #不出现
if current_status == 4 if current_status == 4
ex_show_text.push("未提交") ex_show_text.push("未提交")
end end
else else
current_status = 4 current_status = 4
lock_icon = 0 #显示锁图标 lock_icon = 0
end end
end end
if (course.is_public == 1) && exercise.is_public
lock_icon = 1
end
if exercise_status > 1 if exercise_status > 1
show_unreview_count = unreview_count show_unreview_count = unreview_count
else else
@ -326,9 +363,7 @@ module ExercisesHelper
if exercise_status == 2 && exercise_end_time.present? if exercise_status == 2 && exercise_end_time.present?
ex_left_time = how_much_time(exercise_end_time) ex_left_time = how_much_time(exercise_end_time)
elsif exercise_status == 3 && course.end_date.present? else #已截止后不显示时间
ex_left_time = how_much_time(course.end_date.to_time)
else
ex_left_time = nil ex_left_time = nil
end end
@ -352,109 +387,144 @@ module ExercisesHelper
score2 = 0.0 #填空题 score2 = 0.0 #填空题
score5 = 0.0 #实训题 score5 = 0.0 #实训题
ques_stand = [] #问题是否正确 ques_stand = [] #问题是否正确
exercise_questions = exercise.exercise_questions exercise_questions = exercise.exercise_questions.includes(:exercise_answers,:exercise_shixun_answers,:exercise_standard_answers,:exercise_shixun_challenges)
exercise_questions.each do |q| exercise_questions&.each do |q|
if q.question_type != 5 begin
answers_content = q.exercise_answers.search_answer_users("user_id",user.id) #学生的答案 if q.question_type != 5
else answers_content = q.exercise_answers.where(user_id: user.id) #学生的答案
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 else
each_standard_score = 0.0 answers_content = q.exercise_shixun_answers.where(user_id: user.id) #学生的答案
end end
if q.is_ordered if q.question_type <= 2 #为选择题或判断题时
answers_content.each do |u| if answers_content.present? #学生有回答时
i_standard_answer = standard_answer_array.where(exercise_choice_id:u.exercise_choice_id).pluck(:answer_text).reject(&:blank?).map!(&:downcase) #该选项的全部标准答案 answer_choice_array = []
if i_standard_answer.include?(u.answer_text.downcase) #该空的标准答案包含用户的答案才有分数 answers_content.each do |a|
u.update_attribute("score",each_standard_score) answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
score2 = score2 + each_standard_score
end end
end user_answer_content = answer_choice_array.sort
else standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
st_answer_text = standard_answer_array.pluck(:answer_text).reject(&:blank?).map!(&:downcase) if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
answers_content.each do |u| if standard_answer.size > 0
u_answer_text = u.answer_text.downcase q_score_1 = q.question_score
if st_answer_text.include?(u_answer_text) #只要标准答案包含用户的答案,就有分数。同时,下一次循环时,就会删除该标准答案。防止用户的相同答案获分 # q_score_1 = (q.question_score.to_f / standard_answer.count) #当多选答案正确时每个answer的分数均摊。
u.update_attribute("score",each_standard_score) else
score2 = score2 + each_standard_score q_score_1 = 0.0
st_answer_text.delete(u_answer_text) 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 end
else
score1 += 0.0
end end
end elsif q.question_type == 3 #填空题
elsif q.question_type == 5 #实训题时,主观题这里不评分 if answers_content.present?
q.exercise_shixun_challenges.each do |exercise_cha| null_standard_answer = q.exercise_standard_answers
game = Game.user_games(user.id,exercise_cha.challenge_id).first #当前用户的关卡 standard_answer_array = null_standard_answer.select(:exercise_choice_id,:answer_text)
if game.present? standard_answer_ids = standard_answer_array.pluck(:exercise_choice_id).reject(&:blank?).uniq #标准答案的exercise_choice_id数组
exercise_cha_score = 0 standard_answer_count = standard_answer_ids.count
answer_status = 0 if standard_answer_count > 0 #存在标准答案时才有分数
cha_path = challenge_path exercise_cha.challenge.path q_score_2 = (q.question_score.to_f / standard_answer_count) #每一空的得分
if game.status == 2 && game.final_score >= 0 else
exercise_cha_score = game.real_score exercise_cha.question_score #每一关卡的得分 q_score_2 = 0.0
answer_status = 1
end end
if exercise_cha.exercise_shixun_answers.search_shixun_answers("user_id",user.id).blank? #把关卡的答案存入试卷的实训里 if q.is_ordered
game_challenge = game.game_codes.search_challenge_path(cha_path).first answers_content.each do |u|
if game_challenge.present? i_standard_answer = standard_answer_array.where(exercise_choice_id:u.exercise_choice_id).pluck(:answer_text).reject(&:blank?).map!(&:downcase) #该选项的全部标准答案
game_code = game_challenge if i_standard_answer.include?(u.answer_text.downcase) #该空的标准答案包含用户的答案才有分数
code = game_code.try(:new_code) 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 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 end
sx_option = { score5 += exercise_cha_score
:exercise_question_id => q.id, else
:exercise_shixun_challenge_id => exercise_cha.id, score5 += 0.0
:user_id => user.id,
:score => exercise_cha_score,
:answer_text => code,
:status => answer_status
}
ExerciseShixunAnswer.create(sx_option)
end end
score5 += exercise_cha_score
end end
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 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 end
total_score = score1 + score2 + score5 total_score = score1 + score2 + score5
{ {
"total_score":total_score, "total_score":total_score.round(1),
"stand_status":ques_stand "stand_status":ques_stand
} }
end end
@ -467,9 +537,9 @@ module ExercisesHelper
ex_user_user = ex_user.user ex_user_user = ex_user.user
exercise_user_name = ex_user_user.real_name exercise_user_name = ex_user_user.real_name
exercise_user_id = ex_user_user.id 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 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 #继续答题 commit_status = 2 #继续答题
else else
commit_status = ex_user.commit_status commit_status = ex_user.commit_status
@ -478,18 +548,21 @@ module ExercisesHelper
ex_user_end_at = ex_user.end_at ex_user_end_at = ex_user.end_at
course_member = course.students.course_find_by_ids("user_id",ex_user.user.id) 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? 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) if current_user_group_id == 0
current_user_group_name = course_group.first.name if course_group.present? current_user_group_name = "未分班"
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
else 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_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 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 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 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) def user_question_answers(q,ex_answerer_id,student_status,is_teacher_or,ex_status,ques_type,ex_type)
answered_content = [] answered_content = []
user_score = 0.0 user_score = nil
shixun_type = 0 shixun_type = 0
question_comment = [] 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) exercise_answers = q.exercise_shixun_answers.search_shixun_answers("user_id",ex_answerer_id)
else else
exercise_answers = q.exercise_answers.search_exercise_answer("user_id",ex_answerer_id) #试卷用户的回答 exercise_answers = q.exercise_answers.search_exercise_answer("user_id",ex_answerer_id) #试卷用户的回答
end end
if student_status == 2 #当前为老师,或为学生且已提交 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 end
if ques_type <= 2 if ques_type <= 2
answered_content = exercise_answers.pluck(:exercise_choice_id) answered_content = exercise_answers&.pluck(:exercise_choice_id)
elsif ques_type == 3 elsif ques_type == 3
exercise_answers.each do |a| exercise_answers&.each do |a|
u_answer = { u_answer = {
"choice_id":a.exercise_choice_id, "choice_id":a.exercise_choice_id,
"answer_text": a.answer_text "answer_text": a.answer_text
@ -623,7 +722,7 @@ module ExercisesHelper
answered_content.push(u_answer) answered_content.push(u_answer)
end end
elsif ques_type == 4 elsif ques_type == 4
answered_content = exercise_answers.pluck(:answer_text) answered_content = exercise_answers&.pluck(:answer_text)
end end
if ques_type == 5 #存在实训题,及已经做了实训题的 if ques_type == 5 #存在实训题,及已经做了实训题的
if ex_status == 3 || is_teacher_or == 1 #如果试卷已截止,则可以看到分数,否则不能查看分数 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) question_comment = q.exercise_answer_comments.search_answer_comments("exercise_answer_id",q_answer_id)
end end
{ {
"user_score": user_score.round(1), "user_score": (user_score.present? ? user_score.round(1).to_s : nil),
"answered_content":answered_content, "answered_content":answered_content,
"shixun_type":shixun_type, "shixun_type":shixun_type,
"question_comment":question_comment "question_comment":question_comment
@ -662,8 +761,35 @@ module ExercisesHelper
result result
end 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) def content_line(content)
content.split(/\r?\n/).length content.split(/\r?\n/).length + 1
end end
end end

@ -35,16 +35,23 @@ module ExportHelper
else else
head_cells_add = [] head_cells_add = []
end 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?) @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_user = w.user
w_1 = (index + 1) w_1 = (index + 1)
w_2 = w_user.login if w_user.present?
w_3 = w_user.real_name w_2 = w_user&.login.present? ? w_user&.login : "--"
w_3_1 = w_user.mail w_3 = w_user&.real_name.present? ? w_user&.real_name : "--"
w_4 = w_user.student_id.present? ? w_user.student_id : "--" w_3_1 = w_user&.mail.present? ? w_user.mail : "--"
course_name = course.course_member(w.user_id).try(:course_group_name) 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 : "--" w_5 = course_name.present? ? course_name : "--"
#0 未提交, 1 按时提交, 2 延迟提交 #0 未提交, 1 按时提交, 2 延迟提交
if w.work_status == 0 if w.work_status == 0
@ -85,8 +92,22 @@ module ExportHelper
w_15 = w.work_score.nil? ? "未评分" : w.work_score.round(1) w_15 = w.work_score.nil? ? "未评分" : w.work_score.round(1)
w_16 = w.commit_time ? format_time(w.commit_time) : "--" w_16 = w.commit_time ? format_time(w.commit_time) : "--"
w_17 = w.update_time ? format_time(w.update_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?) row_cells_column = row_cells_column.reject(&:blank?)
@work_cells_column.push(row_cells_column) @work_cells_column.push(row_cells_column)
end end
@ -102,17 +123,17 @@ module ExportHelper
if allow_late_boolean #允许迟交 if allow_late_boolean #允许迟交
eff_score_cell.push("迟交扣分") eff_score_cell.push("迟交扣分")
end 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?) @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) myshixun = w.try(:myshixun)
w_user = w.user w_user = w.user
w_1 = (index + 1) w_1 = (index + 1)
w_2 = w_user.login w_2 = w_user&.login.present? ? w_user&.login : "--"
w_3 = w_user.real_name w_3 = w_user&.real_name.present? ? w_user&.real_name : "--"
w_3_1 = w_user.mail w_3_1 = w_user&.mail.present? ? w_user.mail : "--"
w_4 = w_user.student_id.present? ? w_user.student_id : "--" 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 : "--" w_5 = course_name.present? ? course_name : "--"
#0 未提交, 1 按时提交, 2 延迟提交 #0 未提交, 1 按时提交, 2 延迟提交
if w.work_status == 0 if w.work_status == 0
@ -124,7 +145,7 @@ module ExportHelper
else else
w_6 = "--" w_6 = "--"
end 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_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_9 = myshixun ? (myshixun.try(:passed_count) > 0 ? myshixun.total_spend_time : '--') : "--" #总耗时
w_10 = myshixun ? myshixun.output_times : 0 #评测次数 w_10 = myshixun ? myshixun.output_times : 0 #评测次数
@ -142,8 +163,22 @@ module ExportHelper
end end
w_15 = w.work_score.nil? ? "--" : w.work_score.round(1) w_15 = w.work_score.nil? ? "--" : w.work_score.round(1)
w_16 = w.update_time ? format_time(w.update_time) : "--" "更新时间" w_16 = w.update_time ? format_time(w.update_time) : "--" "更新时间"
w_17 = w.cost_time w_17 = (game_spend_time 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] 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?) row_cells_column = row_cells_column.reject(&:blank?)
@work_cells_column.push(row_cells_column) @work_cells_column.push(row_cells_column)
end end
@ -170,17 +205,17 @@ module ExportHelper
head_cells_format = head_cells_format + ["交叉评分"] head_cells_format = head_cells_format + ["交叉评分"]
end end
head_cells_format = head_cells_format + %w(迟交扣分 最终成绩 提交时间 更新时间) head_cells_format = head_cells_format + %w(迟交扣分 最终成绩 提交时间 更新时间 评语)
@head_cells_column = head_cells_format @head_cells_column = head_cells_format
@task_cells_column = [] @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_1 = (index+1)
w_user = work.user w_user = work.user
w_2 = w_user.login w_2 = w_user&.login.present? ? w_user&.login : "--"
w_3 = w_user.real_name w_3 = w_user&.real_name.present? ? w_user&.real_name : "--"
w_3_1 = w_user.mail w_3_1 = w_user&.mail.present? ? w_user.mail : "--"
w_4 = w_user.student_id.present? ? w_user.student_id : "--" w_4 = w_user.student_id.present? ? w_user.student_id : "--"
w_5 = work.class_grouping_name w_5 = work.class_grouping_name
if task_type_boolean #是否分组 if task_type_boolean #是否分组
@ -188,7 +223,16 @@ module ExportHelper
else else
w_6 = nil w_6 = nil
end 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 #关联项目 if task_project_boolean #关联项目
w_project = project_info work, current_user, @user_course_identity #因为课堂引用了export_helper w_project = project_info work, current_user, @user_course_identity #因为课堂引用了export_helper
w_8 = w_project[:name] w_8 = w_project[:name]
@ -212,8 +256,22 @@ module ExportHelper
w_13 = work.work_score.nil? ? "未评分" : work.work_score.round(1) w_13 = work.work_score.nil? ? "未评分" : work.work_score.round(1)
w_14 = work.commit_time.present? ? format_time(work.commit_time) : "--" w_14 = work.commit_time.present? ? format_time(work.commit_time) : "--"
w_15 = work.update_time.present? ? format_time(work.update_time) : "--" w_15 = work.update_time.present? ? format_time(work.update_time) : "--"
teacher_comments = work.graduation_work_scores
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] 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?) row_cells_column = row_cells_column.reject(&:blank?)
@task_cells_column.push(row_cells_column) @task_cells_column.push(row_cells_column)
@ -231,21 +289,11 @@ module ExportHelper
else else
@table_columns = @table_columns + %w(最终成绩 开始答题时间 提交时间) @table_columns = @table_columns + %w(最终成绩 开始答题时间 提交时间)
end 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_info = e_user.user
user_course_id = user_info.course_members.course_find_by_ids("course_id",course.id).first member = course.students.find_by_user_id(e_user.user_id)
if user_course_id.present? user_course = member.try(:course_group_name)
get_course_group_id = user_course_id.course_group_id user_obj_score = e_user.objective_score < 0.0 ? 0.0 : e_user.objective_score.round(1).to_s
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
user_suj_score = e_user.subjective_score < 0.0 ? 0.0 : e_user.subjective_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 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 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_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_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_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] user_student_id,user_course,user_commit_stu]
if ques_type_boolean if ques_type_boolean
other_user_option = [user_obj_score,user_suj_score,user_score,user_start_time,user_end_time] 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 = [] @topic_body_cells = []
if students.count > 0 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 user = student.user
student_topic = course.student_graduation_topics.user_topics_accept(user.id).first student_topic = course.student_graduation_topics.user_topics_accept(user.id).first
if student_topic.present? if student_topic.present?
@ -286,11 +337,11 @@ module ExportHelper
topic = nil topic = nil
end end
w_1 = (index+1) w_1 = (index+1)
w_2 = user.login w_2 = user&.login.present? ? user&.login : "--"
w_3 = user.real_name w_3 = user&.real_name.present? ? user&.real_name : "--"
w_3_1 = user.mail w_3_1 = user&.mail.present? ? user.mail : "--"
w_4 = user.user_extension.student_id w_4 = user.student_id.present? ? user.student_id : "--"
w_5 = student.course_group_name w_5 = student&.course_group_name.present? ? student.course_group_name : "--"
w_6 = topic.present? ? topic.name : "--" w_6 = topic.present? ? topic.name : "--"
w_7 = topic.present? ? topic.teacher.full_name : "--" w_7 = topic.present? ? topic.teacher.full_name : "--"
w_8 = topic.present? ? topic.teacher.identity : "--" w_8 = topic.present? ? topic.teacher.identity : "--"
@ -346,11 +397,11 @@ module ExportHelper
end end
if file_size > MAX_DOWN_SIZE if file_size > MAX_DOWN_SIZE
status = -1 status = -2
elsif file_count > 0 elsif file_count > 0
status = 0 status = 0
else else
status = -2 status = -1
end end
status status
end end
@ -459,6 +510,8 @@ module ExportHelper
zipfile_name = "#{output_path}/#{rename_zipfile}" zipfile_name = "#{output_path}/#{rename_zipfile}"
# 同名文件重命名时用
index = 1
Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name)) Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile| Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
files_paths.each do |filename| files_paths.each do |filename|
@ -468,7 +521,11 @@ module ExportHelper
begin begin
zipfile.add(rename_file, filename) zipfile.add(rename_file, filename)
rescue Exception => e 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 next
end end
end end
@ -485,4 +542,14 @@ module ExportHelper
attach.filename attach.filename
end 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 end

@ -14,7 +14,7 @@ module GraduationTasksHelper
# 交叉评阅 # 交叉评阅
def cross_comment task, user_id 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}] [{id: 1, name: "只看我的交叉评阅", count: task.graduation_work_comment_assignations.myself(user_id).count}]
else else
[] []
@ -67,7 +67,7 @@ module GraduationTasksHelper
# 作品数统计type 1 已提交 0 未提交 # 作品数统计type 1 已提交 0 未提交
def grduationwork_count task, type def grduationwork_count task, type
works = task.graduation_works 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 end
# 普通/分组 作业作品状态数组 # 普通/分组 作业作品状态数组
@ -131,4 +131,20 @@ module GraduationTasksHelper
end end
end 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 end

@ -15,7 +15,6 @@ module GraduationWorksHelper
end end
end end
# work_score 最终成绩; late_penalty 迟交扣分; final_score 最终评分 # work_score 最终成绩; late_penalty 迟交扣分; final_score 最终评分
{username: work.user.full_name, login: work.user.login, work_score: work_score, final_score: work.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 }
end end
end end

@ -65,7 +65,7 @@ module HomeworkCommonsHelper
# 作业统一设置、游客身份、超级管理员、分班权限不限的老师身份 # 作业统一设置、游客身份、超级管理员、分班权限不限的老师身份
if homework_common.unified_setting || identity > Course::STUDENT || identity == Course::ADMIN || 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 case ho_detail_manual.comment_status
when 0 when 0
status << "未发布" status << "未发布"
@ -174,9 +174,9 @@ module HomeworkCommonsHelper
end end
# 作品数统计type 1 已提交 0 未提交 # 作品数统计type 1 已提交 0 未提交
def studentwork_count homework_common, type, user_id def studentwork_count homework_common, type, member
student_works = homework_common.teacher_works(user_id) student_works = homework_common.teacher_works(member)
type == 1 ? student_works.select{|work| work.work_status != 0}.size : student_works.select{|work| work.work_status = 0}.size type == 1 ? student_works.where("work_status != 0").size : student_works.where(work_status: 0).size
end end
# 上次查重的时间 # 上次查重的时间
@ -223,10 +223,10 @@ module HomeworkCommonsHelper
end end
# 作品状态 # 作品状态
def homework_status homework, user_id def homework_status homework, member
[{id: 0, name: "未提交", count: homework.unfinished_count(user_id)}, [{id: 0, name: "未提交", count: homework.unfinished_count(member)},
{id: 1, name: "按时提交", count: homework.finished_count(user_id)}, {id: 1, name: "按时提交", count: homework.finished_count(member)},
{id: 2, name: "延时提交", count: homework.delay_finished_count(user_id)}] {id: 2, name: "延时提交", count: homework.delay_finished_count(member)}]
end end
# 作品分数的显示 # 作品分数的显示

@ -1,11 +1,15 @@
module PollsHelper module PollsHelper
#获取试卷的已答/未答人数 #获取试卷的已答/未答人数
def get_poll_answers(poll_users) def get_poll_answers(poll_users, status)
@commit_poll_users = poll_users.commit_by_status(1) #当前老师的全部学生中已提交的 if status == 1
@poll_answers = @commit_poll_users.present? ? @commit_poll_users.count : 0 #表示已经提交了的用户 @poll_answers = 0
course_all_members_count = poll_users.present? ? poll_users.count : 0 @poll_unanswers = 0
@poll_unanswers = (course_all_members_count - @poll_answers) 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 end
def poll_votes_count(votes,user_ids) def poll_votes_count(votes,user_ids)
@ -55,29 +59,29 @@ module PollsHelper
#当前为老师(非课堂成员、统一设置)的时候,显示的是老师身份的对应试卷的状态,因为该试卷,可能对应老师的多个分班 #当前为老师(非课堂成员、统一设置)的时候,显示的是老师身份的对应试卷的状态,因为该试卷,可能对应老师的多个分班
poll_status = poll.polls_status poll_status = poll.polls_status
else else
poll_status = poll.get_poll_status(user.id) #当前用户查看的试卷的发布状态 poll_status = poll.get_poll_status(user) #当前用户查看的试卷的发布状态
end end
if is_teacher_or == 1 if is_teacher_or == 1
poll_users_list = poll.all_poll_users(user.id) #当前老师所在班级的全部学生 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) ex_pb_time = poll.get_poll_times(user.id,true)
poll_publish_time = ex_pb_time[:publish_time] poll_publish_time = ex_pb_time[:publish_time]
poll_end_time = ex_pb_time[:end_time] poll_end_time = ex_pb_time[:end_time]
current_status = 3 current_status = 3
lock_icon = 1 #不显示锁图标 lock_icon = 0 #不显示锁图标
elsif is_teacher_or == 2 elsif is_teacher_or == 2
poll_users_list = poll.get_poll_exercise_users 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) # get_poll_answers(poll_all_users)
ex_pb_time = poll.get_poll_times(user.id,false) ex_pb_time = poll.get_poll_times(user.id,false)
poll_publish_time = ex_pb_time[:publish_time] poll_publish_time = ex_pb_time[:publish_time]
poll_end_time = ex_pb_time[:end_time] poll_end_time = ex_pb_time[:end_time]
current_status = poll.check_user_votes_status(user) current_status = poll.check_user_votes_status(user)
lock_icon = 1 #不显示锁图标 lock_icon = 0 #不显示锁图标
else else
poll_users_list = poll.get_poll_exercise_users 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_publish_time = poll.publish_time
poll_end_time = poll.end_time poll_end_time = poll.end_time
current_status = 4 current_status = 4
@ -87,6 +91,9 @@ module PollsHelper
lock_icon = 0 #显示锁图标 lock_icon = 0 #显示锁图标
end end
end end
if (course.is_public == 1) && poll.is_public
lock_icon = 1
end
{ {
"publish_time":poll_publish_time, "publish_time":poll_publish_time,
"end_time":poll_end_time, "end_time":poll_end_time,
@ -110,15 +117,22 @@ module PollsHelper
poll_user_name = user.nickname poll_user_name = user.nickname
end end
course_member = course_members.find_by(user_id:user.id) 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_id = course_member.present? ? course_member.course_group_id : nil
course_group = course.course_groups.find_by_id(current_user_group_id) 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_name":poll_user_name,
"user_id": user.id, "user_id": user.id,
"student_id":user_student_id, "student_id":user_student_id,
"group_name":course_group.try(:name), "group_name":course_group_name,
"group_id":course_group.try(:id), "group_id":course_group_id,
"login":user.login "login":user.login
} }
end end
end end

@ -41,7 +41,7 @@ module StudentWorksHelper
def student_efficiency(homework_common, work) def student_efficiency(homework_common, work)
myshixun_ids = homework_common.student_works.pluck(:myshixun_id) 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 #student_works_user_id = homework_common.student_works.pluck(:user_id).uniq
#shixun = homework_common.shixuns.first #shixun = homework_common.shixuns.first
#logger.info("#########shixun_id: ###{shixun.id}") #logger.info("#########shixun_id: ###{shixun.id}")
@ -54,11 +54,11 @@ module StudentWorksHelper
objects = objects =
myshixuns.map do |myshixun| 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) 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) all_time = (myshixun.games.pluck(:cost_time).sum / 60.0)
# 通关得分 # 通关得分
@ -145,7 +145,7 @@ module StudentWorksHelper
else else
user_name = message_user.real_name user_name = message_user.real_name
user_login = message_user.login user_login = message_user.login
image_url = url_to_avatar(score.user) image_url = url_to_avatar(message_user)
end end
{user_name: user_name, user_login: user_login, user_image_url: image_url} {user_name: user_name, user_login: user_login, user_image_url: image_url}
end end

@ -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

@ -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

@ -2,10 +2,20 @@
class ExercisePublishNotifyJob < ApplicationJob class ExercisePublishNotifyJob < ApplicationJob
queue_as :notify queue_as :notify
def perform(exercise_id, receiver_ids) def perform(exercise_id, group_ids)
exercise = Exercise.find_by(id: exercise_id) exercise = Exercise.find_by(id: exercise_id)
return if exercise.blank? return if exercise.blank?
user = exercise.user 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[ attrs = %i[
user_id trigger_user_id container_id container_type parent_container_id parent_container_type 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' viewed: 0, tiding_type: 'Exercise'
} }
Tiding.bulk_insert(*attrs) do |worker| 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) unless exercise.tidings.exists?(parent_container_type: 'ExercisePublish', user_id: teacher_ids)
exercise.course.teachers.find_each do |teacher| teacher_ids.each do |user_id|
worker.add same_attrs.merge(user_id: teacher.user_id) worker.add same_attrs.merge(user_id: user_id)
end end
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) worker.add same_attrs.merge(user_id: user_id)
end end
end end

@ -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

@ -5,6 +5,8 @@ class GraduationTaskPublishNotifyJob < ApplicationJob
def perform(graduation_task_id) def perform(graduation_task_id)
task = GraduationTask.find_by(id: graduation_task_id) task = GraduationTask.find_by(id: graduation_task_id)
return if task.blank? return if task.blank?
course = task.course
return if course.blank?
attrs = %i[ attrs = %i[
user_id trigger_user_id container_id container_type parent_container_id parent_container_type 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' viewed: 0, tiding_type: 'GraduationTask'
} }
Tiding.bulk_insert(*attrs) do |worker| Tiding.bulk_insert(*attrs) do |worker|
task.course.students.find_each do |student| course.course_members.pluck(:user_id).uniq.each do |user_id|
worker.add same_attrs.merge(user_id: student.user_id) worker.add same_attrs.merge(user_id: user_id)
end end
end end
end end

@ -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

@ -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

@ -24,7 +24,7 @@ class HomeworkCommonPushNotifyJob < ApplicationJob
same_attrs = { same_attrs = {
trigger_user_id: homework.user_id, container_id: homework.id, container_type: 'HomeworkCommon', trigger_user_id: homework.user_id, container_id: homework.id, container_type: 'HomeworkCommon',
parent_container_id: homework.id, parent_container_type: 'HomeworkPublish', 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' viewed: 0, tiding_type: 'HomeworkCommon'
} }
Tiding.bulk_insert(*attrs) do |worker| Tiding.bulk_insert(*attrs) do |worker|

@ -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

@ -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

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save