合并阿里云

dev_auth
杨树林 5 years ago
commit 485fd7c3b1

@ -471,45 +471,45 @@ $(document).on('turbolinks:load', function(){
' </div>\n' + ' </div>\n' +
' <div id="small_panel_'+count+'" class="small_panel">\n' + ' <div id="small_panel_'+count+'" class="small_panel">\n' +
' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' + ' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' +
' <span class="col-1 mt-2 subName">第1阶段</span>\n' + ' <span class="mt-2 subName mr10">第1阶段</span>\n' +
' <div class="flex-1">\n' + ' <div class="flex-1">\n' +
' <div class="row">\n' + ' <div class="row">\n' +
' <span class="mt-2 ml20">有效时间:</span>\n' + ' <div class="row col-6"><span class="mt-2 ml20">有效时间:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding">\n' +
' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' + ' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' +
' </div>\n' + ' </div>\n' +
' <span class="mt-2">~</span>\n' + ' <span class="mt-2">~</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' + ' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-2 text-right mt-2 no_padding">总任务数:</span>\n' + ' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding">总任务数:</span>\n' +
' <div class="col-1 no_padding input_small">\n' + ' <div class="col-6 no_padding ">\n' +
' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' + ' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-1 text-right mt-2 no_padding">成绩来源:</span>\n' + ' <div class="row col-4"><span class="col-3 text-right mt-2 no_padding">成绩来源:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-7 no_padding ">\n' +
' <select class="form-control" name="stage[][score_source]">\n' + ' <select class="form-control" name="stage[][score_source]">\n' +
' <option value="0">经验值</option>\n' + ' <option value="0">经验值</option>\n' +
' <option value="1">预测准确率</option>\n' + ' <option value="1">预测准确率</option>\n' +
' </select>\n' + ' </select>\n' +
' </div>\n' + ' </div></div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="row mt-2" id="task_Input_sub_new_new">\n' + ' <div class="row mt-2" id="task_Input_sub_new_new">\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务1</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务1</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务2</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务2</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务3</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务3</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
@ -547,45 +547,45 @@ $(document).on('turbolinks:load', function(){
var html='<div class="row d-flex small_panel_item" attr_line="sub_'+index+'_'+count+'" count="'+count+'">\n' + var html='<div class="row d-flex small_panel_item" attr_line="sub_'+index+'_'+count+'" count="'+count+'">\n' +
' <span class="col-1 mt-2 subName">第'+showCount+'阶段</span>\n' + ' <span class="mr10 mt-2 subName">第'+showCount+'阶段</span>\n' +
' <div class="flex-1">\n' + ' <div class="flex-1">\n' +
' <div class="row">\n' + ' <div class="row">\n' +
' <span class="mt-2 ml20">有效时间:</span>\n' + ' <div class="row col-6"><span class="mt-2 ml20 mr10">有效时间:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' + ' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' +
' </div>\n' + ' </div>\n' +
' <span class="mt-2">~</span>\n' + ' <span class="mt-2">~</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' + ' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-2 text-right mt-2 no_padding">总任务数:</span>\n' + ' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding mr10">总任务数:</span>\n' +
' <div class="col-1 no_padding input_small">\n' + ' <div class="col-6 no_padding ">\n' +
' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' + ' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-1 text-right mt-2 no_padding">成绩来源:</span>\n' + ' <div class="row col-4"><span class="col-3 mr10 text-right mt-2 no_padding">成绩来源:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-7 no_padding ">\n' +
' <select class="form-control" name="stage[][score_source]">\n' + ' <select class="form-control" name="stage[][score_source]">\n' +
' <option value="0">经验值</option>\n' + ' <option value="0">经验值</option>\n' +
' <option value="1">预测准确率</option>\n' + ' <option value="1">预测准确率</option>\n' +
' </select>\n' + ' </select>\n' +
' </div>\n' + ' </div></div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="row mt-2" id="task_Input_sub_'+index+'_'+count+'">\n'+ ' <div class="row mt-2" id="task_Input_sub_'+index+'_'+count+'">\n'+
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务1</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务1</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务2</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务2</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务3</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务3</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
@ -600,6 +600,67 @@ $(document).on('turbolinks:load', function(){
$(".stage-update-form .section-start-time").datetimepicker(timeOptions); $(".stage-update-form .section-start-time").datetimepicker(timeOptions);
$(".stage-update-form .section-end-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');
} }
}); });
@ -633,8 +694,8 @@ function change_total(item) {
var html = ""; var html = "";
if(count > divCount){ if(count > divCount){
for(var i=0;i < count-divCount ;i++){ for(var i=0;i < count-divCount ;i++){
html+='<div class="col-4 row task_Input_div"><span class="col-3 text-center mt-3">任务'+(divCount+i+1)+'</span>\n' + html+='<div class="col-4 row task_Input_div"><span class="col-4 text-right mt-3 no_padding mr10">任务'+(divCount+i+1)+'</span>\n' +
'<div class="col-8">\n' + '<div class="col-6 no_padding">\n' +
'<input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + '<input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
'</div>\n' + '</div>\n' +
'</div>'; '</div>';
@ -688,45 +749,45 @@ function addNewTab(competition_id) {
' </div>\n' + ' </div>\n' +
' <div id="small_panel_'+count+'" class="small_panel">\n' + ' <div id="small_panel_'+count+'" class="small_panel">\n' +
' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' + ' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' +
' <span class="col-1 mt-2 subName">第1阶段</span>\n' + ' <span class="mt-2 subName mr10">第1阶段</span>\n' +
' <div class="flex-1">\n' + ' <div class="flex-1">\n' +
' <div class="row">\n' + ' <div class="row">\n' +
' <span class="mt-2 ml20">有效时间:</span>\n' + ' <div class="row col-6"><span class="mt-2 ml20 mr10">有效时间:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' + ' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' +
' </div>\n' + ' </div>\n' +
' <span class="mt-2">~</span>\n' + ' <span class="mt-2">~</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding input_middle">\n' +
' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' + ' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-2 text-right mt-2 no_padding">总任务数:</span>\n' + ' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding mr10">总任务数:</span>\n' +
' <div class="col-1 no_padding input_small">\n' + ' <div class="col-6 no_padding ">\n' +
' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' + ' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-1 text-right mt-2 no_padding">成绩来源:</span>\n' + ' <div class="row col-4"><span class="col-3 text-right mt-2 no_padding mr10">成绩来源:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-7 no_padding ">\n' +
' <select class="form-control" name="stage[][score_source]">\n' + ' <select class="form-control" name="stage[][score_source]">\n' +
' <option value="0">经验值</option>\n' + ' <option value="0">经验值</option>\n' +
' <option value="1">预测准确率</option>\n' + ' <option value="1">预测准确率</option>\n' +
' </select>\n' + ' </select>\n' +
' </div>\n' + ' </div></div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="row mt-2" id="task_Input_sub_new_new">\n' + ' <div class="row mt-2" id="task_Input_sub_new_new">\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务1</span>\n' + ' <span class="col-3 text-right mt-3 no_padding mr10">任务1</span>\n' +
' <div class="col-8">\n' + ' <div class="col-8 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务2</span>\n' + ' <span class="col-3 text-right mt-3 no_padding mr10">任务2</span>\n' +
' <div class="col-8">\n' + ' <div class="col-8 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务3</span>\n' + ' <span class="col-3 text-right no_padding mr10 mt-3">任务3</span>\n' +
' <div class="col-8">\n' + ' <div class="col-8 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +

@ -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)) 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({ $.notify({
message: message || '操作成功' message: message || '操作成功'
},{ },{
type: 'success' type: 'success'
}); });
} }
function showErrorNotify(message){
$.notify({
message: message || '操作失败'
},{
type: 'danger'
});
}

@ -87,5 +87,30 @@
.row:last-child{ .row:last-child{
border:none; border:none;
} }
.task_Input_div:nth-child(3n-2) > span.col-4{
flex: 0 0 81px;
max-width: 81px;
}
.task_Input_div:nth-child(3n-2){
flex: 0 0 50%;
max-width: 50%;
}
.task_Input_div:nth-child(3n-1){
flex: 0 0 25%;
max-width: 25%;
}
.task_Input_div:nth-child(3n){
flex: 0 0 33.3%;
max-width: 33.3%;
}
.task_Input_div:nth-child(3n) > span.col-4{
flex: 0 0 25%;
max-width: 25%;
}
.task_Input_div:nth-child(3n) > div.col-6{
flex: 0 0 58.3%;
max-width: 58.3%;
}
} }
} }

@ -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 def index
@modules = current_competition.unhidden_competition_modules.order(position: :asc) @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 end
def show def show

@ -22,7 +22,7 @@ class Competitions::CompetitionsController < Competitions::BaseController
@count = competitions.count @count = competitions.count
competitions = competitions.order(published_at: :desc, online_time: :desc) 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) ids = @competitions.map(&:id)
@member_count_map = TeamMember.where(competition_id: ids).group(:competition_id).count @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) user_ids = all_members.map(&:user_id)
rank = user_ids.index(current_user.id).to_i + 1 rank = user_ids.index(current_user.id).to_i + 1
if rank > 10 if rank > 10
current_member = all_members.select{|member| member.user_id == current_user.id} current_member = all_members.select{|member| member.user_id == current_user.id}.first
@course_members << current_member @course_members << current_member if current_member.present?
end end
end end
end end

@ -605,6 +605,21 @@ class ExercisesController < ApplicationController
end end
end end
# 对未提交的用户进行调分
def adjust_score
exercise_user = @exercise.exercise_users.find_by!(user_id: params[:user_id])
tip_exception("已提交的作品请去评阅页进行调分") if exercise_user.commit_status == 1
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 def my_exercises
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do

