Merge remote-tracking branch 'origin/dev_aliyun' into dev_aliyun

dev_auth
杨树明 5 years ago
commit 2f63dee3fe

@ -600,6 +600,67 @@ $(document).on('turbolinks:load', function(){
$(".stage-update-form .section-start-time").datetimepicker(timeOptions);
$(".stage-update-form .section-end-time").datetimepicker(timeOptions);
});
// 奖项设置
var $prizeContainer = $('#competition-prize-card');
var competitionId = $prizeContainer.data('id');
$(document).on('prize.save.success', function(){
$.ajax({
method: 'GET',
url: '/admins/competitions/' + competitionId + '/competition_prizes',
dataType: 'script'
})
});
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $imageElement;
if(data.suffix === '_member'){
$imageElement = $('.prize-member-image-' + data.source_id);
} else if(data.suffix === '_team'){
$imageElement = $('.prize-team-image-' + data.source_id);
} else {
$imageElement = $('.prize-teacher-image-' + data.source_id);
}
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
})
// 生成获奖记录
$prizeContainer.on('click', '.generate-prize-user-action', function(){
var $link = $(this);
var generateRequest = function(){
return $.ajax({
method: 'POST',
url: '/admins/competitions/' + competitionId + '/competition_prize_users',
dataType: 'json',
success: function(data){
if(data && data.status === 0){
show_success_flash();
$link.remove();
} else {
showErrorNotify(data.message);
}
},
error: function(res){
var data = res.responseJSON;
showErrorNotify(data.message);
}
})
}
customConfirm({
content: '确认生成吗?',
ok: function () {
customLoading({
ajax: generateRequest
})
}
})
});
} else {
$(document).unbind('prize.save.success');
}
});

@ -0,0 +1,46 @@
$(document).on('turbolinks:load', function() {
$('.admin-modal-container').on('show.bs.modal', '.admin-save-competition-prize-modal', function(event){
var $modal = $('.modal.admin-save-competition-prize-modal');
var $form = $modal.find('form.admin-save-competition-prize-form');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
'competition_prize[name]': {
required: true,
maxlength: 10
},
'competition_prize[num]': {
required: true,
digits: true,
min: 1
}
}
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
var url = $form.attr('action');
var formMethod = $form.data('form-method')
if ($form.valid()) {
$.ajax({
method: formMethod,
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(data){
if(data && data.status === 0) {
show_success_flash();
$(document).trigger('prize.save.success');
$modal.modal('hide');
} else {
$modal.find('.error').html(data.message)
}
}
});
}
});
})
});

