diff --git a/app/assets/javascripts/cooperative/competition_settings/index.js b/app/assets/javascripts/cooperative/competition_settings/index.js new file mode 100644 index 000000000..66a73cbb3 --- /dev/null +++ b/app/assets/javascripts/cooperative/competition_settings/index.js @@ -0,0 +1,803 @@ +$(document).on('turbolinks:load', function(){ + if ($('body.cooperative-competition-settings-index-page').length > 0) { + + var dateOptions = { + autoclose: true, + language: 'zh-CN', + format: 'yyyy-mm-dd', + startDate: '2017-04-01' + }; + + var timeOptions = { + autoclose: 1, + language: 'zh-CN', + format: 'yyyy-mm-dd hh:ii', + minuteStep: 30 + }; + + var defineDateRangeSelect = function (element) { + var options = $.extend({inputs: $(element).find('.start-date, .end-date')}, dateOptions); + $(element).datepicker(options); + + $(element).find('.start-date').datepicker().on('changeDate', function (e) { + $(element).find('.end-date').datepicker('setStartDate', e.date); + }); + }; + $(".competition-start-end-date .start-date").datetimepicker(timeOptions); + + $(".competition-start-end-date .end-date").datetimepicker(timeOptions); + + $(".nav-setting-form .enroll_end_time").datetimepicker(timeOptions); + + $(".stage-update-form .section-start-time").datetimepicker(timeOptions); + $(".stage-update-form .section-end-time").datetimepicker(timeOptions); + + defineDateRangeSelect('.teaching-mode-date'); + // defineTimeRangeSelect('.competition-start-end-date'); + + var $basicForm = $('form.basic-setting-form'); + + $basicForm.validate({ + errorElement: 'span', + errorClass: 'danger text-danger', + rules: { + name: "required", + subTitle: "required", + startTime: "required", + endTime: "required", + mode: "required", + identifier: "required" + } + }); + + // 保存按钮 + $basicForm.on('click', ".submit-btn", function () { + $basicForm.find('.submit-btn').attr('disabled', 'disabled'); + $basicForm.find('.error').html(''); + var valid = $basicForm.valid(); + + if ($("input[name='mode']:checked").val() == 2) { + var $courseId = $("input[name='course_id']"); + if ($courseId.val() === undefined || $courseId.val().length === 0) { + $courseId.addClass('danger text-danger'); + valid = false; + } else { + $courseId.removeClass('danger text-danger'); + } + } else if ($("input[name='mode']:checked").val() == 3) { + var $techStartTime = $("input[name='teach_start_time']"); + var $techEndTime = $("input[name='teach_end_time']"); + if ($techStartTime.val() === undefined || $techStartTime.val().length === 0) { + $techStartTime.addClass('danger text-danger'); + valid = false; + } else { + $techStartTime.removeClass('danger text-danger'); + } + + if ($techEndTime.val() === undefined || $techEndTime.val().length === 0) { + $techEndTime.addClass('danger text-danger'); + valid = false; + } else { + $techEndTime.removeClass('danger text-danger'); + } + } else { + $("input[name='course_id']").removeClass('danger text-danger'); + $("input[name='teach_start_time']").removeClass('danger text-danger'); + $("input[name='teach_end_time']").removeClass('danger text-danger'); + } + + if (!valid) return; + $.ajax({ + method: 'POST', + dataType: 'json', + url: $basicForm.attr('action'), + data: new FormData($basicForm[0]), + processData: false, + contentType: false, + success: function (data) { + $.notify({message: '保存成功'}); + // window.location.reload(); + }, + error: function (res) { + var data = res.responseJSON; + $basicForm.find('.error').html(data.message); + }, + complete: function () { + $basicForm.find('.submit-btn').attr('disabled', false); + } + }); + }); + + var selectOptions = { + theme: 'bootstrap4', + placeholder: '请输入要添加的单位名称', + multiple: true, + minimumInputLength: 1, + ajax: { + delay: 500, + url: '/api/schools/search.json', + dataType: 'json', + data: function(params){ + return { keyword: params.term }; + }, + processResults: function(data){ + return { results: data.schools } + } + }, + templateResult: function (item) { + if(!item.id || item.id === '') return item.text; + return item.name || item.text; + }, + templateSelection: function(item){ + return item.name || item.text; + } + }; + + $('.sponsor-select').select2(selectOptions); + $('.allow-school-select').select2(selectOptions); + + $('.manager-select').select2({ + theme: 'bootstrap4', + placeholder: '请输入要添加的管理员姓名', + multiple: true, + minimumInputLength: 1, + ajax: { + delay: 500, + url: '/cooperative/users', + dataType: 'json', + data: function(params){ + return { keyword: params.term }; + }, + processResults: function(data){ + return { results: data.users } + } + }, + templateResult: function (item) { + if(!item.id || item.id === '') return item.text; + return $("
" + item.real_name + "" + item.school_name + "" + item.hidden_phone + "
"); + }, + templateSelection: function(item){ + if (item.id) { + } + return item.real_name || item.text; + } + }); + + + // 排行榜 + //链接 + $(".nav-setting-form").on("click",".add_linkBtn",function () { + var length=$(".nav-setting-form").find(".linkFormItem").length + 1; + var html='
\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' +\n' + + ' ×\n' + + '
'; + $(this).parents(".linkFormItem").after(html); + }); + + $(".nav-setting-form").on("click", ".del_linkBtn", function () { + $(this).parents(".linkFormItem").remove(); + }); + + //有关报名要求 + $(".addRequireBtn").on("click",function () { + var length=$("#requireForm").find(".requireForm_item").length + 1; + var html='
\n' + + '
  
\n' + + '
\n' + + ' \n' + + '
\n' + + ' ~\n' + + '
\n' + + ' \n' + + '
\n' + + ' \n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '
\n' + + '
'; + $("#requireForm").append(html); + }); + + $("#requireForm").on("click",".delRequrieBtn",function () { + $(this).parents(".requireForm_item").remove(); + }); + + $('.nav-setting-form').on('click', '.module_hidden', function(){ + var checkEle = $(this); + if (checkEle.is(':checked')) { + checkEle.prev().val(0); + } else { + checkEle.prev().val(1); + } + }); + + $('.competition-staff-settings').on('click', '.mutiple-limited-radio', function(){ + var radio = $(this); + if (radio.is(':checked')) { + radio.parent().parent().siblings().find('.mutiple-limited-radio').attr('checked', false) + } else { + radio.parent().parent().siblings().find('.mutiple-limited-radio').attr('checked', true) + } + }); + + var $navForm = $('form.nav-setting-form'); + $navForm.on('click', ".submit-btn", function () { + $navForm.find('.submit-btn').attr('disabled', 'disabled'); + $navForm.find('.error').html(''); + var valid = $navForm.valid(); + + if (!valid) return; + $.ajax({ + method: 'POST', + dataType: 'json', + url: $navForm.attr('action'), + data: new FormData($navForm[0]), + processData: false, + contentType: false, + success: function (data) { + $.notify({message: '保存成功'}); + // window.location.reload(); + }, + error: function (res) { + var data = res.responseJSON; + $navForm.find('.error').html(data.message); + }, + complete: function () { + $navForm.find('.submit-btn').attr('disabled', false); + } + }); + }); + +// 排行榜设置 + //删除小阶段 + $("#large_panel").on("click",".small_panel_item_del",function () { + var list = $(this).parents(".small_panel"); + $(this).parents(".small_panel_item").remove(); + + for(var i=0;i < $(list).find(".subName").length;i++){ + console.log(i); + $(list).find(".subName").eq(i).html("第"+parseInt(i+1)+"阶段"); + } + }); + + // $('form.stage-update-form').validate({ + // errorElement: 'span', + // errorClass: 'danger text-danger', + // rules: { + // stage_name: "required", + // "stage[][start_time]": "required", + // "stage[][end_time]": "required", + // "stage[][mission_count]": { + // required: true, + // min: 1 + // }, + // "stage[][entry]": { + // required: true, + // min: 1 + // }, + // score_rate: { + // required: true, + // range: [0, 100] + // } + // }, + // messages: { + // "stage[][mission_count]": { + // min: ">=1" + // }, + // "stage[][entry]": { + // min: ">=1" + // }, + // } + // }); + + $('.competition-chart-setting').on('click', ".update-stage", function () { + var updateForm = $(this).parents("form"); + $(this).attr('disabled', 'disabled'); + updateForm.find('.error').html(''); + // var valid = updateForm.valid(); + var valid = true; + + var $stageName = updateForm.find('input[name="stage_name"]'); + if($stageName.val() === undefined || $stageName.val().length === 0){ + $stageName.addClass('danger text-danger'); + valid = false; + } else { + $stageName.removeClass('danger text-danger'); + } + + var $scoreRate = updateForm.find('input[name="score_rate"]'); + if($scoreRate.val() === undefined || $scoreRate.val().length === 0){ + $scoreRate.addClass('danger text-danger'); + valid = false; + } else if (parseInt($scoreRate.val()) > 100 || parseInt($scoreRate.val()) < 0) { + $scoreRate.addClass('danger text-danger'); + $scoreRate.after('0-100之间的数值'); + valid = false; + } else { + $scoreRate.removeClass('danger text-danger'); + $scoreRate.siblings().remove(); + } + + updateForm.find('input[name="stage[][start_time]"]').each(function(_, e){ + var $ele = $(e); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + } + }); + + updateForm.find('input[name="stage[][end_time]"]').each(function(_, e){ + var $ele = $(e); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + } + }); + + updateForm.find('input[name="stage[][mission_count]"]').each(function(i, e){ + var $ele = $(e); + var $entry = updateForm.find('input[name="stage[][entry]"]').eq(i); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else if (parseInt($ele.val()) < 1) { + $ele.addClass('danger text-danger'); + $ele.after('大于等于1'); + valid = false; + } else if (parseInt($ele.val()) > parseInt($entry.val())) { + $ele.addClass('danger text-danger'); + $ele.after('不能大于总任务数'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + $ele.siblings().remove(); + } + }); + + updateForm.find('input[name="stage[][entry]"]').each(function(_, e){ + var $ele = $(e); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else if (parseInt($ele.val()) < 1) { + $ele.addClass('danger text-danger'); + $ele.after('大于等于1'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + $ele.siblings().remove(); + } + }); + + updateForm.find('input[name="stage[][identifiers][]"]').each(function(_, e){ + var $ele = $(e); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + } + }); + + if (!valid) return; + + updateForm.find('input[name="stage[][mission_count]"]').each(function(_, e){ + var $missionCount = $(e); + var $entryCount = $(e).parents("div.row").find('input[name="stage[][mission_count]"]'); + if(parseInt($missionCount.val()) > parseInt($entryCount.val()) ){ + $missionCount.addClass('danger text-danger'); + $missionCount.after('不能大于总任务数'); + valid = false; + } else { + $missionCount.removeClass('danger text-danger'); + $missionCount.siblings().remove(); + } + }); + + $.ajax({ + method: 'POST', + dataType: 'json', + url: updateForm.attr('action'), + data: new FormData(updateForm[0]), + processData: false, + contentType: false, + success: function (data) { + $.notify({message: '保存成功'}); + window.location.reload(); + }, + error: function (res) { + var data = res.responseJSON; + $navForm.find('.error').html(data.message); + }, + complete: function () { + $navForm.find('.submit-btn').attr('disabled', false); + } + }); + }); + + $(".competition-chart-stages").on("click", ".add-new-tab", function () { + if($(".new-stage-form").length > 0){ + alert("请先保存上一个tab"); + } else { + var count = parseInt($("#large_panel").find(".large_panel_part").length)+1; + var html = '
' + + '
\n' + + ' tab标题\n' + + '
\n' + + ' \n' + + '
\n' + + ' 总排行榜占比:\n' + + '
\n' + + ' \n' + + '
%\n' + + '
\n' + + ' 新增子阶段\n' + + '
\n' + + ' 删除\n' + + ' 保存\n' + + '
\n' + + '
\n' + + '
\n' + + ' 第1阶段\n' + + '
\n' + + '
\n' + + '
有效时间:\n' + + '
\n' + + ' \n' + + '
\n' + + ' ~\n' + + '
\n' + + ' \n' + + '
\n' + + '
总任务数:\n' + + '
\n' + + ' \n' + + '
\n' + + '
成绩来源:\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务1\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务2\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务3\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' 删除\n' + + ' \n' + + '
\n' + + '
'; + $("#large_panel").append(html); + + $(".stage-update-form .section-start-time").datetimepicker(timeOptions); + $(".stage-update-form .section-end-time").datetimepicker(timeOptions); + } + }); + + //新增子阶段 + $(".competition-chart-stages").on("click", ".add-task-sub", function () { + var index = $(this).parents(".large_panel_part").attr("attr_line"); + var count= 0; + + console.log("sdfsf"); + console.log($("#small_panel_"+index).find(".small_panel_item").length > 0); + + if($("#small_panel_"+index).find(".small_panel_item").length > 0){ + count = parseInt($("#small_panel_"+index).find(".small_panel_item").last().attr("count")) + 1; + + console.log($("#small_panel_"+index).find(".small_panel_item").last().attr("count")); + }else{ + count = 1; + } + + var showCount=parseInt($("#small_panel_"+index).find(".small_panel_item").length) + 1; + + + var html='
\n' + + ' 第'+showCount+'阶段\n' + + '
\n' + + '
\n' + + '
有效时间:\n' + + '
\n' + + ' \n' + + '
\n' + + ' ~\n' + + '
\n' + + ' \n' + + '
\n' + + '
总任务数:\n' + + '
\n' + + ' \n' + + '
\n' + + '
成绩来源:\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n'+ + '
\n' + + ' 任务1\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务2\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务3\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' 删除\n' + + ' \n' + + '
'; + $("#small_panel_"+index).append(html); + + $(".stage-update-form .section-start-time").datetimepicker(timeOptions); + $(".stage-update-form .section-end-time").datetimepicker(timeOptions); + }); + + // 奖项设置 + var $prizeContainer = $('#competition-prize-card'); + var competitionId = $prizeContainer.data('id'); + $(document).on('prize.save.success', function(){ + $.ajax({ + method: 'GET', + url: '/cooperative/competitions/' + competitionId + '/competition_prizes', + dataType: 'script' + }) + }); + + $('.modal.cooperative-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: '/cooperative/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'); + } +}); + +//添加主办方或者开放范围 +function addSponsor(item){ + var html=''; + $(item).parents(".sponsorPanel").append(html); +} +//删除 +function del_sponsor(item){ + $(item).parents(".sponsor_label").remove(); +} + +// 小阶段修改总任务数 +function change_total(item) { + var count=parseInt($(item).val()); + + + var index = $(item).parents(".small_panel_item").attr("attr_line"); + var indexLarge = $(item).parents(".large_panel_part").attr("attr_line"); + console.log(indexLarge); + console.log(index); + + var divCount=parseInt($("#task_Input_"+index).find(".task_Input_div").length); + + + var html = ""; + if(count > divCount){ + for(var i=0;i < count-divCount ;i++){ + html+='
任务'+(divCount+i+1)+'\n' + + '
\n' + + '\n' + + '
\n' + + '
'; + } + $("#task_Input_"+index).append(html); + }else{ + var delCount = divCount - count ; + console.log(divCount); + console.log(count); + var _max=parseInt($("#task_Input_"+index).find(".task_Input_div:last").index()); + + console.log(_max); + var _get= _max - delCount; + + console.log(_get); + if(count == 0){ + $("#task_Input_"+index).empty(); + }else{ + $("#task_Input_"+index).find(".task_Input_div:gt("+_get+")").remove(); + } + + } + +} + +//删除tab +function Del_tab(item) { + $(item).parents(".large_panel_part").remove(); +} +//新增tab +function addNewTab(competition_id) { + if($(".new-stage-form").length > 0){ + alert("请先保存上一个tab"); + } else { + var count = parseInt($("#large_panel").find(".large_panel_part").length)+1; + var html = '
' + + '
\n' + + ' tab标题\n' + + '
\n' + + ' \n' + + '
\n' + + ' 总排行榜占比:\n' + + '
\n' + + ' \n' + + '
%\n' + + '
\n' + + ' 新增子阶段\n' + + '
\n' + + ' 删除\n' + + ' 保存\n' + + '
\n' + + '
\n' + + '
\n' + + ' 第1阶段\n' + + '
\n' + + '
\n' + + '
有效时间:\n' + + '
\n' + + ' \n' + + '
\n' + + ' ~\n' + + '
\n' + + ' \n' + + '
\n' + + '
总任务数:\n' + + '
\n' + + ' \n' + + '
\n' + + '
成绩来源:\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务1\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务2\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务3\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' 删除\n' + + ' \n' + + '
\n' + + '
'; + $("#large_panel").append(html); + } +} diff --git a/app/assets/javascripts/cooperative/competitions/index.js b/app/assets/javascripts/cooperative/competitions/index.js new file mode 100644 index 000000000..20ba586da --- /dev/null +++ b/app/assets/javascripts/cooperative/competitions/index.js @@ -0,0 +1,148 @@ +$(document).on('turbolinks:load', function() { + if ($('body.cooperative-competitions-index-page').length > 0) { + $('.modal.cooperative-upload-file-modal').on('upload:success', function(e, data){ + var $imageElement = $('.competition-image-' + data.source_id); + $imageElement.attr('src', data.url); + $imageElement.show(); + $imageElement.next().html('重新上传'); + }); + } + + $(".cooperative-competition-list-form").on("change", '.competitions-hot-select', function () { + var s_value = $(this).get(0).checked ? 1 : 0; + var json = {}; + json["hot"] = s_value; + $.ajax({ + url: "/cooperative/competitions/hot_setting", + type: "POST", + dataType:'json', + data: json, + success: function(){ + $.notify({ message: '操作成功' }); + } + }); + }); + + // ============== 新增竞赛 =============== + var $modal = $('.modal.cooperative-create-competition-modal'); + var $form = $modal.find('form.cooperative-create-competition-form'); + var $competitionNameInput = $form.find('input[name="competition_name"]'); + + $form.validate({ + errorElement: 'span', + errorClass: 'danger text-danger', + rules: { + competition_name: { + required: true + } + } + }); + + // modal ready fire + $modal.on('show.bs.modal', function () { + $competitionNameInput.val(''); + }); + + $modal.on('click', '.submit-btn', function(){ + $form.find('.error').html(''); + + if ($form.valid()) { + var url = $form.data('url'); + + $.ajax({ + method: 'POST', + dataType: 'json', + url: url, + data: $form.serialize(), + success: function(){ + $.notify({ message: '创建成功' }); + $modal.modal('hide'); + + setTimeout(function(){ + window.location.reload(); + }, 500); + }, + error: function(res){ + var data = res.responseJSON; + $form.find('.error').html(data.message); + } + }); + } + }); + + // 导入学生 + var $importScoreModal = $('.modal.cooperative-import-competition-score-modal'); + var $importScoreForm = $importScoreModal.find('form.cooperative-import-competition-score-form'); + var $competitionIdInput = $importScoreForm.find('input[name="competition_id"]'); + + $importScoreModal.on('show.bs.modal', function(event){ + resetFileInputFunc($importScoreModal.find('.upload-file-input')); + $importScoreModal.find('.file-names').html('选择文件'); + $importScoreModal.find('.upload-file-input').trigger('click'); + + var $link = $(event.relatedTarget); + var competitionId = $link.data('competition-id'); + $competitionIdInput.val(competitionId); + }); + + $importScoreModal.on('change', '.upload-file-input', function(e){ + var file = $(this)[0].files[0]; + $importScoreModal.find('.file-names').html(file ? file.name : '请选择文件'); + }); + + var importUserFormValid = function(){ + if($importScoreForm.find('input[name="file"]').val() == undefined || $importScoreForm.find('input[name="file"]').val().length == 0){ + $importScoreForm.find('.error').html('请选择文件'); + return false; + } + + return true; + }; + + var buildResultMessage = function(data){ + var messageHtml = "
导入结果:成功" + data.success + "条,失败"+ data.fail.length + "条
"; + + if(data.fail.length > 0){ + messageHtml += ''; + + data.fail.forEach(function(item){ + messageHtml += ''; + }); + + messageHtml += '
数据失败原因
' + item.data + '' + item.message + '
' + } + + return messageHtml; + }; + + $importScoreModal.on('click', '.submit-btn', function(){ + $importScoreForm.find('.error').html(''); + + if (importUserFormValid()) { + $('body').mLoading({ text: '正在导入...' }); + + $.ajax({ + method: 'POST', + dataType: 'json', + url: '/cooperative/import_competition_scores', + data: new FormData($importScoreForm[0]), + processData: false, + contentType: false, + success: function(data){ + $('body').mLoading('destroy'); + $importScoreModal.modal('hide'); + + showMessageModal(buildResultMessage(data), function(){ + window.location.reload(); + }); + }, + error: function(res){ + $('body').mLoading('destroy'); + var data = res.responseJSON; + $importScoreForm.find('.error').html(data.message); + } + }); + } + }); +}); + diff --git a/app/assets/javascripts/cooperative/enroll_lists/index.js b/app/assets/javascripts/cooperative/enroll_lists/index.js new file mode 100644 index 000000000..bf5e953e3 --- /dev/null +++ b/app/assets/javascripts/cooperative/enroll_lists/index.js @@ -0,0 +1,9 @@ +$(document).on('turbolinks:load', function() { + if($('body.cooperative-enroll-lists-index-page').length > 0){ + var search_form = $(".search-form"); + //导出 + $(".competition-enroll-list-form").on("click","#enroll-lists-export",function () { + window.location.href = "/cooperative/competitions/"+$(this).attr("data-competition-id")+"/enroll_lists/export.xlsx?" + search_form.serialize(); + }); + } +}); \ No newline at end of file diff --git a/app/assets/stylesheets/cooperative/competition_settings.scss b/app/assets/stylesheets/cooperative/competition_settings.scss new file mode 100644 index 000000000..deaf08452 --- /dev/null +++ b/app/assets/stylesheets/cooperative/competition_settings.scss @@ -0,0 +1,116 @@ +.cooperative-competition-settings-index-page { + .competition-mode-container { + .row { + height: 35px; + } + + .des-row { + height: auto; + } + + .form-control { + font-size: 14px; + } + + //.mode-input { + // input { + // width: 40%; + // } + //} + } + + .col-md-label{ + -webkit-box-flex: 0; + flex: 0 0 10%; + max-width: 10%; + min-width: 30px; + padding-right: 15px; + padding-left: 15px; + position: relative; + } + .col-md-label-s{ + -webkit-box-flex: 0; + flex: 0 0 30px; + padding-right: 15px; + padding-left: 15px; + position: relative; + } + .setBtn_s{ + height: 35px; + line-height: 20px; + } + + .sponsor_label{ + border:1px solid #4CACFF; + border-radius: 5px; + background-color: rgba(76,172,255,0.3); + color: #333; + padding:0px 4px; + height: 30px; + line-height: 30px; + float: left; + margin: 4px 5px; + + span{ + display: block; + float: left; + height: 28px; + line-height: 28px; + margin-right: 5px; + } + + a{ + font-size: 18px; + float: left; + height: 28px; + line-height: 28px; + } + } + + .large_panel{ + padding:0px 15px; + + .large_panel_part{ + border-top: 1px solid #eaeaea; + } + .large_panel_part:first-child{ + border:none; + } + + .large_panel_part >.row ,.small_panel >.row{ + border-bottom: 1px solid #eaeaea; + padding:20px 0px; + } + .small_panel{ + margin-left: 20px; + } + .row:last-child{ + 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 25%; + max-width: 25%; + } + .task_Input_div:nth-child(3n) > span.col-4{ + flex: 0 0 33.3%; + max-width: 33.3%; + } + .task_Input_div:nth-child(3n) > div.col-6{ + flex: 0 0 50%; + max-width: 50%; + } + } +} \ No newline at end of file diff --git a/app/controllers/cooperative/base_controller.rb b/app/controllers/cooperative/base_controller.rb index 556cd7aa9..e77de3e23 100644 --- a/app/controllers/cooperative/base_controller.rb +++ b/app/controllers/cooperative/base_controller.rb @@ -16,7 +16,8 @@ class Cooperative::BaseController < ApplicationController private def current_laboratory - @_current_laboratory ||= Laboratory.find_by_subdomain(request.subdomain) + # @_current_laboratory ||= Laboratory.find_by_subdomain(request.subdomain) + @_current_laboratory ||= Laboratory.find 1 end def current_setting_or_default(name) diff --git a/app/controllers/cooperative/competition_prize_users_controller.rb b/app/controllers/cooperative/competition_prize_users_controller.rb new file mode 100644 index 000000000..8f350e06c --- /dev/null +++ b/app/controllers/cooperative/competition_prize_users_controller.rb @@ -0,0 +1,51 @@ +class Cooperative::CompetitionPrizeUsersController < Cooperative::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)) + + respond_to do |format| + format.js + format.html + format.xlsx do + @all_prize_users = prize_users + filename = "#{@competition.name}竞赛获奖人信息列表_#{Time.current.strftime('%Y%m%d%H%M%S')}.xlsx" + render xlsx: 'index', filename: filename + end + end + 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 ||= current_laboratory.competitions.find(params[:competition_id]) + end +end \ No newline at end of file diff --git a/app/controllers/cooperative/competition_prizes_controller.rb b/app/controllers/cooperative/competition_prizes_controller.rb new file mode 100644 index 000000000..a7e78e376 --- /dev/null +++ b/app/controllers/cooperative/competition_prizes_controller.rb @@ -0,0 +1,43 @@ +class Cooperative::CompetitionPrizesController < Cooperative::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 ||= current_laboratory.competitions.find(params[:competition_id]) + end + + def save_params + params.require(:competition_prize).permit(:name, :category, :num) + end +end \ No newline at end of file diff --git a/app/controllers/cooperative/competition_settings_controller.rb b/app/controllers/cooperative/competition_settings_controller.rb new file mode 100644 index 000000000..08a40a83c --- /dev/null +++ b/app/controllers/cooperative/competition_settings_controller.rb @@ -0,0 +1,33 @@ +class Cooperative::CompetitionSettingsController < Cooperative::BaseController + def index + @competition = current_competition + end + + def basic_setting + Admins::CompetitionBasicSettingService.call(current_competition, basic_form_params) + render_ok + end + + def nav_setting + Admins::CompetitionNavSettingService.call(current_competition, nav_form_params) + render_ok + end + + private + + def current_competition + @_current_competition ||= current_laboratory.competitions.find(params[:competition_id]) + end + + def basic_form_params + params.permit(:identifier, :name, :sub_title, :start_time, :end_time, :mode, + :identifier, :bonus, :awards_count, :description, :course_id, :teach_start_time, + :teach_end_time, sponsor_schools: [], region_schools: [], manager_ids: []) + end + + def nav_form_params + params.permit(:enroll_end_time, + competition_staffs: %i[category minimum maximum mutiple_limited], + navbar: %i[module_type module_id name hidden position url]) + end +end \ No newline at end of file diff --git a/app/controllers/cooperative/competition_stages_controller.rb b/app/controllers/cooperative/competition_stages_controller.rb new file mode 100644 index 000000000..544fe4981 --- /dev/null +++ b/app/controllers/cooperative/competition_stages_controller.rb @@ -0,0 +1,194 @@ +class Cooperative::CompetitionStagesController < Cooperative::BaseController + + def create + Admins::CompetitionStageCreateService.call(current_competition, update_form_params) + render_ok + end + + def update + Admins::CompetitionStageUpdateService.call(current_competition, update_form_params, current_stage) + render_ok + end + + def destroy + current_stage.destroy! + end + + def calculate_stage_score + if current_stage.max_end_time && current_stage.max_end_time < Time.now + + ActiveRecord::Base.transaction do + begin + + current_stage.competition_scores.destroy_all + + if current_stage.competition_stage_sections.size > 0 + # 是否只有老师参赛 + only_teacher = current_competition.member_staff.blank? + stage_sections = current_stage.competition_stage_sections.includes(:competition_entries) + shixuns = Shixun.where(identifier: current_stage.competition_entries.pluck(:shixun_identifier).reject(&:blank?)) + challenges = Challenge.where(shixun_id: shixuns.pluck(:id)) + + # 计算每个战队的成绩 + current_competition.competition_teams.each do |team| + totoal_score = 0 + total_time = 0 + # 只有老师参赛则计算所有参赛队员的成绩,否则只计算学生的成绩 + user_ids = only_teacher ? team.team_members.pluck(:user_id) : team.team_members.where(is_teacher: 0).pluck(:user_id) + + stage_sections.each do |section| + shixun_identifiers = section.competition_entries.pluck(:shixun_identifier).reject(&:blank?) + shixun_ids = shixuns.select{ |shixun| shixun_identifiers.include?(shixun.identifier) }.map(&:id) + section_challenges = challenges.select{ |challenge| shixun_ids.include?(challenge.shixun_id) } + if section.score_source == 0 + result1 = chart_stage_score user_ids, section.start_time, section.end_time, section_challenges, section_challenges.length/shixun_ids.length + else + result1 = chart_stage_rate user_ids, section.start_time, section.end_time, section_challenges, section_challenges.length/shixun_ids.length + end + score = result1[0] + time = result1[1] + + totoal_score += score + total_time += time + end + + # 比赛已截止且未有分数纪录 则创建 + unless team.competition_scores.exists?(competition_id: current_competition.id, competition_stage_id: current_stage.id) + CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: current_competition.id, + competition_stage_id: current_stage.id, score: totoal_score, cost_time: total_time) + end + end + + # 如果计算的是最后一个阶段,则同时计算总成绩(只有一个阶段则不需计算) + if current_stage.max_end_time == current_competition.max_stage_end_time && current_competition.competition_stages.size > 1 + calculate_total_score current_competition + end + end + + rescue Exception => e + uid_logger_error(e.message) + @message = "#{e.message}" + end + end + + @message = "计算成功" + else + @message = "#{current_stage.name}还未结束" + end + end + + def send_message + if current_stage.max_end_time && current_stage.max_end_time > Time.now + User.where(id: TeamMember.where(competition_team_id: current_competition.competition_teams.pluck(:id)).pluck(:user_id).uniq).each do |user| + name = current_competition.name + "#{current_competition.sub_title}(#{stage.name})" + begin + if user.phone.present? + Educoder::Sms.send(mobile: user.phone.to_s, code: '1', send_type:'competition_start', user_name:user.show_name, + name:name, result:section.start_time.strftime('%Y-%m-%d %H:%M:%S')) + end + rescue => e + logger_error(e) + render_error("发送验证码出错") + end + end + else + render_error("#{current_stage.name}已结束") + end + end + + private + + def current_competition + @_current_competition ||= current_laboratory.competitions.find(params[:competition_id]) + end + + def current_stage + @_current_stage ||= CompetitionStage.find_by!(competition_id: params[:competition_id], id: params[:id]) + end + + def update_form_params + params.permit(:stage_name, :score_rate, stage: [:start_time, :end_time, :entry, :score_source, identifiers: []]) + end + + + # challenges 每阶段的所有关卡 + # s_time 阶段开始时间 e_time 阶段结束时间 + # rate 关卡经验值与分数的比值 + # challenge_count 每个实训的关卡数 + # 对三个实训的所有关卡循环: 找到在比赛时间内通关的最低耗时 + def chart_stage_score user_ids, s_time, e_time, challenges, challenge_count + total_score = 0 + total_time = 0 + length = challenge_count #每个实训的关卡数 + for i in 1..length + score = 0 + time = 0 + challenges.select{|challenge| challenge.position == i}.each do |challenge| + Game.where(:challenge_id => challenge.id, :user_id => user_ids, :status => 2).select{|game| game.open_time >= s_time && game.end_time <= e_time }.each do |game| + game_score = challenge.score + cost_time = (game.end_time.to_i - s_time.to_i) > 0 ? (game.end_time.to_i - s_time.to_i) : 0 + if score < game_score + score = game_score + time = cost_time + elsif score == game_score + time = cost_time > time ? time : cost_time + end + end + end + total_score += score + total_time += time + end + return [total_score, total_time] + end + + def chart_stage_rate user_ids, s_time, e_time, challenges, challenge_count + # 第三阶段的得分和耗时 + total_score = 0 + total_time = 0 + length = challenge_count #每个实训的关卡数 + for i in 1..length + score3 = 0 + time3 = 0 + + challenges.select{|challenge| challenge.position == i}.each do |challenge| + Game.where(:challenge_id => challenge.id, :user_id => user_ids, :status => 2).select{|game| game.open_time >= s_time && game.end_time <= e_time }.each do |game| + outputs = game.outputs.select{|output| !output.text_scor.nil? && output.created_at <= e_time } + if outputs.present? + outputs = outputs.sort { |a, b| b[:text_scor].to_f <=> a[:text_scor].to_f } + myshixun_score = outputs.first.text_scor.to_f + myshixun_time = outputs.first.created_at.to_i - s_time.to_i + if score3 < myshixun_score + score3 = myshixun_score + time3 = myshixun_time + elsif score3 == myshixun_score + time3 = myshixun_time > time3 ? time3 : myshixun_time + end + end + end + end + + total_score += score3 + total_time += time3 + end + return [total_score, total_time] + end + + def calculate_total_score competition + competition.competition_scores.where(competition_stage_id: 0).destroy_all + competition.competition_teams.each do |team| + total_score = 0 + total_time = 0 + + competition.competition_stages.where("score_rate > 0").each do |stage| + stage_score = team.competition_scores.where(competition_stage_id: stage.id).take + total_score += stage_score.try(:score).to_f * stage.score_rate + total_time += stage_score.try(:cost_time).to_i + end + + unless team.competition_scores.exists?(competition_id: competition.id, competition_stage_id: 0) + CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: competition.id, + competition_stage_id: 0, score: total_score, cost_time: total_time) + end + end + end +end \ No newline at end of file diff --git a/app/controllers/cooperative/competitions_controller.rb b/app/controllers/cooperative/competitions_controller.rb new file mode 100644 index 000000000..891f997f4 --- /dev/null +++ b/app/controllers/cooperative/competitions_controller.rb @@ -0,0 +1,57 @@ +class Cooperative::CompetitionsController < Cooperative::BaseController + before_action :find_competition, except: [:index] + + def index + # params[:sort_by] = params[:sort_by].presence || 'created_at' + # params[:sort_direction] = params[:sort_direction].presence || 'desc' + @competitions = current_laboratory.competitions.order("created_at desc") + @params_page = params[:page] || 1 + @competitions = paginate @competitions + ids = @competitions.map(&:id) + @member_count_map = TeamMember.where(competition_id: ids).group(:competition_id).count + + @competition_hot = ModuleSetting.exists?(module_type: "Competition", property: "hot") + respond_to do |format| + format.js + format.html + end + end + + def create + name = params[:competition_name].to_s.strip + Competition.create!(name: name) + render_ok + end + + def hot_setting + if params[:hot].to_i == 1 && !ModuleSetting.exists?(module_type: "Competition", property: "hot") + ModuleSetting.create!(module_type: "Competition", property: "hot") + elsif params[:hot].to_i == 0 && ModuleSetting.exists?(module_type: "Competition", property: "hot") + ModuleSetting.where(module_type: "Competition", property: "hot").destroy_all + end + render_ok + end + + def publish + @competition.update_attributes!(published_at: Time.now) + end + + def unpublish + @competition.update_attributes!(published_at: nil) + end + + def online_switch + if @competition.status + @competition.update_attributes!(status: false) + else + @competition.update_attributes!(status: true, online_time: Time.now) + end + end + + private + + def find_competition + @competition = current_laboratory.competitions.find_by(id: params[:id]) + end + +end \ No newline at end of file diff --git a/app/controllers/cooperative/enroll_lists_controller.rb b/app/controllers/cooperative/enroll_lists_controller.rb new file mode 100644 index 000000000..c228150b9 --- /dev/null +++ b/app/controllers/cooperative/enroll_lists_controller.rb @@ -0,0 +1,33 @@ +class Cooperative::EnrollListsController < Cooperative::BaseController + + def index + @competition = current_competition + default_sort('created_at', 'desc') + enroll_lists = Admins::CompetitionEnrollListQuery.call(@competition, params) + + @params_page = params[:page] || 1 + @enroll_lists = paginate enroll_lists.preload(competition_team: [:user, :teachers], user: { user_extension: :school }) + @personal = @competition.personal? + + respond_to do |format| + format.js + format.html + end + end + + def export + default_sort('created_at', 'desc') + @enroll_lists = Admins::CompetitionEnrollListQuery.call(current_competition, params) + @enroll_lists = @enroll_lists.preload(competition_team: [:user, :teachers], user: { user_extension: :school }) + @competition_scores = current_competition.competition_scores.where(competition_stage_id: 0).order("score desc, cost_time desc").pluck(:competition_team_id) + @personal = current_competition.personal? + filename = ["#{current_competition.name}竞赛报名列表", Time.zone.now.strftime('%Y-%m-%d%H:%M:%S')].join('-') << '.xlsx' + render xlsx: 'export', filename: filename + end + + private + def current_competition + @_current_competition ||= current_laboratory.competitions.find(params[:competition_id]) + end + +end \ No newline at end of file diff --git a/app/views/cooperative/carousels/index.html.erb b/app/views/cooperative/carousels/index.html.erb index 4b7c0bcc5..5f8957865 100644 --- a/app/views/cooperative/carousels/index.html.erb +++ b/app/views/cooperative/carousels/index.html.erb @@ -12,7 +12,7 @@