@ -125,7 +125,7 @@ class HomeworkCommonsController < ApplicationController
# 学生已提交作品且补交(提交)已截止、作品公开、非匿评阶段 # 学生已提交作品且补交(提交)已截止、作品公开、非匿评阶段
if @work&.work_status.to_i > 0 && (@homework.work_public || @homework.score_open) && 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)) ((!@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 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" 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("缺少answer_open_evaluation参数") if params[:answer_open_evaluation].nil?
tip_exception("缺少work_efficiency参数") if params[:work_efficiency].nil? tip_exception("缺少work_efficiency参数") if params[:work_efficiency].nil?
tip_exception("缺少eff_score参数") if params[:work_efficiency] && params[:eff_score].blank? 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("效率分不能小于等于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("缺少shixun_evaluation参数") if params[:shixun_evaluation].blank?
tip_exception("缺少challenge_settings参数") if params[:challenge_settings].blank? tip_exception("缺少challenge_settings参数") if params[:challenge_settings].blank?
# tip_exception("缺少challenge_id参数") if params[:challenge_settings][:challenge_id].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 # params[:challenge_settings][:challenge_score].length != params[:challenge_settings][:challenge_id].length
current_eff_score = @homework.eff_score current_eff_score = @homework.eff_score
@homework.total_score = params[:total_score]
@homework.work_efficiency = params[:work_efficiency] @homework.work_efficiency = params[:work_efficiency]
@homework.eff_score = params[:work_efficiency] ? params[:eff_score].to_i : 0 @homework.eff_score = params[:work_efficiency] ? params[:eff_score].to_i : 0

@ -534,7 +534,9 @@ class StudentWorksController < ApplicationController
# 作品调分 # 作品调分
def adjust_score def adjust_score
tip_exception("分数不能为空") if params[:score].blank? 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 ActiveRecord::Base.transaction do
begin begin
# 分数不为空的历史评阅都置为失效 # 分数不为空的历史评阅都置为失效

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

@ -8,6 +8,12 @@ class Users::ProfessionalAuthAppliesController < Users::BaseAccountController
render_error(ex.message) render_error(ex.message)
end end
def destroy
return render_error('已认证后不能撤销') if observed_user.professional_certification?
observed_user.process_professional_apply&.revoke!
render_ok
end
private private
def create_params 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 :competition_managers, dependent: :destroy
has_many :managers, through: :competition_managers, source: :user 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 after_create :create_competition_modules
def mode_type def mode_type
@ -46,6 +49,12 @@ class Competition < ApplicationRecord
end end
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 def sponsor_schools_name
sponsor_schools.map{|sponsor| sponsor.school.name} sponsor_schools.map{|sponsor| sponsor.school.name}
end end
@ -131,7 +140,7 @@ class Competition < ApplicationRecord
end end
def all_module_types def all_module_types
%w[home enroll inform chart resource] %w[home enroll inform chart resource certificate]
end end
def max_stage_end_time def max_stage_end_time
@ -146,6 +155,10 @@ class Competition < ApplicationRecord
user && competition_managers.exists?(user_id: user.id) user && competition_managers.exists?(user_id: user.id)
end end
def finished?
end_time.blank? || end_time < Time.now
end
private private
def get_module_name type def get_module_name type
@ -155,6 +168,7 @@ class Competition < ApplicationRecord
when 'inform' then '通知公告' when 'inform' then '通知公告'
when 'chart' then '排行榜' when 'chart' then '排行榜'
when 'resource' then '资料下载' when 'resource' then '资料下载'
when 'certificate' then '获奖证书'
else '' else ''
end end
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 :members, -> { without_teachers }, class_name: 'TeamMember'
has_many :teachers, -> { only_teachers }, class_name: 'TeamMember' has_many :teachers, -> { only_teachers }, class_name: 'TeamMember'
has_many :competition_prize_users, dependent: :destroy
def group_team_type? def group_team_type?
team_type.zero? team_type.zero?
end end
@ -48,4 +50,24 @@ class CompetitionTeam < ApplicationRecord
def members_name def members_name
members.map{|member| member.user.real_name}.join(",") members.map{|member| member.user.real_name}.join(",")
end 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 end

@ -1,8 +1,10 @@
class ExerciseUser < ApplicationRecord class ExerciseUser < ApplicationRecord
# commit_method 0 为默认, 1为学生的手动提交2为倒计时结束后自动提交3为试卷定时截止的自动提交, 4为教师手动的立即截止 # commit_method 0 为默认, 1为学生的手动提交2为倒计时结束后自动提交3为试卷定时截止的自动提交, 4为教师手动的立即截止, 5为老师调分
belongs_to :user belongs_to :user
belongs_to :exercise belongs_to :exercise
has_many :exercise_user_scores, dependent: :destroy
scope :commit_exercise_by_status, lambda { |s| where(commit_status: s) } scope :commit_exercise_by_status, lambda { |s| where(commit_status: s) }
scope :exercise_user_committed, -> {where("commit_status != ?",0) } 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)} 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? phone.present?
end end
def email_binded?
mail.present?
end
def self.current=(user) def self.current=(user)
Thread.current[:current_user] = user Thread.current[:current_user] = user
end 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 class Users::ApplyAuthenticationService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params attr_reader :user, :params
def initialize(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 %> <% end %>
</div> </div>
<% when 'inform', 'chart', 'resource' %> <% when 'inform', 'chart', 'resource', 'certificate' %>
<div class="row mt-2 new_module_div linkFormItem"> <div class="row mt-2 new_module_div linkFormItem">
<div class="col-1 text-right"> <div class="col-1 text-right">
<label class="checkbox checkbox-primary mt-1"> <label class="checkbox checkbox-primary mt-1">
@ -315,16 +315,6 @@
<% end %> <% end %>
<% 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="error my-2 danger text-danger"></div>
<div class="row mt-2 mb-4"> <div class="row mt-2 mb-4">
@ -386,34 +376,40 @@
<div id="small_panel_<%= index + 1 %>" class="small_panel"> <div id="small_panel_<%= index + 1 %>" class="small_panel">
<% stage.competition_stage_sections.each_with_index do |section, j| %> <% stage.competition_stage_sections.each_with_index do |section, j| %>
<div class="row d-flex small_panel_item" attr_line="sub_<%= index %>_<%= j %>" count="<%= j + 1 %>"> <div class="row d-flex small_panel_item" attr_line="sub_<%= index %>_<%= j %>" count="<%= j + 1 %>">
<span class="col-1 mt-2 subName">第<%= j + 1 %>阶段</span> <span class="mt-2 subName mr10">第<%= j + 1 %>阶段</span>
<div class="flex-1"> <div class="flex-1">
<div class="row"> <div class="row">
<span class="mt-2 ml20">有效时间:</span> <div class="row col-6">
<div class="col-2 no_padding input_middle"> <span class="ml20 mt-2 mr10">有效时间:</span>
<%= text_field_tag 'stage[][start_time]', section.start_time&.strftime('%Y-%m-%d %H:%M'), autocomplete: 'off', class: 'section-start-time form-control', placeholder: '有效开始时间' %> <div class="col-4 no_padding">
</div> <%= text_field_tag 'stage[][start_time]', section.start_time&.strftime('%Y-%m-%d %H:%M'), autocomplete: 'off', class: 'section-start-time form-control', placeholder: '有效开始时间' %>
<span class="mt-2">~</span> </div>
<div class="col-2 no_padding input_middle"> <span class="mt-2">~</span>
<%= text_field_tag 'stage[][end_time]', section.end_time&.strftime('%Y-%m-%d %H:%M'), autocomplete: 'off', class: 'section-end-time form-control', placeholder: '有效结束时间' %> <div class="col-4 no_padding">
<%= text_field_tag 'stage[][end_time]', section.end_time&.strftime('%Y-%m-%d %H:%M'), autocomplete: 'off', class: 'section-end-time form-control', placeholder: '有效结束时间' %>
</div>
</div> </div>
<span class="col-2 text-right mt-2 no_padding">总任务数:</span> <div class="row col-3">
<div class="col-1 no_padding input_small"> <span class="col-4 text-right mt-2 no_padding mr10">总任务数:</span>
<input type="number" class="form-control task_all" value="<%= section.entry %>" onchange="change_total(this)" name="stage[][entry]"/> <div class="col-6 no_padding">
<input type="number" class="form-control task_all" value="<%= section.entry %>" onchange="change_total(this)" name="stage[][entry]"/>
</div>
</div> </div>
<span class="col-1 text-right mt-2 no_padding">成绩来源:</span> <div class="row col-4">
<div class="col-2 no_padding input_middle"> <span class="col-3 text-right mt-2 no_padding mr10">成绩来源:</span>
<select class="form-control" name="stage[][score_source]"> <div class="col-7 no_padding">
<option value="0" <%= section.score_source == 0 ? "selected='selected'" : "" %>>经验值</option> <select class="form-control" name="stage[][score_source]">
<option value="1" <%= section.score_source == 1 ? "selected='selected'" : "" %>>预测准确率</option> <option value="0" <%= section.score_source == 0 ? "selected='selected'" : "" %>>经验值</option>
</select> <option value="1" <%= section.score_source == 1 ? "selected='selected'" : "" %>>预测准确率</option>
</select>
</div>
</div> </div>
</div> </div>
<div class="row mt-2" id="task_Input_sub_<%= index %>_<%= j %>"> <div class="row mt-2" id="task_Input_sub_<%= index %>_<%= j %>">
<% section.competition_entries.each_with_index do |entry, z| %> <% section.competition_entries.each_with_index do |entry, z| %>
<div class="col-4 row task_Input_div"> <div class="col-4 row task_Input_div">
<span class="col-3 text-center mt-3">任务<%= z+1 %></span> <span class="col-4 text-right mt-3 no_padding mr10">任务<%= z+1 %></span>
<div class="col-8"> <div class="col-6 no_padding">
<input type="text" class="form-control mt-2" value="<%= entry.shixun_identifier %>" name="stage[][identifiers][]" placeholder="请填写实训ID"> <input type="text" class="form-control mt-2" value="<%= entry.shixun_identifier %>" name="stage[][identifiers][]" placeholder="请填写实训ID">
</div> </div>
</div> </div>
@ -450,45 +446,51 @@
</div> </div>
<div id="small_panel_1" class="small_panel"> <div id="small_panel_1" class="small_panel">
<div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1"> <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">
<span class="col-1 mt-2 subName">第1阶段</span> <span class="mt-2 subName mr10">第1阶段</span>
<div class="flex-1"> <div class="flex-1">
<div class="row"> <div class="row">
<span class="mt-2 ml20">有效时间:</span> <div class="row col-6">
<div class="col-2 no_padding input_middle"> <span class="mt-2 ml20 mr10">有效时间:</span>
<%= text_field_tag 'stage[][start_time]', '', autocomplete: 'off', class: 'section-start-time form-control', placeholder: '有效开始时间' %> <div class="col-4 no_padding">
</div> <%= text_field_tag 'stage[][start_time]', '', autocomplete: 'off', class: 'section-start-time form-control', placeholder: '有效开始时间' %>
<span class="mt-2">~</span> </div>
<div class="col-2 no_padding input_middle"> <span class="mt-2">~</span>
<%= text_field_tag 'stage[][end_time]', '', autocomplete: 'off', class: 'section-end-time form-control', placeholder: '有效结束时间' %> <div class="col-4 no_padding">
<%= text_field_tag 'stage[][end_time]', '', autocomplete: 'off', class: 'section-end-time form-control', placeholder: '有效结束时间' %>
</div>
</div> </div>
<span class="col-2 text-right mt-2 no_padding">总任务数:</span> <div class="row col-3">
<div class="col-1 no_padding input_small"> <span class="col-4 text-right mt-2 no_padding mr10">总任务数:</span>
<input type="number" class="form-control task_all" onchange="change_total(this)" value="3" name="stage[][entry]"/> <div class="col-6 no_padding">
<input type="number" class="form-control task_all" onchange="change_total(this)" value="3" name="stage[][entry]"/>
</div>
</div> </div>
<span class="col-1 text-right mt-2 no_padding">成绩来源:</span> <div class="row col-4">
<div class="col-2 no_padding input_middle"> <span class="col-3 text-right mt-2 no_padding mr10">成绩来源:</span>
<select class="form-control" name="stage[][score_source]"> <div class="col-7 no_padding">
<option value="0">经验值</option> <select class="form-control" name="stage[][score_source]">
<option value="1">预测准确率</option> <option value="0">经验值</option>
</select> <option value="1">预测准确率</option>
</select>
</div>
</div> </div>
</div> </div>
<div class="row mt-2" id="task_Input_sub_new_new"> <div class="row mt-2" id="task_Input_sub_new_new">
<div class="col-4 row task_Input_div"> <div class="col-4 row task_Input_div">
<span class="col-3 text-center mt-3">任务1</span> <span class="col-4 text-right mt-3 no_padding mr10">任务1</span>
<div class="col-8"> <div class="col-6 no_padding">
<input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID"> <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">
</div> </div>
</div> </div>
<div class="col-4 row task_Input_div"> <div class="col-4 row task_Input_div">
<span class="col-3 text-center mt-3">任务2</span> <span class="col-4 text-right mt-3 no_padding mr10">任务2</span>
<div class="col-8"> <div class="col-6 no_padding">
<input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID"> <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">
</div> </div>
</div> </div>
<div class="col-4 row task_Input_div"> <div class="col-4 row task_Input_div">
<span class="col-3 text-center mt-3">任务3</span> <span class="col-4 text-right mt-3 no_padding mr10">任务3</span>
<div class="col-8"> <div class="col-6 no_padding">
<input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID"> <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">
</div> </div>
</div> </div>
@ -506,5 +508,36 @@
</div> </div>
</div> </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> <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" %> <%= link_to '报名列表', admins_competition_enroll_lists_path(@competition), class: "nav-link search-form-tab active" %>
</li> </li>
<li class="nav-item"> <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> </li>
</ul> </ul>

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

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

@ -1,6 +1,6 @@
json.extract! @competition, :id, :name, :sub_title, :identifier, :bonus, :mode json.extract! @competition, :id, :name, :sub_title, :identifier, :bonus, :mode
json.visits_count @competition.visits 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.member_count member_count.zero? ? 268 : member_count
json.start_time @competition.start_time&.strftime("%Y-%m-%d") json.start_time @competition.start_time&.strftime("%Y-%m-%d")

@ -5,7 +5,8 @@ json.competitions do
json.competition_status competition.competition_status json.competition_status competition.competition_status
json.visits_count competition.visits 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.member_count member_count.zero? ? 268 : member_count
json.image url_to_avatar(competition) 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| json.course_members @course_members.each do |member|
user = member.user user = member.user
json.user_login user.login json.user_login user&.login
json.user_name user.real_name json.user_name user&.real_name
# json.course_group member.course_group_name # json.course_group member.course_group_name
json.total_score member.score json.total_score member.score
end 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.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, 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_settings @course_groups do |group|
json.group_id group.id json.group_id group.id

@ -86,7 +86,7 @@ if @homework.homework_type == "practice"
json.work_efficiency @homework.work_efficiency json.work_efficiency @homework.work_efficiency
json.student_works @student_works.each do |work| 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.late_penalty work.late_penalty if @homework.allow_late
json.work_score work_score_format(work.work_score, @current_user == work.user, @score_open) json.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.tidding_count 0
json.user_phone_binded @user.phone.present? json.user_phone_binded @user.phone.present?
json.phone @user.phone json.phone @user.phone
json.email @user.mail
json.profile_completed @user.profile_completed? json.profile_completed @user.profile_completed?
json.professional_certification @user.professional_certification json.professional_certification @user.professional_certification
if @course if @course

@ -2,3 +2,5 @@ admins-mirror_scripts: 'admins-mirror_repositories'
admins-laboratory_settings: 'admins-laboratories' admins-laboratory_settings: 'admins-laboratories'
admins-carousels: '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 :password, only: [:update]
resource :avatar, only: [:update] resource :avatar, only: [:update]
resource :auth_attachment, only: [:create] resource :auth_attachment, only: [:create]
resource :authentication_apply, only: [:create] resource :authentication_apply, only: [:create, :destroy]
resource :professional_auth_apply, only: [:create] resource :professional_auth_apply, only: [:create, :destroy]
resources :open_users, only: [:destroy] resources :open_users, only: [:destroy]
end end
end end
@ -510,7 +510,7 @@ Rails.application.routes.draw do
post :join_exercise_banks # 加入习题集 post :join_exercise_banks # 加入习题集
post :publish # 立即发布 post :publish # 立即发布
post :end_exercise # 立即截止 post :end_exercise # 立即截止
``
end end
end end
@ -626,6 +626,7 @@ Rails.application.routes.draw do
post :cancel_exercise post :cancel_exercise
get :begin_commit #提交前的弹窗 get :begin_commit #提交前的弹窗
get :publish_groups get :publish_groups
post :adjust_score
end end
resources :exercise_questions,only:[:new,:create,:index] resources :exercise_questions,only:[:new,:create,:index]
end end
@ -809,6 +810,14 @@ Rails.application.routes.draw do
get :chart_rules get :chart_rules
post :update_chart_rules post :update_chart_rules
end 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
end end
@ -1043,6 +1052,14 @@ Rails.application.routes.draw do
post :calculate_stage_score post :calculate_stage_score
end end
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 end
resources :weapp_carousels, only: [:index, :create, :update, :destroy] do 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

@ -29898,13 +29898,35 @@ function customConfirm(opts){
return $.confirm($.extend({}, defaultOpts, 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({ $.notify({
message: message || '操作成功' message: message || '操作成功'
},{ },{
type: 'success' type: 'success'
}); });
} }
function showErrorNotify(message){
$.notify({
message: message || '操作失败'
},{
type: 'danger'
});
}
; ;
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
@ -136519,45 +136541,45 @@ $(document).on('turbolinks:load', function(){
' </div>\n' + ' </div>\n' +
' <div id="small_panel_'+count+'" class="small_panel">\n' + ' <div id="small_panel_'+count+'" class="small_panel">\n' +
' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' + ' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' +
' <span class="col-1 mt-2 subName">第1阶段</span>\n' + ' <span class="mt-2 subName mr10">第1阶段</span>\n' +
' <div class="flex-1">\n' + ' <div class="flex-1">\n' +
' <div class="row">\n' + ' <div class="row">\n' +
' <span class="mt-2 ml20">有效时间:</span>\n' + ' <div class="row col-6"><span class="mt-2 ml20">有效时间:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding">\n' +
' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' + ' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' +
' </div>\n' + ' </div>\n' +
' <span class="mt-2">~</span>\n' + ' <span class="mt-2">~</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' + ' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-2 text-right mt-2 no_padding">总任务数:</span>\n' + ' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding">总任务数:</span>\n' +
' <div class="col-1 no_padding input_small">\n' + ' <div class="col-6 no_padding ">\n' +
' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' + ' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-1 text-right mt-2 no_padding">成绩来源:</span>\n' + ' <div class="row col-4"><span class="col-3 text-right mt-2 no_padding">成绩来源:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-7 no_padding ">\n' +
' <select class="form-control" name="stage[][score_source]">\n' + ' <select class="form-control" name="stage[][score_source]">\n' +
' <option value="0">经验值</option>\n' + ' <option value="0">经验值</option>\n' +
' <option value="1">预测准确率</option>\n' + ' <option value="1">预测准确率</option>\n' +
' </select>\n' + ' </select>\n' +
' </div>\n' + ' </div></div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="row mt-2" id="task_Input_sub_new_new">\n' + ' <div class="row mt-2" id="task_Input_sub_new_new">\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务1</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务1</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务2</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务2</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务3</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务3</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
@ -136595,45 +136617,45 @@ $(document).on('turbolinks:load', function(){
var html='<div class="row d-flex small_panel_item" attr_line="sub_'+index+'_'+count+'" count="'+count+'">\n' + var html='<div class="row d-flex small_panel_item" attr_line="sub_'+index+'_'+count+'" count="'+count+'">\n' +
' <span class="col-1 mt-2 subName">第'+showCount+'阶段</span>\n' + ' <span class="mr10 mt-2 subName">第'+showCount+'阶段</span>\n' +
' <div class="flex-1">\n' + ' <div class="flex-1">\n' +
' <div class="row">\n' + ' <div class="row">\n' +
' <span class="mt-2 ml20">有效时间:</span>\n' + ' <div class="row col-6"><span class="mt-2 ml20 mr10">有效时间:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' + ' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' +
' </div>\n' + ' </div>\n' +
' <span class="mt-2">~</span>\n' + ' <span class="mt-2">~</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' + ' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-2 text-right mt-2 no_padding">总任务数:</span>\n' + ' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding mr10">总任务数:</span>\n' +
' <div class="col-1 no_padding input_small">\n' + ' <div class="col-6 no_padding ">\n' +
' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' + ' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-1 text-right mt-2 no_padding">成绩来源:</span>\n' + ' <div class="row col-4"><span class="col-3 mr10 text-right mt-2 no_padding">成绩来源:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-7 no_padding ">\n' +
' <select class="form-control" name="stage[][score_source]">\n' + ' <select class="form-control" name="stage[][score_source]">\n' +
' <option value="0">经验值</option>\n' + ' <option value="0">经验值</option>\n' +
' <option value="1">预测准确率</option>\n' + ' <option value="1">预测准确率</option>\n' +
' </select>\n' + ' </select>\n' +
' </div>\n' + ' </div></div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="row mt-2" id="task_Input_sub_'+index+'_'+count+'">\n'+ ' <div class="row mt-2" id="task_Input_sub_'+index+'_'+count+'">\n'+
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务1</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务1</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务2</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务2</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务3</span>\n' + ' <span class="col-4 text-right mt-3 no_padding mr10">任务3</span>\n' +
' <div class="col-8">\n' + ' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
@ -136648,6 +136670,67 @@ $(document).on('turbolinks:load', function(){
$(".stage-update-form .section-start-time").datetimepicker(timeOptions); $(".stage-update-form .section-start-time").datetimepicker(timeOptions);
$(".stage-update-form .section-end-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');
} }
}); });
@ -136681,8 +136764,8 @@ function change_total(item) {
var html = ""; var html = "";
if(count > divCount){ if(count > divCount){
for(var i=0;i < count-divCount ;i++){ for(var i=0;i < count-divCount ;i++){
html+='<div class="col-4 row task_Input_div"><span class="col-3 text-center mt-3">任务'+(divCount+i+1)+'</span>\n' + html+='<div class="col-4 row task_Input_div"><span class="col-4 text-right mt-3 no_padding mr10">任务'+(divCount+i+1)+'</span>\n' +
'<div class="col-8">\n' + '<div class="col-6 no_padding">\n' +
'<input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + '<input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
'</div>\n' + '</div>\n' +
'</div>'; '</div>';
@ -136736,45 +136819,45 @@ function addNewTab(competition_id) {
' </div>\n' + ' </div>\n' +
' <div id="small_panel_'+count+'" class="small_panel">\n' + ' <div id="small_panel_'+count+'" class="small_panel">\n' +
' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' + ' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' +
' <span class="col-1 mt-2 subName">第1阶段</span>\n' + ' <span class="mt-2 subName mr10">第1阶段</span>\n' +
' <div class="flex-1">\n' + ' <div class="flex-1">\n' +
' <div class="row">\n' + ' <div class="row">\n' +
' <span class="mt-2 ml20">有效时间:</span>\n' + ' <div class="row col-6"><span class="mt-2 ml20 mr10">有效时间:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' + ' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' +
' </div>\n' + ' </div>\n' +
' <span class="mt-2">~</span>\n' + ' <span class="mt-2">~</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-4 no_padding input_middle">\n' +
' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' + ' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-2 text-right mt-2 no_padding">总任务数:</span>\n' + ' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding mr10">总任务数:</span>\n' +
' <div class="col-1 no_padding input_small">\n' + ' <div class="col-6 no_padding ">\n' +
' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' + ' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' +
' </div>\n' + ' </div></div>\n' +
' <span class="col-1 text-right mt-2 no_padding">成绩来源:</span>\n' + ' <div class="row col-4"><span class="col-3 text-right mt-2 no_padding mr10">成绩来源:</span>\n' +
' <div class="col-2 no_padding input_middle">\n' + ' <div class="col-7 no_padding ">\n' +
' <select class="form-control" name="stage[][score_source]">\n' + ' <select class="form-control" name="stage[][score_source]">\n' +
' <option value="0">经验值</option>\n' + ' <option value="0">经验值</option>\n' +
' <option value="1">预测准确率</option>\n' + ' <option value="1">预测准确率</option>\n' +
' </select>\n' + ' </select>\n' +
' </div>\n' + ' </div></div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="row mt-2" id="task_Input_sub_new_new">\n' + ' <div class="row mt-2" id="task_Input_sub_new_new">\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务1</span>\n' + ' <span class="col-3 text-right mt-3 no_padding mr10">任务1</span>\n' +
' <div class="col-8">\n' + ' <div class="col-8 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务2</span>\n' + ' <span class="col-3 text-right mt-3 no_padding mr10">任务2</span>\n' +
' <div class="col-8">\n' + ' <div class="col-8 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
' <div class="col-4 row task_Input_div">\n' + ' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-center mt-3">任务3</span>\n' + ' <span class="col-3 text-right no_padding mr10 mt-3">任务3</span>\n' +
' <div class="col-8">\n' + ' <div class="col-8 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' + ' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' + ' </div>\n' +
' </div>\n' + ' </div>\n' +
@ -137786,8 +137869,8 @@ $(document).on('turbolinks:load', function() {
data: $form.serialize() data: $form.serialize()
}); });
} }
}); });
}) })
}); });
$(document).on('turbolinks:load', function () { $(document).on('turbolinks:load', function () {
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-subject-modal', function () { $('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-subject-modal', function () {
@ -138085,6 +138168,52 @@ $(document).on('turbolinks:load', function() {
}); });
} }
}); });
$(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)
}
}
});
}
});
})
});
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-upload-file-modal'); var $modal = $('.modal.admin-upload-file-modal');
if ($modal.length > 0) { if ($modal.length > 0) {

@ -25681,6 +25681,48 @@ input.form-control {
border: none; 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 */ /* line 4, app/assets/stylesheets/admins/cooperatives.scss */
.admins-cooperatives-index-page .coo-img-card .coo-img-item > .drag { .admins-cooperatives-index-page .coo-img-card .coo-img-item > .drag {
cursor: move; cursor: move;
@ -26142,7 +26184,7 @@ input.form-control {
/* line 27, app/assets/stylesheets/admins/sidebar.scss */ /* line 27, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header-logo > .logo-label { #sidebar.active .sidebar-header-logo > .logo-label {
display: none; display: none;
} }
/* line 33, app/assets/stylesheets/admins/sidebar.scss */ /* line 33, app/assets/stylesheets/admins/sidebar.scss */
@ -26214,25 +26256,25 @@ input.form-control {
/* line 83, app/assets/stylesheets/admins/sidebar.scss */ /* line 83, app/assets/stylesheets/admins/sidebar.scss */
#sidebar .sidebar-header-logo { #sidebar .sidebar-header-logo {
display: -webkit-box; display: -webkit-box;
display: flex; display: flex;
-webkit-box-pack: justify; -webkit-box-pack: justify;
justify-content: space-between; justify-content: space-between;
-webkit-box-align: center; -webkit-box-align: center;
align-items: center; align-items: center;
} }
/* line 88, app/assets/stylesheets/admins/sidebar.scss */ /* line 88, app/assets/stylesheets/admins/sidebar.scss */
#sidebar .sidebar-header-logo > img { #sidebar .sidebar-header-logo > img {
width: 40px; width: 40px;
height: auto; height: auto;
} }
/* line 93, app/assets/stylesheets/admins/sidebar.scss */ /* line 93, app/assets/stylesheets/admins/sidebar.scss */
#sidebar .sidebar-header-logo > .logo-label { #sidebar .sidebar-header-logo > .logo-label {
font-size: 18px; font-size: 18px;
color: darkgrey; color: darkgrey;
margin-left: 10px; margin-left: 10px;
} }
/* line 101, app/assets/stylesheets/admins/sidebar.scss */ /* line 101, app/assets/stylesheets/admins/sidebar.scss */
@ -26336,7 +26378,7 @@ input.form-control {
} }
@media (max-width: 768px) { @media (max-width: 768px) {
/* line 182, app/assets/stylesheets/admins/sidebar.scss */ /* line 182, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active { #sidebar.active {
padding: 10px 5px; padding: 10px 5px;
min-width: 40px; min-width: 40px;
@ -26346,47 +26388,39 @@ input.form-control {
-webkit-transform: none; -webkit-transform: none;
transform: none; transform: none;
} }
/* line 190, app/assets/stylesheets/admins/sidebar.scss */
/* line 190, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header { #sidebar.active .sidebar-header {
padding: 0px; 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 { #sidebar.active .sidebar-header .sidebar-header-logo {
display: none; display: none;
} }
/* line 197, app/assets/stylesheets/admins/sidebar.scss */
/* line 197, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header #sidebarCollapse { #sidebar.active .sidebar-header #sidebarCollapse {
width: 30px; width: 30px;
height: 20px; height: 20px;
} }
/* line 203, app/assets/stylesheets/admins/sidebar.scss */
/* line 203, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul li a { #sidebar.active ul li a {
padding: 10px; padding: 10px;
font-size: 0.85em; 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 { #sidebar.active ul li a i {
margin-right: 0; margin-right: 0;
display: block; display: block;
margin-bottom: 5px; 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 { #sidebar.active > ul > li > a > i {
font-size: 1.8em; 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 { #sidebar.active ul ul a {
padding: 10px !important; padding: 10px !important;
} }
/* line 227, app/assets/stylesheets/admins/sidebar.scss */
/* line 227, app/assets/stylesheets/admins/sidebar.scss */
.dropdown-toggle::after { .dropdown-toggle::after {
top: auto; top: auto;
bottom: 10px; bottom: 10px;

@ -29891,13 +29891,35 @@ function customConfirm(opts){
return $.confirm($.extend({}, defaultOpts, 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({ $.notify({
message: '操作成功' message: message || '操作成功'
},{ },{
type: 'success' type: 'success'
}); });
} }
function showErrorNotify(message){
$.notify({
message: message || '操作失败'
},{
type: 'danger'
});
}
; ;
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :

File diff suppressed because one or more lines are too long

@ -960,7 +960,7 @@ class Registration extends React.Component {
<Breadcrumb separator=">"> <Breadcrumb separator=">">
<Breadcrumb.Item><Link to={"/competitions"}>在线竞赛</Link></Breadcrumb.Item> <Breadcrumb.Item><Link to={"/competitions"}>在线竞赛</Link></Breadcrumb.Item>
<Breadcrumb.Item><Link <Breadcrumb.Item><Link
to={`/competitions/${this.props.match.params.identifier}/common_header`}>{competition_name === undefined || competition_name === null || competition_name === "" ? "全国高校计算机大赛" : competition_name}</Link></Breadcrumb.Item> to={`/competitions/${this.props.match.params.identifier}`}>{competition_name === undefined || competition_name === null || competition_name === "" ? "全国高校计算机大赛" : competition_name}</Link></Breadcrumb.Item>
{/*<Breadcrumb.Item*/} {/*<Breadcrumb.Item*/}
{/* href={`/competitions/${this.props.match.params.identifier}/common_header`}></Breadcrumb.Item>*/} {/* href={`/competitions/${this.props.match.params.identifier}/common_header`}></Breadcrumb.Item>*/}
<Breadcrumb.Item>报名</Breadcrumb.Item> <Breadcrumb.Item>报名</Breadcrumb.Item>

@ -117,16 +117,14 @@ class CompetitionsIndex extends Component{
size="large" size="large"
dataSource={datas&&datas} dataSource={datas&&datas}
renderItem={(item,key) => ( renderItem={(item,key) => (
<a target="_blank" <a target="_blank" href={item.competition_status==="ended"?`/competitions/${item.identifier}`:item.competition_status==="nearly_published"?item.permission.editable==true?`/competitions/${item.identifier}`:null:item.competition_status==="progressing"?`/competitions/${item.identifier}`:null}
href={item.competition_status === "ended" ? `/competitions/${item.identifier}/common_header` : item.competition_status === "nearly_published" ? item.permission.editable == true ? `/competitions/${item.identifier}/common_header` : null : item.competition_status === "progressing" ? `/competitions/${item.identifier}/common_header` : null} className={item.competition_status==="ended"?"competitionstitlesshou":item.competition_status==="nearly_published"?
className={item.competition_status==="ended"?"competitionstitlesshou":item.competition_status==="nearly_published"? item.permission.editable==true?"competitionstitlesshou":"endedfont":"competitionstitlesshou"}
item.permission.editable == true ? "competitionstitlesshou" : "endedfont" : "competitionstitlesshou"}
> >
<div className={"CompetitionsList"} > <div className={"CompetitionsList"} >
{item.competition_status==="nearly_published"? {item.competition_status==="nearly_published"?
item.permission.editable == true ? "" : item.permission.editable==true?"":<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div>:""}
<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div> : ""}
{/*<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div>*/} {/*<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div>*/}
{/*{item.description===null||item.description===undefined||item.description===""?<style>*/} {/*{item.description===null||item.description===undefined||item.description===""?<style>*/}
{/*{*/} {/*{*/}
@ -175,9 +173,9 @@ class CompetitionsIndex extends Component{
> >
<List.Item.Meta <List.Item.Meta
title={<a className={item.competition_status==="ended"?"competitionstitlesshou":item.competition_status==="nearly_published"? title={<a className={item.competition_status==="ended"?"competitionstitlesshou":item.competition_status==="nearly_published"?
item.permission.editable == true ? "competitionstitlesshou" : "endedfont" : "competitionstitlesshou"}> item.permission.editable==true?"competitionstitlesshou":"endedfont":"competitionstitlesshou"}>
<a target="_blank" className={"competitionstitles"} <a target="_blank" className={"competitionstitles"}
href={item.competition_status === "ended" ? `/competitions/${item.identifier}/common_header` : item.competition_status === "nearly_published" ? item.permission.editable == true ? `/competitions/${item.identifier}/common_header` : null : item.competition_status === "progressing" ? `/competitions/${item.identifier}/common_header` : null} href={item.competition_status==="ended"?`/competitions/${item.identifier}`:item.competition_status==="nearly_published"? item.permission.editable==true?`/competitions/${item.identifier}`:null:item.competition_status==="progressing"?`/competitions/${item.identifier}`:null}
>{item.name}{item.sub_title===null?"":`——${item.sub_title}`}</a> >{item.name}{item.sub_title===null?"":`——${item.sub_title}`}</a>
{/*<span>{item.sub_title===null?"":*/} {/*<span>{item.sub_title===null?"":*/}
{/*<Tag className="competitionsrelative" color="#87d068">{item.sub_title}</Tag>}*/} {/*<Tag className="competitionsrelative" color="#87d068">{item.sub_title}</Tag>}*/}

@ -3,7 +3,6 @@ import { Breadcrumb,Layout,Table, Divider, Tag,Badge,Tooltip} from 'antd';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import axios from 'axios'; import axios from 'axios';
import NoneData from "../../courses/shixunHomework/shixunHomework";
import './Competitionteams.css'; import './Competitionteams.css';
const { Content } = Layout; const { Content } = Layout;

@ -3,11 +3,9 @@ import { Breadcrumb,Layout,Table, Divider, Tag,Badge,Row, Col,Button, Menu, Icon
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import axios from 'axios'; import axios from 'axios';
import {markdownToHTML,getImageUrl} from 'educoder'; import {markdownToHTML,getImageUrl} from 'educoder';
import CompetitionContents from './CompetitionCommonChild/CompetitionContents'; import CompetitionContents from './CompetitionContents';
import CompetitionContentsChart from './CompetitionCommonChild/CompetitionContentsChart'; import CompetitionContentsChart from './CompetitionContentsChart';
import CompetitionContentsMd from './CompetitionCommonChild/CompetitionContentsMd'; import CompetitionContentsMd from './CompetitionContentsMd';
import CompetitionContentspdf from './CompetitionCommonChild/CompetitionContentspdf';
import NoneData from "../../courses/shixunHomework/shixunHomework";
import './CompetitionCommon.css'; import './CompetitionCommon.css';
@ -254,13 +252,6 @@ class CompetitionCommon extends Component{
} }
isdownloadpdf=()=>{
this.setState({
isdownloadpdftype:true
})
}
render() { render() {
let {data,thiskeys,Competitionedittype}=this.state; let {data,thiskeys,Competitionedittype}=this.state;
@ -374,15 +365,9 @@ class CompetitionCommon extends Component{
} }
})} })}
</Menu> </Menu>
<Menu mode="inline" className="CompetitionMenu" onClick={(e)=>this.isdownloadpdf(e)}>
<Menu.Item>
<a>证书下载</a>
</Menu.Item>
</Menu>
</Sider> </Sider>
{this.state.isdownloadpdftype===true?"":<Layout className={"teamsLayoutleft CompetitionContents mb30"}> <Layout className={"teamsLayoutleft CompetitionContents mb30"}>
{this.state.module_type==="chart"?Competitionedittype===false?<CompetitionContentsChart {this.state.module_type==="chart"?Competitionedittype===false?<CompetitionContentsChart
{...this.props} {...this.props}
{...this.state} {...this.state}
@ -404,14 +389,8 @@ class CompetitionCommon extends Component{
{...this.props} {...this.props}
{...this.state} {...this.state}
/>:""} />:""}
</Layout>} </Layout>
{this.state.isdownloadpdftype===true?<Layout className={"teamsLayoutleft CompetitionContents mb30"}>
<CompetitionContentspdf
{...this.props}
{...this.state}
/>
</Layout>:""}
</Layout> </Layout>
</div> </div>

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import {Button,Layout} from 'antd'; import {Button,Layout} from 'antd';
import axios from 'axios'; import axios from 'axios';
import {markdownToHTML,getImageUrl,AttachmentList} from 'educoder'; import {markdownToHTML,getImageUrl,AttachmentList} from 'educoder';
// import NoneData from "../../../courses/shixunHomework/shixunHomework";
const { Header, Footer, Sider, Content } = Layout; const { Header, Footer, Sider, Content } = Layout;
class CompetitionContents extends Component{ class CompetitionContents extends Component{

@ -2,7 +2,6 @@ import React, { Component } from 'react';
import {Button,Layout,Tabs,Icon, Card, Avatar, Row, Col ,Table} from 'antd'; import {Button,Layout,Tabs,Icon, Card, Avatar, Row, Col ,Table} from 'antd';
import {markdownToHTML,getImageUrl} from 'educoder'; import {markdownToHTML,getImageUrl} from 'educoder';
import axios from 'axios'; import axios from 'axios';
// import NoneData from "../../../courses/shixunHomework/shixunHomework";
const { Content } = Layout; const { Content } = Layout;
const { TabPane } = Tabs; const { TabPane } = Tabs;

@ -69,7 +69,7 @@ class Competitions extends Component {
/> />
{/*新版竞赛详情页面*/} {/*新版竞赛详情页面*/}
<Route path="/competitions/:identifier/common_header" <Route path="/competitions/:identifier"
render={ render={
(props) => (<CompetitionCommon {...this.props} {...props} {...this.state} />) (props) => (<CompetitionCommon {...this.props} {...props} {...this.state} />)
} }

@ -3171,7 +3171,7 @@ class Listofworksstudentone extends Component {
} }
daochuzuoye = () => { 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); this.confirmysl(url);
} }

@ -414,7 +414,7 @@ class ShixunhomeWorkItem extends Component{
{ {
discussMessage && discussMessage.upper_category_name && discussMessage && discussMessage.upper_category_name &&
<ConditionToolTip title={discussMessage.upper_category_name} condition={ discussMessage.upper_category_name.length > 22 }> <ConditionToolTip title={discussMessage.upper_category_name} condition={ discussMessage.upper_category_name.length > 22 }>
{ <div className=" color-grey9 task-hide fr" style={discussMessage.time_status===1||discussMessage.time_status===2||discussMessage.time_status===3||discussMessage.time_status===4||discussMessage.time_status===5||discussMessage.time_status===6?{"maxWidth":"268px"}:{"maxWidth":"550px"}} title={discussMessage.upper_category_name}>所属目录{discussMessage.upper_category_name}</div>} { <div className=" color-grey9 task-hide fr" style={discussMessage.time_status===1||discussMessage.time_status===2||discussMessage.time_status===3||discussMessage.time_status===4||discussMessage.time_status===5||discussMessage.time_status===6?{"maxWidth":"216px"}:{"maxWidth":"550px"}} title={discussMessage.upper_category_name}>所属目录{discussMessage.upper_category_name}</div>}
</ConditionToolTip> </ConditionToolTip>
} }

@ -130,6 +130,9 @@ class Trainingjobsetting extends Component {
work_efficiencys: false, work_efficiencys: false,
task_pass: false, //是否允许跳关 task_pass: false, //是否允许跳关
CalculateMax: 100,//总分值 CalculateMax: 100,//总分值
borredszf:"ml10 color-grey-9",
borredszfl:true,
borredszfls:''
} }
// console.log("获取到的值") // console.log("获取到的值")
// console.log("Trainingjobsetting") // console.log("Trainingjobsetting")
@ -627,6 +630,15 @@ class Trainingjobsetting extends Component {
} }
} }
if(this.state.borredszfl===false){
this.setState({
borredszf:this.state.borredszf,
borredszfls:this.state.borredszfls,
borredszfl:this.state.borredszfl,
})
this.scrollToAnchor("zongfentimeid");
return;
}
var latedeductiontwos = 0; var latedeductiontwos = 0;
if (this.state.completionefficiencyscore === true) { if (this.state.completionefficiencyscore === true) {
latedeductiontwos = this.state.latedeductiontwo; latedeductiontwos = this.state.latedeductiontwo;
@ -640,7 +652,7 @@ class Trainingjobsetting extends Component {
// console.log(len); // console.log(len);
} }
var max = latedeductiontwos + len; let max = latedeductiontwos + len;
// if (max > 100) { // if (max > 100) {
// console.log("max>100"); // console.log("max>100");
// this.props.showNotification(`总分值+效率效率分之和要等于100现在分值为` + max); // this.props.showNotification(`总分值+效率效率分之和要等于100现在分值为` + max);
@ -651,6 +663,20 @@ class Trainingjobsetting extends Component {
// this.props.showNotification(`总分值+效率效率分之和要等于100现在分值为` + max); // this.props.showNotification(`总分值+效率效率分之和要等于100现在分值为` + max);
// return; // 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`; var url = `/homework_commons/${homeworkid}/update_settings.json`;
@ -1162,20 +1188,33 @@ class Trainingjobsetting extends Component {
//总比分 //总比分
Totalscorecalculation = (value) => { Totalscorecalculation = (value) => {
if (value === "" || value === undefined) {
this.setState({
CalculateMax: value,
})
if ( value === undefined || value === null || value === "" ) {
this.setState({
borredszf:"ml10 color-grey-9 bor-reds ",
borredszfls:"不能为空",
borredszfl:false,
})
return return
} }
var re = /^[0-9]+.?[0-9]*$/; //判断字符串是否为数字 //判断正整数 /^[1-9]+[0-9]*]*$/ var re = /^[0-9]+.?[0-9]*$/; //判断字符串是否为数字 //判断正整数 /^[1-9]+[0-9]*]*$/
var nubmer = value; var nubmer = value;
if (!re.test(nubmer)) { if (!re.test(nubmer)) {
this.props.showNotification(`请输入正确的数字`);
this.setState({ this.setState({
CalculateMax: 0 borredszf:"ml10 color-grey-9 bor-reds ",
borredszfls:"请输入数字",
borredszfl:false,
}) })
return; return;
} }
this.setState({
borredszf:"ml10 color-grey-9 ",
borredszfls:"",
borredszfl:true,
})
// if (nubmer > 100) { // if (nubmer > 100) {
// this.props.showNotification(`请输入小于100的数`); // this.props.showNotification(`请输入小于100的数`);
// //
@ -1194,9 +1233,7 @@ class Trainingjobsetting extends Component {
this.Empiricalvalueratio(myvalues, value, true); this.Empiricalvalueratio(myvalues, value, true);
} }
this.setState({
CalculateMax: value,
})
} }
@ -1238,7 +1275,7 @@ class Trainingjobsetting extends Component {
this.Empiricalvalueratio(value, this.state.CalculateMax, true); this.Empiricalvalueratio(value, this.state.CalculateMax, true);
} else if (this.state.proportion === "自定义分值") { } else if (this.state.proportion === "自定义分值") {
this.Calculatethetotalscore(value, this.state.challenge_settings); // this.Calculatethetotalscore(value, this.state.challenge_settings);
} }
} }
@ -1284,7 +1321,16 @@ class Trainingjobsetting extends Component {
if (this.state.completionefficiencyscore === true) { if (this.state.completionefficiencyscore === true) {
latedeductiontwos = this.state.latedeductiontwo; 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) { // if (nubmer > 100) {
// message.error("请输入小于100的数"); // message.error("请输入小于100的数");
// this.setState({ // this.setState({
@ -2209,7 +2255,7 @@ class Trainingjobsetting extends Component {
const dataformat = 'YYYY-MM-DD HH:mm'; const dataformat = 'YYYY-MM-DD HH:mm';
let {flagPageEdit, testscripttiptype, publish_timebool, end_timebool, late_timesbool, work_efficiencys, flagPageEdits, flagPageEditstwo, flagPageEditsbox, whethertopay, handclass, flagPageEditsthrees, flagPageEditsfor, rules, rulest, unifiedsetting, group_settings, course_group, unit_e_tip, borreds, borredss, unit_p_tip, end_time, late_time, score_open, publish_time, starttimetype, modalsType, modalsTopval, loadtype, modalSave, endtimetype, latetimetype, allowlate, latepenaltytype, jobsettingsdata, endOpen, mystyle, mystyles, task_pass} = this.state; let {flagPageEdit, testscripttiptype, publish_timebool, end_timebool,borredszf,borredszfl,borredszfls, late_timesbool, work_efficiencys, flagPageEdits, flagPageEditstwo, flagPageEditsbox, whethertopay, handclass, flagPageEditsthrees, flagPageEditsfor, rules, rulest, unifiedsetting, group_settings, course_group, unit_e_tip, borreds, borredss, unit_p_tip, end_time, late_time, score_open, publish_time, starttimetype, modalsType, modalsTopval, loadtype, modalSave, endtimetype, latetimetype, allowlate, latepenaltytype, jobsettingsdata, endOpen, mystyle, mystyles, task_pass} = this.state;
// console.log(publish_timebool); // console.log(publish_timebool);
// console.log(!flagPageEditstwo); // console.log(!flagPageEditstwo);
const radioStyle = { const radioStyle = {
@ -2570,17 +2616,29 @@ class Trainingjobsetting extends Component {
fontWeight: "bold", fontWeight: "bold",
fontSize: "16px", fontSize: "16px",
}}>总分值</span> }}>总分值</span>
<InputNumber min={0} className="ml10 color-grey-9" <InputNumber min={0} className={borredszf}
style={{width: "100px", color: "#999999"}} style={{width: "100px", color: "#999999"}}
disabled={!flagPageEdit} disabled={!flagPageEdit}
id={"zongfentimeid"}
step={0.1} step={0.1}
onChange={this.Totalscorecalculation} onChange={(e)=>this.Totalscorecalculation(e)}
value={this.state.CalculateMax} value={this.state.CalculateMax}
/> />
<span className="ml10 font-16" <span className="ml10 font-16"
style={{color: "#999999", height: "28px", marginTop: "9px", lineHeight: "28px"}}></span> style={{color: "#999999", height: "28px", marginTop: "9px", lineHeight: "28px"}}></span>
</div> </div>
<div className=" mt10 mt20" style={{marginLeft: "82px"}}> {
borredszfl===false?
<div >
<span className="fl" style={{marginLeft: "101px", marginTop: "2px",color: "#FF0000"}}>{borredszfls}</span>
</div>
:
<div className="myslHeight">
</div>
}
<div style={{marginLeft: "82px"}}>
<span className="c_grey font-16" style={{color: "#333333"}}> 关卡任务的选择和分值设置 </span><span <span className="c_grey font-16" style={{color: "#333333"}}> 关卡任务的选择和分值设置 </span><span
className="ml15 font-14" style={{textAlign: "left", color: "#FF8204"}}>(总分值 = 效率分+ 关卡任务总分)</span> className="ml15 font-14" style={{textAlign: "left", color: "#FF8204"}}>(总分值 = 效率分+ 关卡任务总分)</span>
</div> </div>
@ -2689,12 +2747,12 @@ class Trainingjobsetting extends Component {
{this.state.challenge_settings === undefined ? "" : this.state.challenge_settings.map((object, index) => { {this.state.challenge_settings === undefined ? "" : this.state.challenge_settings.map((object, index) => {
return ( return (
<li className="yslflexhomes" key={index}> <li className="yslflexhomes" key={index}>
<Checkbox className="ml110 font-16" <Checkbox className="ml110 font-16 maxnamewidth340"
disabled={!flagPageEditsbox} disabled={!flagPageEditsbox}
style={{"width": "200px", color: "#05101A", lineHeight: "48px"}} style={{"width": "340px", color: "#05101A", lineHeight: "48px"}}
checked={object.checked} checked={object.checked}
onChange={(value) => this.onChangedatasheet(value, index)} onChange={(value) => this.onChangedatasheet(value, index)}
>{object.challenge_name}</Checkbox> ><a title={object.challenge_name} >{object.challenge_name}</a></Checkbox>
{ {
object.checked === false ? object.checked === false ?
<div style={{lineHeight: "48px", width: "60px"}}> <div style={{lineHeight: "48px", width: "60px"}}>
@ -2707,6 +2765,7 @@ class Trainingjobsetting extends Component {
width: "60px", width: "60px",
textAlign: "center", textAlign: "center",
marginTop: "14px", marginTop: "14px",
marginLeft: "5px "
}}>可不做 }}>可不做
</div> </div>
</div> </div>
@ -2714,7 +2773,7 @@ class Trainingjobsetting extends Component {
<div style={{lineHeight: "48px", width: "60px"}}></div> <div style={{lineHeight: "48px", width: "60px"}}></div>
} }
<InputNumber disabled={!flagPageEdits} className=" c_grey" min={0} <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)} onChange={(value) => this.hangeTopicNametwodatasheet(value, index)}
step={0.1} step={0.1}
value={object.challenge_score} value={object.challenge_score}

@ -88,3 +88,34 @@
.pd30bt{ .pd30bt{
padding: 10px 30px 0px 30px; padding: 10px 30px 0px 30px;
} }
.bor-reds{
border:1px solid #FF0000!important;
border-radius: 1px!important;
border-top-left-radius: 1px!important;
border-top-right-radius: 1px!important;
border-bottom-right-radius: 1px!important;
border-bottom-left-radius: 1px!important;
}
.bor-reds input {
border:1px solid #FF0000!important;
border-radius: 1px!important;
border-top-left-radius: 1px!important;
border-top-right-radius: 1px!important;
border-bottom-right-radius: 1px!important;
border-bottom-left-radius: 1px!important;
}
.myslHeight{
height: 20px;
min-height: 20px;
}
.maxnamewidth340 {
max-width: 340px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: default;
width: 340px;
max-width: 340px;
}

@ -1,5 +1,5 @@
import React, {Component} from "react"; import React,{ Component } from "react";
import {Row, Col, Popover, Button, Icon} from "antd"; import {Row, Col,Popover,Button,Icon} from "antd";
import { import {
G2, G2,
Chart, Chart,
@ -16,20 +16,22 @@ import {
Util Util
} from "bizcharts"; } from "bizcharts";
class Dynamiclist extends Component { class Dynamiclist extends Component{
constructor(props) { constructor(props){
super(props); super(props);
this.state = {} this.state={
}
} }
render() { render(){
const data = [] const data = []
let {course_members} = this.props; let {course_members}=this.props;
if (course_members) { if(course_members){
if (course_members.length > 0) { if(course_members.length>0){
course_members.map((item, key) => { course_members.map((item,key)=>{
data.push({'name': item.user_name, '活跃度': item.total_score}) data.push({'name':item.user_name,'活跃度':item.total_score})
}) })
} }
} }
@ -59,31 +61,30 @@ class Dynamiclist extends Component {
</p> </p>
</div> </div>
); );
return ( return(
<React.Fragment> <React.Fragment>
<Row> <Row>
<Col span={12} className={"top10s"}>Top 10</Col> <Col span={12} className={"top10s"}>Top 10</Col>
<Col span={12} className={"Statisticsliboxjsgz"}> <Col span={12} className={"Statisticsliboxjsgz"}>
<span className={"mr10"}>计算规则</span> <span className={"mr10"}>计算规则</span>
<Popover placement="bottom" content={content} trigger="hover"> <Popover placement="bottom" title={"活动规则计算说明"} content={content} trigger="hover">
<Icon type="exclamation-circle"/> <Icon type="info-circle" />
</Popover> </Popover>
</Col> </Col>
</Row> </Row>
{/*scale={cols}*/} {/*scale={cols}*/}
<Chart height={400} data={data} forceFit> <Chart height={400} data={data} forceFit>
<Axis name="name"/> <Axis name="name" />
<Axis name="活跃度"/> <Axis name="活跃度" />
<Tooltip <Tooltip
crosshairs={{ crosshairs={{
type: "y" type: "y"
}} }}
/> />
<Geom type="interval" position="name*活跃度"/> <Geom type="interval" position="name*活跃度" />
</Chart> </Chart>
</React.Fragment> </React.Fragment>
) )
} }
} }
export default Dynamiclist; export default Dynamiclist;

@ -65,7 +65,7 @@
font-size: 16px; font-size: 16px;
} }
.Statisticsli { .Statisticsli{
clear: both; clear: both;
margin: 0; margin: 0;
padding: 5px 12px; padding: 5px 12px;
@ -80,7 +80,7 @@
transition: all 0.3s; transition: all 0.3s;
} }
.StatisticsMenubox { .StatisticsMenubox{
position: relative; position: relative;
margin: 0; margin: 0;
padding: 4px 0; padding: 4px 0;
@ -90,39 +90,42 @@
background-clip: padding-box; background-clip: padding-box;
border-radius: 4px; border-radius: 4px;
outline: none; outline: none;
-webkit-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); -webkit-box-shadow: 0 2px 8px rgba(0,0,0,0.15);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); box-shadow: 0 2px 8px rgba(0,0,0,0.15);
-webkit-transform: translate3d(0, 0, 0); -webkit-transform: translate3d(0, 0, 0);
} }
.Statisticslibox li label { .Statisticslibox li label{
width: 200px; width: 200px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.Statisticslibox .ant-menu-item{
.Statisticslibox .ant-menu-item {
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
text-overflow: clip; text-overflow: clip;
} }
.top10s { .top10s{
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
color: rgba(51, 51, 51, 1); color: rgba(51,51,51,1);
} }
.Statisticsliboxjsgz { .Statisticsliboxjsgz{
font-size: 12px; font-size:12px;
color: rgba(51, 51, 51, 1); color:rgba(51,51,51,1);
text-align: right; text-align: right;
} }
.Statisticscircle p { .Statisticscircle p{
height: 30px; height: 30px;
font-size: 12px; font-size: 12px;
color: rgba(153, 153, 153, 1); color: rgba(153,153,153,1);
line-height: 30px; line-height: 20px;
}
.Statisticsmxxy{
font-size: 16px;
margin-left:15px;
} }

@ -1,10 +1,12 @@
import React,{ Component } from "react"; import React,{ Component } from "react";
import {Table, Pagination, Tooltip, Spin, Row, Col, Checkbox, Tabs, Menu, Dropdown, Icon, Input} from "antd"; import {Table, Pagination,Tooltip,Spin, Row, Col ,Checkbox,Tabs,Menu, Dropdown, Icon,Input} from "antd";
import {WordsBtn, on, off, trigger, getImageUrl, sortDirections} from 'educoder'; import { WordsBtn,on, off, trigger ,getImageUrl,sortDirections} from 'educoder';
import axios from'axios'; import axios from'axios';
import Dropdownbox from './Dropdownbox'; import Dropdownbox from './Dropdownbox';
import Dynamiclist from './Dynamiclist'; import Dynamiclist from './Dynamiclist';
import NoneData from "../../courses/coursesPublic/NoneData";
import './Statistics.css'; import './Statistics.css';
const { TabPane } = Tabs; const { TabPane } = Tabs;
class Statistics extends Component{ class Statistics extends Component{
constructor(props){ constructor(props){
@ -12,165 +14,163 @@ class Statistics extends Component{
this.state={ this.state={
nd1:60, nd1:60,
nd2:40, nd2:40,
nd3: 20, nd3:20,
data: undefined, data:undefined,
bomdata: undefined, bomdata:undefined,
topisSpin: true, topisSpin:true,
bomisSpin: true, bomisSpin:true,
sort: 'desc', sort:'desc',
course_groups: [], course_groups:[],
page: 1, page:1,
all_count: null, all_count:null,
activeKey: '1', activeKey:'1',
visible: false, visible: false,
group_ids: [], group_ids:[],
course_members: [] course_members:[]
} }
} }
componentDidMount() { componentDidMount() {
this.getdatas() this.getdatas()
} }
getdatas = () => { getdatas=()=>{
let {page, group_ids, sort} = this.state; let {page,group_ids,sort}=this.state;
let courseId = this.props.match.params.coursesId; let courseId=this.props.match.params.coursesId;
let url = `/courses/${courseId}/statistics.json`; let url=`/courses/${courseId}/statistics.json`;
axios.get(url).then((result) => { axios.get(url).then((result) => {
if (result) { if (result) {
this.setState({ this.setState({
data: result.data.top_scores, data:result.data.top_scores,
topisSpin: false topisSpin:false
}) })
} }
}).catch((error) => { }).catch((error) => {
console.log(error); console.log(error);
this.setState({ this.setState({
topisSpin: false, topisSpin:false,
}) })
}) })
let courseurl = `/courses/${courseId}/all_course_groups.json`; let courseurl=`/courses/${courseId}/all_course_groups.json`;
axios.get(courseurl).then((result) => { axios.get(courseurl).then((result) => {
if (result) { if (result) {
this.setState({ this.setState({
course_groups: result.data.course_groups course_groups:result.data.course_groups
}) })
let list = result.data.course_groups; let list=result.data.course_groups;
if (list.length > 0) { // if(list.length>0){
this.setState({ // this.setState({
group_ids: [list[0].id], // group_ids:[list[0].id],
}) // })
this.getwork_scoredata(page, [list[0].id], sort); // }
} this.getwork_scoredata(page,undefined,sort);
} }
}).catch((error) => { }).catch((error) => {
console.log(error); console.log(error);
}) })
} }
getDynamiclistdatas = (group_ids) => { getDynamiclistdatas=(group_ids)=>{
let courseId = this.props.match.params.coursesId; let courseId=this.props.match.params.coursesId;
let url = `/courses/${courseId}/act_score.json`; let url=`/courses/${courseId}/act_score.json`;
let data = { let data={
group_ids: group_ids, group_ids:group_ids,
} }
axios.get(url, { axios.get(url,{params:
params:
data data
}).then((result) => { }).then((result) => {
if (result) { if (result) {
this.setState({ this.setState({
course_members: result.data.course_members, course_members:result.data.course_members,
bomisSpin: false bomisSpin:false
}) })
} }
}).catch((error) => { }).catch((error) => {
console.log(error); console.log(error);
this.setState({ this.setState({
bomisSpin: false, bomisSpin:false,
}) })
}) })
} }
getwork_scoredata = (page, group_ids, sort) => { getwork_scoredata=(page,group_ids,sort)=>{
let {activeKey} = this.state; let {activeKey}=this.state;
this.setState({ this.setState({
page: page, page:page,
sort: sort, sort:sort,
group_ids: group_ids, group_ids:this.props.isStudent()===true?undefined:group_ids,
bomisSpin: true, bomisSpin:true,
}) })
if (activeKey === '1') { if(activeKey==='1'){
let courseId = this.props.match.params.coursesId; let courseId=this.props.match.params.coursesId;
let url = `/courses/${courseId}/work_score.json`; let url=`/courses/${courseId}/work_score.json`;
let data = { let data={
limit: 20, limit:20,
page: page, page:page,
group_ids: group_ids, group_ids:this.props.isStudent()===true?undefined:group_ids,
sort: sort sort:sort
} }
axios.get(url, { axios.get(url,{params:
params:
data data
}).then((result) => { }).then((result) => {
if (result) { if (result) {
this.setState({ this.setState({
bomdata: result.data.course_members, bomdata:result.data.course_members,
all_count: result.data.all_count, all_count:result.data.all_count,
bomisSpin: false bomisSpin:false
}) })
} }
}).catch((error) => { }).catch((error) => {
console.log(error); console.log(error);
this.setState({ this.setState({
bomisSpin: false, bomisSpin:false,
}) })
}) })
} else { }else{
this.getDynamiclistdatas(group_ids) this.getDynamiclistdatas(group_ids)
} }
} }
activeKey = (key) => { activeKey=(key)=>{
if (key === "1") { if(key==="1"){
let {page, group_ids, sort} = this.state; let {page,group_ids,sort}=this.state;
// this.getdatas() // this.getdatas()
this.getwork_scoredata(page, group_ids, sort) this.getwork_scoredata(page,group_ids,sort)
} else { }else{
let {group_ids} = this.state; let{group_ids}=this.state;
this.getDynamiclistdatas(group_ids) this.getDynamiclistdatas(group_ids)
} }
this.setState({ this.setState({
activeKey: key activeKey:key
}) })
} }
PaginationCourse = (pageNumber) => { PaginationCourse=(pageNumber)=>{
let {group_ids, sort} = this.state; let {group_ids,sort}=this.state;
this.getwork_scoredata(pageNumber, group_ids, sort); this.getwork_scoredata(pageNumber,group_ids,sort);
} }
derivefun = (url) => { derivefun=(url)=>{
let {group_ids} = this.state; let{group_ids}=this.state;
let data = { let data={
group_id: group_ids group_id:group_ids
} }
axios.get(url, { axios.get(url,{params:
params:
data data
}).then((response) => { }).then((response)=>{
if (response === undefined) { if(response === undefined){
return return
} }
if (response.data.status && response.data.status === -1) { if(response.data.status&&response.data.status===-1){
this.props.showNotification(response.data.message); this.props.showNotification(response.data.message);
} else if (response.data.status && response.data.status === -2) { }else if(response.data.status&&response.data.status===-2){
// if(response.data.message === "100"){ // if(response.data.message === "100"){
// // 已超出文件导出的上限数量100 ),建议: // // 已超出文件导出的上限数量100 ),建议:
// //
@ -186,7 +186,7 @@ class Statistics extends Component{
// }) // })
// } // }
this.props.showNotification(response.data.message); this.props.showNotification(response.data.message);
} else { }else {
// this.props.showNotification(`正在下载中`); // this.props.showNotification(`正在下载中`);
// window.open("/api"+url, '_blank'); // window.open("/api"+url, '_blank');
this.props.slowDownload(url); this.props.slowDownload(url);
@ -198,31 +198,31 @@ class Statistics extends Component{
// 筛选 // 筛选
handleTableChange = (pagination, filters, data) => { handleTableChange =(pagination, filters, data)=>{
let order = data.order; let order=data.order;
let {page, group_ids} = this.state; let {page,group_ids}=this.state;
if (order === "descend") { if(order==="descend"){
this.getwork_scoredata(page, group_ids, 'desc') this.getwork_scoredata(page,group_ids,'desc')
} else { }else{
this.getwork_scoredata(page, group_ids, 'asc') this.getwork_scoredata(page,group_ids,'asc')
} }
} }
render(){ render(){
let {nd1, nd2, nd3, data, bomdata} = this.state; let {nd1,nd2,nd3,data,bomdata,course_members}=this.state;
const columns = [ const columns = [
{ {
title: this.props.isAdmin() === true ? '序号' : '排名', title: this.props.isAdmin()===true?'序号':'排名',
dataIndex: 'index', dataIndex: 'index',
render: (text, record, index) => { render: (text, record,index) => {
return this.props.isAdmin() === true ? (this.state.page - 1) * 20 + index + 1 : record.rank return this.props.isAdmin()===true?(this.state.page - 1) * 20 + index + 1:record.rank
} }
}, },
{ {
title: '姓名', title: '姓名',
dataIndex: 'user_name', dataIndex:'user_name',
render: (text, record) => ( render: (text, record) => (
<span>{record.user_name}</span> <span>{record.user_name}</span>
) )
@ -231,68 +231,66 @@ class Statistics extends Component{
title: '分班', title: '分班',
dataIndex: 'course_group', dataIndex: 'course_group',
render: (text, record) => ( render: (text, record) => (
<span>{record.course_group}</span> <span >{record.course_group}</span>
) )
}, },
{ {
title: '实训作业', title: '实训作业',
dataIndex: 'practice_score', dataIndex: 'practice_score',
render: (text, record) => ( render: (text, record) => (
<span>{record.practice_score.toFixed(2)}</span> <span >{record.practice_score.toFixed(2)}</span>
) )
}, },
{ {
title: '普通作业', title: '普通作业',
dataIndex: 'common_score', dataIndex: 'common_score',
render: (text, record) => ( render: (text, record) => (
<span>{record.common_score.toFixed(2)}</span> <span >{record.common_score.toFixed(2)}</span>
) )
}, },
{ {
title: '分组作业', title: '分组作业',
dataIndex: 'group_score', dataIndex: 'group_score',
render: (text, record) => ( render: (text, record) => (
<span>{record.group_score.toFixed(2)}</span> <span >{record.group_score.toFixed(2)}</span>
) )
}, },
{ {
title: '毕设任务', title: '毕设任务',
dataIndex: 'graduation_score', dataIndex: 'graduation_score',
render: (text, record) => ( render: (text, record) => (
<span>{record.graduation_score.toFixed(2)}</span> <span >{record.graduation_score.toFixed(2)}</span>
) )
}, },
{ {
title: '试卷', title: '试卷',
dataIndex: 'exercise_score', dataIndex: 'exercise_score',
render: (text, record) => ( render: (text, record) => (
<span>{record.exercise_score}</span> <span >{record.exercise_score}</span>
) )
}, },
{ {
title: '总成绩', title: '总成绩',
dataIndex: 'total_score', dataIndex: 'total_score',
sorter: this.props.isAdmin() === true ? true : false, sorter: this.props.isAdmin()===true?true:false,
defaultSortOrder: 'descend', defaultSortOrder: 'descend',
sortDirections: sortDirections, sortDirections: sortDirections,
render: (text, record) => ( render: (text, record) => (
<span>{record.total_score.toFixed(2)}</span> <span >{record.total_score.toFixed(2)}</span>
) )
}, },
]; ];
let course_grouptype = false; let course_grouptype=false;
if (this.props && this.props.course_modules != undefined) { if(this.props&&this.props.course_modules!=undefined){
{ {this.props&&this.props.course_modules.map((item,key)=>{
this.props && this.props.course_modules.map((item, key) => { if(item.type==="course_group"){
if (item.type === "course_group") { course_grouptype=true
course_grouptype = true }
} })}
})
}
} }
if (course_grouptype === false) { if(course_grouptype===false){
columns.some((item, key) => { columns.some((item,key)=> {
if (item.title === "分班") { if (item.title === "分班") {
columns.splice(key, 1) columns.splice(key, 1)
return true return true
@ -317,168 +315,166 @@ class Statistics extends Component{
<Dropdownbox <Dropdownbox
{...this.props} {...this.props}
{...this.state} {...this.state}
postwork_scoredata={(group_idss) => this.getwork_scoredata(1, group_idss, 'desc')} postwork_scoredata={(group_idss)=>this.getwork_scoredata(1,group_idss,'desc')}
/> />
<a className={"ml20 ant-btn-link"} <a className={"ml20 ant-btn-link"} onClick={()=>this.derivefun(`/courses/${this.props.match.params.coursesId}/export_member_scores_excel.xlsx`)}>导出</a>
onClick={() => this.derivefun(`/courses/${this.props.match.params.coursesId}/export_member_scores_excel.xlsx`)}>导出</a>
</React.Fragment>; </React.Fragment>;
return( return(
<React.Fragment> <React.Fragment>
<div className="edu-back-white"> <div className="edu-back-white">
<Spin size="large" spinning={this.state.topisSpin}> <Spin size="large" spinning={this.state.topisSpin}>
<p className="clearfix padding30"> <p className="clearfix padding30">
<Row gutter={24}> <Row gutter={24}>
<Col> <Col className={"Statisticsmxxy"}>
明星学员 明星学员
</Col> </Col>
</Row> </Row>
<Row type="flex" justify="center" align="bottom"> <Row type="flex" justify="center" align="bottom">
{data && data.map((item, key) => { {data&&data.map((item,key)=>{
if (key === 3) { if(key===3){
return ( return(
<Col span={3}> <Col span={3}>
<li className="pr rankingss"> <li className="pr rankingss">
<a href={`/users/${item.user_login}`} className="color-dark"> <a href={`/users/${item.user_login}`} className="color-dark">
<img src={getImageUrl(`images/${item.avatar_url}`)}/> <img src={getImageUrl(`images/${item.avatar_url}`)}/>
</a> </a>
</li> </li>
</Col> </Col>
) )
} }
})} })}
{data && data.map((item, key) => { {data&&data.map((item,key)=>{
if (key === 1) { if(key===1){
return ( return(
<Col span={5}> <Col span={5}>
<li className="pr rankingss"> <li className="pr rankingss">
<a href={`/users/${item.user_login}`} className="color-dark"> <a href={`/users/${item.user_login}`} className="color-dark">
<img src={getImageUrl(`images/${item.avatar_url}`)} className={"mb10"}/> <img src={getImageUrl(`images/${item.avatar_url}`)} className={"mb10"}/>
</a> </a>
</li> </li>
<Col className={`height-${nd2}`}> <Col className={`height-${nd2}`}>
</Col>
</Col>
)
}
})}
{data && data.map((item, key) => {
if (key === 0) {
return (
<Col span={5} className={"relatives"}>
<li className="pr rankingss">
<img src="https://test-newweb.educoder.net/images/educoder/huangguan.png"
className="huangguans mb5"/>
<a href={`/users/${item.user_login}`} className="color-dark">
<img src={getImageUrl(`images/${item.avatar_url}`)} className={"mb10 mt5"}/>
</a>
</li>
<Col className={`height-${nd1}`}>
</Col>
</Col> </Col>
) </Col>
} )
}
})}
})}
{data && data.map((item, key) => {
if (key === 2) { {data&&data.map((item,key)=>{
return ( if(key===0){
<Col span={5}> return(
<li className="pr rankingss"> <Col span={5} className={"relatives"}>
<a href={`/users/${item.user_login}`} className="color-dark"> <li className="pr rankingss">
<img src={getImageUrl(`images/${item.avatar_url}`)} className={"mb10"}/> <img src="https://test-newweb.educoder.net/images/educoder/huangguan.png" className="huangguans mb5" />
</a> <a href={`/users/${item.user_login}`} className="color-dark">
</li> <img src={getImageUrl(`images/${item.avatar_url}`)} className={"mb10 mt5"}/>
<Col className={`height-${nd3}`}> </a>
</li>
</Col> <Col className={`height-${nd1}`}>
</Col> </Col>
) </Col>
} )
}
})} })}
{data&&data.map((item,key)=>{
if(key===2){
return(
<Col span={5}>
<li className="pr rankingss">
<a href={`/users/${item.user_login}`} className="color-dark">
<img src={getImageUrl(`images/${item.avatar_url}`)} className={"mb10"}/>
</a>
</li>
<Col className={`height-${nd3}`}>
{data && data.map((item, key) => {
if (key === 4) {
return (
<Col span={3}>
<li className="pr rankingss">
<a href={`/users/${item.user_login}`} className="color-dark">
<img src={getImageUrl(`images/${item.avatar_url}`)}/>
</a>
</li>
</Col> </Col>
) </Col>
} )
}
})} })}
</Row> {data&&data.map((item,key)=>{
if(key===4){
return(
<Col span={3}>
<li className="pr rankingss">
<a href={`/users/${item.user_login}`} className="color-dark">
<img src={getImageUrl(`images/${item.avatar_url}`)}/>
</a>
</li>
</Col>
)
}
})}
<Row className="mt10" type="flex" justify="center" align="bottom">
{data && data.map((item, key) => { </Row>
if (key === 3) {
return (
<Col span={3} className={"Statisticscenter"}> <Row className="mt10" type="flex" justify="center" align="bottom">
<Col>{item.user_name}</Col>
<Col>4th</Col> {data&&data.map((item,key)=>{
</Col> if(key===3){
) return(
} <Col span={3} className={"Statisticscenter"}>
})} <Col>{item.user_name}</Col>
{data && data.map((item, key) => { <Col>4th</Col>
if (key === 1) { </Col>
return ( )
<Col span={5} className={"Statisticscenter"}> }
<Col>{item.user_name}</Col> })}
<Col>2th</Col> {data&&data.map((item,key)=>{
</Col> if(key===1){
) return(
} <Col span={5} className={"Statisticscenter"}>
})} <Col>{item.user_name}</Col>
{data && data.map((item, key) => { <Col>2nd</Col>
if (key === 0) { </Col>
return ( )
<Col span={5} className={"Statisticscenter"}> }
<Col>{item.user_name}</Col> })}
<Col>1th</Col> {data&&data.map((item,key)=>{
</Col> if(key===0){
) return(
} <Col span={5} className={"Statisticscenter"}>
})} <Col>{item.user_name}</Col>
{data && data.map((item, key) => { <Col>1st</Col>
if (key === 2) { </Col>
return ( )
<Col span={5} className={"Statisticscenter"}> }
<Col>{item.user_name}</Col> })}
<Col>3th</Col> {data&&data.map((item,key)=>{
</Col> if(key===2){
) return(
} <Col span={5} className={"Statisticscenter"}>
})} <Col>{item.user_name}</Col>
{data && data.map((item, key) => { <Col>3rd</Col>
if (key === 4) { </Col>
return ( )
<Col span={3} className={"Statisticscenter"}> }
<Col>{item.user_name}</Col> })}
<Col>5th</Col> {data&&data.map((item,key)=>{
</Col> if(key===4){
) return(
} <Col span={3} className={"Statisticscenter"}>
})} <Col>{item.user_name}</Col>
<Col>5th</Col>
</Col>
)
}
})}
</Row> </Row>
</p> </p>
</Spin> </Spin>
</div> </div>
@ -494,31 +490,30 @@ class Statistics extends Component{
} }
.ant-table-thead > tr > th, .ant-table-tbody > tr > td { .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 16px 0px; padding: 16px 0px;
text-align: center;
} }
` `
}</style> }</style>
<Tabs className="statisticsTabs" activeKey={this.state.activeKey} onChange={this.activeKey} <Tabs className="statisticsTabs" activeKey={this.state.activeKey} onChange={this.activeKey} tabBarExtraContent={this.props.isAdmin()===true?operations:""}>
tabBarExtraContent={this.props.isAdmin() === true ? operations : ""}> <TabPane tab="学习成绩" key="1" className={"statisticsTabs1"} >
<TabPane tab="学习成绩" key="1" className={"statisticsTabs1"}> {bomdata===undefined||bomdata===null?"":bomdata.length===0?<NoneData/>:<Table
<Table columns={columns}
columns={columns} dataSource={bomdata}
dataSource={bomdata} pagination={false}
pagination={false} onChange={this.handleTableChange}
onChange={this.handleTableChange} />}
/> </TabPane>
</TabPane> <TabPane tab="课堂活跃度" key="2">
<TabPane tab="课堂活跃度" key="2"> {course_members===undefined||course_members===null?"":course_members.length===0?<NoneData/>:<Dynamiclist
<Dynamiclist {...this.state}
{...this.state} {...this.props}
{...this.props} />}
/> </TabPane>
</TabPane> </Tabs>
</Tabs>
</Spin> </Spin>
</div> </div>
{this.state.all_count === undefined || this.state.all_count === null || this.state.activeKey === "2" ? '' : this.state.all_count > 20 && this.props.isAdmin() === true ? {this.state.all_count===undefined||this.state.all_count===null||this.state.activeKey==="2"?'':this.state.all_count >20&&this.props.isAdmin()===true?<div className="mb40 edu-txt-center padding20-30"
<div className="mb40 edu-txt-center padding20-30"
> >
@ -526,12 +521,12 @@ class Statistics extends Component{
showQuickJumper showQuickJumper
defaultCurrent={1} defaultCurrent={1}
pageSize={20} pageSize={20}
total={this.state.all_count === undefined ? 0 : this.state.all_count === null ? 0 : this.state.all_count} total={this.state.all_count===undefined?0:this.state.all_count===null?0:this.state.all_count}
current={this.state.page} current={this.state.page}
onChange={this.PaginationCourse} onChange={this.PaginationCourse}
/> />
</div> : ""} </div>:""}
</React.Fragment> </React.Fragment>
) )

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

@ -427,14 +427,14 @@ export default class TPMchallengesnew extends Component {
<Link to={go_back_url === undefined ? "" : go_back_url} <Link to={go_back_url === undefined ? "" : go_back_url}
className="color-grey-6 fr font-15 mt3">返回</Link> className="color-grey-6 fr font-15 mt3">返回</Link>
{ next_challenge===undefined?"":
<a href={next_challenge}className="fr color-blue mr15 mt4">下一关</a>
}
{ prev_challenge===undefined?"": { prev_challenge===undefined?"":
<a href={prev_challenge} className="fr color-blue mr15 mt4">上一关</a> <a href={prev_challenge} className="fr color-blue mr15 mt4">上一关</a>
} }
{ next_challenge===undefined?"":
<a href={next_challenge}className="fr color-blue mr15 mt4">下一关</a>
}
<a href={practice_url === undefined ? "" : practice_url} <a href={practice_url === undefined ? "" : practice_url}

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