@ -66,10 +66,32 @@ function customConfirm(opts){
return $.confirm($.extend({}, defaultOpts, opts))
}
function show_success_flash(message) {
function customLoading(opts) {
var loading;
var defaultOpts = {
content: opts.ajax,
contentLoaded: function(){
setTimeout(function(){
loading.close()
}, 200);
}
}
loading = $.confirm($.extend({}, defaultOpts, opts));
return loading;
}
function show_success_flash(message){
$.notify({
message: message || '操作成功'
},{
type: 'success'
});
}
function showErrorNotify(message){
$.notify({
message: message || '操作失败'
},{
type: 'danger'
});
}

@ -0,0 +1,41 @@
class Admins::CompetitionPrizeUsersController < Admins::BaseController
def index
@competition = current_competition
prize_users = Admins::CompetitionPrizeUserQuery.call(params.merge(competition_id: current_competition.id))
include_class = [:competition_team, :competition_prize, :approver,
user: [:process_real_name_apply, :process_professional_apply, user_extension: :school]]
@prize_users = paginate(prize_users.preload(include_class))
end
def create
Admins::CreateCompetitionPrizeUsersService.call(current_competition)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def approve
Admins::ApproveCompetitionPrizeUserService.call(current_prize_user, current_user)
@prize_user = current_prize_user
rescue ApplicationService::Error => ex
render_js_error(ex.message, type: :notify)
end
def unapprove
Admins::UnapproveCompetitionPrizeUserService.call(current_prize_user, current_user)
@prize_user = current_prize_user
rescue ApplicationService::Error => ex
render_js_error(ex.message, type: :notify)
end
private
def current_prize_user
@_current_prize_user ||= current_competition.competition_prize_users.find(params[:id])
end
def current_competition
@_current_competition ||= Competition.find(params[:competition_id])
end
end

@ -0,0 +1,43 @@
class Admins::CompetitionPrizesController < Admins::BaseController
def index
@competition = current_competition
end
def new
@prize = current_competition.competition_prizes.new
end
def create
@prize = current_competition.competition_prizes.create!(save_params)
render_ok
end
def edit
@prize = current_competition_prize
end
def update
current_competition_prize.update!(save_params)
render_ok
end
def destroy
current_competition_prize.destroy!
render_delete_success
end
private
def current_competition_prize
@_current_competition_prize ||= current_competition.competition_prizes.find(params[:id])
end
def current_competition
@_current_competition ||= Competition.find(params[:competition_id])
end
def save_params
params.require(:competition_prize).permit(:name, :category, :num)
end
end

@ -0,0 +1,23 @@
class Competitions::CertificatesController < Competitions::BaseController
def personal
prize_user = CompetitionPrizeUser.find_by!(user: current_user, id: params[:id])
return render_not_found unless prize_user.certificate_exist?
team = prize_user.competition_team
prize = prize_user.competition_prize
filename = "#{current_competition.name}-#{prize.name}-#{team.name}-#{prize_user.user.real_name}.pdf"
send_file prize_user.certificate_path, filename: filename
end
def team
team = CompetitionTeam.find(id: params[:id])
return render_forbidden unless team.team_members.exists?(user_id: current_user.id)
return render_not_found unless team.certificate_exist?
prize = team.competition_prize_users.first.competition_prize
filename = "#{current_competition.name}-#{prize.name}-#{team.name}.pdf"
send_file team.certificate_path, filename: filename
end
end

@ -5,6 +5,11 @@ class Competitions::CompetitionModulesController < Competitions::BaseController
def index
@modules = current_competition.unhidden_competition_modules.order(position: :asc)
# 未登录、未获奖用户,不展示获奖证书栏目
if !current_user.logged? || !current_competition.competition_prize_users.exists?(user: current_user)
@modules = @modules.select { |mod| mod.name != '获奖证书' }
end
end
def show

@ -22,7 +22,7 @@ class Competitions::CompetitionsController < Competitions::BaseController
@count = competitions.count
competitions = competitions.order(published_at: :desc, online_time: :desc)
@competitions = paginate(competitions.includes(sponsor_schools: :school, current_stage_section: :competition_stage))
@competitions = paginate(competitions.includes(:competition_mode_setting, sponsor_schools: :school, current_stage_section: :competition_stage))
ids = @competitions.map(&:id)
@member_count_map = TeamMember.where(competition_id: ids).group(:competition_id).count

@ -0,0 +1,25 @@
class Competitions::PrizeLeaderAccountsController < Competitions::BaseController
before_action :require_prize_team_leader!
def update
Competitions::SavePrizeTeamAccountService.call(current_competition, current_user, update_params)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
private
def require_prize_team_leader!
prize_user = current_competition.competition_prize_users.joins(:competition_prize)
.where(competition_prizes: { category: :bonus })
.find_by(leader: true, user_id: current_user.id)
return if prize_user.present?
render_forbidden
end
def update_params
params.permit(:bank, :second_bank, :card_no)
end
end

@ -0,0 +1,26 @@
class Competitions::PrizesController < Competitions::BaseController
before_action :require_prize_user!
def show
self_prizes = current_competition.competition_prize_users.where(user_id: current_user.id).includes(:competition_team)
@leader = self_prizes.any?(&:leader?) # 是否为队长
@bank_account = self_prizes.find(&:leader?).extra if @leader
@self_prizes = self_prizes.select(&:certificate_exist?) # 个人证书quit
@team_prizes = self_prizes.map(&:competition_team).uniq.select(&:certificate_exists?) # 团队证书
prize_users = current_competition.competition_prize_users.where(competition_team_id: self_prizes.map(&:competition_team_id))
.includes(:competition_team, user: [:user_extension, :process_real_name_apply, :process_professional_apply])
@prize_user_map = prize_users.group_by(&:competition_team)
end
private
def require_prize_user!
return if current_competition.competition_prize_users.exists?(user: current_user)
render_forbidden
end
end

@ -257,8 +257,8 @@ class CoursesController < ApplicationController
user_ids = all_members.map(&:user_id)
rank = user_ids.index(current_user.id).to_i + 1
if rank > 10
current_member = all_members.select{|member| member.user_id == current_user.id}
@course_members << current_member
current_member = all_members.select{|member| member.user_id == current_user.id}.first
@course_members << current_member if current_member.present?
end
end
end

@ -605,6 +605,21 @@ class ExercisesController < ApplicationController
end
end
# 对未提交的用户进行调分
def adjust_score
exercise_user = @exercise.exercise_users.find_by!(user_id: params[:user_id])
tip_exception("已提交的作品请去评阅页进行调分") if exercise_user.commit_status == 1
tip_exception("分数不能为空") if params[:score].blank?
tip_exception("分数不能超过0-#{@exercise.question_scores}") if params[:score].to_f < 0 || params[:score].to_f.round(1) > @exercise.question_scores.round(1)
ActiveRecord::Base.transaction do
start_at_time = exercise_user.start_at || Time.now
exercise_user.update_attributes!(start_at: start_at_time, end_at: Time.now, status: 1, commit_status: 1, score: params[:score].to_f.round(2), commit_method: 5)
ExerciseUserScore.create!(exercise_id: @exercise.id, exercise_user_id: exercise_user.id, score: params[:score], comment: params[:comment])
normal_status("操作成功")
end
end
#我的题库
def my_exercises
ActiveRecord::Base.transaction do

@ -125,7 +125,7 @@ class HomeworkCommonsController < ApplicationController
# 学生已提交作品且补交(提交)已截止、作品公开、非匿评阶段
if @work&.work_status.to_i > 0 && (@homework.work_public || @homework.score_open) &&
((!@homework.anonymous_comment && @homework.end_or_late) || (@homework_detail_manual.comment_status > 4 && @homework.end_or_late))
@student_works = student_works.where("user_id != #{@work.user_id}")
@student_works = student_works.where("student_works.user_id != #{@work.user_id}")
# 匿评、申诉阶段只能看到分配给自己的匿评作品
elsif @work&.work_status.to_i > 0 && @homework.anonymous_comment && @homework_detail_manual.comment_status > 2 && @homework_detail_manual.comment_status <= 4
@ -572,10 +572,13 @@ class HomeworkCommonsController < ApplicationController
if @homework.homework_type == "practice"
# 实训作业的评分设置
tip_exception("总分值不能为空") if params[:total_score].blank?
tip_exception("总分值不能小于0") if params[:total_score].to_i < 0
tip_exception("缺少answer_open_evaluation参数") if params[:answer_open_evaluation].nil?
tip_exception("缺少work_efficiency参数") if params[:work_efficiency].nil?
tip_exception("缺少eff_score参数") if params[:work_efficiency] && params[:eff_score].blank?
tip_exception("效率分不能小于等于0") if params[:eff_score] && params[:eff_score].to_i <= 0
tip_exception("效率分不能大于总分值") if params[:eff_score] && params[:eff_score].to_i > params[:total_score].to_i
tip_exception("缺少shixun_evaluation参数") if params[:shixun_evaluation].blank?
tip_exception("缺少challenge_settings参数") if params[:challenge_settings].blank?
# tip_exception("缺少challenge_id参数") if params[:challenge_settings][:challenge_id].blank?
@ -584,6 +587,7 @@ class HomeworkCommonsController < ApplicationController
# params[:challenge_settings][:challenge_score].length != params[:challenge_settings][:challenge_id].length
current_eff_score = @homework.eff_score
@homework.total_score = params[:total_score]
@homework.work_efficiency = params[:work_efficiency]
@homework.eff_score = params[:work_efficiency] ? params[:eff_score].to_i : 0

@ -534,7 +534,9 @@ class StudentWorksController < ApplicationController
# 作品调分
def adjust_score
tip_exception("分数不能为空") if params[:score].blank?
tip_exception("分数不能超过0-100") if params[:score].to_f < 0 || params[:score].to_f > 100
tip_exception("分数不能超过0-100") if @homework.homework_type != "practice" && (params[:score].to_f < 0 || params[:score].to_f.round(1) > 100.round(1))
tip_exception("已提交的作品请去评阅页进行调分") if @homework.homework_type == "practice" && @work.work_status > 0
tip_exception("分数不能超过总分值#{@homework.total_score}") if @homework.homework_type == "practice" && (params[:score].to_f < 0 || params[:score].to_f.round(1) > @homework.total_score.round(1))
ActiveRecord::Base.transaction do
begin
# 分数不为空的历史评阅都置为失效

@ -4,10 +4,16 @@ class Users::AuthenticationAppliesController < Users::BaseAccountController
def create
Users::ApplyAuthenticationService.call(observed_user, create_params)
render_ok
rescue Users::ApplyAuthenticationService::Error => ex
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def destroy
return render_error('已认证后不能撤销') if observed_user.authentication?
observed_user.process_real_name_apply&.revoke!
render_ok
end
private
def create_params

@ -8,6 +8,12 @@ class Users::ProfessionalAuthAppliesController < Users::BaseAccountController
render_error(ex.message)
end
def destroy
return render_error('已认证后不能撤销') if observed_user.professional_certification?
observed_user.process_professional_apply&.revoke!
render_ok
end
private
def create_params

@ -0,0 +1,9 @@
class Competitions::SavePrizeTeamAccountForm
include ActiveModel::Model
attr_accessor :bank, :second_bank, :card_no
validates :bank, presence: true
validates :second_bank, presence: true
validates :card_no, presence: true
end

@ -0,0 +1,10 @@
module Admins::CompetitionPrizeUsersHelper
def display_auth_state(flag, other = false, success: nil, normal: nil, error: nil)
success ||= '<i class="fa fa-check text-success font-16"/>'.html_safe
normal ||= '--'
error ||= '<i class="fa fa-close text-secondary font-16"/>'.html_safe
return success if flag
other ? normal : error
end
end

@ -29,6 +29,9 @@ class Competition < ApplicationRecord
has_many :competition_managers, dependent: :destroy
has_many :managers, through: :competition_managers, source: :user
has_many :competition_prizes, dependent: :destroy
has_many :competition_prize_users, dependent: :destroy
after_create :create_competition_modules
def mode_type
@ -46,6 +49,12 @@ class Competition < ApplicationRecord
end
end
# 报名数
def team_member_count
course = competition_mode_setting&.course if mode == 2
course ? course.students.count : team_members.count
end
def sponsor_schools_name
sponsor_schools.map{|sponsor| sponsor.school.name}
end
@ -131,7 +140,7 @@ class Competition < ApplicationRecord
end
def all_module_types
%w[home enroll inform chart resource]
%w[home enroll inform chart resource certificate]
end
def max_stage_end_time
@ -146,6 +155,10 @@ class Competition < ApplicationRecord
user && competition_managers.exists?(user_id: user.id)
end
def finished?
end_time.blank? || end_time < Time.now
end
private
def get_module_name type
@ -155,6 +168,7 @@ class Competition < ApplicationRecord
when 'inform' then '通知公告'
when 'chart' then '排行榜'
when 'resource' then '资料下载'
when 'certificate' then '获奖证书'
else ''
end
end

@ -0,0 +1,21 @@
class CompetitionPrize < ApplicationRecord
extend Enumerize
belongs_to :competition
has_many :competition_prize_users, dependent: :destroy
enumerize :category, in: %i[bonus unset]
def self.member_suffix
'_member'
end
def self.teacher_suffix
'_teacher'
end
def self.team_suffix
'_team'
end
end

@ -0,0 +1,48 @@
class CompetitionPrizeUser < ApplicationRecord
include AASM
belongs_to :competition
belongs_to :competition_team
belongs_to :competition_prize
belongs_to :user
belongs_to :approver, class_name: 'User', optional: true # 审批人
serialize :extra, JSON
aasm(:status) do
state :pending, initial: true
state :approved
event :approve do
transitions from: [:pending], to: :approved, guard: :user_certified?
end
event :unapprove do
transitions from: [:approved], to: :pending
end
end
delegate :bank, :second_bank, :card_no, to: :extra, allow_nil: true
def user_certified?
user.certification? && user.professional_certification?
end
def certificate_exist?
Util::FileManage.exists?(self)
end
def certificate_url
Util::FileManage.source_disk_file_url(self)
end
def certificate_path
Util::FileManage.source_disk_filename(self)
end
def role_text
return '队长' if leader?
user.is_teacher? ? '教师' : '队员'
end
end

@ -11,6 +11,8 @@ class CompetitionTeam < ApplicationRecord
has_many :members, -> { without_teachers }, class_name: 'TeamMember'
has_many :teachers, -> { only_teachers }, class_name: 'TeamMember'
has_many :competition_prize_users, dependent: :destroy
def group_team_type?
team_type.zero?
end
@ -48,4 +50,24 @@ class CompetitionTeam < ApplicationRecord
def members_name
members.map{|member| member.user.real_name}.join(",")
end
def all_prize_approved?
!competition_prize_users.exists?(status: :pending)
end
def certificate_exists?
Util::FileManage.exists?(self, self.class.certificate_suffix)
end
def certificate_url
Util::FileManage.source_disk_file_url(self, self.class.certificate_suffix)
end
def certificate_path
Util::FileManage.source_disk_filename(self, self.class.certificate_suffix)
end
def self.certificate_suffix
'_CERT'
end
end

@ -1,8 +1,10 @@
class ExerciseUser < ApplicationRecord
# commit_method 0 为默认, 1为学生的手动提交2为倒计时结束后自动提交3为试卷定时截止的自动提交, 4为教师手动的立即截止
# commit_method 0 为默认, 1为学生的手动提交2为倒计时结束后自动提交3为试卷定时截止的自动提交, 4为教师手动的立即截止, 5为老师调分
belongs_to :user
belongs_to :exercise
has_many :exercise_user_scores, dependent: :destroy
scope :commit_exercise_by_status, lambda { |s| where(commit_status: s) }
scope :exercise_user_committed, -> {where("commit_status != ?",0) }
scope :current_exercise_user, lambda { |user_id,exercise_id| where(user_id: user_id,exercise_id:exercise_id)}

@ -0,0 +1,5 @@
class ExerciseUserScore < ApplicationRecord
belongs_to :exercise
belongs_to :exercise_user
belongs_to :user
end

@ -503,6 +503,10 @@ class User < ApplicationRecord
phone.present?
end
def email_binded?
mail.present?
end
def self.current=(user)
Thread.current[:current_user] = user
end

@ -0,0 +1,77 @@
class Admins::CompetitionPrizeUserQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :rank, default_by: :rank, default_direction: :asc
def initialize(params)
@params = params
end
def call
records = CompetitionPrizeUser.all
# 竞赛过滤
records = records.where(competition_id: params[:competition_id]) if params[:competition_id].present?
# 关键字检索
keyword = params[:keyword].to_s.strip
if keyword.present?
like_sql = 'competition_teams.name LIKE :keyword OR schools.name LIKE :keyword'
records = records.left_joins(:competition_team, user: { user_extension: :school })
.where(like_sql, keyword: "%#{keyword}%")
end
# 奖项过滤
records = records.where(competition_prize_id: params[:prize_id]) if params[:prize_id].present?
# 审批状态过滤
records = records.where(status: params[:status]) if params[:status].present?
# 职业过滤
if params[:identity].present?
records = records.left_joins(user: :user_extension).where(user_extensions: { identity: params[:identity] })
end
# 实名认证过滤
records = real_name_auth_filter(records) if params[:real_name_auth].present?
# 职业认证过滤
records = professional_auth_filter(records) if params[:professional_auth].present?
custom_sort(records, params[:sort_by], params[:sort_direction])
end
private
def real_name_auth_filter(records)
records = records.left_joins(:user)
sql = ApplyUserAuthentication.real_name_auth.processing.where('apply_user_authentications.user_id = users.id').to_sql
case params[:real_name_auth]
when 'authed' then
records.where(users: { authentication: true })
when 'not_authed' then
records.where(users: { authentication: false }).where("NOT EXISTS (#{sql})")
when 'authing' then
records.where(users: { authentication: false }).where("EXISTS (#{sql})")
else records
end
end
def professional_auth_filter(records)
records = records.left_joins(:user)
sql = ApplyUserAuthentication.professional_auth.processing.where('apply_user_authentications.user_id = users.id').to_sql
case params[:professional_auth]
when 'authed' then
records.where(users: { professional_certification: true })
when 'not_authed' then
records.where(users: { professional_certification: false }).where("NOT EXISTS (#{sql})")
when 'authing' then
records.where(users: { professional_certification: false }).where("EXISTS (#{sql})")
else records
end
end
end

@ -0,0 +1,26 @@
class Admins::ApproveCompetitionPrizeUserService < ApplicationService
attr_reader :prize_user, :approver
def initialize(prize_user, approver)
@prize_user = prize_user
@approver = approver
end
def call
raise Error, '请勿重复审批' if prize_user.approved?
raise Error, '该用户未认证完成' unless prize_user.user_certified?
ActiveRecord::Base.transaction do
prize_user.approve
prize_user.approver = approver
prize_user.approved_at = Time.now
prize_user.save!
if prize_user.competition_team.all_prize_approved?
# TODO: 生成团队证书
end
# TODO: 生成个人证书
end
end
end

@ -0,0 +1,70 @@
class Admins::CreateCompetitionPrizeUsersService < ApplicationService
attr_reader :competition
def initialize(competition)
@competition = competition
end
def call
raise Error, '竞赛还未结束' unless competition.finished?
raise Error, '请勿重复生成' if competition.competition_prize_users.exists?
raise Error, '请先设置奖项' if prizes.blank?
raise Error, '无获奖队伍' if prize_teams.blank?
ActiveRecord::Base.transaction do
columns = %i[competition_id competition_team_id competition_prize_id user_id
status rank leader created_at updated_at]
CompetitionPrizeUser.bulk_insert(*columns) do |worker|
prize_teams.each_with_index do |team, index|
rank = index + 1
prize = team_prize(rank) # 根据排名获取当前队伍奖项
team.team_members.each do |member|
attr = {
competition_id: competition.id,
competition_team_id: team.id,
competition_prize_id: prize.id,
user_id: member.user_id,
leader: member.creator?,
status: :pending,
rank: rank
}
worker.add(attr)
end
end
end
end
end
private
def prizes
@_prizes ||= competition.competition_prizes.order(id: :asc).to_a
end
def team_prize(rank)
current = 0
prizes.each do |prize|
return prize if rank > current && rank <= current + prize.num
current += prize.num
end
end
def prize_teams
@_prize_teams ||= begin
prize_num_total = prizes.sum(&:num)
# 只有一个阶段则成绩为该阶段成绩否则为stage ID为0的总成绩
stage_id = competition.competition_stages.count == 1 ? competition.competition_stages.first.id : 0
competition.competition_teams.joins(:competition_scores)
.where(competition_scores: { competition_stage_id: stage_id })
.order("competition_scores.score desc, competition_scores.cost_time desc")
.includes(:team_members)
.limit(prize_num_total)
end
end
end

@ -0,0 +1,27 @@
class Admins::UnapproveCompetitionPrizeUserService < ApplicationService
attr_reader :prize_user, :approver
def initialize(prize_user, approver)
@prize_user = prize_user
@approver = approver
end
def call
raise Error, '状态有误' if prize_user.pending?
ActiveRecord::Base.transaction do
prize_user.unapprove
prize_user.approver = approver
prize_user.approved_at = nil
prize_user.save!
# 删除团队证书
team_certificate_path = Util::FileManage.source_disk_filename(prize_user.competition_team, CompetitionTeam.certificate_suffix)
File.delete(team_certificate_path) if File.exist?(team_certificate_path)
# 删除个人证书
user_certificate_path = Util::FileManage.source_disk_filename(prize_user)
File.delete(user_certificate_path) if File.exist?(user_certificate_path)
end
end
end

@ -0,0 +1,19 @@
class Competitions::SavePrizeTeamAccountService < ApplicationService
attr_reader :competition, :user, :params
def initialize(competition, user, params)
@competition = competition
@user = user
@params = params
end
def call
Competitions::SavePrizeTeamAccountForm.new(params).validate!
prize_leaders = competition.competition_prize_users.where(competition.competition_prize_users)
raise Error, '审批通过后不能修改' if prize_leaders.exists?(status: :approved)
prize_leaders.update_all(extra: params)
end
end

@ -1,6 +1,4 @@
class Users::ApplyAuthenticationService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params
def initialize(user, params)

@ -0,0 +1 @@
$('.competition-prize-user-list-container .competition-prize-user-item-<%= @prize_user.id %>').html("<%= j( render partial: 'admins/competition_prize_users/shared/tr', locals: { prize_user: @prize_user } ) %>");

@ -0,0 +1,58 @@
<%
define_admin_breadcrumbs do
add_admin_breadcrumb('竞赛列表', admins_competitions_path)
add_admin_breadcrumb(@competition.name)
end
%>
<div class="box search-form-container flex-column mb-0 pb-0 competition-prize-user-form">
<ul class="nav nav-tabs w-100 search-form-tabs">
<li class="nav-item">
<%= link_to '报名列表', admins_competition_enroll_lists_path(@competition), class: "nav-link search-form-tab" %>
</li>
<li class="nav-item">
<%= link_to '获奖证书审批', admins_competition_competition_prize_users_path(@competition), class: "nav-link search-form-tab active" %>
</li>
</ul>
<div class="d-flex">
<%= form_tag(admins_competition_competition_prize_users_path(unsafe_params), method: :get, class: 'search-form mt-3 flex-1 d-flex align-items-end', remote: true) do %>
<div class="form-group mb-0 mr-3">
<label for="status">奖项:</label>
<% prize_options = [['不限', '']] + @competition.competition_prizes.map{ |p| [p.name, p.id] } %>
<%= select_tag(:prize_id, options_for_select(prize_options), class: 'form-control') %>
</div>
<% auth_options = [['不限', ''], %w(未认证 not_authed), %w(待认证 authing), %w(已认证 authed)] %>
<div class="form-group mb-0 mr-3">
<label for="status">实名认证状态:</label>
<%= select_tag(:real_name_auth, options_for_select(auth_options), class: 'form-control') %>
</div>
<div class="form-group mb-0 mr-3">
<label for="status">职业认证状态:</label>
<%= select_tag(:professional_auth, options_for_select(auth_options), class: 'form-control') %>
</div>
<div class="form-group mb-0 mr-3">
<label for="status">职业:</label>
<%- identity_options = [['不限', ''], %w(教师 0), %w(学生 1)] %>
<%= select_tag(:identity, options_for_select(identity_options), class: 'form-control') %>
</div>
<div class="form-group mb-0 mr-3">
<label for="status">审批状态:</label>
<%- status_options = [['不限', ''], %w(未审批 pending), %w(已审批 approved)] %>
<%= select_tag(:status, options_for_select(status_options), class: 'form-control') %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '战队/学校名称检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<%= link_to '清除', admins_competition_competition_prize_users_path(@competition), class: "btn btn-default",'data-disable-with': '清除中...' %>
<% end %>
</div>
</div>
<div class="box competition-prize-user-list-container">
<%= render(partial: 'admins/competition_prize_users/shared/list', locals: { prize_users: @prize_users }) %>
</div>

@ -0,0 +1 @@
$('.competition-prize-user-list-container').html("<%= j( render partial: 'admins/competition_prize_users/shared/list', locals: { prize_users: @prize_users } ) %>");

@ -0,0 +1,33 @@
<table class="table table-hover text-center competition-prize-user-list-table">
<thead class="thead-light">
<tr>
<th width="6%">奖项</th>
<th width="5%">排名</th>
<th width="10%" class="text-left">战队名称</th>
<th width="8%">真实姓名</th>
<th width="5%">职业</th>
<th width="8%">学号</th>
<th width="10%">单位</th>
<th width="5%">实名</th>
<th width="5%">职业</th>
<th width="5%">手机</th>
<th width="5%">队长</th>
<th width="10%">审批时间</th>
<th width="8%">审批人</th>
<th width="10%">操作</th>
</tr>
</thead>
<tbody style="overflow-wrap:break-word;">
<% if prize_users.present? %>
<% prize_users.each do |prize_user| %>
<tr class="competition-prize-user-item-<%= prize_user.id %>">
<%= render('admins/competition_prize_users/shared/tr', prize_user: prize_user) %>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: prize_users } %>

@ -0,0 +1,26 @@
<%- user = prize_user.user -%>
<td><%= prize_user.competition_prize.name %></td>
<td><%= prize_user.rank %></td>
<td class="text-left"><%= prize_user.competition_team.name %></td>
<td><%= user.real_name %></td>
<td><%= user.identity %></td>
<td><%= user.is_teacher? ? user.user_extension.technical_title : user.user_extension.student_id %></td>
<td><%= user.school_name %></td>
<td><%= display_auth_state(user.authentication?, user.process_real_name_apply.present?) %></td>
<td><%= display_auth_state(user.professional_certification?, user.process_professional_apply.present?) %></td>
<td><%= display_auth_state user.phone_binded? %></td>
<td><%= display_auth_state prize_user.leader?, error: '' %></td>
<td><%= display_text prize_user.approved_at&.strftime('%Y-%m-%d %H:%M') %></td>
<td><%= display_text prize_user.approver&.real_name %></td>
<td class="action-container">
<% if prize_user.pending? %>
<%= link_to('审批通过', approve_admins_competition_competition_prize_user_path(prize_user.competition, prize_user),
data: { confirm: '确认审批通过吗?' },
remote: true, method: :post, class: 'approve-action') %>
<% else %>
<%= link_to('撤销审批', unapprove_admins_competition_competition_prize_user_path(prize_user.competition, prize_user),
data: { confirm: '确认撤销审批吗?' },
remote: true, method: :post, class: 'approve-action') %>
<% end %>
</td>

@ -0,0 +1 @@
$('.competition-prize-user-list-container .competition-prize-user-item-<%= @prize_user.id %>').html("<%= j( render partial: 'admins/competition_prize_users/shared/tr', locals: { prize_user: @prize_user } ) %>");

@ -0,0 +1,2 @@
$('.admin-modal-container').html("<%= j( render partial: 'admins/competition_prizes/shared/save_competition_prize_modal', locals: { prize: @prize, title: '编辑奖项', form_method: 'PATCH' } ) %>");
$('.modal.admin-save-competition-prize-modal').modal('show');

@ -0,0 +1 @@
$('#competition-prize-card .competition-prize-table tbody').html("<%= j( render partial: 'admins/competition_settings/shared/competition_prizes', locals: { competition: @competition } ) %>");

@ -0,0 +1,2 @@
$('.admin-modal-container').html("<%= j( render partial: 'admins/competition_prizes/shared/save_competition_prize_modal', locals: { prize: @prize, title: '新建奖项', form_method: 'POST' } ) %>");
$('.modal.admin-save-competition-prize-modal').modal('show');

@ -0,0 +1,29 @@
<div class="modal fade admin-save-competition-prize-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><%= title ||= '保存奖项设置' %></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= simple_form_for([:admins, prize.competition, prize], data: { form_method: form_method }, html: { class: 'admin-save-competition-prize-form' }, defaults: { wrapper_html: { class: 'offset-md-1 col-md-10' } }) do |f| %>
<%= f.input :name, label: '奖项名称:', placeholder: '请输入奖项名称' %>
<%= f.input :num, as: :integer, label: '数量:', placeholder: '请输入数量', input_html: { min: 1 } %>
<%= f.input :category, label: '奖励类型:' do %>
<%= f.select :category, [%w(奖金 bonus), %w(无 unset)], {}, class: 'form-control' %>
<% end %>
<div class="error text-danger"></div>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -266,7 +266,7 @@
<% end %>
</div>
<% when 'inform', 'chart', 'resource' %>
<% when 'inform', 'chart', 'resource', 'certificate' %>
<div class="row mt-2 new_module_div linkFormItem">
<div class="col-1 text-right">
<label class="checkbox checkbox-primary mt-1">
@ -315,16 +315,6 @@
<% end %>
<% end %>
<!-- <div class="row mt-2">-->
<!-- <div class="col-1 text-right">-->
<!-- <label class="checkbox checkbox-primary mt-1">-->
<!-- <input id="checkbox2" type="checkbox">-->
<!-- <label for="checkbox2">&nbsp;</label>-->
<!-- </label>-->
<!-- </div>-->
<!-- <div class="col-md-label mt-2">获奖证书</div>-->
<!-- </div>-->
<div class="error my-2 danger text-danger"></div>
<div class="row mt-2 mb-4">
@ -518,5 +508,36 @@
</div>
</div>
</div>
<div class="card mb-5" id="competition-prize-card" data-id="<%= @competition.id %>">
<div class="card-header d-flex justify-content-between align-items-center">
<span class="flex-1">奖项配置</span>
<%= link_to '新增奖项', new_admins_competition_competition_prize_path(@competition), remote: true, class: 'btn btn-primary btn-sm add-competition-prize-btn' %>
<% if @competition.finished? && !@competition.competition_prize_users.exists? %>
<%= javascript_void_link '生成获奖记录', class: 'btn btn-primary btn-sm ml-2 generate-prize-user-action' %>
<% end %>
</div>
<div class="card-body row pt-0">
<table class="table text-center competition-prize-table">
<thead>
<th width="8%">序号</th>
<th width="10%">奖项名称</th>
<th width="10%">数量</th>
<th width="10%">奖励类型</th>
<th width="16%">队员个人证书模板</th>
<th width="16%">团队证书模板</th>
<th width="16%">指导老师证书模板</th>
<th width="14%">操作</th>
</thead>
<tbody>
<%= render 'admins/competition_settings/shared/competition_prizes', competition: @competition %>
</tbody>
</table>
</div>
</div>
<div style="margin-bottom: 8.5rem;"></div>
<%# end %>
<%# end %>
<%= render partial: 'admins/shared/modal/upload_file_modal', locals: { title: '上传证书模板', accept: 'image/*' } %>

@ -0,0 +1,27 @@
<% competition.competition_prizes.each_with_index do |prize, index| %>
<tr class="competition-prize-item-<%= prize.id %>">
<td><%= index + 1 %></td>
<td><%= prize.name %></td>
<td><%= prize.num %></td>
<td><%= prize.category_text %></td>
<td>
<% member_image_exists = Util::FileManage.exists?(prize, CompetitionPrize.member_suffix) %>
<%= image_tag(member_image_exists ? Util::FileManage.source_disk_file_url(prize, CompetitionPrize.member_suffix) : '', height: 60, class: "w-100 preview-image prize-member-image-#{prize.id}", style: member_image_exists ? '' : 'display:none') %>
<%= javascript_void_link member_image_exists ? '重新上传' : '上传模板', class: 'action upload-prize-member-image-action', data: { source_id: prize.id, source_type: 'CompetitionPrize', suffix: CompetitionPrize.member_suffix, toggle: 'modal', target: '.admin-upload-file-modal' } %>
</td>
<td>
<% team_image_exists = Util::FileManage.exists?(prize, CompetitionPrize.team_suffix) %>
<%= image_tag(team_image_exists ? Util::FileManage.source_disk_file_url(prize, CompetitionPrize.team_suffix) : '', height: 60, class: "w-100 preview-image prize-team-image-#{prize.id}", style: team_image_exists ? '' : 'display:none') %>
<%= javascript_void_link team_image_exists ? '重新上传' : '上传模板', class: 'action upload-prize-team-image-action', data: { source_id: prize.id, source_type: 'CompetitionPrize', suffix: CompetitionPrize.team_suffix, toggle: 'modal', target: '.admin-upload-file-modal' } %>
</td>
<td>
<% teacher_image_exists = Util::FileManage.exists?(prize, CompetitionPrize.teacher_suffix) %>
<%= image_tag(teacher_image_exists ? Util::FileManage.source_disk_file_url(prize, CompetitionPrize.teacher_suffix) : '', height: 60, class: "w-100 preview-image prize-teacher-image-#{prize.id}", style: teacher_image_exists ? '' : 'display:none') %>
<%= javascript_void_link teacher_image_exists ? '重新上传' : '上传模板', class: 'action upload-prize-teacher-image-action', data: { source_id: prize.id, source_type: 'CompetitionPrize', suffix: CompetitionPrize.teacher_suffix, toggle: 'modal', target: '.admin-upload-file-modal' } %>
</td>
<td class="action-container">
<%= link_to '编辑', edit_admins_competition_competition_prize_path(competition, prize), remote: true, class: 'action edit-competition-prize-action' %>
<%= delete_link '删除', admins_competition_competition_prize_path(competition, prize, element: ".competition-prize-item-#{prize.id}"), class: 'action delete-competition-prize-action' %>
</td>
</tr>
<% end %>

@ -11,7 +11,7 @@
<%= link_to '报名列表', admins_competition_enroll_lists_path(@competition), class: "nav-link search-form-tab active" %>
</li>
<li class="nav-item">
<%= link_to '获奖证书审批', admins_competition_enroll_lists_path(@competition), class: "nav-link search-form-tab" %>
<%= link_to '获奖证书审批', admins_competition_competition_prize_users_path(@competition), class: "nav-link search-form-tab" %>
</li>
</ul>

@ -36,4 +36,6 @@
<div class="box subject-list-container">
<%= render partial: 'admins/subjects/shared/list', locals: { subjects: @subjects } %>
</div>
</div>
<%= render partial: 'admins/shared/modal/upload_file_modal', locals: { title: '上传图片', accept: 'image/*' } %>

@ -69,5 +69,4 @@
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: subjects } %>
<%= render partial: 'admins/shared/modal/upload_file_modal', locals: { title: '上传图片', accept: 'image/*' } %>
<%= render partial: 'admins/shared/paginate', locals: { objects: subjects } %>

@ -1,6 +1,6 @@
json.extract! @competition, :id, :name, :sub_title, :identifier, :bonus, :mode
json.visits_count @competition.visits
member_count = @competition.team_members.count
member_count = @competition.team_member_count
json.member_count member_count.zero? ? 268 : member_count
json.start_time @competition.start_time&.strftime("%Y-%m-%d")

@ -5,7 +5,8 @@ json.competitions do
json.competition_status competition.competition_status
json.visits_count competition.visits
member_count = @member_count_map&.fetch(competition.id, 0) || competition.team_members.count
course = competition.competition_mode_setting&.course if competition.mode == 2
member_count = course ? course.students.count : (@member_count_map&.fetch(competition.id, 0) || competition.team_members.count)
json.member_count member_count.zero? ? 268 : member_count
json.image url_to_avatar(competition)

@ -0,0 +1,55 @@
json.leader @leader
json.bank_account @bank_account if @leader
json.personal_certifications do
json.array! @self_prizes do |prize_user|
json.url personal_competitions_certificate_path(current_competition, prize_user)
end
end
json.team_certifications do
json.array! @team_prizes do |team|
json.url team_competitions_certificate_path(current_competition, team)
end
end
json.teams do
json.array! @prize_user_map do |team, prize_users|
json.extract! team, :id, :name
json.bank_account prize_users.find(&:leader?).extra
json.team_members do
json.array! prize_users do |prize_user|
user = prize_user.user
json.role prize_user.role_text
json.name user.real_name
real_name_auth =
if user.authentication?
'authed'
elsif user.process_real_name_apply.present?
'authing'
else
'not_authed'
end
json.real_name_auth real_name_auth
professional_auth =
if user.professional_certification?
'authed'
elsif user.process_professional_apply.present?
'authing'
else
'not_authed'
end
json.professional_auth professional_auth
json.phone_binded user.phone_binded?
json.email_binded user.email_binded?
end
end
end
end

@ -1,7 +1,7 @@
json.course_members @course_members.each do |member|
user = member.user
json.user_login user.login
json.user_name user.real_name
json.user_login user&.login
json.user_name user&.real_name
# json.course_group member.course_group_name
json.total_score member.score
end

@ -5,7 +5,7 @@ json.partial! "homework_btn_check", locals: {identity: @user_course_identity, ho
json.partial! "student_btn_check", locals: {identity: @user_course_identity, homework: @homework, work: @work}
json.(@homework, :unified_setting, :publish_time, :end_time, :late_penalty, :allow_late, :late_time, :work_public,
:score_open, :answer_public)
:score_open, :answer_public, :total_score)
json.group_settings @course_groups do |group|
json.group_id group.id

@ -86,7 +86,7 @@ if @homework.homework_type == "practice"
json.work_efficiency @homework.work_efficiency
json.student_works @student_works.each do |work|
json.(work, :id, :work_status, :update_time, :ultimate_score)
json.(work, :id, :work_status, :update_time, :ultimate_score, :myshixun_id)
json.late_penalty work.late_penalty if @homework.allow_late
json.work_score work_score_format(work.work_score, @current_user == work.user, @score_open)

@ -10,6 +10,7 @@ json.user_identity @user.identity
json.tidding_count 0
json.user_phone_binded @user.phone.present?
json.phone @user.phone
json.email @user.mail
json.profile_completed @user.profile_completed?
json.professional_certification @user.professional_certification
if @course

@ -1,4 +1,6 @@
admins-mirror_scripts: 'admins-mirror_repositories'
admins-laboratory_settings: 'admins-laboratories'
admins-carousels: 'admins-laboratories'
admins-competition_settings: 'admins-competitions'
admins-competition_settings: 'admins-competitions'
admins-enroll_lists: 'admins-competitions'
admins-competition_prize_users: 'admins-competitions'

@ -0,0 +1,6 @@
zh-CN:
enumerize:
competition_prize:
category:
bonus: '奖金'
unset: '无'

@ -0,0 +1,8 @@
'zh-CN':
activemodel:
attributes:
competitions/save_prize_team_account_form:
bank: '开户行'
second_bank: '支行'
card_no: '卡号'

@ -114,8 +114,8 @@ Rails.application.routes.draw do
resource :password, only: [:update]
resource :avatar, only: [:update]
resource :auth_attachment, only: [:create]
resource :authentication_apply, only: [:create]
resource :professional_auth_apply, only: [:create]
resource :authentication_apply, only: [:create, :destroy]
resource :professional_auth_apply, only: [:create, :destroy]
resources :open_users, only: [:destroy]
end
end
@ -510,7 +510,7 @@ Rails.application.routes.draw do
post :join_exercise_banks # 加入习题集
post :publish # 立即发布
post :end_exercise # 立即截止
``
end
end
@ -626,6 +626,7 @@ Rails.application.routes.draw do
post :cancel_exercise
get :begin_commit #提交前的弹窗
get :publish_groups
post :adjust_score
end
resources :exercise_questions,only:[:new,:create,:index]
end
@ -809,6 +810,14 @@ Rails.application.routes.draw do
get :chart_rules
post :update_chart_rules
end
resource :prize_leader_account, only: [:update]
resource :prize, only: [:show]
resources :certificates, only: [] do
member do
get :personal
get :team
end
end
end
end
@ -1043,6 +1052,14 @@ Rails.application.routes.draw do
post :calculate_stage_score
end
end
resources :competition_prizes, only: [:index, :new, :create, :edit, :update, :destroy]
resources :competition_prize_users, only: [:index, :create] do
member do
post :approve
post :unapprove
end
end
end
resources :weapp_carousels, only: [:index, :create, :update, :destroy] do

@ -0,0 +1,5 @@
class AddTotalScoreToHomeworkCommons < ActiveRecord::Migration[5.2]
def change
add_column :homework_commons, :total_score, :float, default: 100
end
end

@ -0,0 +1,10 @@
class InitCompetitionCertificateModuleData < ActiveRecord::Migration[5.2]
def change
Competition.find_each do |competition|
competition.competition_modules.where(module_type: 'certificate').delete_all
position = competition.competition_modules.maximum(:position) + 1
competition.competition_modules.create(module_type: 'certificate', position: position, name: '获奖证书', hidden: true)
end
end
end

@ -0,0 +1,13 @@
class CreateCompetitionPrizes < ActiveRecord::Migration[5.2]
def change
create_table :competition_prizes do |t|
t.references :competition
t.string :name
t.string :category
t.integer :num
t.timestamps
end
end
end

@ -0,0 +1,20 @@
class CreateCompetitionPrizeUsers < ActiveRecord::Migration[5.2]
def change
create_table :competition_prize_users do |t|
t.references :competition
t.references :competition_team
t.references :competition_prize
t.references :user
t.references :approver
t.string :status
t.integer :rank
t.boolean :leader, default: false
t.text :extra
t.datetime :approved_at
t.timestamps
end
end
end

@ -0,0 +1,13 @@
class CreateExerciseUserScores < ActiveRecord::Migration[5.2]
def change
create_table :exercise_user_scores do |t|
t.references :exercise, index: true
t.references :exercise_user, index: true
t.float :score
t.text :comment
t.references :user, index: true
t.timestamps
end
end
end

File diff suppressed because one or more lines are too long

@ -20922,9 +20922,9 @@ span.CodeMirror-selectedtext {
}
/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */
/*!
* Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
/*!
* Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
*/
@font-face {
font-family: FontAwesome;
@ -25681,6 +25681,48 @@ input.form-control {
border: none;
}
/* line 91, app/assets/stylesheets/admins/competition_settings.scss */
.admins-competition-settings-index-page .large_panel .task_Input_div:nth-child(3n-2) > span.col-4 {
-webkit-box-flex: 0;
flex: 0 0 81px;
max-width: 81px;
}
/* line 95, app/assets/stylesheets/admins/competition_settings.scss */
.admins-competition-settings-index-page .large_panel .task_Input_div:nth-child(3n-2) {
-webkit-box-flex: 0;
flex: 0 0 50%;
max-width: 50%;
}
/* line 99, app/assets/stylesheets/admins/competition_settings.scss */
.admins-competition-settings-index-page .large_panel .task_Input_div:nth-child(3n-1) {
-webkit-box-flex: 0;
flex: 0 0 25%;
max-width: 25%;
}
/* line 103, app/assets/stylesheets/admins/competition_settings.scss */
.admins-competition-settings-index-page .large_panel .task_Input_div:nth-child(3n) {
-webkit-box-flex: 0;
flex: 0 0 33.3%;
max-width: 33.3%;
}
/* line 107, app/assets/stylesheets/admins/competition_settings.scss */
.admins-competition-settings-index-page .large_panel .task_Input_div:nth-child(3n) > span.col-4 {
-webkit-box-flex: 0;
flex: 0 0 25%;
max-width: 25%;
}
/* line 111, app/assets/stylesheets/admins/competition_settings.scss */
.admins-competition-settings-index-page .large_panel .task_Input_div:nth-child(3n) > div.col-6 {
-webkit-box-flex: 0;
flex: 0 0 58.3%;
max-width: 58.3%;
}
/* line 4, app/assets/stylesheets/admins/cooperatives.scss */
.admins-cooperatives-index-page .coo-img-card .coo-img-item > .drag {
cursor: move;
@ -26142,7 +26184,7 @@ input.form-control {
/* line 27, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header-logo > .logo-label {
display: none;
display: none;
}
/* line 33, app/assets/stylesheets/admins/sidebar.scss */
@ -26214,25 +26256,25 @@ input.form-control {
/* line 83, app/assets/stylesheets/admins/sidebar.scss */
#sidebar .sidebar-header-logo {
display: -webkit-box;
display: flex;
-webkit-box-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
align-items: center;
display: -webkit-box;
display: flex;
-webkit-box-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
align-items: center;
}
/* line 88, app/assets/stylesheets/admins/sidebar.scss */
#sidebar .sidebar-header-logo > img {
width: 40px;
height: auto;
width: 40px;
height: auto;
}
/* line 93, app/assets/stylesheets/admins/sidebar.scss */
#sidebar .sidebar-header-logo > .logo-label {
font-size: 18px;
color: darkgrey;
margin-left: 10px;
font-size: 18px;
color: darkgrey;
margin-left: 10px;
}
/* line 101, app/assets/stylesheets/admins/sidebar.scss */
@ -26336,7 +26378,7 @@ input.form-control {
}
@media (max-width: 768px) {
/* line 182, app/assets/stylesheets/admins/sidebar.scss */
/* line 182, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active {
padding: 10px 5px;
min-width: 40px;
@ -26346,47 +26388,39 @@ input.form-control {
-webkit-transform: none;
transform: none;
}
/* line 190, app/assets/stylesheets/admins/sidebar.scss */
/* line 190, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header {
padding: 0px;
}
/* line 193, app/assets/stylesheets/admins/sidebar.scss */
/* line 193, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header .sidebar-header-logo {
display: none;
}
/* line 197, app/assets/stylesheets/admins/sidebar.scss */
/* line 197, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header #sidebarCollapse {
width: 30px;
height: 20px;
}
/* line 203, app/assets/stylesheets/admins/sidebar.scss */
/* line 203, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul li a {
padding: 10px;
font-size: 0.85em;
}
/* line 207, app/assets/stylesheets/admins/sidebar.scss */
/* line 207, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul li a i {
margin-right: 0;
display: block;
margin-bottom: 5px;
}
/* line 214, app/assets/stylesheets/admins/sidebar.scss */
/* line 214, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active > ul > li > a > i {
font-size: 1.8em;
}
/* line 218, app/assets/stylesheets/admins/sidebar.scss */
/* line 218, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul ul a {
padding: 10px !important;
}
/* line 227, app/assets/stylesheets/admins/sidebar.scss */
/* line 227, app/assets/stylesheets/admins/sidebar.scss */
.dropdown-toggle::after {
top: auto;
bottom: 10px;

@ -29891,13 +29891,35 @@ function customConfirm(opts){
return $.confirm($.extend({}, defaultOpts, opts))
}
function show_success_flash(){
function customLoading(opts) {
var loading;
var defaultOpts = {
content: opts.ajax,
contentLoaded: function(){
setTimeout(function(){
loading.close()
}, 200);
}
}
loading = $.confirm($.extend({}, defaultOpts, opts));
return loading;
}
function show_success_flash(message){
$.notify({
message: '操作成功'
message: message || '操作成功'
},{
type: 'success'
});
}
function showErrorNotify(message){
$.notify({
message: message || '操作失败'
},{
type: 'danger'
});
}
;
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :

File diff suppressed because one or more lines are too long

@ -54,11 +54,11 @@ class RegistrationSearch extends React.Component {
/>
<p style={{
width: "300px",
width: "583px",
color: "#07140E",
fontSize: '16px',
marginTop: " 7px",
marginLeft: "583px",
marginLeft: "300px",
textAlign: "right",
lineHeight: " 24px"
}}>战队总数<span

@ -3171,7 +3171,7 @@ class Listofworksstudentone extends Component {
}
daochuzuoye = () => {
let url = `/homework_commons/${this.props.match.params.homeworkid}/works_list.xlsx?group_id=${this.state.checkedValuesineinfo === undefined || this.state.checkedValuesineinfo === null ? "" : this.state.checkedValuesineinfo}&search=${this.state.searchtext === undefined || this.state.searchtext === null ? "" : this.state.searchtext}`
let url = `/homework_commons/${this.props.match.params.homeworkid}/works_list.xlsx?course_group=${this.state.checkedValuesineinfo === undefined || this.state.checkedValuesineinfo === null ? "" : this.state.checkedValuesineinfo}&work_status=${this.state.course_groupyslstwo === undefined || this.state.course_groupyslstwo === null ? "" : this.state.course_groupyslstwo}&search=${this.state.searchtext === undefined || this.state.searchtext === null ? "" : this.state.searchtext}`
this.confirmysl(url);
}

@ -636,6 +636,7 @@ class Trainingjobsetting extends Component {
borredszfls:this.state.borredszfls,
borredszfl:this.state.borredszfl,
})
this.scrollToAnchor("zongfentimeid");
return;
}
var latedeductiontwos = 0;
@ -651,7 +652,7 @@ class Trainingjobsetting extends Component {
// console.log(len);
}
var max = latedeductiontwos + len;
let max = latedeductiontwos + len;
// if (max > 100) {
// console.log("max>100");
// this.props.showNotification(`总分值+效率效率分之和要等于100现在分值为` + max);
@ -662,6 +663,20 @@ class Trainingjobsetting extends Component {
// this.props.showNotification(`总分值+效率效率分之和要等于100现在分值为` + max);
// return;
// }
if (this.state.proportion === "自定义分值") {
try {
if(parseFloat(this.state.CalculateMax)!==parseFloat(max)){
this.props.showNotification(`分值之和必须等于总分值:${this.state.CalculateMax}`);
this.scrollToAnchor("zongfentimeid");
return;
}
}catch (e) {
}
}
}
var url = `/homework_commons/${homeworkid}/update_settings.json`;
@ -1260,7 +1275,7 @@ class Trainingjobsetting extends Component {
this.Empiricalvalueratio(value, this.state.CalculateMax, true);
} else if (this.state.proportion === "自定义分值") {
this.Calculatethetotalscore(value, this.state.challenge_settings);
// this.Calculatethetotalscore(value, this.state.challenge_settings);
}
}
@ -1306,7 +1321,16 @@ class Trainingjobsetting extends Component {
if (this.state.completionefficiencyscore === true) {
latedeductiontwos = this.state.latedeductiontwo;
}
this.Calculatethetotalscore(latedeductiontwos, challenge_settings);
if (this.state.proportion === "均分比例") {
this.Calculatethetotalscore(latedeductiontwos, challenge_settings);
} else if (this.state.proportion === "经验值比例") {
this.Calculatethetotalscore(latedeductiontwos, challenge_settings);
}
// if (nubmer > 100) {
// message.error("请输入小于100的数");
// this.setState({
@ -2595,6 +2619,7 @@ class Trainingjobsetting extends Component {
<InputNumber min={0} className={borredszf}
style={{width: "100px", color: "#999999"}}
disabled={!flagPageEdit}
id={"zongfentimeid"}
step={0.1}
onChange={(e)=>this.Totalscorecalculation(e)}
value={this.state.CalculateMax}
@ -2722,12 +2747,12 @@ class Trainingjobsetting extends Component {
{this.state.challenge_settings === undefined ? "" : this.state.challenge_settings.map((object, index) => {
return (
<li className="yslflexhomes" key={index}>
<Checkbox className="ml110 font-16"
<Checkbox className="ml110 font-16 maxnamewidth340"
disabled={!flagPageEditsbox}
style={{"width": "200px", color: "#05101A", lineHeight: "48px"}}
style={{"width": "340px", color: "#05101A", lineHeight: "48px"}}
checked={object.checked}
onChange={(value) => this.onChangedatasheet(value, index)}
>{object.challenge_name}</Checkbox>
><a title={object.challenge_name} >{object.challenge_name}</a></Checkbox>
{
object.checked === false ?
<div style={{lineHeight: "48px", width: "60px"}}>
@ -2740,6 +2765,7 @@ class Trainingjobsetting extends Component {
width: "60px",
textAlign: "center",
marginTop: "14px",
marginLeft: "5px "
}}>可不做
</div>
</div>
@ -2747,7 +2773,7 @@ class Trainingjobsetting extends Component {
<div style={{lineHeight: "48px", width: "60px"}}></div>
}
<InputNumber disabled={!flagPageEdits} className=" c_grey" min={0}
style={{"width": "100px", "margin-left": "100px", color: "#666666"}}
style={{"width": "100px", "margin-left": "20px ", color: "#666666"}}
onChange={(value) => this.hangeTopicNametwodatasheet(value, index)}
step={0.1}
value={object.challenge_score}

@ -109,3 +109,13 @@
height: 20px;
min-height: 20px;
}
.maxnamewidth340 {
max-width: 340px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: default;
width: 340px;
max-width: 340px;
}

@ -0,0 +1,22 @@
TPIContextProvider
tpi主要的state容器主要接口`/tasks/${stageId}.json`一次性获取所有tpi首屏展示所需要的信息除了代码内容。
接口返回的内容包括
当前用户信息、shixun、challenge、game、测试集、vnc等等
其他接口:
`/tasks/${game.identifier}/check_test_sets.json`
解锁测试集
`/tasks/${game.identifier}/plus_or_cancel_praise.json`
给关卡点赞
`/tasks/${game.identifier}/picture_display.json`
如果评测通过,服务端返回了`data.picture`,会调用这个接口获取可视化的评测结果,类型包括
qrcode 二维码 安卓实训
image 图片
txt
html
mp3
mp4
代码内容通过以下接口获取:
`/tasks/${game.identifier}/rep_content.json?path=${path}&status=${status}&retry=${isRetry ? 1 : 0}`

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe ExerciseUserScore, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading…
Cancel
Save