diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js index c69986a57..dde8bc823 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -11,6 +11,7 @@ //= require select2 //= require jquery.cxselect //= require bootstrap-datepicker +//= require bootstrap-datetimepicker //= require bootstrap.viewer //= require jquery.mloading //= require jquery-confirm.min diff --git a/app/assets/javascripts/admins/competition_settings/index.js b/app/assets/javascripts/admins/competition_settings/index.js new file mode 100644 index 000000000..cd10aeb4f --- /dev/null +++ b/app/assets/javascripts/admins/competition_settings/index.js @@ -0,0 +1,200 @@ +$(document).on('turbolinks:load', function(){ + if ($('body.admins-competition-settings-index-page').length > 0) { + + var dateOptions = { + autoclose: true, + language: 'zh-CN', + format: 'yyyy-mm-dd', + startDate: '2017-04-01' + }; + + var timeOptions = { + autoclose: true, + language: 'zh-CN', + format: 'yyyy-mm-dd hh:ii:ss', + 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); + }); + }; + + // var defineTimeRangeSelect = function (element) { + // var options = $.extend({inputs: $(element).find('.start-date, .end-date')}, timeOptions); + // $(element).datetimepicker(options); + // + // $(element).find('.start-date').datetimepicker().on('changeDate', function (e) { + // $(element).find('.end-date').datetimepicker('setStartDate', e.date); + // }); + // }; + + defineDateRangeSelect('.teaching-mode-date'); + defineDateRangeSelect('.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 || $course_id.val().length === 0) { + $courseId.addClass('danger text-danger'); + valid = false; + } else { + $courseId.removeClass('danger text-danger'); + } + } else if ($("input[name='mode']:checked").val() == 4) { + 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'); + } + } + + 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); + } + }); + }); + } +}); + + +$(function () { + //MD编辑 + $("#MD_typeFrom").on("click",".add_MD_type",function () { + + var length=$(".MD_type").find(".add_MD_type").length + 1; + var html='
\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' \n' + + '
'; + $("#MD_typeFrom").append(html); + }) + $("#MD_typeFrom").on("click",".del_MD_type",function () { + $(this).parents(".MD_type").remove(); + }) + + + //链接 + $("#linkForm").on("click",".add_linkBtn",function () { + var length=$("#linkForm").find(".linkFormItem").length + 1; + var html='
\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' \n' + + '
' + $("#linkForm").append(html) + }) + $("#linkForm").on("click",".del_linkBtn",function () { + $(this).parents(".lineFromItem").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(); + }) +}) \ No newline at end of file diff --git a/app/assets/javascripts/admins/enroll_lists/index.js b/app/assets/javascripts/admins/enroll_lists/index.js index 04bd95070..f53b82f41 100644 --- a/app/assets/javascripts/admins/enroll_lists/index.js +++ b/app/assets/javascripts/admins/enroll_lists/index.js @@ -3,7 +3,7 @@ $(document).on('turbolinks:load', function() { let search_form = $(".search-form"); //导出 $(".competition-enroll-list-form").on("click","#enroll-lists-export",function () { - window.location.href = "/admins/competitions/"+$(this).attr("data-competition-id")+"/enroll_lists.xls?" + search_form.serialize(); + window.location.href = "/admins/competitions/"+$(this).attr("data-competition-id")+"/enroll_lists/export.xlsx?" + search_form.serialize(); }); } }); \ No newline at end of file diff --git a/app/assets/javascripts/bootstrap-datetimepicker.js b/app/assets/javascripts/bootstrap-datetimepicker.js new file mode 100755 index 000000000..8838cbcd2 --- /dev/null +++ b/app/assets/javascripts/bootstrap-datetimepicker.js @@ -0,0 +1,2636 @@ +/*! version : 4.17.47 + ========================================================= + bootstrap-datetimejs + https://github.com/Eonasdan/bootstrap-datetimepicker + Copyright (c) 2015 Jonathan Peterson + ========================================================= + */ +/* + The MIT License (MIT) + + Copyright (c) 2015 Jonathan Peterson + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +/*global define:false */ +/*global exports:false */ +/*global require:false */ +/*global jQuery:false */ +/*global moment:false */ +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // AMD is used - Register as an anonymous module. + define(['jquery', 'moment'], factory); + } else if (typeof exports === 'object') { + module.exports = factory(require('jquery'), require('moment')); + } else { + // Neither AMD nor CommonJS used. Use global variables. + if (typeof jQuery === 'undefined') { + throw 'bootstrap-datetimepicker requires jQuery to be loaded first'; + } + if (typeof moment === 'undefined') { + throw 'bootstrap-datetimepicker requires Moment.js to be loaded first'; + } + factory(jQuery, moment); + } +}(function ($, moment) { + 'use strict'; + if (!moment) { + throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first'); + } + + var dateTimePicker = function (element, options) { + var picker = {}, + date, + viewDate, + unset = true, + input, + component = false, + widget = false, + use24Hours, + minViewModeNumber = 0, + actualFormat, + parseFormats, + currentViewMode, + datePickerModes = [ + { + clsName: 'days', + navFnc: 'M', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'y', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'y', + navStep: 10 + }, + { + clsName: 'decades', + navFnc: 'y', + navStep: 100 + } + ], + viewModes = ['days', 'months', 'years', 'decades'], + verticalModes = ['top', 'bottom', 'auto'], + horizontalModes = ['left', 'right', 'auto'], + toolbarPlacements = ['default', 'top', 'bottom'], + keyMap = { + 'up': 38, + 38: 'up', + 'down': 40, + 40: 'down', + 'left': 37, + 37: 'left', + 'right': 39, + 39: 'right', + 'tab': 9, + 9: 'tab', + 'escape': 27, + 27: 'escape', + 'enter': 13, + 13: 'enter', + 'pageUp': 33, + 33: 'pageUp', + 'pageDown': 34, + 34: 'pageDown', + 'shift': 16, + 16: 'shift', + 'control': 17, + 17: 'control', + 'space': 32, + 32: 'space', + 't': 84, + 84: 't', + 'delete': 46, + 46: 'delete' + }, + keyState = {}, + + /******************************************************************************** + * + * Private functions + * + ********************************************************************************/ + + hasTimeZone = function () { + return moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== ''; + }, + + getMoment = function (d) { + var returnMoment; + + if (d === undefined || d === null) { + returnMoment = moment(); //TODO should this use format? and locale? + } else if (moment.isDate(d) || moment.isMoment(d)) { + // If the date that is passed in is already a Date() or moment() object, + // pass it directly to moment. + returnMoment = moment(d); + } else if (hasTimeZone()) { // There is a string to parse and a default time zone + // parse with the tz function which takes a default time zone if it is not in the format string + returnMoment = moment.tz(d, parseFormats, options.useStrict, options.timeZone); + } else { + returnMoment = moment(d, parseFormats, options.useStrict); + } + + if (hasTimeZone()) { + returnMoment.tz(options.timeZone); + } + + return returnMoment; + }, + + isEnabled = function (granularity) { + if (typeof granularity !== 'string' || granularity.length > 1) { + throw new TypeError('isEnabled expects a single character string parameter'); + } + switch (granularity) { + case 'y': + return actualFormat.indexOf('Y') !== -1; + case 'M': + return actualFormat.indexOf('M') !== -1; + case 'd': + return actualFormat.toLowerCase().indexOf('d') !== -1; + case 'h': + case 'H': + return actualFormat.toLowerCase().indexOf('h') !== -1; + case 'm': + return actualFormat.indexOf('m') !== -1; + case 's': + return actualFormat.indexOf('s') !== -1; + default: + return false; + } + }, + + hasTime = function () { + return (isEnabled('h') || isEnabled('m') || isEnabled('s')); + }, + + hasDate = function () { + return (isEnabled('y') || isEnabled('M') || isEnabled('d')); + }, + + getDatePickerTemplate = function () { + var headTemplate = $('') + .append($('') + .append($('').addClass('prev').attr('data-action', 'previous') + .append($('').addClass(options.icons.previous)) + ) + .append($('').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5'))) + .append($('').addClass('next').attr('data-action', 'next') + .append($('').addClass(options.icons.next)) + ) + ), + contTemplate = $('') + .append($('') + .append($('').attr('colspan', (options.calendarWeeks ? '8' : '7'))) + ); + + return [ + $('
').addClass('datepicker-days') + .append($('').addClass('table-condensed') + .append(headTemplate) + .append($('')) + ), + $('
').addClass('datepicker-months') + .append($('
').addClass('table-condensed') + .append(headTemplate.clone()) + .append(contTemplate.clone()) + ), + $('
').addClass('datepicker-years') + .append($('
').addClass('table-condensed') + .append(headTemplate.clone()) + .append(contTemplate.clone()) + ), + $('
').addClass('datepicker-decades') + .append($('
').addClass('table-condensed') + .append(headTemplate.clone()) + .append(contTemplate.clone()) + ) + ]; + }, + + getTimePickerMainTemplate = function () { + var topRow = $(''), + middleRow = $(''), + bottomRow = $(''); + + if (isEnabled('h')) { + topRow.append($('
') + .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour }).addClass('btn').attr('data-action', 'incrementHours').append($('').addClass(options.icons.up)))); + middleRow.append($('') + .append($('').addClass('timepicker-hour').attr({ 'data-time-component': 'hours', 'title': options.tooltips.pickHour }).attr('data-action', 'showHours'))); + bottomRow.append($('') + .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour }).addClass('btn').attr('data-action', 'decrementHours').append($('').addClass(options.icons.down)))); + } + if (isEnabled('m')) { + if (isEnabled('h')) { + topRow.append($('').addClass('separator')); + middleRow.append($('').addClass('separator').html(':')); + bottomRow.append($('').addClass('separator')); + } + topRow.append($('') + .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute }).addClass('btn').attr('data-action', 'incrementMinutes') + .append($('').addClass(options.icons.up)))); + middleRow.append($('') + .append($('').addClass('timepicker-minute').attr({ 'data-time-component': 'minutes', 'title': options.tooltips.pickMinute }).attr('data-action', 'showMinutes'))); + bottomRow.append($('') + .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute }).addClass('btn').attr('data-action', 'decrementMinutes') + .append($('').addClass(options.icons.down)))); + } + if (isEnabled('s')) { + if (isEnabled('m')) { + topRow.append($('').addClass('separator')); + middleRow.append($('').addClass('separator').html(':')); + bottomRow.append($('').addClass('separator')); + } + topRow.append($('') + .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond }).addClass('btn').attr('data-action', 'incrementSeconds') + .append($('').addClass(options.icons.up)))); + middleRow.append($('') + .append($('').addClass('timepicker-second').attr({ 'data-time-component': 'seconds', 'title': options.tooltips.pickSecond }).attr('data-action', 'showSeconds'))); + bottomRow.append($('') + .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond }).addClass('btn').attr('data-action', 'decrementSeconds') + .append($('').addClass(options.icons.down)))); + } + + if (!use24Hours) { + topRow.append($('').addClass('separator')); + middleRow.append($('') + .append($('').addClass('separator')); + } + + return $('
').addClass('timepicker-picker') + .append($('').addClass('table-condensed') + .append([topRow, middleRow, bottomRow])); + }, + + getTimePickerTemplate = function () { + var hoursView = $('
').addClass('timepicker-hours') + .append($('
').addClass('table-condensed')), + minutesView = $('
').addClass('timepicker-minutes') + .append($('
').addClass('table-condensed')), + secondsView = $('
').addClass('timepicker-seconds') + .append($('
').addClass('table-condensed')), + ret = [getTimePickerMainTemplate()]; + + if (isEnabled('h')) { + ret.push(hoursView); + } + if (isEnabled('m')) { + ret.push(minutesView); + } + if (isEnabled('s')) { + ret.push(secondsView); + } + + return ret; + }, + + getToolbar = function () { + var row = []; + if (options.showTodayButton) { + row.push($('
').append($('').attr({ 'data-action': 'today', 'title': options.tooltips.today }).append($('').addClass(options.icons.today)))); + } + if (!options.sideBySide && hasDate() && hasTime()) { + row.push($('').append($('').attr({ 'data-action': 'togglePicker', 'title': options.tooltips.selectTime }).append($('').addClass(options.icons.time)))); + } + if (options.showClear) { + row.push($('').append($('').attr({ 'data-action': 'clear', 'title': options.tooltips.clear }).append($('').addClass(options.icons.clear)))); + } + if (options.showClose) { + row.push($('').append($('').attr({ 'data-action': 'close', 'title': options.tooltips.close }).append($('').addClass(options.icons.close)))); + } + return $('').addClass('table-condensed').append($('').append($('').append(row))); + }, + + getTemplate = function () { + var template = $('
').addClass('bootstrap-datetimepicker-widget dropdown-menu'), + dateView = $('
').addClass('datepicker').append(getDatePickerTemplate()), + timeView = $('
').addClass('timepicker').append(getTimePickerTemplate()), + content = $('
    ').addClass('list-unstyled'), + toolbar = $('
  • ').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar()); + + if (options.inline) { + template.removeClass('dropdown-menu'); + } + + if (use24Hours) { + template.addClass('usetwentyfour'); + } + + if (isEnabled('s') && !use24Hours) { + template.addClass('wider'); + } + + if (options.sideBySide && hasDate() && hasTime()) { + template.addClass('timepicker-sbs'); + if (options.toolbarPlacement === 'top') { + template.append(toolbar); + } + template.append( + $('
    ').addClass('row') + .append(dateView.addClass('col-md-6')) + .append(timeView.addClass('col-md-6')) + ); + if (options.toolbarPlacement === 'bottom') { + template.append(toolbar); + } + return template; + } + + if (options.toolbarPlacement === 'top') { + content.append(toolbar); + } + if (hasDate()) { + content.append($('
  • ').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView)); + } + if (options.toolbarPlacement === 'default') { + content.append(toolbar); + } + if (hasTime()) { + content.append($('
  • ').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView)); + } + if (options.toolbarPlacement === 'bottom') { + content.append(toolbar); + } + return template.append(content); + }, + + dataToOptions = function () { + var eData, + dataOptions = {}; + + if (element.is('input') || options.inline) { + eData = element.data(); + } else { + eData = element.find('input').data(); + } + + if (eData.dateOptions && eData.dateOptions instanceof Object) { + dataOptions = $.extend(true, dataOptions, eData.dateOptions); + } + + $.each(options, function (key) { + var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1); + if (eData[attributeName] !== undefined) { + dataOptions[key] = eData[attributeName]; + } + }); + return dataOptions; + }, + + place = function () { + var position = (component || element).position(), + offset = (component || element).offset(), + vertical = options.widgetPositioning.vertical, + horizontal = options.widgetPositioning.horizontal, + parent; + + if (options.widgetParent) { + parent = options.widgetParent.append(widget); + } else if (element.is('input')) { + parent = element.after(widget).parent(); + } else if (options.inline) { + parent = element.append(widget); + return; + } else { + parent = element; + element.children().first().after(widget); + } + + // Top and bottom logic + if (vertical === 'auto') { + if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() && + widget.height() + element.outerHeight() < offset.top) { + vertical = 'top'; + } else { + vertical = 'bottom'; + } + } + + // Left and right logic + if (horizontal === 'auto') { + if (parent.width() < offset.left + widget.outerWidth() / 2 && + offset.left + widget.outerWidth() > $(window).width()) { + horizontal = 'right'; + } else { + horizontal = 'left'; + } + } + + if (vertical === 'top') { + widget.addClass('top').removeClass('bottom'); + } else { + widget.addClass('bottom').removeClass('top'); + } + + if (horizontal === 'right') { + widget.addClass('pull-right'); + } else { + widget.removeClass('pull-right'); + } + + // find the first parent element that has a non-static css positioning + if (parent.css('position') === 'static') { + parent = parent.parents().filter(function () { + return $(this).css('position') !== 'static'; + }).first(); + } + + if (parent.length === 0) { + throw new Error('datetimepicker component should be placed within a non-static positioned container'); + } + + widget.css({ + top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(), + bottom: vertical === 'top' ? parent.outerHeight() - (parent === element ? 0 : position.top) : 'auto', + left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto', + right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left) + }); + }, + + notifyEvent = function (e) { + if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) { + return; + } + element.trigger(e); + }, + + viewUpdate = function (e) { + if (e === 'y') { + e = 'YYYY'; + } + notifyEvent({ + type: 'dp.update', + change: e, + viewDate: viewDate.clone() + }); + }, + + showMode = function (dir) { + if (!widget) { + return; + } + if (dir) { + currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir)); + } + widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show(); + }, + + fillDow = function () { + var row = $('
'), + currentDate = viewDate.clone().startOf('w').startOf('d'); + + if (options.calendarWeeks === true) { + row.append($(''); + if (options.calendarWeeks) { + row.append(''); + } + html.push(row); + } + clsNames = ['day']; + if (currentDate.isBefore(viewDate, 'M')) { + clsNames.push('old'); + } + if (currentDate.isAfter(viewDate, 'M')) { + clsNames.push('new'); + } + if (currentDate.isSame(date, 'd') && !unset) { + clsNames.push('active'); + } + if (!isValid(currentDate, 'd')) { + clsNames.push('disabled'); + } + if (currentDate.isSame(getMoment(), 'd')) { + clsNames.push('today'); + } + if (currentDate.day() === 0 || currentDate.day() === 6) { + clsNames.push('weekend'); + } + notifyEvent({ + type: 'dp.classify', + date: currentDate, + classNames: clsNames + }); + row.append(''); + currentDate.add(1, 'd'); + } + + daysView.find('tbody').empty().append(html); + + updateMonths(); + + updateYears(); + + updateDecades(); + }, + + fillHours = function () { + var table = widget.find('.timepicker-hours table'), + currentHour = viewDate.clone().startOf('d'), + html = [], + row = $(''); + + if (viewDate.hour() > 11 && !use24Hours) { + currentHour.hour(12); + } + while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) { + if (currentHour.hour() % 4 === 0) { + row = $(''); + html.push(row); + } + row.append(''); + currentHour.add(1, 'h'); + } + table.empty().append(html); + }, + + fillMinutes = function () { + var table = widget.find('.timepicker-minutes table'), + currentMinute = viewDate.clone().startOf('h'), + html = [], + row = $(''), + step = options.stepping === 1 ? 5 : options.stepping; + + while (viewDate.isSame(currentMinute, 'h')) { + if (currentMinute.minute() % (step * 4) === 0) { + row = $(''); + html.push(row); + } + row.append(''); + currentMinute.add(step, 'm'); + } + table.empty().append(html); + }, + + fillSeconds = function () { + var table = widget.find('.timepicker-seconds table'), + currentSecond = viewDate.clone().startOf('m'), + html = [], + row = $(''); + + while (viewDate.isSame(currentSecond, 'm')) { + if (currentSecond.second() % 20 === 0) { + row = $(''); + html.push(row); + } + row.append(''); + currentSecond.add(5, 's'); + } + + table.empty().append(html); + }, + + fillTime = function () { + var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]'); + + if (!use24Hours) { + toggle = widget.find('.timepicker [data-action=togglePeriod]'); + newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'); + + toggle.text(date.format('A')); + + if (isValid(newDate, 'h')) { + toggle.removeClass('disabled'); + } else { + toggle.addClass('disabled'); + } + } + timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh')); + timeComponents.filter('[data-time-component=minutes]').text(date.format('mm')); + timeComponents.filter('[data-time-component=seconds]').text(date.format('ss')); + + fillHours(); + fillMinutes(); + fillSeconds(); + }, + + update = function () { + if (!widget) { + return; + } + fillDate(); + fillTime(); + }, + + setValue = function (targetMoment) { + var oldDate = unset ? null : date; + + // case of calling setValue(null or false) + if (!targetMoment) { + unset = true; + input.val(''); + element.data('date', ''); + notifyEvent({ + type: 'dp.change', + date: false, + oldDate: oldDate + }); + update(); + return; + } + + targetMoment = targetMoment.clone().locale(options.locale); + + if (hasTimeZone()) { + targetMoment.tz(options.timeZone); + } + + if (options.stepping !== 1) { + targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping)).seconds(0); + + while (options.minDate && targetMoment.isBefore(options.minDate)) { + targetMoment.add(options.stepping, 'minutes'); + } + } + + if (isValid(targetMoment)) { + date = targetMoment; + viewDate = date.clone(); + input.val(date.format(actualFormat)); + element.data('date', date.format(actualFormat)); + unset = false; + update(); + notifyEvent({ + type: 'dp.change', + date: date.clone(), + oldDate: oldDate + }); + } else { + if (!options.keepInvalid) { + input.val(unset ? '' : date.format(actualFormat)); + } else { + notifyEvent({ + type: 'dp.change', + date: targetMoment, + oldDate: oldDate + }); + } + notifyEvent({ + type: 'dp.error', + date: targetMoment, + oldDate: oldDate + }); + } + }, + + /** + * Hides the widget. Possibly will emit dp.hide + */ + hide = function () { + var transitioning = false; + if (!widget) { + return picker; + } + // Ignore event if in the middle of a picker transition + widget.find('.collapse').each(function () { + var collapseData = $(this).data('collapse'); + if (collapseData && collapseData.transitioning) { + transitioning = true; + return false; + } + return true; + }); + if (transitioning) { + return picker; + } + if (component && component.hasClass('btn')) { + component.toggleClass('active'); + } + widget.hide(); + + $(window).off('resize', place); + widget.off('click', '[data-action]'); + widget.off('mousedown', false); + + widget.remove(); + widget = false; + + notifyEvent({ + type: 'dp.hide', + date: date.clone() + }); + + input.blur(); + + viewDate = date.clone(); + + return picker; + }, + + clear = function () { + setValue(null); + }, + + parseInputDate = function (inputDate) { + if (options.parseInputDate === undefined) { + if (!moment.isMoment(inputDate) || inputDate instanceof Date) { + inputDate = getMoment(inputDate); + } + } else { + inputDate = options.parseInputDate(inputDate); + } + //inputDate.locale(options.locale); + return inputDate; + }, + + /******************************************************************************** + * + * Widget UI interaction functions + * + ********************************************************************************/ + actions = { + next: function () { + var navFnc = datePickerModes[currentViewMode].navFnc; + viewDate.add(datePickerModes[currentViewMode].navStep, navFnc); + fillDate(); + viewUpdate(navFnc); + }, + + previous: function () { + var navFnc = datePickerModes[currentViewMode].navFnc; + viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc); + fillDate(); + viewUpdate(navFnc); + }, + + pickerSwitch: function () { + showMode(1); + }, + + selectMonth: function (e) { + var month = $(e.target).closest('tbody').find('span').index($(e.target)); + viewDate.month(month); + if (currentViewMode === minViewModeNumber) { + setValue(date.clone().year(viewDate.year()).month(viewDate.month())); + if (!options.inline) { + hide(); + } + } else { + showMode(-1); + fillDate(); + } + viewUpdate('M'); + }, + + selectYear: function (e) { + var year = parseInt($(e.target).text(), 10) || 0; + viewDate.year(year); + if (currentViewMode === minViewModeNumber) { + setValue(date.clone().year(viewDate.year())); + if (!options.inline) { + hide(); + } + } else { + showMode(-1); + fillDate(); + } + viewUpdate('YYYY'); + }, + + selectDecade: function (e) { + var year = parseInt($(e.target).data('selection'), 10) || 0; + viewDate.year(year); + if (currentViewMode === minViewModeNumber) { + setValue(date.clone().year(viewDate.year())); + if (!options.inline) { + hide(); + } + } else { + showMode(-1); + fillDate(); + } + viewUpdate('YYYY'); + }, + + selectDay: function (e) { + var day = viewDate.clone(); + if ($(e.target).is('.old')) { + day.subtract(1, 'M'); + } + if ($(e.target).is('.new')) { + day.add(1, 'M'); + } + setValue(day.date(parseInt($(e.target).text(), 10))); + if (!hasTime() && !options.keepOpen && !options.inline) { + hide(); + } + }, + + incrementHours: function () { + var newDate = date.clone().add(1, 'h'); + if (isValid(newDate, 'h')) { + setValue(newDate); + } + }, + + incrementMinutes: function () { + var newDate = date.clone().add(options.stepping, 'm'); + if (isValid(newDate, 'm')) { + setValue(newDate); + } + }, + + incrementSeconds: function () { + var newDate = date.clone().add(1, 's'); + if (isValid(newDate, 's')) { + setValue(newDate); + } + }, + + decrementHours: function () { + var newDate = date.clone().subtract(1, 'h'); + if (isValid(newDate, 'h')) { + setValue(newDate); + } + }, + + decrementMinutes: function () { + var newDate = date.clone().subtract(options.stepping, 'm'); + if (isValid(newDate, 'm')) { + setValue(newDate); + } + }, + + decrementSeconds: function () { + var newDate = date.clone().subtract(1, 's'); + if (isValid(newDate, 's')) { + setValue(newDate); + } + }, + + togglePeriod: function () { + setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h')); + }, + + togglePicker: function (e) { + var $this = $(e.target), + $parent = $this.closest('ul'), + expanded = $parent.find('.in'), + closed = $parent.find('.collapse:not(.in)'), + collapseData; + + if (expanded && expanded.length) { + collapseData = expanded.data('collapse'); + if (collapseData && collapseData.transitioning) { + return; + } + if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it + expanded.collapse('hide'); + closed.collapse('show'); + } else { // otherwise just toggle in class on the two views + expanded.removeClass('in'); + closed.addClass('in'); + } + if ($this.is('span')) { + $this.toggleClass(options.icons.time + ' ' + options.icons.date); + } else { + $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); + } + + // NOTE: uncomment if toggled state will be restored in show() + //if (component) { + // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); + //} + } + }, + + showPicker: function () { + widget.find('.timepicker > div:not(.timepicker-picker)').hide(); + widget.find('.timepicker .timepicker-picker').show(); + }, + + showHours: function () { + widget.find('.timepicker .timepicker-picker').hide(); + widget.find('.timepicker .timepicker-hours').show(); + }, + + showMinutes: function () { + widget.find('.timepicker .timepicker-picker').hide(); + widget.find('.timepicker .timepicker-minutes').show(); + }, + + showSeconds: function () { + widget.find('.timepicker .timepicker-picker').hide(); + widget.find('.timepicker .timepicker-seconds').show(); + }, + + selectHour: function (e) { + var hour = parseInt($(e.target).text(), 10); + + if (!use24Hours) { + if (date.hours() >= 12) { + if (hour !== 12) { + hour += 12; + } + } else { + if (hour === 12) { + hour = 0; + } + } + } + setValue(date.clone().hours(hour)); + actions.showPicker.call(picker); + }, + + selectMinute: function (e) { + setValue(date.clone().minutes(parseInt($(e.target).text(), 10))); + actions.showPicker.call(picker); + }, + + selectSecond: function (e) { + setValue(date.clone().seconds(parseInt($(e.target).text(), 10))); + actions.showPicker.call(picker); + }, + + clear: clear, + + today: function () { + var todaysDate = getMoment(); + if (isValid(todaysDate, 'd')) { + setValue(todaysDate); + } + }, + + close: hide + }, + + doAction = function (e) { + if ($(e.currentTarget).is('.disabled')) { + return false; + } + actions[$(e.currentTarget).data('action')].apply(picker, arguments); + return false; + }, + + /** + * Shows the widget. Possibly will emit dp.show and dp.change + */ + show = function () { + var currentMoment, + useCurrentGranularity = { + 'year': function (m) { + return m.month(0).date(1).hours(0).seconds(0).minutes(0); + }, + 'month': function (m) { + return m.date(1).hours(0).seconds(0).minutes(0); + }, + 'day': function (m) { + return m.hours(0).seconds(0).minutes(0); + }, + 'hour': function (m) { + return m.seconds(0).minutes(0); + }, + 'minute': function (m) { + return m.seconds(0); + } + }; + + if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) { + return picker; + } + if (input.val() !== undefined && input.val().trim().length !== 0) { + setValue(parseInputDate(input.val().trim())); + } else if (unset && options.useCurrent && (options.inline || (input.is('input') && input.val().trim().length === 0))) { + currentMoment = getMoment(); + if (typeof options.useCurrent === 'string') { + currentMoment = useCurrentGranularity[options.useCurrent](currentMoment); + } + setValue(currentMoment); + } + widget = getTemplate(); + + fillDow(); + fillMonths(); + + widget.find('.timepicker-hours').hide(); + widget.find('.timepicker-minutes').hide(); + widget.find('.timepicker-seconds').hide(); + + update(); + showMode(); + + $(window).on('resize', place); + widget.on('click', '[data-action]', doAction); // this handles clicks on the widget + widget.on('mousedown', false); + + if (component && component.hasClass('btn')) { + component.toggleClass('active'); + } + place(); + widget.show(); + if (options.focusOnShow && !input.is(':focus')) { + input.focus(); + } + + notifyEvent({ + type: 'dp.show' + }); + return picker; + }, + + /** + * Shows or hides the widget + */ + toggle = function () { + return (widget ? hide() : show()); + }, + + keydown = function (e) { + var handler = null, + index, + index2, + pressedKeys = [], + pressedModifiers = {}, + currentKey = e.which, + keyBindKeys, + allModifiersPressed, + pressed = 'p'; + + keyState[currentKey] = pressed; + + for (index in keyState) { + if (keyState.hasOwnProperty(index) && keyState[index] === pressed) { + pressedKeys.push(index); + if (parseInt(index, 10) !== currentKey) { + pressedModifiers[index] = true; + } + } + } + + for (index in options.keyBinds) { + if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') { + keyBindKeys = index.split(' '); + if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) { + allModifiersPressed = true; + for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) { + if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) { + allModifiersPressed = false; + break; + } + } + if (allModifiersPressed) { + handler = options.keyBinds[index]; + break; + } + } + } + } + + if (handler) { + handler.call(picker, widget); + e.stopPropagation(); + e.preventDefault(); + } + }, + + keyup = function (e) { + keyState[e.which] = 'r'; + e.stopPropagation(); + e.preventDefault(); + }, + + change = function (e) { + var val = $(e.target).val().trim(), + parsedDate = val ? parseInputDate(val) : null; + setValue(parsedDate); + e.stopImmediatePropagation(); + return false; + }, + + attachDatePickerElementEvents = function () { + input.on({ + 'change': change, + 'blur': options.debug ? '' : hide, + 'keydown': keydown, + 'keyup': keyup, + 'focus': options.allowInputToggle ? show : '' + }); + + if (element.is('input')) { + input.on({ + 'focus': show + }); + } else if (component) { + component.on('click', toggle); + component.on('mousedown', false); + } + }, + + detachDatePickerElementEvents = function () { + input.off({ + 'change': change, + 'blur': blur, + 'keydown': keydown, + 'keyup': keyup, + 'focus': options.allowInputToggle ? hide : '' + }); + + if (element.is('input')) { + input.off({ + 'focus': show + }); + } else if (component) { + component.off('click', toggle); + component.off('mousedown', false); + } + }, + + indexGivenDates = function (givenDatesArray) { + // Store given enabledDates and disabledDates as keys. + // This way we can check their existence in O(1) time instead of looping through whole array. + // (for example: options.enabledDates['2014-02-27'] === true) + var givenDatesIndexed = {}; + $.each(givenDatesArray, function () { + var dDate = parseInputDate(this); + if (dDate.isValid()) { + givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true; + } + }); + return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false; + }, + + indexGivenHours = function (givenHoursArray) { + // Store given enabledHours and disabledHours as keys. + // This way we can check their existence in O(1) time instead of looping through whole array. + // (for example: options.enabledHours['2014-02-27'] === true) + var givenHoursIndexed = {}; + $.each(givenHoursArray, function () { + givenHoursIndexed[this] = true; + }); + return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false; + }, + + initFormatting = function () { + var format = options.format || 'L LT'; + + actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) { + var newinput = date.localeData().longDateFormat(formatInput) || formatInput; + return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740 + return date.localeData().longDateFormat(formatInput2) || formatInput2; + }); + }); + + + parseFormats = options.extraFormats ? options.extraFormats.slice() : []; + if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) { + parseFormats.push(actualFormat); + } + + use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1); + + if (isEnabled('y')) { + minViewModeNumber = 2; + } + if (isEnabled('M')) { + minViewModeNumber = 1; + } + if (isEnabled('d')) { + minViewModeNumber = 0; + } + + currentViewMode = Math.max(minViewModeNumber, currentViewMode); + + if (!unset) { + setValue(date); + } + }; + + /******************************************************************************** + * + * Public API functions + * ===================== + * + * Important: Do not expose direct references to private objects or the options + * object to the outer world. Always return a clone when returning values or make + * a clone when setting a private variable. + * + ********************************************************************************/ + picker.destroy = function () { + ///Destroys the widget and removes all attached event listeners + hide(); + detachDatePickerElementEvents(); + element.removeData('DateTimePicker'); + element.removeData('date'); + }; + + picker.toggle = toggle; + + picker.show = show; + + picker.hide = hide; + + picker.disable = function () { + ///Disables the input element, the component is attached to, by adding a disabled="true" attribute to it. + ///If the widget was visible before that call it is hidden. Possibly emits dp.hide + hide(); + if (component && component.hasClass('btn')) { + component.addClass('disabled'); + } + input.prop('disabled', true); + return picker; + }; + + picker.enable = function () { + ///Enables the input element, the component is attached to, by removing disabled attribute from it. + if (component && component.hasClass('btn')) { + component.removeClass('disabled'); + } + input.prop('disabled', false); + return picker; + }; + + picker.ignoreReadonly = function (ignoreReadonly) { + if (arguments.length === 0) { + return options.ignoreReadonly; + } + if (typeof ignoreReadonly !== 'boolean') { + throw new TypeError('ignoreReadonly () expects a boolean parameter'); + } + options.ignoreReadonly = ignoreReadonly; + return picker; + }; + + picker.options = function (newOptions) { + if (arguments.length === 0) { + return $.extend(true, {}, options); + } + + if (!(newOptions instanceof Object)) { + throw new TypeError('options() options parameter should be an object'); + } + $.extend(true, options, newOptions); + $.each(options, function (key, value) { + if (picker[key] !== undefined) { + picker[key](value); + } else { + throw new TypeError('option ' + key + ' is not recognized!'); + } + }); + return picker; + }; + + picker.date = function (newDate) { + /// + ///Returns the component's model current date, a moment object or null if not set. + ///date.clone() + /// + /// + ///Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration. + ///Takes string, Date, moment, null parameter. + /// + if (arguments.length === 0) { + if (unset) { + return null; + } + return date.clone(); + } + + if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) { + throw new TypeError('date() parameter must be one of [null, string, moment or Date]'); + } + + setValue(newDate === null ? null : parseInputDate(newDate)); + return picker; + }; + + picker.format = function (newFormat) { + ///test su + ///info about para + ///returns foo + if (arguments.length === 0) { + return options.format; + } + + if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) { + throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat); + } + + options.format = newFormat; + if (actualFormat) { + initFormatting(); // reinit formatting + } + return picker; + }; + + picker.timeZone = function (newZone) { + if (arguments.length === 0) { + return options.timeZone; + } + + if (typeof newZone !== 'string') { + throw new TypeError('newZone() expects a string parameter'); + } + + options.timeZone = newZone; + + return picker; + }; + + picker.dayViewHeaderFormat = function (newFormat) { + if (arguments.length === 0) { + return options.dayViewHeaderFormat; + } + + if (typeof newFormat !== 'string') { + throw new TypeError('dayViewHeaderFormat() expects a string parameter'); + } + + options.dayViewHeaderFormat = newFormat; + return picker; + }; + + picker.extraFormats = function (formats) { + if (arguments.length === 0) { + return options.extraFormats; + } + + if (formats !== false && !(formats instanceof Array)) { + throw new TypeError('extraFormats() expects an array or false parameter'); + } + + options.extraFormats = formats; + if (parseFormats) { + initFormatting(); // reinit formatting + } + return picker; + }; + + picker.disabledDates = function (dates) { + /// + ///Returns an array with the currently set disabled dates on the component. + ///options.disabledDates + /// + /// + ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of + ///options.enabledDates if such exist. + ///Takes an [ string or Date or moment ] of values and allows the user to select only from those days. + /// + if (arguments.length === 0) { + return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates); + } + + if (!dates) { + options.disabledDates = false; + update(); + return picker; + } + if (!(dates instanceof Array)) { + throw new TypeError('disabledDates() expects an array parameter'); + } + options.disabledDates = indexGivenDates(dates); + options.enabledDates = false; + update(); + return picker; + }; + + picker.enabledDates = function (dates) { + /// + ///Returns an array with the currently set enabled dates on the component. + ///options.enabledDates + /// + /// + ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist. + ///Takes an [ string or Date or moment ] of values and allows the user to select only from those days. + /// + if (arguments.length === 0) { + return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates); + } + + if (!dates) { + options.enabledDates = false; + update(); + return picker; + } + if (!(dates instanceof Array)) { + throw new TypeError('enabledDates() expects an array parameter'); + } + options.enabledDates = indexGivenDates(dates); + options.disabledDates = false; + update(); + return picker; + }; + + picker.daysOfWeekDisabled = function (daysOfWeekDisabled) { + if (arguments.length === 0) { + return options.daysOfWeekDisabled.splice(0); + } + + if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) { + options.daysOfWeekDisabled = false; + update(); + return picker; + } + + if (!(daysOfWeekDisabled instanceof Array)) { + throw new TypeError('daysOfWeekDisabled() expects an array parameter'); + } + options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) { + currentValue = parseInt(currentValue, 10); + if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) { + return previousValue; + } + if (previousValue.indexOf(currentValue) === -1) { + previousValue.push(currentValue); + } + return previousValue; + }, []).sort(); + if (options.useCurrent && !options.keepInvalid) { + var tries = 0; + while (!isValid(date, 'd')) { + date.add(1, 'd'); + if (tries === 31) { + throw 'Tried 31 times to find a valid date'; + } + tries++; + } + setValue(date); + } + update(); + return picker; + }; + + picker.maxDate = function (maxDate) { + if (arguments.length === 0) { + return options.maxDate ? options.maxDate.clone() : options.maxDate; + } + + if ((typeof maxDate === 'boolean') && maxDate === false) { + options.maxDate = false; + update(); + return picker; + } + + if (typeof maxDate === 'string') { + if (maxDate === 'now' || maxDate === 'moment') { + maxDate = getMoment(); + } + } + + var parsedDate = parseInputDate(maxDate); + + if (!parsedDate.isValid()) { + throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate); + } + if (options.minDate && parsedDate.isBefore(options.minDate)) { + throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat)); + } + options.maxDate = parsedDate; + if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) { + setValue(options.maxDate); + } + if (viewDate.isAfter(parsedDate)) { + viewDate = parsedDate.clone().subtract(options.stepping, 'm'); + } + update(); + return picker; + }; + + picker.minDate = function (minDate) { + if (arguments.length === 0) { + return options.minDate ? options.minDate.clone() : options.minDate; + } + + if ((typeof minDate === 'boolean') && minDate === false) { + options.minDate = false; + update(); + return picker; + } + + if (typeof minDate === 'string') { + if (minDate === 'now' || minDate === 'moment') { + minDate = getMoment(); + } + } + + var parsedDate = parseInputDate(minDate); + + if (!parsedDate.isValid()) { + throw new TypeError('minDate() Could not parse date parameter: ' + minDate); + } + if (options.maxDate && parsedDate.isAfter(options.maxDate)) { + throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat)); + } + options.minDate = parsedDate; + if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) { + setValue(options.minDate); + } + if (viewDate.isBefore(parsedDate)) { + viewDate = parsedDate.clone().add(options.stepping, 'm'); + } + update(); + return picker; + }; + + picker.defaultDate = function (defaultDate) { + /// + ///Returns a moment with the options.defaultDate option configuration or false if not set + ///date.clone() + /// + /// + ///Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared. + ///Takes a string, Date, moment, boolean:false + /// + if (arguments.length === 0) { + return options.defaultDate ? options.defaultDate.clone() : options.defaultDate; + } + if (!defaultDate) { + options.defaultDate = false; + return picker; + } + + if (typeof defaultDate === 'string') { + if (defaultDate === 'now' || defaultDate === 'moment') { + defaultDate = getMoment(); + } else { + defaultDate = getMoment(defaultDate); + } + } + + var parsedDate = parseInputDate(defaultDate); + if (!parsedDate.isValid()) { + throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate); + } + if (!isValid(parsedDate)) { + throw new TypeError('defaultDate() date passed is invalid according to component setup validations'); + } + + options.defaultDate = parsedDate; + + if ((options.defaultDate && options.inline) || input.val().trim() === '') { + setValue(options.defaultDate); + } + return picker; + }; + + picker.locale = function (locale) { + if (arguments.length === 0) { + return options.locale; + } + + if (!moment.localeData(locale)) { + throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!'); + } + + options.locale = locale; + date.locale(options.locale); + viewDate.locale(options.locale); + + if (actualFormat) { + initFormatting(); // reinit formatting + } + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.stepping = function (stepping) { + if (arguments.length === 0) { + return options.stepping; + } + + stepping = parseInt(stepping, 10); + if (isNaN(stepping) || stepping < 1) { + stepping = 1; + } + options.stepping = stepping; + return picker; + }; + + picker.useCurrent = function (useCurrent) { + var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute']; + if (arguments.length === 0) { + return options.useCurrent; + } + + if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) { + throw new TypeError('useCurrent() expects a boolean or string parameter'); + } + if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) { + throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', ')); + } + options.useCurrent = useCurrent; + return picker; + }; + + picker.collapse = function (collapse) { + if (arguments.length === 0) { + return options.collapse; + } + + if (typeof collapse !== 'boolean') { + throw new TypeError('collapse() expects a boolean parameter'); + } + if (options.collapse === collapse) { + return picker; + } + options.collapse = collapse; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.icons = function (icons) { + if (arguments.length === 0) { + return $.extend({}, options.icons); + } + + if (!(icons instanceof Object)) { + throw new TypeError('icons() expects parameter to be an Object'); + } + $.extend(options.icons, icons); + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.tooltips = function (tooltips) { + if (arguments.length === 0) { + return $.extend({}, options.tooltips); + } + + if (!(tooltips instanceof Object)) { + throw new TypeError('tooltips() expects parameter to be an Object'); + } + $.extend(options.tooltips, tooltips); + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.useStrict = function (useStrict) { + if (arguments.length === 0) { + return options.useStrict; + } + + if (typeof useStrict !== 'boolean') { + throw new TypeError('useStrict() expects a boolean parameter'); + } + options.useStrict = useStrict; + return picker; + }; + + picker.sideBySide = function (sideBySide) { + if (arguments.length === 0) { + return options.sideBySide; + } + + if (typeof sideBySide !== 'boolean') { + throw new TypeError('sideBySide() expects a boolean parameter'); + } + options.sideBySide = sideBySide; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.viewMode = function (viewMode) { + if (arguments.length === 0) { + return options.viewMode; + } + + if (typeof viewMode !== 'string') { + throw new TypeError('viewMode() expects a string parameter'); + } + + if (viewModes.indexOf(viewMode) === -1) { + throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value'); + } + + options.viewMode = viewMode; + currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber); + + showMode(); + return picker; + }; + + picker.toolbarPlacement = function (toolbarPlacement) { + if (arguments.length === 0) { + return options.toolbarPlacement; + } + + if (typeof toolbarPlacement !== 'string') { + throw new TypeError('toolbarPlacement() expects a string parameter'); + } + if (toolbarPlacements.indexOf(toolbarPlacement) === -1) { + throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value'); + } + options.toolbarPlacement = toolbarPlacement; + + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.widgetPositioning = function (widgetPositioning) { + if (arguments.length === 0) { + return $.extend({}, options.widgetPositioning); + } + + if (({}).toString.call(widgetPositioning) !== '[object Object]') { + throw new TypeError('widgetPositioning() expects an object variable'); + } + if (widgetPositioning.horizontal) { + if (typeof widgetPositioning.horizontal !== 'string') { + throw new TypeError('widgetPositioning() horizontal variable must be a string'); + } + widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase(); + if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) { + throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')'); + } + options.widgetPositioning.horizontal = widgetPositioning.horizontal; + } + if (widgetPositioning.vertical) { + if (typeof widgetPositioning.vertical !== 'string') { + throw new TypeError('widgetPositioning() vertical variable must be a string'); + } + widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase(); + if (verticalModes.indexOf(widgetPositioning.vertical) === -1) { + throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')'); + } + options.widgetPositioning.vertical = widgetPositioning.vertical; + } + update(); + return picker; + }; + + picker.calendarWeeks = function (calendarWeeks) { + if (arguments.length === 0) { + return options.calendarWeeks; + } + + if (typeof calendarWeeks !== 'boolean') { + throw new TypeError('calendarWeeks() expects parameter to be a boolean value'); + } + + options.calendarWeeks = calendarWeeks; + update(); + return picker; + }; + + picker.showTodayButton = function (showTodayButton) { + if (arguments.length === 0) { + return options.showTodayButton; + } + + if (typeof showTodayButton !== 'boolean') { + throw new TypeError('showTodayButton() expects a boolean parameter'); + } + + options.showTodayButton = showTodayButton; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.showClear = function (showClear) { + if (arguments.length === 0) { + return options.showClear; + } + + if (typeof showClear !== 'boolean') { + throw new TypeError('showClear() expects a boolean parameter'); + } + + options.showClear = showClear; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.widgetParent = function (widgetParent) { + if (arguments.length === 0) { + return options.widgetParent; + } + + if (typeof widgetParent === 'string') { + widgetParent = $(widgetParent); + } + + if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) { + throw new TypeError('widgetParent() expects a string or a jQuery object parameter'); + } + + options.widgetParent = widgetParent; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.keepOpen = function (keepOpen) { + if (arguments.length === 0) { + return options.keepOpen; + } + + if (typeof keepOpen !== 'boolean') { + throw new TypeError('keepOpen() expects a boolean parameter'); + } + + options.keepOpen = keepOpen; + return picker; + }; + + picker.focusOnShow = function (focusOnShow) { + if (arguments.length === 0) { + return options.focusOnShow; + } + + if (typeof focusOnShow !== 'boolean') { + throw new TypeError('focusOnShow() expects a boolean parameter'); + } + + options.focusOnShow = focusOnShow; + return picker; + }; + + picker.inline = function (inline) { + if (arguments.length === 0) { + return options.inline; + } + + if (typeof inline !== 'boolean') { + throw new TypeError('inline() expects a boolean parameter'); + } + + options.inline = inline; + return picker; + }; + + picker.clear = function () { + clear(); + return picker; + }; + + picker.keyBinds = function (keyBinds) { + if (arguments.length === 0) { + return options.keyBinds; + } + + options.keyBinds = keyBinds; + return picker; + }; + + picker.getMoment = function (d) { + return getMoment(d); + }; + + picker.debug = function (debug) { + if (typeof debug !== 'boolean') { + throw new TypeError('debug() expects a boolean parameter'); + } + + options.debug = debug; + return picker; + }; + + picker.allowInputToggle = function (allowInputToggle) { + if (arguments.length === 0) { + return options.allowInputToggle; + } + + if (typeof allowInputToggle !== 'boolean') { + throw new TypeError('allowInputToggle() expects a boolean parameter'); + } + + options.allowInputToggle = allowInputToggle; + return picker; + }; + + picker.showClose = function (showClose) { + if (arguments.length === 0) { + return options.showClose; + } + + if (typeof showClose !== 'boolean') { + throw new TypeError('showClose() expects a boolean parameter'); + } + + options.showClose = showClose; + return picker; + }; + + picker.keepInvalid = function (keepInvalid) { + if (arguments.length === 0) { + return options.keepInvalid; + } + + if (typeof keepInvalid !== 'boolean') { + throw new TypeError('keepInvalid() expects a boolean parameter'); + } + options.keepInvalid = keepInvalid; + return picker; + }; + + picker.datepickerInput = function (datepickerInput) { + if (arguments.length === 0) { + return options.datepickerInput; + } + + if (typeof datepickerInput !== 'string') { + throw new TypeError('datepickerInput() expects a string parameter'); + } + + options.datepickerInput = datepickerInput; + return picker; + }; + + picker.parseInputDate = function (parseInputDate) { + if (arguments.length === 0) { + return options.parseInputDate; + } + + if (typeof parseInputDate !== 'function') { + throw new TypeError('parseInputDate() sholud be as function'); + } + + options.parseInputDate = parseInputDate; + + return picker; + }; + + picker.disabledTimeIntervals = function (disabledTimeIntervals) { + /// + ///Returns an array with the currently set disabled dates on the component. + ///options.disabledTimeIntervals + /// + /// + ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of + ///options.enabledDates if such exist. + ///Takes an [ string or Date or moment ] of values and allows the user to select only from those days. + /// + if (arguments.length === 0) { + return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals); + } + + if (!disabledTimeIntervals) { + options.disabledTimeIntervals = false; + update(); + return picker; + } + if (!(disabledTimeIntervals instanceof Array)) { + throw new TypeError('disabledTimeIntervals() expects an array parameter'); + } + options.disabledTimeIntervals = disabledTimeIntervals; + update(); + return picker; + }; + + picker.disabledHours = function (hours) { + /// + ///Returns an array with the currently set disabled hours on the component. + ///options.disabledHours + /// + /// + ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of + ///options.enabledHours if such exist. + ///Takes an [ int ] of values and disallows the user to select only from those hours. + /// + if (arguments.length === 0) { + return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours); + } + + if (!hours) { + options.disabledHours = false; + update(); + return picker; + } + if (!(hours instanceof Array)) { + throw new TypeError('disabledHours() expects an array parameter'); + } + options.disabledHours = indexGivenHours(hours); + options.enabledHours = false; + if (options.useCurrent && !options.keepInvalid) { + var tries = 0; + while (!isValid(date, 'h')) { + date.add(1, 'h'); + if (tries === 24) { + throw 'Tried 24 times to find a valid date'; + } + tries++; + } + setValue(date); + } + update(); + return picker; + }; + + picker.enabledHours = function (hours) { + /// + ///Returns an array with the currently set enabled hours on the component. + ///options.enabledHours + /// + /// + ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist. + ///Takes an [ int ] of values and allows the user to select only from those hours. + /// + if (arguments.length === 0) { + return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours); + } + + if (!hours) { + options.enabledHours = false; + update(); + return picker; + } + if (!(hours instanceof Array)) { + throw new TypeError('enabledHours() expects an array parameter'); + } + options.enabledHours = indexGivenHours(hours); + options.disabledHours = false; + if (options.useCurrent && !options.keepInvalid) { + var tries = 0; + while (!isValid(date, 'h')) { + date.add(1, 'h'); + if (tries === 24) { + throw 'Tried 24 times to find a valid date'; + } + tries++; + } + setValue(date); + } + update(); + return picker; + }; + /** + * Returns the component's model current viewDate, a moment object or null if not set. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration. + * @param {Takes string, viewDate, moment, null parameter.} newDate + * @returns {viewDate.clone()} + */ + picker.viewDate = function (newDate) { + if (arguments.length === 0) { + return viewDate.clone(); + } + + if (!newDate) { + viewDate = date.clone(); + return picker; + } + + if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) { + throw new TypeError('viewDate() parameter must be one of [string, moment or Date]'); + } + + viewDate = parseInputDate(newDate); + viewUpdate(); + return picker; + }; + + // initializing element and component attributes + if (element.is('input')) { + input = element; + } else { + input = element.find(options.datepickerInput); + if (input.length === 0) { + input = element.find('input'); + } else if (!input.is('input')) { + throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element'); + } + } + + if (element.hasClass('input-group')) { + // in case there is more then one 'input-group-addon' Issue #48 + if (element.find('.datepickerbutton').length === 0) { + component = element.find('.input-group-addon'); + } else { + component = element.find('.datepickerbutton'); + } + } + + if (!options.inline && !input.is('input')) { + throw new Error('Could not initialize DateTimePicker without an input element'); + } + + // Set defaults for date here now instead of in var declaration + date = getMoment(); + viewDate = date.clone(); + + $.extend(true, options, dataToOptions()); + + picker.options(options); + + initFormatting(); + + attachDatePickerElementEvents(); + + if (input.prop('disabled')) { + picker.disable(); + } + if (input.is('input') && input.val().trim().length !== 0) { + setValue(parseInputDate(input.val().trim())); + } + else if (options.defaultDate && input.attr('placeholder') === undefined) { + setValue(options.defaultDate); + } + if (options.inline) { + show(); + } + return picker; + }; + + /******************************************************************************** + * + * jQuery plugin constructor and defaults object + * + ********************************************************************************/ + + /** + * See (http://jquery.com/). + * @name jQuery + * @class + * See the jQuery Library (http://jquery.com/) for full details. This just + * documents the function and classes that are added to jQuery by this plug-in. + */ + /** + * See (http://jquery.com/) + * @name fn + * @class + * See the jQuery Library (http://jquery.com/) for full details. This just + * documents the function and classes that are added to jQuery by this plug-in. + * @memberOf jQuery + */ + /** + * Show comments + * @class datetimepicker + * @memberOf jQuery.fn + */ + $.fn.datetimepicker = function (options) { + options = options || {}; + + var args = Array.prototype.slice.call(arguments, 1), + isInstance = true, + thisMethods = ['destroy', 'hide', 'show', 'toggle'], + returnValue; + + if (typeof options === 'object') { + return this.each(function () { + var $this = $(this), + _options; + if (!$this.data('DateTimePicker')) { + // create a private copy of the defaults object + _options = $.extend(true, {}, $.fn.datetimepicker.defaults, options); + $this.data('DateTimePicker', dateTimePicker($this, _options)); + } + }); + } else if (typeof options === 'string') { + this.each(function () { + var $this = $(this), + instance = $this.data('DateTimePicker'); + if (!instance) { + throw new Error('bootstrap-datetimepicker("' + options + '") method was called on an element that is not using DateTimePicker'); + } + + returnValue = instance[options].apply(instance, args); + isInstance = returnValue === instance; + }); + + if (isInstance || $.inArray(options, thisMethods) > -1) { + return this; + } + + return returnValue; + } + + throw new TypeError('Invalid arguments for DateTimePicker: ' + options); + }; + + $.fn.datetimepicker.defaults = { + timeZone: '', + format: false, + dayViewHeaderFormat: 'MMMM YYYY', + extraFormats: false, + stepping: 1, + minDate: false, + maxDate: false, + useCurrent: true, + collapse: true, + locale: moment.locale(), + defaultDate: false, + disabledDates: false, + enabledDates: false, + icons: { + time: 'glyphicon glyphicon-time', + date: 'glyphicon glyphicon-calendar', + up: 'glyphicon glyphicon-chevron-up', + down: 'glyphicon glyphicon-chevron-down', + previous: 'glyphicon glyphicon-chevron-left', + next: 'glyphicon glyphicon-chevron-right', + today: 'glyphicon glyphicon-screenshot', + clear: 'glyphicon glyphicon-trash', + close: 'glyphicon glyphicon-remove' + }, + tooltips: { + today: 'Go to today', + clear: 'Clear selection', + close: 'Close the picker', + selectMonth: 'Select Month', + prevMonth: 'Previous Month', + nextMonth: 'Next Month', + selectYear: 'Select Year', + prevYear: 'Previous Year', + nextYear: 'Next Year', + selectDecade: 'Select Decade', + prevDecade: 'Previous Decade', + nextDecade: 'Next Decade', + prevCentury: 'Previous Century', + nextCentury: 'Next Century', + pickHour: 'Pick Hour', + incrementHour: 'Increment Hour', + decrementHour: 'Decrement Hour', + pickMinute: 'Pick Minute', + incrementMinute: 'Increment Minute', + decrementMinute: 'Decrement Minute', + pickSecond: 'Pick Second', + incrementSecond: 'Increment Second', + decrementSecond: 'Decrement Second', + togglePeriod: 'Toggle Period', + selectTime: 'Select Time' + }, + useStrict: false, + sideBySide: false, + daysOfWeekDisabled: false, + calendarWeeks: false, + viewMode: 'days', + toolbarPlacement: 'default', + showTodayButton: false, + showClear: false, + showClose: false, + widgetPositioning: { + horizontal: 'auto', + vertical: 'auto' + }, + widgetParent: null, + ignoreReadonly: false, + keepOpen: false, + focusOnShow: true, + inline: false, + keepInvalid: false, + datepickerInput: '.datepickerinput', + keyBinds: { + up: function (widget) { + if (!widget) { + return; + } + var d = this.date() || this.getMoment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().subtract(7, 'd')); + } else { + this.date(d.clone().add(this.stepping(), 'm')); + } + }, + down: function (widget) { + if (!widget) { + this.show(); + return; + } + var d = this.date() || this.getMoment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().add(7, 'd')); + } else { + this.date(d.clone().subtract(this.stepping(), 'm')); + } + }, + 'control up': function (widget) { + if (!widget) { + return; + } + var d = this.date() || this.getMoment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().subtract(1, 'y')); + } else { + this.date(d.clone().add(1, 'h')); + } + }, + 'control down': function (widget) { + if (!widget) { + return; + } + var d = this.date() || this.getMoment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().add(1, 'y')); + } else { + this.date(d.clone().subtract(1, 'h')); + } + }, + left: function (widget) { + if (!widget) { + return; + } + var d = this.date() || this.getMoment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().subtract(1, 'd')); + } + }, + right: function (widget) { + if (!widget) { + return; + } + var d = this.date() || this.getMoment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().add(1, 'd')); + } + }, + pageUp: function (widget) { + if (!widget) { + return; + } + var d = this.date() || this.getMoment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().subtract(1, 'M')); + } + }, + pageDown: function (widget) { + if (!widget) { + return; + } + var d = this.date() || this.getMoment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().add(1, 'M')); + } + }, + enter: function () { + this.hide(); + }, + escape: function () { + this.hide(); + }, + //tab: function (widget) { //this break the flow of the form. disabling for now + // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]'); + // if(toggle.length > 0) toggle.click(); + //}, + 'control space': function (widget) { + if (!widget) { + return; + } + if (widget.find('.timepicker').is(':visible')) { + widget.find('.btn[data-action="togglePeriod"]').click(); + } + }, + t: function () { + this.date(this.getMoment()); + }, + 'delete': function () { + this.clear(); + } + }, + debug: false, + allowInputToggle: false, + disabledTimeIntervals: false, + disabledHours: false, + enabledHours: false, + viewDate: false + }; + + return $.fn.datetimepicker; +})); diff --git a/app/assets/stylesheets/admins/competition_settings.scss b/app/assets/stylesheets/admins/competition_settings.scss new file mode 100644 index 000000000..ad1dd14b3 --- /dev/null +++ b/app/assets/stylesheets/admins/competition_settings.scss @@ -0,0 +1,42 @@ +.admins-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: 5px; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index bb40e7950..9312a694f 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -34,16 +34,20 @@ input.form-control { .font-14 { font-size: 14px !important; } .font-16 { font-size: 16px !important; } .font-18 { font-size: 18px !important; } +.font-20 { font-size: 20px !important; } +.font-24 { font-size: 24px !important; } .padding10-5 { padding: 10px 5px;} .width100 { width: 100%;} .mb10 { margin-bottom: 10px ;} .mt10 { margin-top: 10px ;} .mr10{ margin-right: 10px; } +.ml10{ margin-left: 10px; }.ml20{ margin-left: 20px; } .textarea-width-100{width:100%; resize: none; border: 1px solid #ccc;} .padding10{padding: 10px;} .padding5-10{padding: 5px 10px;} .position-r{position:relative;} .color-grey-c{color:#ccc} +.color-blue{color:#4CACFF} .inline-block{display:inline-block;} .hide{display: none;} .show{display: block;} diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index fed6ec280..f515d386d 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -73,15 +73,21 @@ class AccountsController < ApplicationController def login @user = User.try_to_login(params[:login], params[:password]) - if @user - # user is already in local database - return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked? - return normal_status(-2, "错误的账号或密码") unless @user.check_password?(params[:password].to_s) - else + return normal_status(-2, "错误的账号或密码") if @user.blank? + # user is already in local database + return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked? + + login_control = LimitForbidControl::UserLogin.new(@user) + return normal_status(-2, "登录密码出错已达上限,将锁定密码1小时") if login_control.forbid? + + password_ok = @user.check_password?(params[:password].to_s) + unless password_ok + login_control.increment! return normal_status(-2, "错误的账号或密码") end successful_authentication(@user) + login_control.clear # 重置每日密码错误次数 session[:user_id] = @user.id end diff --git a/app/controllers/admins/competition_settings_controller.rb b/app/controllers/admins/competition_settings_controller.rb index 390ad17e8..9fee83c3e 100644 --- a/app/controllers/admins/competition_settings_controller.rb +++ b/app/controllers/admins/competition_settings_controller.rb @@ -1,10 +1,15 @@ class Admins::CompetitionSettingsController < Admins::BaseController - def show + def index @competition = current_competition end - def update - Admins::SaveLaboratorySettingService.call(current_competition, form_params) + 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 @@ -14,7 +19,11 @@ class Admins::CompetitionSettingsController < Admins::BaseController @_current_competition ||= Competition.find(params[:competition_id]) end - def form_params - params.permit(:identifier, :name, :nav_logo, :login_logo, :tab_logo, :footer, navbar: %i[name link hidden]) + 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) + end + + def nav_form_params + params.permit(:enroll_end_time, competition_staffs: %i[category minimum maximum mutiple_limited], nav_module: %i[module_type name hidden position url]) end end \ No newline at end of file diff --git a/app/controllers/admins/competition_stages_controller.rb b/app/controllers/admins/competition_stages_controller.rb new file mode 100644 index 000000000..537240bde --- /dev/null +++ b/app/controllers/admins/competition_stages_controller.rb @@ -0,0 +1,83 @@ +class Admins::CompetitionStagesController < Admins::BaseController + + def create + if @competition.competition_stages.exists?(name: params[:stage_name]) + render_error "已存在同名的阶段" + else + @competition.competition_stages << CompetitionStage.new(name: params[:stage_name]) + render_ok + end + end + + def update + current_stage.update_attributes!(name: params[:stage_name], score_rate: params[:score_rate]) + render_ok + end + + def destroy + current_stage.destroy! + render_ok + end + + def create_stage_section + ActiveRecord::Base.transaction do + new_section = CompetitionStageSection.create!(competition_id: current_stage.competition_id, competition_stage_id: current_stage.id, + start_time: params[:new_start_time], end_time: params[:new_end_time], + entry: params[:entry], mission_count: params[:mission_count], score_source: params[:score_source]) + unless params[:shixun_identifiers].blank? + params[:shixun_identifiers].each do |identifier| + new_section.competition_entries << CompetitionEntry.new(competition_stage_id: current_stage.id, shixun_identifier: identifier) + end + end + render_ok + end + end + + def update_stage_section + ActiveRecord::Base.transaction do + section = current_stage.competition_stage_sections.find_by!(id: params[:section_id]) + if section.present? + section_entries = section.competition_entries + if !params[:shixun_identifiers] + section_entries.destroy_all + else + if params[:shixun_identifiers].length < section_entries.size + section_entries[params[:shixun_identifiers].length, section_entries.size - 1].each(&:destroy) + end + + params[:shixun_identifiers].each_with_index do |identifier, index| + entry = section_entries[index] + if entry.present? + entry.update_attributes!(shixun_identifier: identifier) + else + section.competition_entries << CompetitionEntry.new(competition_stage_id: current_stage.id, shixun_identifier: identifier) + end + end + end + section.update_attributes!(start_time: params[:new_start_time], end_time: params[:new_end_time], + entry: params[:entry], mission_count: params[:mission_count], score_source: params[:score_source]) + render_ok + end + end + end + + def destroy_stage_section + section = current_stage.competition_stage_sections.find_by!(id: params[:section_id]) + section.destroy! + render_ok + end + + def calculate_stage_score + + end + + private + + def current_competition + @_current_competition ||= Competition.find(params[:competition_id]) + end + + def current_stage + @_current_stage ||= CompetitionStage.find_by!(competition_id: params[:competition_id], id: params[:stage_id]) + end +end \ No newline at end of file diff --git a/app/controllers/admins/enroll_lists_controller.rb b/app/controllers/admins/enroll_lists_controller.rb index ccac6a72d..fb7cec9b0 100644 --- a/app/controllers/admins/enroll_lists_controller.rb +++ b/app/controllers/admins/enroll_lists_controller.rb @@ -2,8 +2,7 @@ class Admins::EnrollListsController < Admins::BaseController def index @competition = current_competition - params[:sort_by] = params[:sort_by].presence || 'created_at' - params[:sort_direction] = params[:sort_direction].presence || 'desc' + default_sort('created_at', 'desc') enroll_lists = Admins::CompetitionEnrollListQuery.call(@competition, params) @params_page = params[:page] || 1 @@ -13,10 +12,23 @@ class Admins::EnrollListsController < Admins::BaseController respond_to do |format| format.js format.html - format.xls + format.xls{ + filename = "#{@competition.name}竞赛报名列表_#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}.xls" + send_data(shixun_list_xls(shixuns), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename)) + } 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 ||= Competition.find(params[:competition_id]) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index df3e9c96e..db72590ee 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -86,8 +86,18 @@ class ApplicationController < ActionController::Base when 8, 3, 5 # 邮箱类型的发送 sigle_para = {email: value} + # 60s内不能重复发送 + send_email_limit_cache_key = "send_email_60_second_limit:#{value}" + tip_exception(-1, '请勿频繁操作') if Rails.cache.exist?(send_email_limit_cache_key) + + # 短时间内不能大量发送 + send_email_control = LimitForbidControl::SendEmailCode.new(value) + tip_exception(-1, '邮件发送太频繁,请稍后再试') if send_email_control.forbid? begin UserMailer.register_email(value, code).deliver_now + + Rails.cache.write(send_email_limit_cache_key, 1, expires_in: 1.minute) + send_email_control.increment! # Mailer.run.email_register(code, value) rescue Exception => e logger_error(e) @@ -112,6 +122,8 @@ class ApplicationController < ActionController::Base "验证码发送次数超过频率" when 43 "一天内同一手机号发送次数超过限制" + when 53 + "手机号接收超过频率限制" end end diff --git a/app/controllers/competitions/competition_teams_controller.rb b/app/controllers/competitions/competition_teams_controller.rb index 6a4dbfd34..db4608807 100644 --- a/app/controllers/competitions/competition_teams_controller.rb +++ b/app/controllers/competitions/competition_teams_controller.rb @@ -60,7 +60,12 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController def index @personal = current_competition.personal? - admin_or_business? ? all_competition_teams : user_competition_teams + if admin_or_business? + all_competition_teams + user_competition_teams + else + user_competition_teams + end end def create @@ -113,8 +118,8 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController teams = teams.joins(users: { user_extension: :school }).where('schools.name LIKE ?', "%#{keyword}%") end - @count = teams.count - @teams = paginate(teams.includes(:user, users: { user_extension: :school })) + @all_count = teams.count + @all_teams = paginate(teams.includes(:user, users: { user_extension: :school })) end def user_competition_teams diff --git a/app/controllers/competitions/competitions_controller.rb b/app/controllers/competitions/competitions_controller.rb index a17564737..2cae06774 100644 --- a/app/controllers/competitions/competitions_controller.rb +++ b/app/controllers/competitions/competitions_controller.rb @@ -34,6 +34,7 @@ class Competitions::CompetitionsController < Competitions::BaseController def update @competition.update_attributes!(introduction: params[:introduction]) + Attachment.associate_container(params[:attachment_ids], @competition.id, @competition.class) if params[:attachment_ids] normal_status("更新成功") end @@ -106,13 +107,8 @@ class Competitions::CompetitionsController < Competitions::BaseController @stage = @competition.competition_stages.find_by(id: params[:stage_id]) end - if @competition.identifier == "gcc-annotation-2018" - @records = @competition.competition_teams.joins(:competition_scores) - .select("competition_teams.*, score, cost_time").order("score desc, cost_time desc") - else - @records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i}) - .select("competition_teams.*, score, cost_time").order("score desc, cost_time desc") - end + @records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i}) + .select("competition_teams.*, score, cost_time").order("score desc, cost_time desc") current_team_ids = @competition.team_members.where(user_id: current_user.id).pluck(:competition_team_id).uniq @user_ranks = @records.select{|com_team| current_team_ids.include?(com_team.id)} diff --git a/app/controllers/discusses_controller.rb b/app/controllers/discusses_controller.rb index 6ddf71ba4..cbb19cb7f 100644 --- a/app/controllers/discusses_controller.rb +++ b/app/controllers/discusses_controller.rb @@ -7,22 +7,20 @@ class DiscussesController < ApplicationController def index page = params[:page].to_i offset = page * LIMIT + @manger = @container.has_manager?(current_user) || current_user.is_certification_teacher + # 总数,分页使用 - if current_user.admin? + if @manger @disscuss_count = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil).count disscusses = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil) + @discusses = disscusses.limit(LIMIT).joins("left join games on discusses.challenge_id = games.challenge_id and discusses.user_id = games.user_id") + .select("discusses.*, games.identifier").includes(:user, :praise_treads).offset(offset) else disscusses = Discuss.where("dis_id = :dis_id and dis_type = :dis_type and root_id is null and (discusses.hidden = :hidden or discusses.user_id = :user_id)", {dis_id: @container.id, dis_type: @container.class.to_s, hidden: false, user_id: current_user.id}) @disscuss_count = disscusses.count("discusses.id") - end - @manger = @container.has_manager?(current_user) - if @manger - @discusses = disscusses.limit(LIMIT).joins("left join games on discusses.challenge_id = games.challenge_id and discusses.user_id = games.user_id") - .select("discusses.*, games.identifier").includes(:user, :praise_treads).offset(offset) - else @discusses = disscusses.limit(LIMIT).includes(:user, :praise_treads).offset(offset) end diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb index 168d05299..da2b9eb2d 100644 --- a/app/controllers/homework_commons_controller.rb +++ b/app/controllers/homework_commons_controller.rb @@ -439,6 +439,7 @@ class HomeworkCommonsController < ApplicationController def settings @user = current_user @work = @homework.user_work(current_user.id) if @user_course_identity == Course::STUDENT + @course_groups = @course.course_groups.where(id: @course.charge_group_ids(@user)) end def update_settings diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb index 4e587513a..4b2e3f54f 100644 --- a/app/controllers/myshixuns_controller.rb +++ b/app/controllers/myshixuns_controller.rb @@ -264,11 +264,13 @@ class MyshixunsController < ApplicationController unless @hide_code || (@myshixun.shixun&.vnc_evaluate && params[:evaluate].present?) # 远程版本库文件内容 last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"] - content = if @myshixun.mirror_name.select {|a| a.include?("MachineLearning") || a.include?("Python")}.present? && params[:content].present? - params[:content].gsub(/\t/, ' ').gsub(/ /, ' ') # 这个不是空格,在windows机器上带来的问题 - else - params[:content] - end + + content = + if python_file?(path) + params[:content].gsub(/\t/, ' ').gsub(/ /, ' ') + else + params[:content] + end uid_logger_dubug("###11222333####{content}") uid_logger_dubug("###222333####{last_content}") @@ -374,4 +376,9 @@ class MyshixunsController < ApplicationController @repo_path = @myshixun.try(:repo_path) @path = params[:path] end + + def python_file?(path) + false if path.blank? + path.to_s.split(".").last.downcase == "py" + end end diff --git a/app/controllers/schools_controller.rb b/app/controllers/schools_controller.rb index f0dd6dd75..c6265c274 100644 --- a/app/controllers/schools_controller.rb +++ b/app/controllers/schools_controller.rb @@ -11,6 +11,10 @@ class SchoolsController < ApplicationController end def for_option - render_ok(schools: School.select(:id, :name).as_json) + schools = School.all + keyword = params[:keyword].to_s.strip + schools = schools.where('name LIKE ?', "%#{keyword}%") if keyword + + render_ok(schools: schools.select(:id, :name).as_json) end end diff --git a/app/controllers/weapps/check_accounts_controller.rb b/app/controllers/weapps/check_accounts_controller.rb new file mode 100644 index 000000000..429c165b3 --- /dev/null +++ b/app/controllers/weapps/check_accounts_controller.rb @@ -0,0 +1,38 @@ +class Weapps::CheckAccountsController < Weapps::BaseController + def create + params[:type] == 'register' ? check_can_register : check_can_bind + end + + private + + def check_can_bind + if params[:login] =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ + user = User.find_by(mail: params[:login]) + return render_error('该邮箱尚未注册') if user.blank? + elsif params[:login] =~ /^1\d{10}$/ + user = User.find_by(phone: params[:login]) + return render_error('该手机号尚未注册') if user.blank? + else + user = User.find_by(login: params[:login]) + return render_error('该账号尚未注册') if user.blank? + end + + return render_error('该账号已经绑定') if user.wechat_open_user.present? + + render_ok + end + + def check_can_register + if params[:login] =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ + user = User.find_by(mail: params[:login]) + return render_error('该邮箱已注册') if user.present? + elsif params[:login] =~ /^1\d{10}$/ + user = User.find_by(phone: params[:login]) + return render_error('该手机号已注册') if user.present? + else + return render_error('请输入正确的邮箱或手机号') + end + + render_ok + end +end \ No newline at end of file diff --git a/app/controllers/weapps/code_sessions_controller.rb b/app/controllers/weapps/code_sessions_controller.rb index 687605fc4..c92c3cb70 100644 --- a/app/controllers/weapps/code_sessions_controller.rb +++ b/app/controllers/weapps/code_sessions_controller.rb @@ -1,8 +1,10 @@ class Weapps::CodeSessionsController < Weapps::BaseController def create - logged = false return render_error('code不能为空') if params[:code].blank? + reset_session + logged = false + result = Wechat::Weapp.jscode2session(params[:code]) # 能根据 code 拿到 unionid @@ -28,7 +30,7 @@ class Weapps::CodeSessionsController < Weapps::BaseController set_session_openid(result['openid']) set_weapp_session_key(result['session_key']) # weapp session_key写入缓存 后续解密需要 - render_ok(openid: result['openid'], logged: logged) + render_ok(openid: result['openid'], logged: logged) unless logged rescue Wechat::Error => ex render_error(ex.message) end diff --git a/app/controllers/weapps/sessions_controller.rb b/app/controllers/weapps/sessions_controller.rb index f65111399..371a3f7d3 100644 --- a/app/controllers/weapps/sessions_controller.rb +++ b/app/controllers/weapps/sessions_controller.rb @@ -19,6 +19,5 @@ class Weapps::SessionsController < Weapps::BaseController OpenUsers::Wechat.create!(user: user, uid: session_unionid) if user.wechat_open_user.blank? successful_authentication(user) - render_ok end end \ No newline at end of file diff --git a/app/forms/competitions/save_team_form.rb b/app/forms/competitions/save_team_form.rb index 10685d260..dd2610083 100644 --- a/app/forms/competitions/save_team_form.rb +++ b/app/forms/competitions/save_team_form.rb @@ -73,10 +73,10 @@ class Competitions::SaveTeamForm # 竞赛是否限制了职业 def check_creator_identity_enrollable - if user.is_teacher? && competition.teacher_enroll_forbidden? + if creator.is_teacher? && competition.teacher_enroll_forbidden? errors.add(:creator, :teacher_enroll_forbidden) return false - elsif !user.is_teacher? && competition.member_enroll_forbidden? + elsif !creator.is_teacher? && competition.member_enroll_forbidden? errors.add(:creator, :member_enroll_forbidden) return false end @@ -86,9 +86,9 @@ class Competitions::SaveTeamForm # 创建者是否能多次报名 def check_creator_multiple_enrollable - return unless competition.enrolled?(user) + return unless competition.enrolled?(creator) - if (user.is_teacher? && competition.teacher_multiple_limited?) || (!user.is_teacher? && competition.member_multiple_limited?) + if (creator.is_teacher? && competition.teacher_multiple_limited?) || (!creator.is_teacher? && competition.member_multiple_limited?) errors.add(:creator, :enrolled) return false end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1d684350c..614e45425 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -15,6 +15,17 @@ module ApplicationHelper EduSetting.get(name) end + # xss共计问题 + def content_safe content + tags = %w( + a abbr b bdo blockquote br caption cite code col colgroup dd del dfn dl + dt em figcaption figure h1 h2 h3 h4 h5 h6 hgroup i img ins kbd li mark + ol p pre q rp rt ruby s samp small strike strong sub sup table tbody td + tfoot th thead time tr u ul var wbr div span + ) + sanitize content, tags: tags + end + def graduation_navigation graduation graduation.class.to_s == "GraduationTopic" ? "毕设选题" : "毕设任务" end diff --git a/app/jobs/course_add_student_create_works_job.rb b/app/jobs/course_add_student_create_works_job.rb index d8bd6363c..fec28f395 100644 --- a/app/jobs/course_add_student_create_works_job.rb +++ b/app/jobs/course_add_student_create_works_job.rb @@ -25,7 +25,7 @@ class CourseAddStudentCreateWorksJob < ApplicationJob student_ids.each do |user_id| same_attrs = {user_id: user_id} course.homework_commons.where(homework_type: %i[normal group practice]).each do |homework| - next if homework.student_works.where(user_id: user_id).any? + next if StudentWork.where(user_id: user_id, homework_common_id: homework.id).any? worker.add same_attrs.merge(homework_common_id: homework.id) end end @@ -36,7 +36,7 @@ class CourseAddStudentCreateWorksJob < ApplicationJob student_ids.each do |user_id| same_attrs = {user_id: user_id} course.exercises.each do |exercise| - next if exercise.exercise_users.where(user_id: user_id).any? + next if ExerciseUser.where(user_id: user_id, exercise_id: exercise.id).any? worker.add same_attrs.merge(exercise_id: exercise.id) end end @@ -47,7 +47,7 @@ class CourseAddStudentCreateWorksJob < ApplicationJob student_ids.each do |user_id| same_attrs = {user_id: user_id} course.polls.each do |poll| - next if poll.poll_users.where(user_id: user_id).any? + next if PollUser.where(user_id: user_id, poll_id: poll.id).any? worker.add same_attrs.merge(poll_id: poll.id) end end @@ -58,7 +58,7 @@ class CourseAddStudentCreateWorksJob < ApplicationJob student_ids.each do |user_id| same_attrs = {user_id: user_id, course_id: course.id} course.graduation_tasks.each do |task| - next if task.graduation_works.where(user_id: user_id).any? + next if GraduationWork.where(user_id: user_id, graduation_task_id: task.id).any? worker.add same_attrs.merge(graduation_task_id: task.id) end end diff --git a/app/libs/limit_forbid_control.rb b/app/libs/limit_forbid_control.rb new file mode 100644 index 000000000..f45a53130 --- /dev/null +++ b/app/libs/limit_forbid_control.rb @@ -0,0 +1,2 @@ +module LimitForbidControl +end \ No newline at end of file diff --git a/app/libs/limit_forbid_control/base.rb b/app/libs/limit_forbid_control/base.rb new file mode 100644 index 000000000..f112c1df7 --- /dev/null +++ b/app/libs/limit_forbid_control/base.rb @@ -0,0 +1,56 @@ +class LimitForbidControl::Base + def initialize + end + + def cache_key + raise 'Please overwrite method :cache_Key' + end + + def forbid_cache_key + "#{cache_key}:forbid" + end + + def allow_times + 5 + end + + def cumulative_expires + 1.days + end + + def forbid_expires + 1.hours + end + + def forbid? + Rails.cache.read(forbid_cache_key) + end + + def increment! + value = Rails.cache.read(cache_key) + value = value.to_i + 1 + + # 锁定 + if value >= allow_times.to_i + Rails.cache.write(forbid_cache_key, true, expires_in: forbid_expires) + Rails.cache.delete(cache_key) + else + Rails.cache.write(cache_key, value, expires_in: cumulative_expires) + end + end + + def clear + Rails.cache.delete(forbid_cache_key) + Rails.cache.delete(cache_key) + end + + private + + def redis_cache? + Rails.cache.is_a?(ActiveSupport::Cache::RedisStore) + end + + def day + Time.current.strftime('%Y%m%d') + end +end \ No newline at end of file diff --git a/app/libs/limit_forbid_control/send_email_code.rb b/app/libs/limit_forbid_control/send_email_code.rb new file mode 100644 index 000000000..729446e7c --- /dev/null +++ b/app/libs/limit_forbid_control/send_email_code.rb @@ -0,0 +1,25 @@ +class LimitForbidControl::SendEmailCode < LimitForbidControl::Base + attr_reader :email + + def initialize(email) + super() + @email = email + end + + def allow_times + EduSetting.get('daily_send_email_code_times').presence || 5 + end + + def forbid_expires + num = EduSetting.get('daily_send_email_code_forbid_time').presence.to_i + num.zero? ? 10.minutes : num.to_i.hours + end + + def cumulative_expires + 1.hours + end + + def cache_key + @_cache_key ||= "limit_forbid_control:#{day}:send_email_code:#{email}" + end +end \ No newline at end of file diff --git a/app/libs/limit_forbid_control/user_login.rb b/app/libs/limit_forbid_control/user_login.rb new file mode 100644 index 000000000..882556eb1 --- /dev/null +++ b/app/libs/limit_forbid_control/user_login.rb @@ -0,0 +1,25 @@ +class LimitForbidControl::UserLogin < LimitForbidControl::Base + attr_reader :user + + def initialize(user) + super() + @user = user + end + + def allow_times + EduSetting.get('daily_error_password_times').presence || 5 + end + + def forbid_expires + num = EduSetting.get('daily_error_password_forbid_time').presence.to_i + num.zero? ? 1.hours : num.to_i.hours + end + + def cumulative_expires + 1.days + end + + def cache_key + @_cache_key ||= "limit_forbid_control:#{day}:user_login:#{user.id}" + end +end \ No newline at end of file diff --git a/app/libs/util.rb b/app/libs/util.rb index 84f14a6c0..38b5c9af5 100644 --- a/app/libs/util.rb +++ b/app/libs/util.rb @@ -65,4 +65,19 @@ module Util else "#{str[0..2]}***#{str[-3..-1]}" end end + + def display_cost_time(time) + time = time.to_i + return if time.zero? || time < 60 + + day = time / (24 * 60 * 60) + hour = (time % (24 * 60 * 60)) / (60 * 60) + minute = (time % (60 * 60)) / 60 + + str = '' + str += "#{day}天" unless day.zero? + str += "#{hour}小时" unless hour.zero? + str += "#{minute}分" unless minute.zero? + str + end end \ No newline at end of file diff --git a/app/models/competition.rb b/app/models/competition.rb index 8b9d59ed2..39e4f4dfe 100644 --- a/app/models/competition.rb +++ b/app/models/competition.rb @@ -28,9 +28,9 @@ class Competition < ApplicationRecord def mode_type case mode when 1 - "课堂" - when 2 "实训" + when 2 + "课堂" when 3 "教学" when 4 @@ -40,6 +40,17 @@ class Competition < ApplicationRecord end end + def competition_status + if !status + com_status = "nearly_published" + elsif end_time > Time.now + com_status = "progressing" + else + com_status = "ended" + end + com_status + end + def teacher_staff_num teacher_staff ? "#{teacher_staff.minimum}~#{teacher_staff.maximum}" : "--" end @@ -94,16 +105,31 @@ class Competition < ApplicationRecord GROUP BY competition_stage_id order by competition_stage_id") end - def awards_count - competition_awards.pluck(:num)&.sum > 0 ? competition_awards.pluck(:num)&.sum : 20 + def all_module_types + %w[home enroll inform chart resource] end + # def awards_count + # competition_awards.pluck(:num)&.sum > 0 ? competition_awards.pluck(:num)&.sum : 20 + # end + private + def get_module_name type + case type + when 'home' then '首页' + when 'enroll' then '报名' + when 'inform' then '通知公告' + when 'chart' then '排行榜' + when 'resource' then '资料下载' + else '' + end + end + def create_competition_modules - CompetitionModule.bulk_insert(*%i[competition_id name position created_at updated_at]) do |worker| - %w(首页 报名 通知公告 排行榜 资料下载).each_with_index do |name, index| - worker.add(competition_id: id, name: name, position: index + 1) + CompetitionModule.bulk_insert(*%i[competition_id module_type name position created_at updated_at]) do |worker| + all_module_types.each_with_index do |type, index| + worker.add(competition_id: id, module_type: type, name: get_module_name(type), position: index + 1, ) end end end diff --git a/app/models/competition_module.rb b/app/models/competition_module.rb index 9579533da..76f7610d2 100644 --- a/app/models/competition_module.rb +++ b/app/models/competition_module.rb @@ -6,16 +6,16 @@ class CompetitionModule < ApplicationRecord has_one :competition_module_md_content, dependent: :destroy def module_url - case name - when "首页", "赛制介绍" + case module_type + when "home" "/competitions/#{competition.identifier}" - when "通知公告" + when "inform" "/competitions/#{competition.identifier}/informs?status=1" - when "参赛手册" + when "manual" "/competitions/#{competition.identifier}/informs?status=2" - when "排行榜" + when "chart" "/competitions/#{competition.identifier}/charts" - when "报名" + when "enroll" "/competitions/#{competition.identifier}/competition_teams" else url || "/competitions/#{competition.identifier}/md_content?md_content_id=#{competition_module_md_content&.id}" diff --git a/app/models/competition_team.rb b/app/models/competition_team.rb index 6c2b99859..a05ceb032 100644 --- a/app/models/competition_team.rb +++ b/app/models/competition_team.rb @@ -28,7 +28,7 @@ class CompetitionTeam < ApplicationRecord while self.class.exists?(invite_code: code) code = CODE_CHARS.sample(6).join end - self.code = code + self.invite_code = code code end diff --git a/app/models/myshixun.rb b/app/models/myshixun.rb index 006bbf26d..54dcf9011 100644 --- a/app/models/myshixun.rb +++ b/app/models/myshixun.rb @@ -83,6 +83,11 @@ class Myshixun < ApplicationRecord self.games.select{|game| game.status == 2}.size end + # 查看答案的关卡数 + def view_answer_count + self.games.select{|game| game.status == 2 && game.answer_open != 0}.size + end + # 通关时间 def passed_time self.status == 1 ? self.games.select{|game| game.status == 2}.map(&:end_time).max : "--" diff --git a/app/queries/admins/user_statistic_query.rb b/app/queries/admins/user_statistic_query.rb index d1811e5ab..9f8fed952 100644 --- a/app/queries/admins/user_statistic_query.rb +++ b/app/queries/admins/user_statistic_query.rb @@ -36,8 +36,8 @@ class Admins::UserStatisticQuery < ApplicationQuery study_myshixun = Myshixun.where(user_id: ids) finish_myshixun = Myshixun.where(user_id: ids, status: 1) - study_challenge = Game.joins(:myshixun).where(myshixuns: { user_id: ids }).where(status: [0, 1, 2]) - finish_challenge = Game.joins(:myshixun).where(myshixuns: { user_id: ids }).where(status: 2) + study_challenge = Game.where(user_id: ids).where(status: [0, 1, 2]) + finish_challenge = Game.where(user_id: ids).where(status: 2) if time_range.present? study_myshixun = study_myshixun.where(updated_at: time_range) @@ -50,6 +50,8 @@ class Admins::UserStatisticQuery < ApplicationQuery finish_myshixun_map = finish_myshixun.group(:user_id).count study_challenge_map = study_challenge.group(:user_id).count finish_challenge_map = finish_challenge.group(:user_id).count + evaluate_count_map = study_challenge.group(:user_id).sum(:evaluate_count) + cost_time_map = study_challenge.group(:user_id).sum(:cost_time) users.each do |user| user._extra_data = { @@ -57,6 +59,8 @@ class Admins::UserStatisticQuery < ApplicationQuery finish_shixun_count: finish_myshixun_map.fetch(user.id, 0), study_challenge_count: study_challenge_map.fetch(user.id, 0), finish_challenge_count: finish_challenge_map.fetch(user.id, 0), + evaluate_count: evaluate_count_map.fetch(user.id, 0), + cost_time: cost_time_map.fetch(user.id, 0), } end @@ -102,12 +106,12 @@ class Admins::UserStatisticQuery < ApplicationQuery when 'finish_challenge_count' then users = if time_range.present? - users.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id') - .joins("LEFT JOIN games ON games.myshixun_id = myshixuns.id "\ + users#.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id') + .joins("LEFT JOIN games ON games.user_id = users.id "\ "AND games.status = 2 AND games.updated_at BETWEEN '#{time_range.min}' AND '#{time_range.max}'") else - users.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id') - .joins("LEFT JOIN games ON games.myshixun_id = myshixuns.id AND games.status = 2") + users#.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id') + .joins("LEFT JOIN games ON games.user_id = users.id AND games.status = 2") end users.select("#{base_query_column}, COUNT(*) finish_challenge_count") diff --git a/app/services/admins/competition_basic_setting_service.rb b/app/services/admins/competition_basic_setting_service.rb new file mode 100644 index 000000000..e5a7dd6be --- /dev/null +++ b/app/services/admins/competition_basic_setting_service.rb @@ -0,0 +1,39 @@ +class Admins::CompetitionBasicSettingService < ApplicationService + attr_reader :competition, :params + + def initialize(competition, params) + @params = params + @competition = competition + end + + def call + ActiveRecord::Base.transaction do + competition.name = strip params[:name] + competition.sub_title = strip params[:sub_title] + competition.start_time = params[:start_time] + competition.end_time = params[:end_time] + competition.mode = params[:mode] + competition.identifier = strip params[:identifier] + competition.bonus = params[:bonus] + competition.awards_count = params[:awards_count] + competition.description = strip params[:description] + + competition.save! + + if competition.mode == 1 || competition.mode == 4 + competition.competition_mode_setting.destroy + else + setting = competition.competition_mode_setting || CompetitionModeSetting.create!(competition_id: competition.id) + if competition.mode == 2 + setting.course_id = params[:course_id] + elsif competition.mode == 3 + setting.start_time = params[:teach_start_time] + setting.end_time = params[:teach_end_time] + end + setting.save! + end + + competition + end + end +end \ No newline at end of file diff --git a/app/services/admins/competition_nav_setting_service.rb b/app/services/admins/competition_nav_setting_service.rb new file mode 100644 index 000000000..13b58a799 --- /dev/null +++ b/app/services/admins/competition_nav_setting_service.rb @@ -0,0 +1,36 @@ +class Admins::CompetitionNavSettingService < ApplicationService + attr_reader :competition, :params + + def initialize(competition, params) + @params = params + @competition = competition + end + + def call + ActiveRecord::Base.transaction do + competition.competition_modules.where(module_type: 'md').destroy_all + + # hidden_module_type = competition.all_module_types - params[:module_type] + # competition.competition_modules.where(module_type: hidden_module_type).update_all(hidden: 1) + + params[:nav_module].each do |nav| + module_type = nav["module_type"] + if competition.all_module_types.include?(module_type) + com_module = competition.competition_modules.find_by(module_type: module_type) + else + com_module = CompetitionModule.create!(competition_id: competition.id, module_type: 'md') + end + com_module.update_attributes!(hidden: nav["hidden"] ? 0 : 1, position: nav["position"], name: nav["name"], url: nav["url"]) + end + + if params[:competition_staffs].present? + competition.competition_staffs.delete_all + params[:competition_staffs].each_with_index do |staff_params, index| + competition.competition_staffs.create!(staff_params.merge(position: index + 1)) + end + end + + competition + end + end +end \ No newline at end of file diff --git a/app/services/admins/import_course_member_service.rb b/app/services/admins/import_course_member_service.rb index 8f162902f..9b9393e78 100644 --- a/app/services/admins/import_course_member_service.rb +++ b/app/services/admins/import_course_member_service.rb @@ -36,7 +36,7 @@ class Admins::ImportCourseMemberService < ApplicationService member = course.course_members.find_by(user_id: user.id, role: data.role.to_i) # 如果已是课堂成员且是学生身份and不在指定的分班则移动到该分班 - if member.present? && member.role == :STUDENT && course_group && member.course_group_id != course_group&.id + if member.present? && member.role == 'STUDENT' && course_group && member.course_group_id != course_group&.id member.update!(course_group_id: course_group&.id) elsif member.blank? course.course_members.create!(user_id: user.id, role: data.role.to_i, course_group_id: course_group&.id) diff --git a/app/services/competitions/create_personal_team_service.rb b/app/services/competitions/create_personal_team_service.rb index 12b595cae..907c59dc0 100644 --- a/app/services/competitions/create_personal_team_service.rb +++ b/app/services/competitions/create_personal_team_service.rb @@ -20,8 +20,8 @@ class Competitions::CreatePersonalTeamService < ApplicationService raise Error, '您已报名该竞赛' if enrolled && multiple_limited ActiveRecord::Base.transaction do - team = competition.competition_teams.create!(name: user.show_name, user_id: user.id) - team.team_members.create!(competition_id: competition, user_id: user.id, role: 1, is_teacher: is_teacher) + team = competition.competition_teams.create!(name: user.real_name, user_id: user.id) + team.team_members.create!(competition_id: competition.id, user_id: user.id, role: 1, is_teacher: is_teacher) end end end \ No newline at end of file diff --git a/app/services/competitions/save_team_service.rb b/app/services/competitions/save_team_service.rb index 1021e6e6d..233648fbb 100644 --- a/app/services/competitions/save_team_service.rb +++ b/app/services/competitions/save_team_service.rb @@ -32,7 +32,7 @@ class Competitions::SaveTeamService < ApplicationService private def update_teacher_team_members! - teacher_ids = Array.wrap(params[:teacher_ids]).map(:to_i) + teacher_ids = Array.wrap(params[:teacher_ids]).map(&:to_i) old_teacher_ids = team.team_members.where(role: 3).pluck(:user_id) destroy_teacher_ids = old_teacher_ids - teacher_ids @@ -49,7 +49,7 @@ class Competitions::SaveTeamService < ApplicationService end def update_member_team_members! - member_ids = Array.wrap(params[:member_ids]).map(:to_i) + member_ids = Array.wrap(params[:member_ids]).map(&:to_i) old_member_ids = team.team_members.where(role: 2).pluck(:user_id) destroy_member_ids = old_member_ids - member_ids diff --git a/app/services/create_add_department_apply_service.rb b/app/services/create_add_department_apply_service.rb index 8c3a2127e..e172b001a 100644 --- a/app/services/create_add_department_apply_service.rb +++ b/app/services/create_add_department_apply_service.rb @@ -14,6 +14,7 @@ class CreateAddDepartmentApplyService < ApplicationService school = School.find_by(id: params[:school_id]) raise Error, '学校/单位不存在' if school.blank? + raise Error, '部门已存在' if school.departments.exists?(name: name) department = Department.new department.name = name diff --git a/app/services/oauth/create_or_find_qq_account_service.rb b/app/services/oauth/create_or_find_qq_account_service.rb index 200d436ef..c258993bd 100644 --- a/app/services/oauth/create_or_find_qq_account_service.rb +++ b/app/services/oauth/create_or_find_qq_account_service.rb @@ -16,7 +16,7 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService if user.blank? || !user.logged? new_user = true # 新用户 - login = User.generate_login('q') + login = User.generate_login('Q') @user = User.new(login: login, nickname: params.dig('info', 'nickname'), type: 'User', status: User::STATUS_ACTIVE) end @@ -26,6 +26,9 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService gender = params.dig('extra', 'raw_info', 'gender') == '女' ? 1 : 0 user.create_user_extension!(gender: gender) + # 下载头像 + avatar_path = Util::FileManage.source_disk_filename(user) + Util.download_file(params.dig('info', 'figureurl_qq_1'), avatar_path) end new_open_user = OpenUsers::QQ.create!(user: user, uid: params['uid'], extra: params.dig('extra', 'raw_info')) diff --git a/app/views/admins/competition_settings/index.html.erb b/app/views/admins/competition_settings/index.html.erb new file mode 100644 index 000000000..7133b7254 --- /dev/null +++ b/app/views/admins/competition_settings/index.html.erb @@ -0,0 +1,284 @@ +<% + define_admin_breadcrumbs do + add_admin_breadcrumb('竞赛列表', admins_competitions_path) + add_admin_breadcrumb(@competition.name) + end +%> + +
+
+ 基础设置 +
+
+ <%= form_tag(basic_setting_admins_competition_competition_settings_path(@competition), method: :post, class: 'basic-setting-form flex-1', remote: true) do %> +
+
+
+ 主标题 +
+
+ <%= text_field_tag(:name, @competition.name, autocomplete: 'off', class: 'form-control', placeholder: '竞赛标题') %> +
+
+ +
+
+ 副标题 +
+
+ <%= text_field_tag(:sub_title, @competition.sub_title, autocomplete: 'off', class: 'form-control', placeholder: '竞赛副标题') %> +
+
+ +
+
+ 起止时间 +
+
+ <%= text_field_tag :start_time, @competition.start_time&.strftime('%Y-%m-%d'), autocomplete: 'off', class: 'form-control start-date mx-0 mr-2', placeholder: '竞赛开始时间' %> + <%= text_field_tag :end_time, @competition.end_time&.strftime('%Y-%m-%d'), autocomplete: 'off', class: 'form-control end-date mx-0', placeholder: '竞赛截止时间' %> +
+
+ +
+
+ 竞赛模式 +
+
+ <%= radio_button_tag(:mode, 1, @competition.mode == 1, class: 'form-radio-input') %> + +
+
+ +
+
+
+
+ <%= radio_button_tag(:mode, 2, @competition.mode == 2, class: 'form-radio-input') %> + +
+
+ <%= text_field_tag(:course_id, @competition.competition_mode_setting&.course_id, autocomplete: 'off', class: 'form-control', placeholder: '课堂id') %> +
+
+ +
+
+
+
+ <%= radio_button_tag(:mode, 3, @competition.mode == 3, class: 'form-radio-input') %> + +
+
+ <%= text_field_tag :teach_start_time, @competition.competition_mode_setting&.start_time, autocomplete: 'off', class: 'form-control start-date mx-0 mr-2', placeholder: '统计数据的开始时间' %> + <%= text_field_tag :teach_end_time, @competition.competition_mode_setting&.end_time, autocomplete: 'off', class: 'form-control end-date mx-0', placeholder: '统计数据的结束时间' %> +
+
+ +
+
+
+
+ <%= radio_button_tag(:mode, 4, @competition.mode == 4, class: 'form-radio-input') %> + +
+
+ +
+
+ URL +
+
+ <%= text_field_tag(:identifier, @competition.identifier, autocomplete: 'off', class: 'form-control', placeholder: '请输入url赛事网址') %> +
+
+ +
+
+ 主办方 +
+
+ +
+
+ +
+
+ 奖金 +
+
+
+
¥
+
+ <%= number_field_tag(:bonus, @competition.bonus, autocomplete: 'off', step: 1, min: 0, class: 'form-control', placeholder: '请输入总奖金额') %> +
+
+ +
+
+ 奖项数 +
+
+ <%= number_field_tag(:awards_count, @competition.awards_count, autocomplete: 'off', step: 1, min: 0, class: 'form-control', placeholder: '请输入奖项数') %> +
+
+ +
+
+ 描述 +
+
+ <%= text_area_tag(:description, @competition.description, class: 'form-control', placeholder: '请输入赛事简介') %> +
+
+ +
+ +
+
+
+
+ <%= javascript_void_link '保存', class: 'btn btn-primary submit-btn' %> +
+
+
+ <% end %> +
+
+ +
+
+ 导航设置 +
+
+
+ <% @competition.competition_modules.each do |com_module| %> + <% case com_module.module_type %> + <% when 'home' %> +
+
+
+ +
+
+ <%= text_field_tag('navbar[][name]', com_module.name, id: nil, class: 'form-control', placeholder: '首页') %> + +
+
+ <%= text_field_tag('navbar[][position]', com_module.position, id: nil, class: 'form-control', placeholder: '位置') %> +
+
+
+ <% end %> + <% end %> + +
+
+ +
+
+ 报名 +
+
+
+
  
+
+ 报名截止时间 +
+
+
+
+
  
+
+ 报名要求 +
+
+ +
+
+ +
+
+
  
+
+ +
+ ~ +
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+ + +
+
+ +
+
排行榜
+
+
+
+
+
+ +
+
资料下载
+
+
+ +
+
+
+
+ +
+
获奖证书
+
+ +
+
+
+
<%= javascript_void_link '保存', class: 'btn btn-primary submit-btn' %>
+
+ +
+
+
+ diff --git a/app/views/admins/competition_settings/show.html.erb b/app/views/admins/competition_settings/show.html.erb deleted file mode 100644 index 6272687e4..000000000 --- a/app/views/admins/competition_settings/show.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -<% - define_admin_breadcrumbs do - add_admin_breadcrumb('竞赛列表', admins_competitions_path) - add_admin_breadcrumb(@competition.name) - end -%> - -
-
- 基础设置 -
-
- -
-
- diff --git a/app/views/admins/enroll_lists/export.xlsx.axlsx b/app/views/admins/enroll_lists/export.xlsx.axlsx new file mode 100644 index 000000000..b6f403ab8 --- /dev/null +++ b/app/views/admins/enroll_lists/export.xlsx.axlsx @@ -0,0 +1,29 @@ +wb = xlsx_package.workbook +wb.add_worksheet(name: '报名列表') do |sheet| + sheet.add_row %w(序号 战队ID 战队名称 创建者 指导老师 队员姓名 职业 手机号 邮箱 学号 实名认证 职业认证 队员学校 地区 报名时间 排名) + + @enroll_lists.each_with_index do |member, index| + team = member.competition_team + member_user = member.user + rank = @competition_scores.length > 0 ? @competition_scores.index(member.competition_team_id).to_i + 1 : "--" + data = [ + index + 1, + member.competition_team_id, + @personal ? "--" : team.name, + team.user.real_name, + @personal ? "--" : team.teachers_info, + member_user.real_name, + member_user.identity, + member_user.phone, + member_user.mail, + member_user.student_id, + member_user.authentication ? "√" : "", + member_user.professional_certification ? "√" : "", + member_user.school_name, + member_user.school_province, + member.created_at.strftime('%Y-%m-%d %H:%M'), + rank + ] + sheet.add_row(data) + end +end \ No newline at end of file diff --git a/app/views/admins/enroll_lists/index.html.erb b/app/views/admins/enroll_lists/index.html.erb index 95787d54c..636479377 100644 --- a/app/views/admins/enroll_lists/index.html.erb +++ b/app/views/admins/enroll_lists/index.html.erb @@ -24,7 +24,7 @@ <%= link_to "清除", admins_competition_enroll_lists_path(@competition), class: "btn btn-default",'data-disable-with': '清除中...' %> <% end %> - 导出 + 导出 diff --git a/app/views/admins/myshixuns/shared/_list.html.erb b/app/views/admins/myshixuns/shared/_list.html.erb index 78e42d58b..89ad535c5 100644 --- a/app/views/admins/myshixuns/shared/_list.html.erb +++ b/app/views/admins/myshixuns/shared/_list.html.erb @@ -17,14 +17,10 @@ <% myshixuns.each do |myshixun| %> - + - diff --git a/app/views/admins/user_statistics/export.xlsx.axlsx b/app/views/admins/user_statistics/export.xlsx.axlsx index b66e62a99..1511b6ea3 100644 --- a/app/views/admins/user_statistics/export.xlsx.axlsx +++ b/app/views/admins/user_statistics/export.xlsx.axlsx @@ -1,6 +1,6 @@ wb = xlsx_package.workbook wb.add_worksheet(name: '用户实训情况') do |sheet| - sheet.add_row %w(姓名 单位部门 学习关卡数 完成关卡数 学习实训数 完成实训数) + sheet.add_row %w(姓名 单位部门 学习关卡数 完成关卡数 学习实训数 完成实训数 评测次数 实战时间) @users.each do |user| data = [ @@ -9,7 +9,9 @@ wb.add_worksheet(name: '用户实训情况') do |sheet| user.display_extra_data(:study_challenge_count), user.display_extra_data(:finish_challenge_count), user.display_extra_data(:study_shixun_count), - user.display_extra_data(:finish_shixun_count) + user.display_extra_data(:finish_shixun_count), + user.display_extra_data(:evaluate_count), + Util.display_cost_time(user.display_extra_data(:cost_time)), ] sheet.add_row(data) end diff --git a/app/views/admins/user_statistics/shared/_list.html.erb b/app/views/admins/user_statistics/shared/_list.html.erb index 1e1b14ea3..5759d2f38 100644 --- a/app/views/admins/user_statistics/shared/_list.html.erb +++ b/app/views/admins/user_statistics/shared/_list.html.erb @@ -2,11 +2,13 @@ - - - - - + + + + + + + @@ -23,6 +25,8 @@ + + <% end %> <% else %> diff --git a/app/views/admins/weapp_adverts/shared/_add_weapp_advert_modal.html.erb b/app/views/admins/weapp_adverts/shared/_add_weapp_advert_modal.html.erb index 9909084b8..3937054b5 100644 --- a/app/views/admins/weapp_adverts/shared/_add_weapp_advert_modal.html.erb +++ b/app/views/admins/weapp_adverts/shared/_add_weapp_advert_modal.html.erb @@ -21,7 +21,7 @@ - <%= f.input :link, as: :url, label: '跳转地址', placeholder: '请输入跳转地址' %> + <%= f.input :link, label: '跳转地址', placeholder: '请输入跳转地址' %>
<% end %> diff --git a/app/views/admins/weapp_carousels/shared/_add_weapp_carousel_modal.html.erb b/app/views/admins/weapp_carousels/shared/_add_weapp_carousel_modal.html.erb index 767ae61ae..123ce4a62 100644 --- a/app/views/admins/weapp_carousels/shared/_add_weapp_carousel_modal.html.erb +++ b/app/views/admins/weapp_carousels/shared/_add_weapp_carousel_modal.html.erb @@ -21,7 +21,7 @@ - <%= f.input :link, as: :url, label: '跳转地址', placeholder: '请输入跳转地址' %> + <%= f.input :link, label: '跳转地址', placeholder: '请输入跳转地址' %>
<% end %> diff --git a/app/views/competitions/competition_teams/index.json.jbuilder b/app/views/competitions/competition_teams/index.json.jbuilder index d44fcdf1c..70651b4ae 100644 --- a/app/views/competitions/competition_teams/index.json.jbuilder +++ b/app/views/competitions/competition_teams/index.json.jbuilder @@ -1,12 +1,11 @@ -json.count @count +json.count @all_count json.personal @personal json.competition_teams do - json.array! @teams.each do |team| + json.array! @all_teams&.each do |team| json.extract! team, :id, :name, :invite_code json.team_type team.en_team_type json.school_name team.user.school_name - - json.manage_permission current_user.id == team.user_id + json.created_at team.created_at.strftime("%Y-%m-%d %H:%M") json.creator do json.partial! 'users/user_simple', user: team.user @@ -25,3 +24,30 @@ json.competition_teams do end end end + +json.my_teams @teams.each do |team| + json.extract! team, :id, :name, :invite_code + json.team_type team.en_team_type + json.school_name team.user.school_name + json.created_at team.created_at.strftime("%Y-%m-%d %H:%M") + + json.manage_permission current_user.id == team.user_id + + json.creator do + json.partial! 'users/user_simple', user: team.user + json.role team.team_members.find(&:creator?).en_role + end + + json.team_members do + json.array! team.team_members.each do |member| + json.partial! 'users/user_simple', user: member.user + json.user_id member.user_id + json.role member.en_role + json.identity member.user.identity + json.school_name member.user.school_name + json.student_id member.user.student_id + end + end +end + + diff --git a/app/views/competitions/competitions/common_header.json.jbuilder b/app/views/competitions/competitions/common_header.json.jbuilder index 882d1d1c0..0ecf6cfd5 100644 --- a/app/views/competitions/competitions/common_header.json.jbuilder +++ b/app/views/competitions/competitions/common_header.json.jbuilder @@ -9,15 +9,17 @@ json.enroll_end_time @competition.enroll_end_time&.strftime("%Y-%m-%d %H:%M:%S") json.published @competition.published? json.nearly_published @competition.published_at.present? +json.competition_status @competition.competition_status json.competition_modules @competition_modules do |com_module| - json.(com_module, :name, :position) + json.(com_module, :id, :name, :position, :module_type) json.module_url com_module.module_url + json.has_url com_module.url.present? end json.stages -if @competition.mode == 1 +if @competition.mode == 2 json.course_id @competition.competition_mode_setting&.course_id json.member_of_course @user.member_of_course?(@competition.competition_mode_setting&.course) end diff --git a/app/views/competitions/competitions/index.json.jbuilder b/app/views/competitions/competitions/index.json.jbuilder index 8e99d754d..810cbfd18 100644 --- a/app/views/competitions/competitions/index.json.jbuilder +++ b/app/views/competitions/competitions/index.json.jbuilder @@ -3,6 +3,7 @@ json.competitions do json.array! @competitions.each do |competition| json.extract! competition, :id, :identifier, :name, :sub_title, :bonus, :description, :mode + json.competition_status competition.competition_status json.visits_count competition.visits member_count = @member_count_map&.fetch(competition.id, 0) || competition.team_members.count json.member_count member_count.zero? ? 268 : member_count diff --git a/app/views/discusses/_discuss.json.jbuilder b/app/views/discusses/_discuss.json.jbuilder index 400798150..5244414f9 100644 --- a/app/views/discusses/_discuss.json.jbuilder +++ b/app/views/discusses/_discuss.json.jbuilder @@ -2,7 +2,7 @@ json.author do json.partial! 'users/user', user: discuss.user end json.id discuss.id -json.content discuss.content +json.content content_safe(discuss.content) json.time time_from_now(discuss.created_at) json.position discuss.position json.shixun_id discuss.dis_id diff --git a/app/views/homework_commons/settings.json.jbuilder b/app/views/homework_commons/settings.json.jbuilder index 75604de0c..f62dde87e 100644 --- a/app/views/homework_commons/settings.json.jbuilder +++ b/app/views/homework_commons/settings.json.jbuilder @@ -7,7 +7,7 @@ json.partial! "student_btn_check", locals: {identity: @user_course_identity, hom json.(@homework, :unified_setting, :publish_time, :end_time, :late_penalty, :allow_late, :late_time, :work_public, :score_open, :answer_public) -json.group_settings @course.course_groups do |group| +json.group_settings @course_groups do |group| json.group_id group.id json.group_name group.name json.publish_time group_homework_setting(@homework, group.id).try(:publish_time) diff --git a/app/views/homework_commons/works_list.json.jbuilder b/app/views/homework_commons/works_list.json.jbuilder index 839b40bfd..24d1f354a 100644 --- a/app/views/homework_commons/works_list.json.jbuilder +++ b/app/views/homework_commons/works_list.json.jbuilder @@ -41,6 +41,7 @@ elsif @user_course_identity == Course::STUDENT json.efficiency work_score_format(@work.efficiency, true, @score_open) json.eff_score work_score_format(@work.eff_score, true, @score_open) json.complete_count @work.myshixun.try(:passed_count) + json.view_answer_count @work.myshixun.try(:view_answer_count) else json.(@work, :id, :work_status, :update_time, :ultimate_score) @@ -95,6 +96,7 @@ if @homework.homework_type == "practice" json.cost_time work.myshixun.try(:total_spend_time) json.complete_count work.myshixun.try(:passed_count) + json.view_answer_count work.myshixun.try(:view_answer_count) json.user_login work.user.try(:login) json.user_name work.user.try(:real_name) json.student_id work.user.try(:student_id) diff --git a/app/views/memos/_memo.json.jbuilder b/app/views/memos/_memo.json.jbuilder index a09b7f293..a9c430017 100644 --- a/app/views/memos/_memo.json.jbuilder +++ b/app/views/memos/_memo.json.jbuilder @@ -3,7 +3,7 @@ json.memo do json.forum_id memo.forum_id json.subject memo.subject json.is_md memo.is_md - json.content memo.content + json.content content_safe(memo.content) json.sticky memo.sticky json.reward memo.reward json.viewed_count memo.viewed_count diff --git a/app/views/memos/_replies_list.json.jbuilder b/app/views/memos/_replies_list.json.jbuilder index 9ec6976c2..8f86e79a6 100644 --- a/app/views/memos/_replies_list.json.jbuilder +++ b/app/views/memos/_replies_list.json.jbuilder @@ -1,5 +1,5 @@ json.id memo.id -json.content memo.content +json.content content_safe(memo.content) json.time time_from_now(memo.created_at) json.user_id memo.author_id json.image_url url_to_avatar(memo.author) @@ -15,7 +15,7 @@ json.admin @user.admin? || @user.business? json.children do json.array! memo.children_of_reply do |child| json.id child.id - json.content child.content + json.content content_safe(child.content) json.time time_from_now(child.created_at) json.image_url url_to_avatar(child.author) json.username child.author.full_name diff --git a/app/views/messages/_content.json.jbuilder b/app/views/messages/_content.json.jbuilder index 5e1d9088b..760f1670d 100644 --- a/app/views/messages/_content.json.jbuilder +++ b/app/views/messages/_content.json.jbuilder @@ -1 +1 @@ -json.content content \ No newline at end of file +json.content content_safe(content) \ No newline at end of file diff --git a/app/views/messages/_message_detail.json.jbuilder b/app/views/messages/_message_detail.json.jbuilder index 38532429f..35237f732 100644 --- a/app/views/messages/_message_detail.json.jbuilder +++ b/app/views/messages/_message_detail.json.jbuilder @@ -1,6 +1,6 @@ json.partial! "messages/message_simple", message: message json.partial! "commons/like", message: message -json.content message.message_detail.try(:content) +json.content content_safe(message.message_detail.try(:content)) json.author do json.partial! "users/user_simple", user: message.author end \ No newline at end of file diff --git a/app/views/users/get_user_info.json.jbuilder b/app/views/users/get_user_info.json.jbuilder index e18ccfe05..06794b31e 100644 --- a/app/views/users/get_user_info.json.jbuilder +++ b/app/views/users/get_user_info.json.jbuilder @@ -4,6 +4,7 @@ json.login @user.login json.user_id @user.id json.image_url url_to_avatar(@user) json.admin @user.admin? +json.business @user.business? json.is_teacher @user.user_extension&.teacher? json.user_identity @user.identity json.tidding_count 0 diff --git a/app/views/weapps/code_sessions/create.json.jbuilder b/app/views/weapps/code_sessions/create.json.jbuilder new file mode 100644 index 000000000..280086948 --- /dev/null +++ b/app/views/weapps/code_sessions/create.json.jbuilder @@ -0,0 +1,3 @@ +json.user do + json.partial! 'weapps/shared/user', locals: { user: current_user } +end \ No newline at end of file diff --git a/app/views/weapps/sessions/create.json.jbuilder b/app/views/weapps/sessions/create.json.jbuilder new file mode 100644 index 000000000..280086948 --- /dev/null +++ b/app/views/weapps/sessions/create.json.jbuilder @@ -0,0 +1,3 @@ +json.user do + json.partial! 'weapps/shared/user', locals: { user: current_user } +end \ No newline at end of file diff --git a/app/views/weapps/shared/_user.json.jbuilder b/app/views/weapps/shared/_user.json.jbuilder new file mode 100644 index 000000000..be67384cc --- /dev/null +++ b/app/views/weapps/shared/_user.json.jbuilder @@ -0,0 +1,14 @@ +json.username user.full_name +json.real_name user.real_name +json.login user.login +json.user_id user.id +json.image_url url_to_avatar(user) +json.admin user.admin? +json.business user.business? +json.is_teacher user.user_extension&.teacher? +json.user_identity user.identity +json.tidding_count 0 +json.user_phone_binded user.phone.present? +json.phone user.phone +json.profile_completed user.profile_completed? +json.professional_certification user.professional_certification \ No newline at end of file diff --git a/bootstrap-datetimepicker.css b/bootstrap-datetimepicker.css new file mode 100755 index 000000000..537c6a4ce --- /dev/null +++ b/bootstrap-datetimepicker.css @@ -0,0 +1,418 @@ +/*! + * Datetimepicker for Bootstrap + * + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +.datetimepicker { + padding: 4px; + margin-top: 1px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + direction: ltr; +} + +.datetimepicker-inline { + width: 220px; +} + +.datetimepicker.datetimepicker-rtl { + direction: rtl; +} + +.datetimepicker.datetimepicker-rtl table tr td span { + float: right; +} + +.datetimepicker-dropdown, .datetimepicker-dropdown-left { + top: 0; + left: 0; +} + +[class*=" datetimepicker-dropdown"]:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #cccccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; +} + +[class*=" datetimepicker-dropdown"]:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; +} + +[class*=" datetimepicker-dropdown-top"]:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #cccccc; + border-top-color: rgba(0, 0, 0, 0.2); + border-bottom: 0; +} + +[class*=" datetimepicker-dropdown-top"]:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid #ffffff; + border-bottom: 0; +} + +.datetimepicker-dropdown-bottom-left:before { + top: -7px; + right: 6px; +} + +.datetimepicker-dropdown-bottom-left:after { + top: -6px; + right: 7px; +} + +.datetimepicker-dropdown-bottom-right:before { + top: -7px; + left: 6px; +} + +.datetimepicker-dropdown-bottom-right:after { + top: -6px; + left: 7px; +} + +.datetimepicker-dropdown-top-left:before { + bottom: -7px; + right: 6px; +} + +.datetimepicker-dropdown-top-left:after { + bottom: -6px; + right: 7px; +} + +.datetimepicker-dropdown-top-right:before { + bottom: -7px; + left: 6px; +} + +.datetimepicker-dropdown-top-right:after { + bottom: -6px; + left: 7px; +} + +.datetimepicker > div { + display: none; +} + +.datetimepicker.minutes div.datetimepicker-minutes { + display: block; +} + +.datetimepicker.hours div.datetimepicker-hours { + display: block; +} + +.datetimepicker.days div.datetimepicker-days { + display: block; +} + +.datetimepicker.months div.datetimepicker-months { + display: block; +} + +.datetimepicker.years div.datetimepicker-years { + display: block; +} + +.datetimepicker table { + margin: 0; +} + +.datetimepicker td, +.datetimepicker th { + text-align: center; + width: 20px; + height: 20px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + border: none; +} + +.table-striped .datetimepicker table tr td, +.table-striped .datetimepicker table tr th { + background-color: transparent; +} + +.datetimepicker table tr td.minute:hover { + background: #eeeeee; + cursor: pointer; +} + +.datetimepicker table tr td.hour:hover { + background: #eeeeee; + cursor: pointer; +} + +.datetimepicker table tr td.day:hover { + background: #eeeeee; + cursor: pointer; +} + +.datetimepicker table tr td.old, +.datetimepicker table tr td.new { + color: #999999; +} + +.datetimepicker table tr td.disabled, +.datetimepicker table tr td.disabled:hover { + background: none; + color: #999999; + cursor: default; +} + +.datetimepicker table tr td.today, +.datetimepicker table tr td.today:hover, +.datetimepicker table tr td.today.disabled, +.datetimepicker table tr td.today.disabled:hover { + background-color: #fde19a; + background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a)); + background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -o-linear-gradient(top, #fdd49a, #fdf59a); + background-image: linear-gradient(to bottom, #fdd49a, #fdf59a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0); + border-color: #fdf59a #fdf59a #fbed50; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.datetimepicker table tr td.today:hover, +.datetimepicker table tr td.today:hover:hover, +.datetimepicker table tr td.today.disabled:hover, +.datetimepicker table tr td.today.disabled:hover:hover, +.datetimepicker table tr td.today:active, +.datetimepicker table tr td.today:hover:active, +.datetimepicker table tr td.today.disabled:active, +.datetimepicker table tr td.today.disabled:hover:active, +.datetimepicker table tr td.today.active, +.datetimepicker table tr td.today:hover.active, +.datetimepicker table tr td.today.disabled.active, +.datetimepicker table tr td.today.disabled:hover.active, +.datetimepicker table tr td.today.disabled, +.datetimepicker table tr td.today:hover.disabled, +.datetimepicker table tr td.today.disabled.disabled, +.datetimepicker table tr td.today.disabled:hover.disabled, +.datetimepicker table tr td.today[disabled], +.datetimepicker table tr td.today:hover[disabled], +.datetimepicker table tr td.today.disabled[disabled], +.datetimepicker table tr td.today.disabled:hover[disabled] { + background-color: #fdf59a; +} + +.datetimepicker table tr td.today:active, +.datetimepicker table tr td.today:hover:active, +.datetimepicker table tr td.today.disabled:active, +.datetimepicker table tr td.today.disabled:hover:active, +.datetimepicker table tr td.today.active, +.datetimepicker table tr td.today:hover.active, +.datetimepicker table tr td.today.disabled.active, +.datetimepicker table tr td.today.disabled:hover.active { + background-color: #fbf069; +} + +.datetimepicker table tr td.active, +.datetimepicker table tr td.active:hover, +.datetimepicker table tr td.active.disabled, +.datetimepicker table tr td.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.datetimepicker table tr td.active:hover, +.datetimepicker table tr td.active:hover:hover, +.datetimepicker table tr td.active.disabled:hover, +.datetimepicker table tr td.active.disabled:hover:hover, +.datetimepicker table tr td.active:active, +.datetimepicker table tr td.active:hover:active, +.datetimepicker table tr td.active.disabled:active, +.datetimepicker table tr td.active.disabled:hover:active, +.datetimepicker table tr td.active.active, +.datetimepicker table tr td.active:hover.active, +.datetimepicker table tr td.active.disabled.active, +.datetimepicker table tr td.active.disabled:hover.active, +.datetimepicker table tr td.active.disabled, +.datetimepicker table tr td.active:hover.disabled, +.datetimepicker table tr td.active.disabled.disabled, +.datetimepicker table tr td.active.disabled:hover.disabled, +.datetimepicker table tr td.active[disabled], +.datetimepicker table tr td.active:hover[disabled], +.datetimepicker table tr td.active.disabled[disabled], +.datetimepicker table tr td.active.disabled:hover[disabled] { + background-color: #0044cc; +} + +.datetimepicker table tr td.active:active, +.datetimepicker table tr td.active:hover:active, +.datetimepicker table tr td.active.disabled:active, +.datetimepicker table tr td.active.disabled:hover:active, +.datetimepicker table tr td.active.active, +.datetimepicker table tr td.active:hover.active, +.datetimepicker table tr td.active.disabled.active, +.datetimepicker table tr td.active.disabled:hover.active { + background-color: #003399; +} + +.datetimepicker table tr td span { + display: block; + width: 23%; + height: 54px; + line-height: 54px; + float: left; + margin: 1%; + cursor: pointer; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.datetimepicker .datetimepicker-hours span { + height: 26px; + line-height: 26px; +} + +.datetimepicker .datetimepicker-hours table tr td span.hour_am, +.datetimepicker .datetimepicker-hours table tr td span.hour_pm { + width: 14.6%; +} + +.datetimepicker .datetimepicker-hours fieldset legend, +.datetimepicker .datetimepicker-minutes fieldset legend { + margin-bottom: inherit; + line-height: 30px; +} + +.datetimepicker .datetimepicker-minutes span { + height: 26px; + line-height: 26px; +} + +.datetimepicker table tr td span:hover { + background: #eeeeee; +} + +.datetimepicker table tr td span.disabled, +.datetimepicker table tr td span.disabled:hover { + background: none; + color: #999999; + cursor: default; +} + +.datetimepicker table tr td span.active, +.datetimepicker table tr td span.active:hover, +.datetimepicker table tr td span.active.disabled, +.datetimepicker table tr td span.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.datetimepicker table tr td span.active:hover, +.datetimepicker table tr td span.active:hover:hover, +.datetimepicker table tr td span.active.disabled:hover, +.datetimepicker table tr td span.active.disabled:hover:hover, +.datetimepicker table tr td span.active:active, +.datetimepicker table tr td span.active:hover:active, +.datetimepicker table tr td span.active.disabled:active, +.datetimepicker table tr td span.active.disabled:hover:active, +.datetimepicker table tr td span.active.active, +.datetimepicker table tr td span.active:hover.active, +.datetimepicker table tr td span.active.disabled.active, +.datetimepicker table tr td span.active.disabled:hover.active, +.datetimepicker table tr td span.active.disabled, +.datetimepicker table tr td span.active:hover.disabled, +.datetimepicker table tr td span.active.disabled.disabled, +.datetimepicker table tr td span.active.disabled:hover.disabled, +.datetimepicker table tr td span.active[disabled], +.datetimepicker table tr td span.active:hover[disabled], +.datetimepicker table tr td span.active.disabled[disabled], +.datetimepicker table tr td span.active.disabled:hover[disabled] { + background-color: #0044cc; +} + +.datetimepicker table tr td span.active:active, +.datetimepicker table tr td span.active:hover:active, +.datetimepicker table tr td span.active.disabled:active, +.datetimepicker table tr td span.active.disabled:hover:active, +.datetimepicker table tr td span.active.active, +.datetimepicker table tr td span.active:hover.active, +.datetimepicker table tr td span.active.disabled.active, +.datetimepicker table tr td span.active.disabled:hover.active { + background-color: #003399; +} + +.datetimepicker table tr td span.old { + color: #999999; +} + +.datetimepicker th.switch { + width: 145px; +} + +.datetimepicker th span.glyphicon { + pointer-events: none; +} + +.datetimepicker thead tr:first-child th, +.datetimepicker tfoot th { + cursor: pointer; +} + +.datetimepicker thead tr:first-child th:hover, +.datetimepicker tfoot th:hover { + background: #eeeeee; +} + +.input-append.date .add-on i, +.input-prepend.date .add-on i, +.input-group.date .input-group-addon span { + cursor: pointer; + width: 14px; + height: 14px; +} diff --git a/config/routes.rb b/config/routes.rb index b2037ff78..80e1298cc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -787,7 +787,7 @@ Rails.application.routes.draw do resources :competitions, only: [:index, :show, :update] do resources :competition_modules, only: [:index, :show, :update] resource :competition_staff - resources :competition_teams, only: [:index, :show] do + resources :competition_teams, only: [:index, :show, :create, :update] do post :join, on: :collection post :leave, on: :member get :course_detail, on: :member @@ -854,6 +854,7 @@ Rails.application.routes.draw do resource :register, only: [:create] resource :code_session, only: [:create] resource :verify, only: [:create] + resource :check_account, only: [:create] resources :searchs, only: [:index] end @@ -1022,8 +1023,21 @@ Rails.application.routes.draw do post :hot_setting end - resources :competition_settings, only: [:index, :update] - resources :enroll_lists, only: [:index] + resources :competition_settings, only: [:index] do + post :basic_setting, on: :collection + end + + resources :enroll_lists, only: [:index] do + get :export, on: :collection + end + + resources :competition_stages, only: [:create, :update, :destroy] do + collection do + post :create_stage_section + post :update_stage_section + delete :destroy_stage_section + end + end end resources :weapp_carousels, only: [:index, :create, :update, :destroy] do diff --git a/db/migrate/20190426010412_add_is_invalid_to_student_works_scores.rb b/db/migrate/20190426010412_add_is_invalid_to_student_works_scores.rb index 7b893db6d..2d782f924 100644 --- a/db/migrate/20190426010412_add_is_invalid_to_student_works_scores.rb +++ b/db/migrate/20190426010412_add_is_invalid_to_student_works_scores.rb @@ -1,6 +1,6 @@ class AddIsInvalidToStudentWorksScores < ActiveRecord::Migration[5.2] def change - # add_column :student_works_scores, :is_invalid, :boolean, default: false + add_column :student_works_scores, :is_invalid, :boolean, default: false StudentWorksScore.where("score is not null").order("id desc").find_each do |score| unless score.is_invalid diff --git a/db/migrate/20191022030127_migrate_competition_score_stage_id.rb b/db/migrate/20191022030127_migrate_competition_score_stage_id.rb new file mode 100644 index 000000000..0eefbac48 --- /dev/null +++ b/db/migrate/20191022030127_migrate_competition_score_stage_id.rb @@ -0,0 +1,7 @@ +class MigrateCompetitionScoreStageId < ActiveRecord::Migration[5.2] + def change + change_column_default :competition_scores, :competition_stage_id, 0 + + CompetitionScore.where("competition_stage_id is null").update_all(competition_stage_id: 0) + end +end diff --git a/db/migrate/20191022075223_migrate_competition_mode_default.rb b/db/migrate/20191022075223_migrate_competition_mode_default.rb new file mode 100644 index 000000000..d61d4aa68 --- /dev/null +++ b/db/migrate/20191022075223_migrate_competition_mode_default.rb @@ -0,0 +1,6 @@ +class MigrateCompetitionModeDefault < ActiveRecord::Migration[5.2] + def change + change_column_default :competitions, :mode, from: 0, to: 1 + Competition.all.update_all(mode: 1) + end +end diff --git a/db/migrate/20191022100044_add_awards_count_to_competition.rb b/db/migrate/20191022100044_add_awards_count_to_competition.rb new file mode 100644 index 000000000..ef6657ae6 --- /dev/null +++ b/db/migrate/20191022100044_add_awards_count_to_competition.rb @@ -0,0 +1,5 @@ +class AddAwardsCountToCompetition < ActiveRecord::Migration[5.2] + def change + add_column :competitions, :awards_count, :integer, default: 0 + end +end diff --git a/db/migrate/20191023074837_migrate_competition_module_type.rb b/db/migrate/20191023074837_migrate_competition_module_type.rb new file mode 100644 index 000000000..009b65cc9 --- /dev/null +++ b/db/migrate/20191023074837_migrate_competition_module_type.rb @@ -0,0 +1,28 @@ +class MigrateCompetitionModuleType < ActiveRecord::Migration[5.2] + def change + add_column :competition_modules, :module_type, :string + + Competition.all.each do |competition| + competition.competition_modules.each do |com_module| + mod_type = "" + case com_module.name + when '首页' + mod_type = "home" + when '报名' + mod_type = "enroll" + when '通知公告' + mod_type = "inform" + when '参赛手册' + mod_type = "manual" + when '排行榜' + mod_type = "chart" + when '资料下载 ' + mod_type = "resource" + else + mod_type = "md" + end + com_module.update_attributes!(module_type: mod_type) + end + end + end +end diff --git a/db/migrate/20191023103633_add_column_to_stage_sections.rb b/db/migrate/20191023103633_add_column_to_stage_sections.rb new file mode 100644 index 000000000..baa1754fa --- /dev/null +++ b/db/migrate/20191023103633_add_column_to_stage_sections.rb @@ -0,0 +1,10 @@ +class AddColumnToStageSections < ActiveRecord::Migration[5.2] + def change + def change + add_column :competition_stage_sections, :mission_count, :integer, default: 0 + add_column :competition_stage_sections, :score_source, :integer, default: 0 + + add_column :competition_entries, :shixun_identifier, :string + end + end +end diff --git a/public/images/educoder/competitions/Noentry.jpg b/public/images/educoder/competitions/Noentry.jpg new file mode 100644 index 000000000..5ffc34e17 Binary files /dev/null and b/public/images/educoder/competitions/Noentry.jpg differ diff --git a/public/images/educoder/competitions/Rectanglex.png b/public/images/educoder/competitions/Rectanglex.png new file mode 100755 index 000000000..0aa2a31b1 Binary files /dev/null and b/public/images/educoder/competitions/Rectanglex.png differ diff --git a/public/react/src/modules/competitions/competitimain/courses.jpg b/public/images/educoder/competitions/courses.jpg similarity index 100% rename from public/react/src/modules/competitions/competitimain/courses.jpg rename to public/images/educoder/competitions/courses.jpg diff --git a/public/images/educoder/competitions/groups1.png b/public/images/educoder/competitions/groups1.png new file mode 100644 index 000000000..eee9489f4 Binary files /dev/null and b/public/images/educoder/competitions/groups1.png differ diff --git a/public/images/educoder/competitions/groups2.png b/public/images/educoder/competitions/groups2.png new file mode 100644 index 000000000..a75cecc30 Binary files /dev/null and b/public/images/educoder/competitions/groups2.png differ diff --git a/public/images/educoder/competitions/groups3.png b/public/images/educoder/competitions/groups3.png new file mode 100644 index 000000000..a0caeebd3 Binary files /dev/null and b/public/images/educoder/competitions/groups3.png differ diff --git a/public/images/educoder/competitions/pexjiazai.png b/public/images/educoder/competitions/pexjiazai.png new file mode 100644 index 000000000..78f56b82a Binary files /dev/null and b/public/images/educoder/competitions/pexjiazai.png differ diff --git a/public/images/educoder/competitions/tipregistit.jpg b/public/images/educoder/competitions/tipregistit.jpg new file mode 100644 index 000000000..8aae50232 Binary files /dev/null and b/public/images/educoder/competitions/tipregistit.jpg differ diff --git a/public/react/config/env.js b/public/react/config/env.js index aef6a8ff4..ae1edea65 100644 --- a/public/react/config/env.js +++ b/public/react/config/env.js @@ -9,20 +9,20 @@ delete require.cache[require.resolve('./paths')]; const NODE_ENV = process.env.NODE_ENV; if (!NODE_ENV) { - throw new Error( - 'The NODE_ENV environment variable is required but was not specified.' - ); + throw new Error( + 'The NODE_ENV environment variable is required but was not specified.' + ); } // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use var dotenvFiles = [ - `${paths.dotenv}.${NODE_ENV}.local`, - `${paths.dotenv}.${NODE_ENV}`, - // Don't include `.env.local` for `test` environment - // since normally you expect tests to produce the same - // results for everyone - NODE_ENV !== 'test' && `${paths.dotenv}.local`, - paths.dotenv, + `${paths.dotenv}.${NODE_ENV}.local`, + `${paths.dotenv}.${NODE_ENV}`, + // Don't include `.env.local` for `test` environment + // since normally you expect tests to produce the same + // results for everyone + NODE_ENV !== 'test' && `${paths.dotenv}.local`, + paths.dotenv, ].filter(Boolean); // Load environment variables from .env* files. Suppress warnings using silent @@ -31,13 +31,13 @@ var dotenvFiles = [ // https://github.com/motdotla/dotenv // https://github.com/motdotla/dotenv-expand dotenvFiles.forEach(dotenvFile => { - if (fs.existsSync(dotenvFile)) { - require('dotenv-expand')( - require('dotenv').config({ - path: dotenvFile, - }) - ); - } + if (fs.existsSync(dotenvFile)) { + require('dotenv-expand')( + require('dotenv').config({ + path: dotenvFile, + }) + ); + } }); // We support resolving modules according to `NODE_PATH`. @@ -51,43 +51,43 @@ dotenvFiles.forEach(dotenvFile => { // We also resolve them to make sure all tools using them work consistently. const appDirectory = fs.realpathSync(process.cwd()); process.env.NODE_PATH = (process.env.NODE_PATH || '') - .split(path.delimiter) - .filter(folder => folder && !path.isAbsolute(folder)) - .map(folder => path.resolve(appDirectory, folder)) - .join(path.delimiter); + .split(path.delimiter) + .filter(folder => folder && !path.isAbsolute(folder)) + .map(folder => path.resolve(appDirectory, folder)) + .join(path.delimiter); // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be // injected into the application via DefinePlugin in Webpack configuration. const REACT_APP = /^REACT_APP_/i; function getClientEnvironment(publicUrl) { - const raw = Object.keys(process.env) - .filter(key => REACT_APP.test(key)) - .reduce( - (env, key) => { - env[key] = process.env[key]; - return env; - }, - { - // Useful for determining whether we’re running in production mode. - // Most importantly, it switches React into the correct mode. - NODE_ENV: process.env.NODE_ENV || 'development', - // Useful for resolving the correct path to static assets in `public`. - // For example, . - // This should only be used as an escape hatch. Normally you would put - // images into the `src` and `import` them in code to get their paths. - PUBLIC_URL: '/react/build/.', - } - ); - // Stringify all values so we can feed into Webpack DefinePlugin - const stringified = { - 'process.env': Object.keys(raw).reduce((env, key) => { - env[key] = JSON.stringify(raw[key]); - return env; - }, {}), - }; + const raw = Object.keys(process.env) + .filter(key => REACT_APP.test(key)) + .reduce( + (env, key) => { + env[key] = process.env[key]; + return env; + }, + { + // Useful for determining whether we’re running in production mode. + // Most importantly, it switches React into the correct mode. + NODE_ENV: process.env.NODE_ENV || 'development', + // Useful for resolving the correct path to static assets in `public`. + // For example, . + // This should only be used as an escape hatch. Normally you would put + // images into the `src` and `import` them in code to get their paths. + PUBLIC_URL: '/react/build/.', + } + ); + // Stringify all values so we can feed into Webpack DefinePlugin + const stringified = { + 'process.env': Object.keys(raw).reduce((env, key) => { + env[key] = JSON.stringify(raw[key]); + return env; + }, {}), + }; - return { raw, stringified }; + return { raw, stringified }; } module.exports = getClientEnvironment; diff --git a/public/react/config/webpack.config.dev.js b/public/react/config/webpack.config.dev.js index ef38a18f8..e96f22663 100644 --- a/public/react/config/webpack.config.dev.js +++ b/public/react/config/webpack.config.dev.js @@ -32,7 +32,7 @@ module.exports = { // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s // devtool: "cheap-module-eval-source-map", // 开启调试 - //devtool: "source-map", // 开启调试 + devtool: "source-map", // 开启调试 // These are the "entry points" to our application. // This means they will be the "root" imports that are included in JS bundle. // The first two entry points enable "hot" CSS and auto-refreshes for JS. diff --git a/public/react/config/webpack.config.prod.js b/public/react/config/webpack.config.prod.js index 33c778d45..886d97313 100644 --- a/public/react/config/webpack.config.prod.js +++ b/public/react/config/webpack.config.prod.js @@ -33,7 +33,7 @@ const env = getClientEnvironment(publicUrl); // Assert this just to be safe. // Development builds of React are slow and not intended for production. if (env.stringified['process.env'].NODE_ENV !== '"production"') { - throw new Error('Production builds must have NODE_ENV=production.'); + throw new Error('Production builds must have NODE_ENV=production.'); } // Note: defined here because it will be used more than once. @@ -44,9 +44,9 @@ const cssFilename = './static/css/[name].[contenthash:8].css'; // However, our output is structured with css, js and media folders. // To have this structure working with relative paths, we have to use custom options. const extractTextPluginOptions = shouldUseRelativeAssetPaths - ? // Making sure that the publicPath goes back to to build folder. - { publicPath: Array(cssFilename.split('/').length).join('../') } - : {}; + ? // Making sure that the publicPath goes back to to build folder. + { publicPath: Array(cssFilename.split('/').length).join('../') } + : {}; // This is the production configuration. // It compiles slowly and is focused on producing a fast and minimal bundle. @@ -54,332 +54,331 @@ const extractTextPluginOptions = shouldUseRelativeAssetPaths // 上线用的 // console.log('publicPath ', publicPath) module.exports = { - // externals: { - // 'react': 'window.React' - // }, - // Don't attempt to continue if there are any errors. - bail: true, - // We generate sourcemaps in production. This is slow but gives good results. - // You can exclude the *.map files from the build during deployment. - // devtool: shouldUseSourceMap ? 'nosources-source-map' : false, //正式版 - devtool: shouldUseSourceMap ? 'source-map' : false,//测试版 - // In production, we only want to load the polyfills and the app code. - entry: [require.resolve('./polyfills'), paths.appIndexJs], - output: { - // The build folder. - path: paths.appBuild, - // Generated JS file names (with nested folders). - // There will be one main bundle, and one file per asynchronous chunk. - // We don't currently advertise code splitting but Webpack supports it. - filename: './static/js/[name].[chunkhash:8].js', - chunkFilename: './static/js/[name].[chunkhash:8].chunk.js', - // We inferred the "public path" (such as / or /my-project) from homepage. - // cdn - // publicPath: 'https://shixun.educoder.net/react/build/', //publicPath, https://cdn.educoder.net - // publicPath: 'https://cdn-testeduplus2.educoder.net/react/build/', //publicPath, https://cdn.educoder.net - publicPath: '/react/build/', //publicPath, https://cdn.educoder.net - - // Point sourcemap entries to original disk location (format as URL on Windows) - devtoolModuleFilenameTemplate: info => - path - .relative(paths.appSrc, info.absoluteResourcePath) - .replace(/\\/g, '/'), - }, - resolve: { - // This allows you to set a fallback for where Webpack should look for modules. - // We placed these paths second because we want `node_modules` to "win" - // if there are any conflicts. This matches Node resolution mechanism. - // https://github.com/facebookincubator/create-react-app/issues/253 - modules: ['node_modules', paths.appNodeModules].concat( - // It is guaranteed to exist because we tweak it in `env.js` - process.env.NODE_PATH.split(path.delimiter).filter(Boolean) - ), - // These are the reasonable defaults supported by the Node ecosystem. - // We also include JSX as a common component filename extension to support - // some tools, although we do not recommend using it, see: - // https://github.com/facebookincubator/create-react-app/issues/290 - // `web` extension prefixes have been added for better support - // for React Native Web. - extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'], - alias: { - "educoder": __dirname + "/../src/common/educoder.js", - // Support React Native Web - // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ - 'react-native': 'react-native-web', - }, - plugins: [ - // Prevents users from importing files from outside of src/ (or node_modules/). - // This often causes confusion because we only process files within src/ with babel. - // To fix this, we prevent you from importing files out of src/ -- if you'd like to, - // please link the files into your node_modules/ and let module-resolution kick in. - // Make sure your source files are compiled, as they will not be processed in any way. - new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]), - ], - }, - module: { - strictExportPresence: true, - rules: [ - // TODO: Disable require.ensure as it's not a standard language feature. - // We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176. - // { parser: { requireEnsure: false } }, + // externals: { + // 'react': 'window.React' + // }, + // Don't attempt to continue if there are any errors. + bail: true, + // We generate sourcemaps in production. This is slow but gives good results. + // You can exclude the *.map files from the build during deployment. + // devtool: shouldUseSourceMap ? 'nosources-source-map' : false, //正式版 + devtool:false,//测试版 + // In production, we only want to load the polyfills and the app code. + entry: [require.resolve('./polyfills'), paths.appIndexJs], + output: { + // The build folder. + path: paths.appBuild, + // Generated JS file names (with nested folders). + // There will be one main bundle, and one file per asynchronous chunk. + // We don't currently advertise code splitting but Webpack supports it. + filename: './static/js/[name].[chunkhash:8].js', + chunkFilename: './static/js/[name].[chunkhash:8].chunk.js', + // We inferred the "public path" (such as / or /my-project) from homepage. + // cdn + // publicPath: 'https://shixun.educoder.net/react/build/', //publicPath, https://cdn.educoder.net + // publicPath: 'https://cdn-testeduplus2.educoder.net/react/build/', //publicPath, https://cdn.educoder.net + publicPath: '/react/build/', //publicPath, https://cdn.educoder.net - // First, run the linter. - // It's important to do this before Babel processes the JS. - { - test: /\.(js|jsx|mjs)$/, - enforce: 'pre', - use: [ - { - options: { - formatter: eslintFormatter, - eslintPath: require.resolve('eslint'), + // Point sourcemap entries to original disk location (format as URL on Windows) + devtoolModuleFilenameTemplate: info => + path + .relative(paths.appSrc, info.absoluteResourcePath) + .replace(/\\/g, '/'), + }, + resolve: { + // This allows you to set a fallback for where Webpack should look for modules. + // We placed these paths second because we want `node_modules` to "win" + // if there are any conflicts. This matches Node resolution mechanism. + // https://github.com/facebookincubator/create-react-app/issues/253 + modules: ['node_modules', paths.appNodeModules].concat( + // It is guaranteed to exist because we tweak it in `env.js` + process.env.NODE_PATH.split(path.delimiter).filter(Boolean) + ), + // These are the reasonable defaults supported by the Node ecosystem. + // We also include JSX as a common component filename extension to support + // some tools, although we do not recommend using it, see: + // https://github.com/facebookincubator/create-react-app/issues/290 + // `web` extension prefixes have been added for better support + // for React Native Web. + extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'], + alias: { + "educoder": __dirname + "/../src/common/educoder.js", + // Support React Native Web + // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ + 'react-native': 'react-native-web', + }, + plugins: [ + // Prevents users from importing files from outside of src/ (or node_modules/). + // This often causes confusion because we only process files within src/ with babel. + // To fix this, we prevent you from importing files out of src/ -- if you'd like to, + // please link the files into your node_modules/ and let module-resolution kick in. + // Make sure your source files are compiled, as they will not be processed in any way. + new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]), + ], + }, + module: { + strictExportPresence: true, + rules: [ + // TODO: Disable require.ensure as it's not a standard language feature. + // We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176. + // { parser: { requireEnsure: false } }, - }, - loader: require.resolve('eslint-loader'), - }, - ], - include: paths.appSrc, - }, - { - // "oneOf" will traverse all following loaders until one will - // match the requirements. When no loader matches it will fall - // back to the "file" loader at the end of the loader list. - oneOf: [ - // "url" loader works just like "file" loader but it also embeds - // assets smaller than specified size as data URLs to avoid requests. - { - test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], - loader: require.resolve('url-loader'), - options: { - limit: 10000, - name: 'static/media/[name].[hash:8].[ext]', - }, - }, - // Process JS with Babel. - { - test: /\.(js|jsx|mjs)$/, - include: paths.appSrc, - loader: require.resolve('babel-loader'), - options: { - - compact: true, - }, - }, - // The notation here is somewhat confusing. - // "postcss" loader applies autoprefixer to our CSS. - // "css" loader resolves paths in CSS and adds assets as dependencies. - // "style" loader normally turns CSS into JS modules injecting ")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var l=function(){document.removeEventListener("DOMContentLoaded",l,!1),c()};document.addEventListener("DOMContentLoaded",l,!1)}else document.attachEvent&&(a=c,i=z.document,t=!1,(o=function(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(o,50)}h()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,h())});function h(){t||(t=!0,a())}var a,i,t,o}(function(){var c,l;(c=document.createElement("div")).innerHTML=h,h=null,(l=c.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",function(c,l){l.firstChild?function(c,l){l.parentNode.insertBefore(c,l)}(c,l.firstChild):l.appendChild(c)}(l,document.body))})}(window); \ No newline at end of file +!function(o){var c,h='',l=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss");if(l&&!o.__iconfont__svg__cssinject__){o.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var l=function(){document.removeEventListener("DOMContentLoaded",l,!1),c()};document.addEventListener("DOMContentLoaded",l,!1)}else document.attachEvent&&(a=c,i=o.document,t=!1,(z=function(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(z,50)}h()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,h())});function h(){t||(t=!0,a())}var a,i,t,z}(function(){var c,l;(c=document.createElement("div")).innerHTML=h,h=null,(l=c.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",function(c,l){l.firstChild?function(c,l){l.parentNode.insertBefore(c,l)}(c,l.firstChild):l.appendChild(c)}(l,document.body))})}(window); \ No newline at end of file diff --git a/public/react/public/css/iconfont.json b/public/react/public/css/iconfont.json index 1a21d0726..2cfdd7e3d 100644 --- a/public/react/public/css/iconfont.json +++ b/public/react/public/css/iconfont.json @@ -1230,6 +1230,13 @@ "unicode": "e669", "unicode_decimal": 58985 }, + { + "icon_id": "5255211", + "name": "复制", + "font_class": "fuzhi1", + "unicode": "e800", + "unicode_decimal": 59392 + }, { "icon_id": "5291605", "name": "更多", @@ -1530,6 +1537,34 @@ "font_class": "nenghaofenxix", "unicode": "e6be", "unicode_decimal": 59070 + }, + { + "icon_id": "11408531", + "name": "detection@1x", + "font_class": "detectionx", + "unicode": "e6c1", + "unicode_decimal": 59073 + }, + { + "icon_id": "11409495", + "name": "community@1x", + "font_class": "communityx", + "unicode": "e6c2", + "unicode_decimal": 59074 + }, + { + "icon_id": "11409771", + "name": "hosting@1x", + "font_class": "hostingx2", + "unicode": "e6c3", + "unicode_decimal": 59075 + }, + { + "icon_id": "11410432", + "name": "project@1x", + "font_class": "projectx", + "unicode": "e6c4", + "unicode_decimal": 59076 } ] } diff --git a/public/react/public/css/iconfont.svg b/public/react/public/css/iconfont.svg index e9aa3e2f9..f2f298f58 100644 --- a/public/react/public/css/iconfont.svg +++ b/public/react/public/css/iconfont.svg @@ -544,7 +544,12 @@ Created by iconfont - + + + + @@ -673,8 +678,26 @@ Created by iconfont - + + + + + + + + + + + - + diff --git a/public/react/public/css/iconfont.ttf b/public/react/public/css/iconfont.ttf index bf316a765..cef43d726 100644 Binary files a/public/react/public/css/iconfont.ttf and b/public/react/public/css/iconfont.ttf differ diff --git a/public/react/public/css/iconfont.woff b/public/react/public/css/iconfont.woff index b06206850..27daa6142 100644 Binary files a/public/react/public/css/iconfont.woff and b/public/react/public/css/iconfont.woff differ diff --git a/public/react/public/css/iconfont.woff2 b/public/react/public/css/iconfont.woff2 index 374af4f2a..0bbea822f 100644 Binary files a/public/react/public/css/iconfont.woff2 and b/public/react/public/css/iconfont.woff2 differ diff --git a/public/react/src/App.js b/public/react/src/App.js index b6c661597..5988d3532 100644 --- a/public/react/src/App.js +++ b/public/react/src/App.js @@ -76,10 +76,10 @@ const Otherloginstart=Loadable({ loading: Loading, }) -const TestIndex = Loadable({ - loader: () => import('./modules/test'), - loading: Loading, -}) +// const TestIndex = Loadable({ +// loader: () => import('./modules/test'), +// loading: Loading, +// }) const IndexWrapperComponent = Loadable({ loader: () => import('./modules/page/IndexWrapper'), @@ -91,23 +91,23 @@ const CommentComponent = Loadable({ loading: Loading, }) -const TestMaterialDesignComponent = Loadable({ - loader: () => import('./modules/test/md/TestMaterialDesign'), - loading: Loading, -}) -const TestCodeMirrorComponent = Loadable({ - loader: () => import('./modules/test/codemirror/TestCodeMirror'), - loading: Loading, -}) +// const TestMaterialDesignComponent = Loadable({ +// loader: () => import('./modules/test/md/TestMaterialDesign'), +// loading: Loading, +// }) +// const TestCodeMirrorComponent = Loadable({ +// loader: () => import('./modules/test/codemirror/TestCodeMirror'), +// loading: Loading, +// }) -const TestComponent = Loadable({ - loader: () => import('./modules/test/TestRC'), - loading: Loading, -}) -const TestUrlQueryComponent = Loadable({ - loader: () => import('./modules/test/urlquery/TestUrlQuery'), - loading: Loading, -}) +// const TestComponent = Loadable({ +// loader: () => import('./modules/test/TestRC'), +// loading: Loading, +// }) +// const TestUrlQueryComponent = Loadable({ +// loader: () => import('./modules/test/urlquery/TestUrlQuery'), +// loading: Loading, +// }) const TPMIndexComponent = Loadable({ loader: () => import('./modules/tpm/TPMIndex'), @@ -254,10 +254,10 @@ const Interestpage = Loadable({ }) //众包创新 -const ProjectPackages=Loadable({ - loader: () => import('./modules/projectPackages/ProjectPackageIndex'), - loading: Loading, -}) +// const ProjectPackages=Loadable({ +// loader: () => import('./modules/projectPackages/ProjectPackageIndex'), +// loading: Loading, +// }) //竞赛 const NewCompetitions=Loadable({ @@ -285,6 +285,12 @@ const Ecs = Loadable({ loading: Loading, }) + +// //个人竞赛报名 +// const PersonalCompetit = Loadable({ +// loader: () => import('./modules/competition/personal/PersonalCompetit.js'), +// loading: Loading, +// }); class App extends Component { constructor(props) { super(props) @@ -477,10 +483,17 @@ class App extends Component { return () } }> - {/*众包创新*/} - + {/*/!*众包创新*!/*/} + {/**/} {/*竞赛*/} - + { + + return () + } + }> + {/*认证*/} @@ -531,7 +544,12 @@ class App extends Component { return () } }> - + {/* ()*/} + {/*}*/} + {/*/>*/} - - - - - + {/**/} + {/**/} + {/**/} + {/**/} + {/**/} + {/* ()*/} + {/*}*/} + {/*/>*/} + () @@ -601,6 +626,7 @@ class App extends Component { render={ (props)=>() }/> + /g, ">"); + s = s.replace(/ /g, " "); + s = s.replace(/\'/g, "'");//IE下不支持实体名称 + s = s.replace(/\"/g, """); + return s; +} \ No newline at end of file diff --git a/public/react/src/common/educoder.js b/public/react/src/common/educoder.js index ec4659de7..73c707c9b 100644 --- a/public/react/src/common/educoder.js +++ b/public/react/src/common/educoder.js @@ -4,7 +4,7 @@ import { from } from '_array-flatten@2.1.2@array-flatten'; export { getImageUrl as getImageUrl, getUrl as getUrl, getUrl2 as getUrl2, setImagesUrl as setImagesUrl , getUploadActionUrl as getUploadActionUrl, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth - , getTaskUrlById as getTaskUrlById, TEST_HOST } from './UrlTool'; + , getTaskUrlById as getTaskUrlById, TEST_HOST ,htmlEncode as htmlEncode } from './UrlTool'; export { default as queryString } from './UrlTool2'; export { SnackbarHOC as SnackbarHOC } from './SnackbarHOC'; diff --git a/public/react/src/modules/competition/CompetitionMaxImg.js b/public/react/src/modules/competition/CompetitionMaxImg.js new file mode 100644 index 000000000..c5d99a88b --- /dev/null +++ b/public/react/src/modules/competition/CompetitionMaxImg.js @@ -0,0 +1,127 @@ +import React, {Component} from 'react'; +import competition from './comcss/competition.css'; +import {getImageUrl} from 'educoder'; +// 团队竞赛报名大图 +class CompetitionMaxImg extends React.Component { + constructor(props) { + super(props) + this.state = { + GetenrollmentAPI: undefined + } + } + + componentDidMount() { + + } + + componentDidUpdate = (prevProps) => { + if (prevProps.GetenrollmentAPI != this.props.GetenrollmentAPI) { + // ////console.log("团队竞赛报名大图componentDidUpdate"); + // ////console.log(this.props); + // ////console.log(this.props.GetenrollmentAPI); + this.setState({ + GetenrollmentAPI: this.props.GetenrollmentAPI, + }) + } + } + + render() { + let {type, pint} = this.props; + return ( +
+ + { + type === 1 || type === 2 ? +
+

Educoder竞赛平台

+

Educoder是一个面向计算机类的互联网IT教育和实战平台,

+

提供企业级工程实训,以实现工程化专业教学的自动化和智能化。

+
+
+

this.props.Jointheteam()}>加入战队

+
+
+

this.props.Createateam()}>创建战队

+
+ +
+
+ : + type === 3 ? +
+

Educoder竞赛平台

+

高校智能课堂与综合实训平台

+
+
+

this.props.Jointheteam()}>加入战队

+
+
+

this.props.Createateam()}>创建战队

+
+ +
+
+ : + type === 4 || type === 5 ? +
+

Educoder竞赛平台

+

高校智能课堂与综合实训平台

+
+
+

this.props.Jointheteam()}>加入战队

+
+
+

this.props.Createateam()}>创建战队

+
+ +
+
+ : type === 6 ? +
+

Educoder竞赛平台

+

Educoder是一个面向计算机类的互联网IT教育和实战平台,

+

提供企业级工程实训,以实现工程化专业教学的自动化和智能化。

+
+ { + pint === 1 ? +
this.props.Personalregistration()}> +

this.props.Personalregistration()}>立即报名

+
+ : pint === 2 ? +
+

已报名

+
+ : +
+

报名已截止

+
+ } + +
+
+ : +
+
+ } + + +
+ + ) + } + +} + +export default CompetitionMaxImg; diff --git a/public/react/src/modules/competition/RegisListview.js b/public/react/src/modules/competition/RegisListview.js new file mode 100644 index 000000000..a1c283220 --- /dev/null +++ b/public/react/src/modules/competition/RegisListview.js @@ -0,0 +1,50 @@ +import React, {Component} from 'react'; +import { + BrowserRouter as Router, + Route, + Switch +} from 'react-router-dom'; +import axios from 'axios'; +import moment from 'moment'; +import competition from './comcss/competition.css'; +import {Checkbox, Table, Pagination, Menu, Icon} from "antd"; +import {getImageUrl} from 'educoder'; +// 团队竞赛报名无报名子组件团队 在线竞赛 > 全国高校计算机大赛-项目挑战> +class RegisListview extends React.Component { + constructor(props) { + super(props) + + } + + + render() { + return ( +
+
+

创建者

+

战队名称

+

战队成员

+

学校

+

时间

+
+
+ ) + } + +} + +export default RegisListview; diff --git a/public/react/src/modules/competition/RegisListviewdata.js b/public/react/src/modules/competition/RegisListviewdata.js new file mode 100644 index 000000000..44fde6a4b --- /dev/null +++ b/public/react/src/modules/competition/RegisListviewdata.js @@ -0,0 +1,144 @@ +import React, {Component} from 'react'; +import { + BrowserRouter as Router, + Route, + Switch +} from 'react-router-dom'; +import axios from 'axios'; +import moment from 'moment'; +import {SnackbarHOC, WordsBtn, getImageUrl} from 'educoder'; +import {TPMIndexHOC} from '../tpm/TPMIndexHOC'; +import competition from './comcss/competition.css'; +import {Button} from 'antd'; + +// 团队竞赛报名无报名子组件团队 竞赛报名-已创建战队 +class RegisListviewdata extends React.Component { + constructor(props) { + super(props) + this.state = { + item: undefined + } + + } + + componentDidMount() { + ////console.log("RegisListviewdata"); + ////console.log(this.props.item) + this.setState({ + item: this.props.item + }) + + } + render() { + const {item} = this.props; + return ( + +
+ { + item !== undefined ? +
+
+ +
+ + + +

{item.creator.name}

+
+
+

{item.name}

+
+
+ + { + item && item.team_members.map((item, index) => { + return ( + + index === 0 ? + + + + : index === 1 ? + + + + : index === 2 ? + + + + : index === 3 ? + + + + : index === 4 ? + + + + : index === 5 ? +
+ + + + + +
+ : "" + + ) + }) + } +
+
+

{item.school_name}

+
+
+

{item.created_at}

+
+
+
+ : "" + } +
+ + + ) + } + +} + +export default RegisListviewdata; diff --git a/public/react/src/modules/competition/RegisNodata.js b/public/react/src/modules/competition/RegisNodata.js new file mode 100644 index 000000000..a8441f420 --- /dev/null +++ b/public/react/src/modules/competition/RegisNodata.js @@ -0,0 +1,34 @@ +import React, {Component} from 'react'; +import competition from './comcss/competition.css'; +import {getImageUrl} from 'educoder'; +// 团队竞赛报名无报名子组件 +class RegisNodata extends React.Component { + constructor(props) { + super(props) + + + } + + + render() { + return ( +
+
+ +
+

暂无战队参与报名哦,赶紧来成为第一个挑战的吧~

+
+ + ) + } + +} + +export default RegisNodata; diff --git a/public/react/src/modules/competition/Registration.js b/public/react/src/modules/competition/Registration.js new file mode 100644 index 000000000..9bffc492c --- /dev/null +++ b/public/react/src/modules/competition/Registration.js @@ -0,0 +1,797 @@ +import React, {Component} from 'react'; +import { + BrowserRouter as Router, + Route, + Switch +} from 'react-router-dom'; +import axios from 'axios'; +import moment from 'moment'; +import {SnackbarHOC, WordsBtn} from 'educoder'; +import {TPMIndexHOC} from '../tpm/TPMIndexHOC'; +import competition from './comcss/competition.css'; +import {Button, Pagination, message, Spin, Breadcrumb} from 'antd'; +import Registrationitem from './Registrationitem'; +import RegisNodata from './RegisNodata'; +import CompetitionMaxImg from './CompetitionMaxImg'; +import RegistrationSearch from './RegistrationSearch'; +import RegisListview from './RegisListview'; +import RegisListviewdata from './RegisListviewdata'; +import PersonModal from './competmodal/PersonModal'; +import MessagePersonModal from './competmodal/MessagePersonModal'; +import PersonalModalteam from './competmodal/PersonalModalteam'; +import PersonalCompetititem from './personal/PersonalCompetititem'; +import ExittheteamModel from './competmodal/ExittheteamModel'; +// 团队竞赛报名无报名 +class Registration extends React.Component { + /*** + *"personal": false, // 是否为个人赛 + *"enroll_ended": false, // 报名是否截止 + *"enrolled: false, // 是否已经报名 + *"teacher_staff": { // 为空表示不支持老师报名 + *"member_staff": { // 为空表示不支持学生报名 + * personal// 是否是个人赛 + * **/ + constructor(props) { + super(props) + this.state = { + loadingstate: false, + pages: 1, + limit: 20, + type: 7, + tmodalsType: false, + tmodalsTypes: false, + Newtit: true, + keyword: "", + page: 1, + per_page: 20, + data: [], + competition_teams: [], + count: 0, + GetenrollmentAPI: undefined, + personal: false, + enroll_ended: false, + enrolled: false, + teacher_staff: null, + member_staff: null, + messagePer: "提示", + messagePerbool: false, + intpermessages: "确认", + messageexit: "提示", + messageexitol: false, + exitintpermessages: "是否确认退出战队?", + itemid: undefined, + itemiddata: [], + pint: 0, + + + } + } + + componentDidMount() { + console.log(this.props); + + // //////console.log("componentDidMount Registration"); + // //// //////console.log("调用子组件 "); + // //////console.log(this.props.isAdmin()); + // //// //////console.log(this.props.isAdmin()) + try { + const {keyword, page, per_page} = this.state; + this.Getdata(keyword, page, per_page, this.props.user.admin); + this.GetenrollmentAPI(); + } catch (e) { + // const {keyword, page, per_page} = this.state; + // this.Getdata(keyword, page, per_page, this.props.isAdmin()); + // this.GetenrollmentAPI(); + } + } + + componentDidUpdate = (prevProps) => { + if (prevProps.user != this.props.user) { + console.log("componentDidUpdate"); + console.log(this.props); + ////console.log("Registration"); + ////console.log("componentDidUpdate"); + ////console.log(this.props.user.admin); + const {keyword, page, per_page} = this.state; + this.Getdata(keyword, page, per_page, this.props.user.admin); + this.GetenrollmentAPI(); + } + + } + + //获取报名配置API + GetenrollmentAPI = () => { + const url = `/competitions/${this.props.match.params.identifier}/competition_staff.json`; + axios.get((url)).then((result) => { + if (result) { + if (result.data) { + //// //////console.log("获取报名配置API"); + //// //////console.log(result); + this.setState({ + GetenrollmentAPI: result.data, + personal: result.data.personal, + enroll_ended: result.data.enroll_ended, + enrolled: result.data.enrolled, + teacher_staff: result.data.teacher_staff, + member_staff: result.data.member_staff, + }) + if (result.data.enroll_ended === true) { + this.setState({ + pint: 0 + }) + } else if (result.data.enrolled === true) { + this.setState({ + pint: 2 + }) + } else if (result.data.enrolled === false) { + this.setState({ + pint: 1 + }) + } + } + } + }).catch((error) => { + //// //////console.log(error); + }) + } + + Getdata = (keyword, page, per_page, admin) => { + //搜索关键字 keyword + //页数 page + //分页 per_page + const datas = { + keyword: keyword, + page: page, + per_page: per_page, + }; + let url = `/competitions/${this.props.match.params.identifier}/competition_teams.json`; + axios.get((url), {params: datas}).then((result) => { + if (result) { + if (result.data) { + //// //////console.log(result);\ + if (result.data.personal === false) { + //不是个人赛 + if (result.data.my_teams.length === 0) { + // 没有创建数据的 + if (admin === true) { + //管理员 + this.setState({ + type: 4, + count: result.data.count, + data: result.data.my_teams, + competition_teams: result.data.competition_teams, + personal: result.data.personal, + }) + } else { + //普通账号 + this.setState({ + type: 1, + count: result.data.count, + data: result.data.my_teams, + competition_teams: result.data.competition_teams, + personal: result.data.personal, + }) + } + } else { + //有数据的 + + if (admin === true) { + if (result.data.my_teams[0].manage_permission === true) { + this.setState({ + type: 5, + data: result.data.my_teams, + count: result.data.count, + competition_teams: result.data.competition_teams, + personal: result.data.personal, + + }) + } else { + this.setState({ + type: 4, + data: result.data.my_teams, + count: result.data.count, + competition_teams: result.data.competition_teams, + personal: result.data.personal, + + }) + } + } else { + if (result.data.my_teams[0].manage_permission === true) { + //普通账号true 为创建了竞赛 + this.setState({ + type: 2, + data: result.data.my_teams, + count: result.data.count, + personal: result.data.personal, + + }) + } else { + //普通账号true 加入了竞赛 + this.setState({ + type: 3, + data: result.data.my_teams, + count: result.data.count, + personal: result.data.personal, + + }) + } + } + + } + } else { + this.setState({ + type: 6, + data: result.data.my_teams, + count: result.data.count, + competition_teams: result.data.competition_teams, + personal: result.data.personal, + + }) + + } + } + } + this.setState({ + loadingstate: false, + }) + }).catch((error) => { + if (admin === true) { + //管理员 + this.setState({ + type: 4, + count: 0, + competition_teams: [], + data: [], + loadingstate: false, + }) + } else { + //普通账号 + this.setState({ + type: 1, + count: 0, + competition_teams: [], + data: [], + loadingstate: false, + }) + } + }) + + } + + Getdatatype5 = (keyword, page, per_page, admin) => { + //搜索关键字 keyword + //页数 page + //分页 per_page + const datas = { + keyword: keyword, + page: page, + per_page: per_page, + }; + let url = `/competitions/${this.props.match.params.identifier}/competition_teams.json`; + axios.get((url), {params: datas}).then((result) => { + this.setState({ + loadingstate: false, + }) + if (result) { + if (result.data) { + //// //////console.log(result); + if (result.data.personal === false) { + //不是个人赛 + ////console.log("Getdatatype5"); + ////console.log(result.data.my_teams.length); + if (result.data.my_teams.length === 0) { + // 没有创建数据的 + //管理员 + ////console.log("a"); + ////console.log(this.state.competition_teams); + ////console.log(result.data.competition_teams); + this.setState({ + type: 4, + count: result.data.count, + competition_teams: result.data.competition_teams, + data: result.data.my_teams, + personal: result.data.personal, + + }) + } else { + //有数据的 + ////console.log("b"); + + if (result.data.my_teams[0].manage_permission === true) { + this.setState({ + type: 5, + data: result.data.my_teams, + count: result.data.count, + competition_teams: result.data.competition_teams, + personal: result.data.personal, + + + }) + } else { + ////console.log("c"); + + this.setState({ + type: 4, + data: result.data.my_teams, + count: result.data.count, + competition_teams: result.data.competition_teams, + personal: result.data.personal, + + }) + } + } + } else { + //团队赛 + //////console.log("d"); + + this.setState({ + type: 6, + data: result.data.my_teams, + count: result.data.count, + competition_teams: result.data.competition_teams, + personal: result.data.personal, + + }) + } + + } + } + + }).catch((error) => { + ////console.log("k"); + + ////console.log(error); + ////console.log("报错了"); + if (admin === true) { + //管理员 + this.setState({ + count: 0, + competition_teams: [], + data: [], + loadingstate: false, + }) + } else { + //普通账号 + this.setState({ + count: 0, + competition_teams: [], + data: [], + loadingstate: false, + }) + } + }) + } + + + //团队竞赛翻页 + paginationonChangestwo = (pageNumber) => { + this.setState({ + pages: pageNumber, + loadingstate: true, + }) + const {keyword, per_page} = this.state; + this.Getdatatype5(keyword, pageNumber, per_page, this.props.user.admin); + + }; + /** + * 加入战队 + * */ + Jointheteam = () => { + if (this.state.enrolled === true) { + //已经报名 + this.setState({ + messagePerbool: true, + intpermessages: "您已报名,无需重复报" + }) + return; + } + if (this.state.enroll_ended === true) { + //报名截止 + this.setState({ + messagePerbool: true, + intpermessages: "报名已截止,无需报名" + }) + return + } + if (this.props.user.admin === true) { + //老师 + if (this.state.teacher_staff === null) { + //禁止老师 + this.setState({ + messagePerbool: true, + intpermessages: "已禁止老师报名" + }) + return; + } + this.setState({ + tmodalsTypes: true + }) + } else { + //学生 + if (this.state.member_staff === null) { + //禁止学生 + this.setState({ + messagePerbool: true, + intpermessages: "已禁止学生报名" + }) + return; + } + this.setState({ + tmodalsTypes: true + }) + } + // this.setState({ + // tmodalsTypes: true + // }) + + } + + /** + * 创建战队 + **/ + Createateam = () => { + // + if (this.state.enrolled === true) { + //已经报名 + this.setState({ + messagePerbool: true, + intpermessages: "您已报名,无需重复报" + }) + return; + } + if (this.state.enroll_ended === true) { + //报名截止 + this.setState({ + messagePerbool: true, + intpermessages: "报名已截止,无需报名" + }) + return + } + if (this.props.user.admin === true) { + //老师 + if (this.state.teacher_staff === null) { + //禁止老师 + this.setState({ + messagePerbool: true, + intpermessages: "已禁止老师报名" + }) + return; + } + this.setState({ + tmodalsType: true, + Newtit: true, + }) + } else { + //学生 + if (this.state.member_staff === null) { + //禁止学生 + this.setState({ + messagePerbool: true, + intpermessages: "已禁止学生报名" + }) + return; + } + this.setState({ + tmodalsType: true, + Newtit: true, + }) + } + } + + //编辑战队 + Createateamedit = (data) => { + this.setState({ + tmodalsType: true, + Newtit: false, + itemiddata: data + }) + } + Tmoconfirm = (bool) => { + //boolfalse 取消 true 确认 + this.setState({ + tmodalsTypes: false + }) + if (bool) { + //确认 + + + } else { + //取消 + + + } + } + + //创建战队确认 + Tmoconfirm1 = (bool) => { + //boolfalse 取消 true 确认 + this.setState({ + tmodalsType: false + }) + if (bool) { + //确认 + this.Refreshteam(); + } else { + //取消 + + + } + } + + //自定义弹框按钮 + messagePerboolbuton = () => { + this.setState({ + messagePerbool: false + }) + } + //显示退出战队弹框 + Exittheteamshow = (itemid, bool) => { + if (bool === true) { + this.setState({ + messageexitol: true, + itemid: itemid, + exitintpermessages: "是否确认删除战队", + }) + } else { + this.setState({ + messageexitol: true, + itemid: itemid, + exitintpermessages: "是否确认退出战队", + }) + } + + + }; + //刷新战队 + Refreshteam = () => { + const {keyword, page, per_page} = this.state; + this.Getdata(keyword, page, per_page, this.props.user.admin); + this.GetenrollmentAPI(); + } + //退出战队 + Exittheteam = (bool) => { + // //////console.log(this.state.itemid); + if (bool) { + this.setState({ + messageexitol: true + }) + + let url = `/competitions/${"gcc-task-2020"}/competition_teams/${this.state.itemid}/leave.json`; + axios.post(url).then((response) => { + if (response) { + if (response.data) { + //////console.log("退出战队"); + //////console.log(response); + this.Refreshteam(); + this.setState({ + messageexitol: false + }) + + } + } + }).catch((error) => { + //////console.log(error) + }); + + } else { + this.setState({ + messageexitol: false + }) + } + } + //搜索战队 + RegistrationSearchvalue = (value) => { + ////console.log("RegistrationSearchvalue"); + ////console.log(this.props.user.admin); + this.setState({ + pages: 1, + limit: 20, + }) + this.Getdatatype5(value, 1, 20, this.props.user.admin); + } + + //个人竞赛 +// /competitions/:identifier/competition_teams.json + Personalregistration = () => { + let {teacher_staff, member_staff, data, enroll_ended, enrolled} = this.state; + if (enroll_ended === true) { + //已截止 + this.props.showNotification(`报名已截止`); + return; + } + if (enrolled === true) { + this.props.showNotification(`你已经报名,不能重复报名!`); + return; + } + const url = `/competitions/${this.props.match.params.identifier}/competition_teams.json`; + axios.post(url).then((response) => { + if (response) { + if (response.data) { + this.props.showNotification(`报名成功,预祝您夺得桂冠!`); + this.Refreshteam(); + } + } + }).catch((error) => { + + }); + } + + + render() { + const {page, pages, limit, type, tmodalsType, tmodalsTypes, data, count, competition_teams, Newtit, itemiddata, messagePerbool, messageexitol, GetenrollmentAPI, loadingstate, pint} = this.state; + + return ( +
+ +
+ + { + messagePerbool === true ? + this.messagePerboolbuton()} + GetenrollmentAPI={GetenrollmentAPI}> + : "" + } + {/*编辑创建战队*/} + { + tmodalsType === true ? + this.Tmoconfirm1(bool)}> + : + "" + } + { + tmodalsTypes === true ? + this.Tmoconfirm(bool)}> + : "" + } + { + messageexitol === true ? + this.Exittheteam(bool)}> + : "" + } + + {/*
*/} + {/*

*/} + {/* 在线竞赛*/} + {/* >*/} + {/* 全国高校计算机大赛-项目挑战*/} + {/* >*/} + {/* 报名*/} + {/*

*/} + {/*
*/} +
+ + 在线竞赛 + 全国高校计算机大赛 + 报名 + +
+ {/*大图*/} + this.Jointheteam()} + pint={pint} + {...this.props} {...this.state} + Createateam={() => this.Createateam()} + Personalregistration={() => this.Personalregistration()} + > + {/*大图结尾*/} + {/*没数据*/} + { + pint === 1 || pint === 3 ? +
+

参赛总人数:{data === null || data === undefined ? 0 : data.length} +

+
+ : ""} + {/*列表*/} + { + type === 6 ? +
+ + { + data && data.map((item, index) => { + return ( + + ) + }) + } + + + +
+ : ""} + { + type === 1 ? + + : + "" + } + {/*普通账号出现单人 战队弹框*/} + { + type === 2 || type === 3 || type === 5 ? + this.Exittheteamshow(itemid)} + Createateamedit={(itemid) => this.Createateamedit(itemid)}> + : "" + } + + { + type === 4 || type === 5 ? + this.RegistrationSearchvalue(value)}> + : "" + } + {/**/} + { + type === 4 || type === 5 ? + + : + "" + } + + + {type === 4 || type === 5 ? + + { + competition_teams && competition_teams.map((item, index) => { + return ( + + ) + }) + } + + + : + "" + } + + { + type === 4 || type === 5 ? + ( + count < 20 ?
: +
+ +
+ ) + + :
+ } + +
+ +
+ ) + } + +} + +export default Registration; diff --git a/public/react/src/modules/competition/RegistrationSearch.js b/public/react/src/modules/competition/RegistrationSearch.js new file mode 100644 index 000000000..122366e0d --- /dev/null +++ b/public/react/src/modules/competition/RegistrationSearch.js @@ -0,0 +1,73 @@ +import React, {Component} from 'react'; +import { + BrowserRouter as Router, + Route, + Switch +} from 'react-router-dom'; +import axios from 'axios'; +import moment from 'moment'; +import competition from './comcss/competition.css'; +import {Checkbox, Input, Table, Pagination, Menu, Icon} from "antd"; + +const Search = Input.Search; + +// 团队竞赛报名无报名子组件团队 在线竞赛 > 全国高校计算机大赛-项目挑战> +class RegistrationSearch extends React.Component { + constructor(props) { + super(props) + this.state = { + keywords: "" + } + } + + setdatafunsval = (e) => { + this.setState({ + keywords: e.target.value + }) + + }; + setdatafuns = (value) => { + //console.log("setdatafuns点击了搜索"); + //console.log(value); + this.setState({ + keywords: value + }) + this.props.RegistrationSearchvalue(value); + }; + + myonPressEnter = (e) => { + //console.log("点击了回车setdatafunsval点击了搜索"); + //console.log(e.target.value); + this.props.RegistrationSearchvalue(e.target.value); + } + render() { + return ( +
+ + 搜索} + onInput={(e) => this.setdatafunsval(e)} + onSearch={(value) => this.setdatafuns(value)} + onPressEnter={(e) => this.myonPressEnter(e)} + /> + +

战队总数:{this.props.count}

+
+ ) + } + +} + +export default RegistrationSearch; diff --git a/public/react/src/modules/competition/Registrationitem.js b/public/react/src/modules/competition/Registrationitem.js new file mode 100644 index 000000000..d252dc30d --- /dev/null +++ b/public/react/src/modules/competition/Registrationitem.js @@ -0,0 +1,84 @@ +import React, {Component} from 'react'; +import { + BrowserRouter as Router, + Route, + Switch +} from 'react-router-dom'; +import axios from 'axios'; +import moment from 'moment'; +import {SnackbarHOC, WordsBtn, getImageUrl} from 'educoder'; +import {TPMIndexHOC} from '../tpm/TPMIndexHOC'; +import competition from './comcss/competition.css'; +import {Button} from 'antd'; +import RegisListviewdata from "./RegisListviewdata"; + +// 团队竞赛报名无报名子组件团队 竞赛报名-已创建战队 +class Registrationitem extends React.Component { + constructor(props) { + super(props) + + + } + + + render() { + let {item} = this.props; + return ( +
+ { + item !== undefined ? +
+
+ + + +
+
+

{item.creator.name}

+ { + item.manage_permission === true ? +

已报名

+ : + "" + } + +
+ +
+

{item.created_at}

+
+ +
+ : "" + } +
+ ) + } + +} + +export default Registrationitem; diff --git a/public/react/src/modules/competition/comcss/competition.css b/public/react/src/modules/competition/comcss/competition.css new file mode 100644 index 000000000..2f7ec665d --- /dev/null +++ b/public/react/src/modules/competition/comcss/competition.css @@ -0,0 +1,781 @@ +/*All*/ +.borders { + border: 0.5px solid; +} + +.borders2 { + border: 1px solid #D9D9D9; +} +/*All*/ +/*Registration.js*/ +/*.registrationback {*/ +/* height: 368px;*/ +/* width: 1200px;*/ +/* border: 0.5px solid;*/ +/* display: flex;*/ +/* display: -webkit-flex;*/ +/* flex-direction: column;*/ +/* align-items: center;*/ +/* background:url(../../../../../images/regis/tipregistit.jpg)*/ + +/*}*/ + +.registrationbackcenter { + display: flex; + display: -webkit-flex; + flex-direction: column; + align-items: center; +} + +/*.registrationback1 {*/ +/* height: 368px;*/ +/* width: 1200px;*/ +/* border: 0.5px solid;*/ +/* display: flex;*/ +/* flex-direction: column;*/ +/* background:url(../../../../../images/regis/tipregistit.jpg)*/ +/*}*/ + +.registrationbackp1 { + color: #ffffff; + font-size: 42px; + margin-top: 80px; + line-height: 42px; + font-weight: bold; + +} + +.registrationbackp11 { + color: #ffffff; + font-size: 48px; + margin-top: 71px; + line-height: 48px; + font-weight: bold; + margin-left: 251px; + +} + +.registrationbackp2 { + color: #ffffff; + font-size: 18px; + margin-top: 16px; + line-height: 20px; +} + +.registrationbackp22 { + margin-left: 251px; + color: #ffffff; + font-size: 36px; + margin-top: 25px; + line-height: 36px; +} + +.registrationbackp3 { + color: #ffffff; + font-size: 18px; + line-height: 20px; + margin-top: 7px; +} + +.registrationbackp4 { + color: #ffffff; + font-size: 26px; + margin-top: 25px; + line-height: 26px; +} + +.registrationbackp5 { + color: #ffffff; + font-size: 26px; + margin-top: 25px; +} + + +.registrationbackp2button { + display: flex; + align-items: center; + margin-top: 36px; +} + +.registrationbackp2button2 { + display: flex; + align-items: center; + margin-top: 40px; +} + +.registrationbackp2button3 { + display: flex; + align-items: center; + margin-top: 44px; + margin-left: 251px; + +} + +.registbut1 { + margin-right: 46px; + text-align: center; + background: #ffffff; + height: 54px; + width: 156px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer + +} + +.personreg1 { + margin-right: 46px; + text-align: center; + background: #C3C1C1; + height: 54px; + width: 156px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer +} + +.registbut11 { + margin-right: 46px; + text-align: center; + font-size: 16px; + color: #ffffff; + height: 48px; + width: 156px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + border: 1px; + border-style: solid; + border-color: #ffffff; + +} + +.registbut111 { + margin-right: 46px; + text-align: center; + color: #ffffff; + height: 41px; + width: 146px; + font-size: 16px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + border: 2px; + border-style: solid; + border-color: #ffffff; + +} + +.registbut1 p { + width: 100%; + height: 100%; + color: #05101A; + line-height: 54px; + font-size: 20px; + font-weight: bold; + cursor: pointer +} + +.registbut11 p { + width: 100%; + height: 100%; + line-height: 48px; + +} + +.registbut22 p { + width: 100%; + height: 100%; + line-height: 48px; +} + +.registbut2 p { + line-height: 54px; + width: 100%; + height: 100%; + color: #05101A; + font-size: 20px; + font-weight: bold; + cursor: pointer + +} + +.personreg1 p { + color: #ffffff; + font-size: 20px; + cursor: not-allowed; +} + +.registbut111 p { + width: 100%; + height: 100%; + line-height: 41px; +} + +.registbut222 p { + width: 100%; + height: 100%; + line-height: 41px; + +} + +.registbut2 { + text-align: center; + color: #05101A; + font-size: 20px; + background: #ffffff; + height: 54px; + width: 156px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer +} + +.registbut22 { + text-align: center; + color: #ffffff; + font-size: 16px; + height: 48px; + width: 156px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + border: 1px; + border-style: solid; + border-color: #ffffff; +} + +.registbut222 { + text-align: center; + color: #ffffff; + font-size: 16px; + height: 41px; + width: 146px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + border: 2px; + border-style: solid; + border-color: #ffffff; +} + +.bootom { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.bootomimg { + height: 80px; + width: 125px; + margin-top: 107px; + +} + +.bootomtext { + color: #999999; + font-size: 16px; + margin-top: 33px; + +} + + +/*Registration.js*/ + +/*Registrationitem.js*/ +/*横向*/ +.regitem { + display: flex; + flex-direction: initial; + margin-top: 44px; +} + +.regitem22 { + display: flex; + flex-direction: initial; + margin-top: 27px; + margin-bottom: 19px; +} + +.yslborderbottom { + border-bottom: 1px solid #EDEDED; +} + +.registrationback { + height: 368px; + width: 1200px; + display: flex; + display: -webkit-flex; + flex-direction: column; + align-items: center; +} + +.registrationback1 { + height: 368px; + width: 1200px; + display: flex; + flex-direction: column; +} + +.regitem2 { + display: flex; + flex-direction: initial; + padding-bottom: 18px; + margin-top: 19px; + +} + +/*垂直*/ +.regitemimg1 { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-left: 17px; +} + +.perregitemimg1 { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-left: 26px; + +} + +.regitemimg2 { + height: 78px; + width: 78px; + background-color: transparent; + margin-bottom: 9px; + border-radius: 50%; +} + +.personregitemimg { + height: 64px; + width: 64px; + border-radius: 50%; +} + + +.regitemimg2 p { + border: 0.5px solid; + color: #999999; + font-size: 14px; +} + +.regitemimgs { + width: 69px; + height: 69px; + margin-top: 3px; + background-color: transparent; + border-radius: 50%; + +} + +.regitemimgs2 { + margin-top: 16px; + width: 49px; + height: 51px; + margin-left: 25px; + border-radius: 50%; + +} + +.regitemimgs22 { + margin-top: 27px; + width: 28px; + height: 28px; + margin-left: 20px; + border-radius: 50%; + +} + +.regitemimgs3 { + /* border: 0.5px solid; */ + height: 22px; + width: 22px; + font-size: 21px !important; + margin-top: 21px; + color: #1C91E8; +} + +.regitemimgs4 { + width: 156px; + display: flex; + flex-direction: row-reverse; + margin-top: 18px; +} + +.regitemimgs5 { + margin-left: 10px; + text-align: center; + background: #ffffff; + height: 40px; + width: 72px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + border: 1px; + border-style: solid; + border-color: #459BE5; + cursor: pointer +} + +.regitemimgs6 { + text-align: center; + background: #ffffff; + height: 40px; + width: 72px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + border: 1px; + cursor: pointer; + border-style: solid; + border-color: #459BE5; +} + +.regitemimgs5 p { + color: #459BE5; + font-size: 14px; + cursor: pointer +} + +.regitemimgs6 p { + color: #459BE5; + font-size: 14px; + cursor: pointer + +} + +/*Registrationitem.js*/ + +/*RegistrationSearch.js*/ +.searchhead { + display: flex; + flex-direction: initial; + margin-top: 24px; + +} + +.packinputs button { + background: #459BE5; +} + +.packinputs { + width: 317px; + height: 34px; +} + + +/*RegistrationSearch.js*/ +.reglistviewdiv { + display: flex; + flex-direction: initial; + margin-top: 25px; +} + +/*RegisListview.js*/ +.reglistviewdivs { + margin-top: 25px; + +} + +.reglistviewdivss { + display: flex; + flex-direction: initial; + +} + +.reglistviewdivss2 { + display: flex; + flex-direction: initial; + +} +.reglistviewdivss2p { + width: 90px; + font-size: 12px; + color: #666666; + text-align: center; + +} + +.reglistviewdivss4p { + width: 90px; + font-size: 12px; + color: #666666; + text-align: center; + +} + +.reglistviewdivss5p { + width: 110px; + font-size: 12px; + color: #666666; + text-align: center; + +} + +.reglistviewdivss33p { + width: 25px; + font-size: 12px; + color: #666666; + text-align: center; + +} + +.reglistviewdivss3p { + width: 31px; + font-size: 12px; + color: #666666; + text-align: center; + +} + +reglistviewdivs2 { + margin-top: 27px; + +} + +/*RegisListview.js*/ + + +/*RegisListviewdata.js*/ +.reglistimg1 { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + +} + +.reglistimg2 { + border: 0.5px solid; + height: 78px; + width: 78px; +} + +/*RegisListviewdata.js*/ + + +/*PersonModal.js*/ +.permaindiv { + display: flex; + flex-direction: column; +} + + +.demo-loading-container { + position: absolute; + bottom: 40px; + width: 100%; + text-align: center; +} + +.demo-infinite-container { + border-radius: 2px; + overflow: auto; + height: 215px; + width: 485px; + +} + +.demo-infinite-containerdiv { + margin-top: 12px; +} + +.demo-infinite-containerdiv2 { + margin-top: 24px; + +} + +.backgroundspersondiv { + background: #ffffff; +} + +.cpersondiv1 { + height: 161px; + width: 410px; +} + +.demo-infinite-container2 { + border-radius: 2px; + overflow: auto; + height: 161px; + width: 410px; + +} + +.demo-infinite-container33 { + border-radius: 2px; + height: 161px; + width: 410px; + +} +.cpersondiv1Items { + color: #05101A; + font-size: 12px; +} + +.personbut1 { + background: #F2F2F2; + border-color: #F2F2F2; + margin-right: 26px; + width: 120px; + height: 38px; + color: #4A4A4A; + font-size: 16px; + border-radius: 3px; + cursor: pointer; +} + +.personbut1 p { + width: 100%; + height: 100%; + text-align: center; + margin-top: 10px; + color: #4A4A4A; + font-size: 16px; + cursor: pointer; +} +.personbut2 { + background: #459BE5; + border-color: #459BE5; + margin-right: 26px; + width: 120px; + height: 38px; + color: #ffffff; + font-size: 16px; + border-radius: 3px; + cursor: pointer; +} + +.personbut2 p { + width: 100%; + height: 100%; + text-align: center; + margin-top: 10px; + color: #ffffff; + font-size: 16px; + cursor: pointer; +} + +/*PersonModal.js*/ + + +/*PersonalModalteam.js*/ +.personaldiv { + display: flex; + display: -webkit-flex; + flex-direction: column; + align-items: center; +} + +.personaldivbutt1 { + + background: #F2F2F2; + border-color: #F2F2F2; + margin-right: 23px; + width: 100px; + height: 38px; + color: #4A4A4A; + font-size: 16px; + border-radius: 3px; + cursor: pointer; +} + +.personaldivbutt1 p { + width: 100%; + height: 100%; + text-align: center; + margin-top: 10px; + color: #666666; + font-size: 16px; + cursor: pointer; +} + +.personaldivbutt2 { + background: #459BE5; + border-color: #459BE5; + width: 100px; + height: 38px; + color: #ffffff; + font-size: 16px; + border-radius: 3px; + cursor: pointer; +} + +.personaldivbutt2 p { + width: 100%; + height: 100%; + text-align: center; + margin-top: 10px; + color: #ffffff; + font-size: 16px; + cursor: pointer; +} + +.task-btn-orange { + background: #4CACFF !important; + color: #fff !important; +} + +.task-btn { + cursor: pointer; + display: inline-block; + border: none; + padding: 0 12px; + letter-spacing: 1px; + text-align: center; + font-size: 14px; + height: 30px; + line-height: 30px; + border-radius: 2px; +} +/*PersonalModalteam.js*/ + + +/*文字长度限制*/ +.maxnamewidth100 { + max-width: 100px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: default; +} + +.maxnamewidth160 { + max-width: 160px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: default; +} + +.maxnamewidth134 { + max-width: 134px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: default; +} + +/*文字长度限制?*/ \ No newline at end of file diff --git a/public/react/src/modules/competition/competmodal/ExittheteamModel.js b/public/react/src/modules/competition/competmodal/ExittheteamModel.js new file mode 100644 index 000000000..29eab7b50 --- /dev/null +++ b/public/react/src/modules/competition/competmodal/ExittheteamModel.js @@ -0,0 +1,59 @@ +import React, {Component} from 'react'; +import {getImageUrl} from 'educoder'; +import {Modal, Input, Spin, Tooltip, Icon, Dropdown, Button} from 'antd'; +import axios from 'axios'; +import competition from '../comcss/competition.css'; +import Registrationitem from "../Registrationitem"; +import InfiniteScroll from 'react-infinite-scroller'; +// import PersonModaltion from "./PersonModaltion"; +const {Search} = Input; + +//退出战队 +class ExittheteamModel extends React.Component { + + constructor(props) { + super(props); + this.state = {} + } + + + render() { + const { + addonAfter, test, test3, Numberofteammentors, Thecurrentnumber, person1, person2 + } = this.state; + //Modal + //keyboard是否支持键盘 esc 关闭 + //closable 是否显示右上角的关闭按钮 + //底部内容,当不需要默认底部按钮时,可以设为 footer={null} + //destroyOnClose 关闭时销毁 Modal 里的子元素 + //centered 垂直居中展示 Modal + //visible 弹出框是否显示 + + return ( + + + +
+
{this.props.exitintpermessages}
+
+ + +
+ ) + } +} + +export default ExittheteamModel; diff --git a/public/react/src/modules/competition/competmodal/MessagePersonModal.js b/public/react/src/modules/competition/competmodal/MessagePersonModal.js new file mode 100644 index 000000000..6f87ab58a --- /dev/null +++ b/public/react/src/modules/competition/competmodal/MessagePersonModal.js @@ -0,0 +1,63 @@ +import React, {Component} from 'react'; +import {getImageUrl} from 'educoder'; +import {Modal, Input, Spin, Tooltip, Icon, Dropdown, Button} from 'antd'; +import axios from 'axios'; +import competition from '../comcss/competition.css'; +import Registrationitem from "../Registrationitem"; +import InfiniteScroll from 'react-infinite-scroller'; +// import PersonModaltion from "./PersonModaltion"; +const {Search} = Input; + +class MessagePersonModal extends React.Component { + + constructor(props) { + super(props); + this.state = {} + } + + + render() { + const { + addonAfter, test, test3, Numberofteammentors, Thecurrentnumber, person1, person2 + } = this.state; + //Modal + //keyboard是否支持键盘 esc 关闭 + //closable 是否显示右上角的关闭按钮 + //底部内容,当不需要默认底部按钮时,可以设为 footer={null} + //destroyOnClose 关闭时销毁 Modal 里的子元素 + //centered 垂直居中展示 Modal + //visible 弹出框是否显示 + + return ( + + +
+
{this.props.intpermessages}
+
this.props.messagePerboolbuton()}>确认 +
+
+
+ ) + } +} + +export default MessagePersonModal; diff --git a/public/react/src/modules/competition/competmodal/PersonModal.js b/public/react/src/modules/competition/competmodal/PersonModal.js new file mode 100644 index 000000000..53091d5e5 --- /dev/null +++ b/public/react/src/modules/competition/competmodal/PersonModal.js @@ -0,0 +1,1146 @@ +import React, {Component} from 'react'; +import {getImageUrl} from 'educoder'; +import {Modal, Input, Spin, Tooltip, Icon, Dropdown, Button, Empty} from 'antd'; +import axios from 'axios'; +import competition from '../comcss/competition.css'; +import Registrationitem from "../Registrationitem"; +import InfiniteScroll from 'react-infinite-scroller'; +// import PersonModaltion from "./PersonModaltion"; +import NoneData from '../../../modules/courses/coursesPublic/NoneData' +const {Search} = Input; + +//创建战队 +class PersonModal extends Component { + //导师是搜索 和学生搜索都会添加到下面框中 + /** + * mydatas最下面列表显示的参数 + * booltech 控制老师是否重复添加的参数 + * myuser 创建者的信息 + * teacher_idss 老师数组 + * member_ids 学生数组 + * polls_nametest 战队名字 + * **/ + + constructor(props) { + super(props); + this.state = { + addonAfter: 0, + loading: false, + loading1: false, + loading2: false, + hasMore: true, + person1: false, + person2: false, + Numberofteammentors: "0-3", + Thecurrentnumber: "0", + keywordteachers: "", + team_idstudents: undefined, + team_idteachers: undefined, + teacher_ids: undefined, + keywordstudents: "", + Aggregatedata: [], + name: "", + teacher_idss: [], + member_ids: [], + myuser: undefined, + mydatas: [], + booltech: false, + boolstud: false, + polls_nametest: "", + myteaherdata: [], + myshtudentdata: [], + Thecurrentnumberbool: false, + + + + } + } + componentDidMount() { + var data = []; + var polls_nametests = ""; + var datas = { + enrollable: false, + id: this.props.user.user_id, + name: this.props.user.real_name, + school_name: this.props.user.user_school, + student_id: null, + identity: this.props.user.user_identity, + type: "导师", + }; + data.push(datas); + + // console.log("itemiddata"); + // console.log("编辑战队") + // console.log(this.props.itemiddata); + try { + if (this.props.Newtit === false) { + for (var i = 0; i < this.props.itemiddata.team_members.length; i++) { + if (i === 0) { + ///因为第一个位置是创建者 所以要过滤掉 + } else { + var datasy = { + enrollable: false, + id: this.props.itemiddata.team_members[i].user_id, + name: this.props.itemiddata.team_members[i].name, + school_name: this.props.itemiddata.team_members[i].school_name, + student_id: null, + identity: this.props.itemiddata.team_members[i].identity, + type: this.props.itemiddata.team_members[i].role === "teacher" ? "导师" : "队员", + }; + data.push(datasy); + } + } + if (this.props.itemiddata) { + polls_nametests = this.props.itemiddata.name; + } + } + } catch (e) { + + } + + this.setState({ + myuser: this.props.user, + mydatas: data, + polls_nametest: polls_nametests + }) + this.setState({ + GetenrollmentAPI: this.props.GetenrollmentAPI, + }) + + } + + componentDidUpdate = (prevProps) => { + if (prevProps.user != this.props.user) { + ////console.log("Registration.js componentDidUpdate"); + ////console.log(this.props); + // ////console.log(prevProps); + //identity职场称 + //user_school学校 + //real_name姓名 + //type 类型 + var data = []; + var datas = { + enrollable: false, + id: undefined, + name: this.props.user.real_name, + school_name: this.props.user.user_school, + student_id: null, + identity: this.props.user.user_identity, + type: "导师", + }; + data.push(datas); + this.setState({ + myuser: this.props.user, + mydatas: data, + }) + } + + if (prevProps.GetenrollmentAPI != this.props.GetenrollmentAPI) { + ////console.log("Registration.js GetenrollmentAPIcomponentDidUpdate"); + ////console.log(this.props); + this.setState({ + GetenrollmentAPI: this.props.GetenrollmentAPI, + }) + } + }; + //创建战队 + Createateam = () => { + + + const {polls_nametest, mydatas, GetenrollmentAPI} = this.state; + var myteaherdata = []; + var myshtudentdata = []; + var i = 0; + for (var a = 0; a < mydatas.length; a++) { + if (mydatas[a].type === "导师") { + i++; + // var objectt = { + // enrollable: mydatas[a].enrollable, + // id: mydatas[a].id, + // identity: mydatas[a].identity, + // name: mydatas[a].name, + // school_name: mydatas[a].school_name, + // } + myteaherdata.push(mydatas[a].id); + } else if (mydatas[a].type === "队员") { + // var objectts = { + // enrollable: mydatas[a].enrollable, + // id: mydatas[a].id, + // name: mydatas[a].name, + // school_name: mydatas[a].school_name, + // student_id: mydatas[a].student_id, + // } + myshtudentdata.push(mydatas[a].id); + } + } + + + try { + if (GetenrollmentAPI) { + if (GetenrollmentAPI.teacher_staff) { + if (GetenrollmentAPI.teacher_staff.minimum > i) { + this.setState({ + Thecurrentnumberbool: true, + Thecurrentnumber: i, + booltech: false, + boolstud: false + }) + return + } else if (GetenrollmentAPI.teacher_staff.maximum < i) { + this.setState({ + Thecurrentnumberbool: true, + Thecurrentnumber: i, + booltech: false, + boolstud: false + }) + return + } + + } + } + } catch (e) { + + } + + // Thecurrentnumber + if (this.props.Newtit === true) { + //创建新的战队 + let url = `/competitions/${this.props.match.params.identifier}/competition_teams.json`; + axios.post(url, { + name: polls_nametest, + teacher_ids: myteaherdata, + member_ids: myshtudentdata, + }).then((result) => { + // ////console.log("获取到创建战队的数据"); + // ////console.log(result); + if (result) { + if (result.data) { + this.props.Tmoconfirm1(true); + } + } + }).catch((error) => { + // ////console.log(error) + }); + } else { + //编辑战队 + let url = `/competitions/${this.props.match.params.identifier}/competition_teams/${this.props.itemiddata.id}.json`; + axios.put(url, { + name: polls_nametest, + teacher_ids: myteaherdata, + member_ids: myshtudentdata, + }).then((result) => { + // ////console.log("获取到编辑战队的数据"); + // ////console.log(result); + if (result) { + if (result.data) { + this.props.Tmoconfirm1(true); + } + } + }).catch((error) => { + // ////console.log(error) + }); + } + } + Getteacherdata = (keywordteachers, team_idteachers, teacher_ids) => { + this.setState({ + person1: true, + person2: false, + }) + //老师姓名 keyword + //当前战队ID team_id + //当前老师ID数组 teacher_ids + // ////console.log("搜索的老师"); + const datas = { + keyword: keywordteachers, + team_id: team_idteachers, + teacher_ids: teacher_ids, + }; + let url = `/competitions/${this.props.match.params.identifier}/teachers.json`; + axios.get((url), {params: datas}).then((result) => { + if (result) { + if (result.data) { + // ////console.log(result); + this.setState({ + teacher_ids: result.data.teachers + }) + } + } + }).catch((error) => { + // ////console.log(error); + }) + }; + Getstudentsdata = (keywordstudents, team_idstudents, student_ids) => { + this.setState({ + person1: false, + person2: true, + }) + //学生姓名 keyword + //当前战队ID team_id + //当前队员ID数组 student_ids + // ////console.log("搜索的学生"); + const datas = { + keyword: keywordstudents, + team_id: team_idstudents, + student_ids: student_ids, + }; + let url = `/competitions/${this.props.match.params.identifier}/students.json`; + axios.get((url), {params: datas}).then((result) => { + if (result) { + if (result.data) { + // ////console.log(result); + this.setState({ + member_ids: result.data.teachers + }) + + } + } + }).catch((error) => { + // ////console.log(error); + }) + }; + + //老师输入框事件 + teacheronChange = (e) => { + // ////console.log(e.target.value); + // ////console.log("老师输入框事件|||||||||||123123123"); + this.setState({ + keywordteachers: e.target.value, + booltech: false, + Thecurrentnumberbool: false + }) + // try { + // if (e.target.value.length > 0) { + // this.setState({ + // person1: true, + // person2: false, + // keywordteachers: e.target.value + // }) + // } else { + // this.setState({ + // person1: false, + // person2: false, + // keywordteachers: e.target.value + // }) + // } + // } catch (e) { + // this.setState({ + // person1: true, + // person2: false, + // keywordteachers: e.target.value + // }) + // } + + // try { + // const {team_idteachers, teacher_ids} = this.state; + // this.Getteacherdata(e.target.value, team_idteachers, teacher_ids); + // } catch (e) { + // + // } + }; + + //学生输入框事件 + studentsonChange = (e) => { + // ////console.log("学生输入框事件"); + // ////console.log(e); + this.setState({ + keywordstudents: e.target.value, + boolstud: false, + Thecurrentnumberbool: false + }); + // try { + // if (e.target.value.length > 0) { + // this.setState({ + // person2: true, + // person1: false, + // keywordstudents: e.target.value + // }); + // } else { + // this.setState({ + // person2: false, + // person1: false, + // keywordstudents: e.target.value + // }); + // } + // } catch (e) { + // this.setState({ + // person2: true, + // person1: false, + // keywordstudents: e.target.value + // }); + // } + + // try { + // const {team_idstudents, student_ids} = this.state; + // this.Getstudentsdata(e.target.value, team_idstudents, student_ids); + // } catch (e) { + // + // } + } + + //点击获取老师数据 + getdatacpersondiv1Items = (object) => { + + var datas = { + enrollable: object.enrollable, + id: object.id, + name: object.name, + school_name: object.school_name, + student_id: null, + identity: object.identity, + type: "导师", + }; + var fordabool = false; + var forda = this.state.mydatas; + // ////console.log("点击获取老师数据"); + // ////console.log(object); + // ////console.log(forda); + for (var i = 0; i < forda.length; i++) { + if (forda[i].id) { + if (forda[i].id === object.id) { + fordabool = true; + break + } + } + } + if (fordabool) { + this.setState({ + person1: false, + keywordteachers: object.name, + booltech: true, + }) + } else { + forda.push(datas); + this.setState({ + person1: false, + keywordteachers: object.name, + mydatas: forda, + booltech: false, + }) + } + + } + //点击获取学生数据2 + getdatacpersondiv1Items2 = (object) => { + var datas = { + enrollable: object.enrollable, + id: object.id, + name: object.name, + school_name: object.school_name, + student_id: object.student_id, + identity: "学生", + type: "队员", + }; + var fordabool = false; + var forda = this.state.mydatas; + // ////console.log("点击获取学生数据2"); + // ////console.log(object); + // ////console.log(forda); + for (var i = 0; i < forda.length; i++) { + if (forda[i].id) { + // // ////console.log(true); + // // ////console.log(forda[i].id); + // // ////console.log(object.id); + if (forda[i].id === object.id) { + fordabool = true; + break + } + } + } + if (fordabool) { + this.setState({ + person2: false, + keywordstudents: object.name, + boolstud: true + }) + } else { + forda.push(datas); + this.setState({ + person2: false, + keywordstudents: object.name, + mydatas: forda, + boolstud: false + }) + } + + + + } + //输入框事件 + changeTopicName = (e) => { + // // ////console.log("调用了changeTopicName"); + let num = parseInt(e.target.value.length); + if (num > 60) { + return; + } + this.setState({ + addonAfter: num < 0 ? 0 : num + }); + this.setState({ + polls_nametest: e.target.value + }) + }; + + //onSearchsou + onSearch = (value) => { + // ////console.log("搜索的数据" + value); + }; + handleInfiniteOnLoad = () => { + // this.setState({ + // loading: true, + // }) + // const test3 = this.state.test; + // this.state.test2.forEach(function (item) { + // test3.push(item) + // }); + // setTimeout(() => { + // this.setState({ + // test: test3, + // hasMore: true, + // loading: false, + // }); + // }, 1000) + + } + handleInfiniteOnLoad1 = () => { + // // ////console.log("调用了方法1111"); + // this.setState({ + // loading1: true, + // }) + // setTimeout(() => { + // // ////console.log("调用了方法11112"); + // this.setState({ + // loading1: false, + // hasMore: true, + // }); + // }, 1000) + + } + handleInfiniteOnLoad2 = () => { + // // ////console.log("调用了方法1111"); + // this.setState({ + // loading2: true, + // + // }) + // setTimeout(() => { + // // ////console.log("调用了方法11113"); + // this.setState({ + // hasMore: true, + // loading2: false, + // }); + // }, 1000) + + } + inputOnBlur = (e) => { + // ////console.log("inputOnBlur"); + // ////console.log(e); + this.setState({ + person1: false + }) + } + inputOnBlur2 = (e) => { + // ////console.log("inputOnBlur"); + // ////console.log(e); + this.setState({ + person2: false + }) + } + + startSearch = (e) => { + // ////console.log("startSearch"); + // ////console.log(e); + this.setState({ + person1: true, + person2: false, + }) + const {keywordteachers, team_idteachers, teacher_ids} = this.state; + this.Getteacherdata(keywordteachers, team_idteachers, teacher_ids); + } + + startSearch2 = (e) => { + // ////console.log("startSearch2"); + // ////console.log(e); + this.setState({ + person1: false, + person2: true, + }) + const {keywordstudents, team_idstudents, student_ids} = this.state; + this.Getstudentsdata(keywordstudents, team_idstudents, student_ids); + } + + inputOnFocus = (e) => { + // ////console.log("inputOnFocus"); + // ////console.log(e); + try { + if (this.state.keywordteachers && this.state.keywordteachers.length > 0) { + this.setState({ + person1: true, + person2: false, + }) + } else { + this.setState({ + person1: false, + person2: false, + }) + } + + } catch (e) { + this.setState({ + person1: true, + person2: false, + }) + } + + } + + inputOnFocus2 = (e) => { + // ////console.log("inputOnFocus2"); + // ////console.log(e); + try { + if (this.state.keywordstudents && this.state.keywordstudents.length > 0) { + this.setState({ + person2: true, + person1: false, + }) + } else { + this.setState({ + person2: false, + person1: false, + }) + } + + } catch (e) { + this.setState({ + person2: true, + person1: false, + }) + } + + + } + + inputOnFocus3 = (e) => { + // ////console.log("inputOnFocus3"); + // ////console.log(e); + this.setState({ + person2: false, + person1: false, + }) + } + deletedata = (item) => { + var {mydatas} = this.state; + if (item) { + var pos = mydatas.indexOf(item); + // ////console.log("deletedata"); + // ////console.log(pos); + var removedItem = mydatas.splice(pos, 1); + // ////console.log("deletedata22222"); + // ////console.log(removedItem) + //removedItem 是被删除的元素 + // ////console.log(mydatas) + this.setState({ + mydatas: mydatas, + }) + } + } + + render() { + const { + addonAfter, Numberofteammentors, Thecurrentnumber, person1, person2, + keywordteachers, team_idteachers, teacher_ids, + keywordstudents, team_idstudents, student_ids, + member_ids, mydatas, booltech, boolstud, GetenrollmentAPI, Thecurrentnumberbool + } = this.state; + //Modal + //keyboard是否支持键盘 esc 关闭 + //closable 是否显示右上角的关闭按钮 + //底部内容,当不需要默认底部按钮时,可以设为 footer={null} + //destroyOnClose 关闭时销毁 Modal 里的子元素 + //centered 垂直居中展示 Modal + //visible 弹出框是否显示 + const listItems = mydatas.map((item, index) => +
+

{item.name === undefined || item.name === null || item.name === "" ? "--" : item.name}

+ { + index === 0 ? +

创建者

+ : +

{item.type === undefined || item.type === null || item.type === "" ? "--" : item.type}

+ } + +

{item.school_name === undefined || item.school_name === null || item.school_name === "" ? "--" : item.school_name}

+

{item.identity === undefined || item.identity === null || item.identity === "" ? "--" : item.identity}

+ { + index === 0 ? +

+ : +

this.deletedata(item)}/>

+ } +
+ ); + var cpersondiv1Items = []; + if (teacher_ids) { + cpersondiv1Items = teacher_ids.map((item, index) => + this.getdatacpersondiv1Items(item)} + > +

{item.name === undefined || item.name === null || item.name === "" ? "--" : item.name}

+

{item.identity === undefined || item.identity === null || item.identity === "" ? "--" : item.identity}

+

{item.school_name === undefined || item.school_name === null || item.school_name === "" ? "--" : item.school_name}

+
+ ); + } + + const cpersondiv1 = ( +
+ +
+ { + cpersondiv1Items.length === 0 ? + + : + this.handleInfiniteOnLoad1()} + // hasMore={!this.state.loading1 && this.state.hasMore} + hasMore={false} + useWindow={false} + > + { + cpersondiv1Items + } + + + } + +
+
+
+ ) + var persondiv2Items = []; + if (member_ids) { + persondiv2Items = member_ids.map((item, index) => + this.getdatacpersondiv1Items2(item)} + > +

{item.name === undefined || item.name === null || item.name === "" ? "--" : item.name}

+

{item.identity === undefined || item.identity === null || item.identity === "" ? "--" : item.identity}

+

{item.school_name === undefined || item.school_name === null || item.school_name === "" ? "--" : item.school_name}

+

{item.enrollable === false ? "" : "已加入其他战队"}

+
+ ); + } + const persondiv2 = ( +
+ {/*this.state.loading2*/} + +
+ { + persondiv2Items.length === 0 ? + + : + this.handleInfiniteOnLoad2()} + // hasMore={!this.state.loading2 && this.state.hasMore} + hasMore={false} + useWindow={false} + > + { + persondiv2Items + } + + + } +
+
+
+ ); + //console.log("PersonModal"); + //console.log(this.props); + return ( + + + + +
+ {/*队名*/} + +
+

+ * + 队名: +

+ + + +
+ + + {/*导师*/} +
+

+ * + 导师: +

+ + {/*
*/} + trigger.parentNode} + visible={this.state.person1}> + this.teacheronChange(e)} + value={this.state.keywordteachers} + suffix={ + this.Getteacherdata(keywordteachers, team_idteachers, teacher_ids)}/> + } + /> + + {/*
*/} +
+ { + booltech === true ? +

该老师已添加

+ : +
+ } + + + {/*队员*/} +
+

+ * + 队员: +

+ + {/* this.onSearch(value)}*/} + {/*/>*/} + + trigger.parentNode} + visible={this.state.person2}> + this.studentsonChange(e)} + value={this.state.keywordstudents} + suffix={ + this.Getstudentsdata(keywordstudents, team_idstudents, student_ids)}/> + } + /> + + +
+ + { + boolstud === true ? +

该队员已添加

+ : +
+ } + {/*表格*/} +
+ {/**/} +
+
+

姓名

+

角色

+

单位

+

其他

+

操作

+
+
+ +
+ this.handleInfiniteOnLoad()} + // hasMore={!this.state.loading && this.state.hasMore} + hasMore={false} + useWindow={false} + > + {listItems} + + +
+
+
+ + {/*最后一行文字*/} + { + GetenrollmentAPI && GetenrollmentAPI.teacher_staff ? + ( + Thecurrentnumberbool === true ? +

战队导师为{GetenrollmentAPI.teacher_staff.minimum}-{GetenrollmentAPI.teacher_staff.maximum}人,现在为{Thecurrentnumber}人

+ + : "" + ) : + "" + } + + + +
+
+
+

this.props.Tmoconfirm1(false)}> 取消

+
+
+

this.Createateam()}>确定

+
+
+
+
+
+ ) + } +} + +export default PersonModal; \ No newline at end of file diff --git a/public/react/src/modules/competition/competmodal/PersonModaltion.js b/public/react/src/modules/competition/competmodal/PersonModaltion.js new file mode 100644 index 000000000..680566297 --- /dev/null +++ b/public/react/src/modules/competition/competmodal/PersonModaltion.js @@ -0,0 +1,50 @@ +import React, {Component} from 'react'; +import { + BrowserRouter as Router, + Route, + Switch +} from 'react-router-dom'; +import axios from 'axios'; +import moment from 'moment'; +import competition from './comcss/competition.css'; +import {Checkbox, Table, Pagination, Menu, Icon} from "antd"; +// 团队竞赛报名无报名子组件团队 在线竞赛 > 全国高校计算机大赛-项目挑战> + +class PersonModaltion extends React.Component { + constructor(props) { + super(props) + + } + + + render() { + return ( +
+
+

姓名

+

角色

+

单位

+

其他

+

操作

+
+
+ ) + } + +} + +export default PersonModaltion; diff --git a/public/react/src/modules/competition/competmodal/PersonalModalteam.js b/public/react/src/modules/competition/competmodal/PersonalModalteam.js new file mode 100644 index 000000000..f86668f34 --- /dev/null +++ b/public/react/src/modules/competition/competmodal/PersonalModalteam.js @@ -0,0 +1,125 @@ +import React, {Component} from 'react'; +import {getImageUrl} from 'educoder'; +import {Modal, Input, Spin, Tooltip, Icon, Dropdown, Button} from 'antd'; +import axios from 'axios'; +import competition from '../comcss/competition.css'; +import Registrationitem from "../Registrationitem"; +import InfiniteScroll from 'react-infinite-scroller'; +// import PersonModaltion from "./PersonModaltion"; +const {Search} = Input; + +//立即申请试用 +class PersonalModalteam extends Component { + + constructor(props) { + super(props); + this.state = { + yslzxueshiskmcdm1: "", + } + } + + + Tmoconfirmto = () => { + let url = `/competitions/${this.props.match.params.identifier}/competition_teams/join.json`; + axios.post(url, { + invite_code: this.state.yslzxueshiskmcdm1 + }).then((result) => { + if (result) { + if (result.data) { + this.props.Tmoconfirm(true) + } + } + }).catch((error) => { + + }); + } + + studentsonChange = (e) => { + this.setState({ + yslzxueshiskmcdm1: e.target.value, + }); + + } + render() { + const { + addonAfter, test, test3, Numberofteammentors, Thecurrentnumber, person1, person2 + } = this.state; + //Modal + //keyboard是否支持键盘 esc 关闭 + //closable 是否显示右上角的关闭按钮 + //底部内容,当不需要默认底部按钮时,可以设为 footer={null} + //destroyOnClose 关闭时销毁 Modal 里的子元素 + //centered 垂直居中展示 Modal + //visible 弹出框是否显示 + + return ( + + + +
+
+

+ 邀请码: +

+ + this.studentsonChange(e)} placeholder="请输入您的邀请码"/> + +
+ +
+
+
+

this.props.Tmoconfirm(false)}>取消

+
+
+

this.Tmoconfirmto()}>确定

+
+
+
+
+
+ ) + } +} + +export default PersonalModalteam; \ No newline at end of file diff --git a/public/react/src/modules/competition/personal/PersonalCompetit.js b/public/react/src/modules/competition/personal/PersonalCompetit.js new file mode 100644 index 000000000..d740e416a --- /dev/null +++ b/public/react/src/modules/competition/personal/PersonalCompetit.js @@ -0,0 +1,97 @@ +import React, {Component} from 'react'; +import {SnackbarHOC, WordsBtn} from 'educoder'; +import {TPMIndexHOC} from '../../tpm/TPMIndexHOC'; +import competition from '../comcss/competition.css'; +import {Button, Pagination,} from 'antd'; +import CompetitionMaxImg from '../CompetitionMaxImg'; +import Registrationitem from '../Registrationitem'; + +// 团队竞赛报名无报名 +class PersonalCompetit extends React.Component { + constructor(props) { + super(props) + this.state = { + loadingstate: false, + page: 1, + limit: 20, + type: 6, + pint: 1, + test: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + } + } + + + paginationonChangestwo = (pageNumber) => { + this.setState({ + page: pageNumber, + loadingstate: true, + }) + } + + render() { + const {test, page, limit, type, pint} = this.state; + const listItems = test.map((item, index) => + + ); + return ( +
+
+ + {/*大图*/} + { + type === 6 ? + + : + "" + } + { + pint === 1 || pint === 3 ? +
+

参赛总人数:132

+
+ : ""} + + {/*列表*/} + { + pint === 1 || pint === 3 ? +
+ { + listItems + } + +
+ : ""} + { + pint === 1 || pint === 3 ? +
+ +
+ : "" + } + +
+ +
+ ) + } + +} + +export default SnackbarHOC()(TPMIndexHOC(PersonalCompetit)); diff --git a/public/react/src/modules/competition/personal/PersonalCompetititem.js b/public/react/src/modules/competition/personal/PersonalCompetititem.js new file mode 100644 index 000000000..bd6a092eb --- /dev/null +++ b/public/react/src/modules/competition/personal/PersonalCompetititem.js @@ -0,0 +1,244 @@ +import React, {Component} from 'react'; +import { + BrowserRouter as Router, + Route, + Switch +} from 'react-router-dom'; +import axios from 'axios'; +import moment from 'moment'; +import {SnackbarHOC, WordsBtn, getImageUrl} from 'educoder'; +import {TPMIndexHOC} from '../../tpm/TPMIndexHOC'; +import competition from '../comcss/competition.css'; +import {Button, message} from 'antd'; +// 点击按钮复制功能 +function jsCopy() { + var e = document.getElementById("copy_invite_code"); + e.select(); + document.execCommand("Copy"); + codesuccess() +} + +function codesuccess() { + message.success('复制成功'); +}; +// 团队竞赛报名无报名子组件团队 竞赛报名-已创建战队 +class PersonalCompetititem extends React.Component { + constructor(props) { + super(props) + this.state = { + data: "" + } + + } + + componentDidMount() { + // // ////console.log(this.props.data) + this.setState({ + data: this.props.data, + }) + + } + + componentDidUpdate = (prevProps) => { + // + // if (prevProps.data != this.props.data) { + // + // } + } + + render() { + const {data} = this.props; + // ////console.log("PersonalCompetititem"); + // ////console.log(data); + // ////console.log(data[0]); + // ////console.log(data&&data[0].creator.image_url); + // const listItems = mydatas.map((item, index) => + // + // ); + // console.log("PersonalCompetititem"); + // console.log(data); + return ( +
+ { + data && data[0] ?
+
+
+ + + +

{data[0].creator.name}

+
+
+

{data[0].name}

+
+
+ { + data && data[0].team_members.map((item, index) => { + return ( + + index === 0 ? + + + + : index === 1 ? + + + + : index === 2 ? + + + + : index === 3 ? + + + + : index === 4 ? + + + + : index === 5 ? +
+ + + + + + + +
+ : "" + ) + }) + } + +
+
+
+ 邀请码: + {data[0].invite_code === null || data[0].invite_code === undefined ? "" : data[0].invite_code} +
+
+ +
+
+ {data[0].invite_code === null || data[0].invite_code === undefined ? + + + : + { + jsCopy() + }} + > + + + } + + { + this.props.type === 5 ? +
+
this.props.Exittheteamshow(data[0].id, true)}> +

this.props.Exittheteamshow(data[0].id, true)}>删除战队

+
+
this.props.Createateamedit(data[0])}> +

this.props.Createateamedit(data[0])}>编辑战队

+
+ +
+ : this.props.type === 2 ? +
+ +
this.props.Exittheteamshow(data[0].id, false)}> +

this.props.Exittheteamshow(data[0].id, false)}>退出战队

+
+ +
+ : + this.props.type === 3 ? +
+ +
this.props.Exittheteamshow(data[0].id, false)}> +

this.props.Exittheteamshow(data[0].id, false)}>退出战队

+
+ +
+ : + "" + + } +
+
+ : "" + } +
+ + + ) + } + +} + +export default PersonalCompetititem; diff --git a/public/react/src/modules/competitions/Competitimain/CompetitionsIndex.js b/public/react/src/modules/competitions/Competitimain/CompetitionsIndex.js new file mode 100644 index 000000000..61e6419b7 --- /dev/null +++ b/public/react/src/modules/competitions/Competitimain/CompetitionsIndex.js @@ -0,0 +1,229 @@ +import React, { Component } from 'react'; +import { Link } from 'react-router-dom'; +import { Menu, Icon, List, Avatar,Row, Col,Tag,Pagination} from 'antd'; +import {getImageUrl} from 'educoder'; +import axios from 'axios'; +import './Competitionsindex.css'; +import NoneData from "../../courses/coursesPublic/NoneData"; + +const { SubMenu } = Menu; + +const IconText = ({ type, text }) => ( + + + {text} + +); + +class CompetitionsIndex extends Component{ + constructor(props) { + super(props) + this.state={ + current: 'all', + datas:undefined, + page:1, + category:undefined + + } + } + + componentDidMount(){ + window.document.title = '竞赛'; + let{category,page}=this.state; + this.getdata(category,page) + } + + getdata=(category,page)=>{ + const Url =`/competitions.json`; + axios.get(Url,{params:{ + category:category, + page:page, + per_page:15, + } + }).then((response) => { + if(response.status===200){ + this.setState({ + datas:response.data.competitions, + count:response.data.count, + }) + } + }) + .catch(function (error) { + console.log(error); + }); + } + + + handleClick = e => { + this.setState({ + current: e.key, + }); + let{category,page}=this.state; + this.getdata(e.key,page) + }; + + setcompetitonurl=(url)=>{ + + if(url!=null){ + this.props.history.replace(url); + } + } + + PaginationCourse=(pageNumber)=>{ + let {category}=this.state; + this.setState({ + page: pageNumber, + }) + this.getdata(category,pageNumber); + } + render() { + let {datas,page,count}=this.state; + admin: true + business: false + console.log(this.props.current_user&&this.props.current_user.business) + return ( +
+
+
+
+ +
+
+
+
+
+ +
+
+ + + 全部 + + + 即将发布 + + + 进行中 + + + 往期比赛 + + +
+
+ +
+ + {datas===undefined?"":datas.length===0?"": ( +
+
+ {item.description===null||item.description===undefined||item.description===""?:""} + + 竞赛时间: 2019-08-07 24: 00~2019-09-10 24: 00, + 报名截止时间:2019-08-07 08:10, + ]} + extra={ +
+ +
+
奖金
+ +
+
浏览数
+ +
+
报名数
+ + + + +
+
¥{item.bonus}
+ +
+
{item.competition_status==="nearly_published"?"--":item.visits_count}
+ +
+
{item.competition_status==="nearly_published"?"--":item.member_count}
+ + + + } + > + + this.setcompetitonurl(item.competition_status==="ended"?null:item.competition_status==="nearly_published"? this.props.current_user&&this.props.current_user.business===true?`/newcompetitions/${item.identifier}/common_header`:this.props.current_user&&this.props.current_user.admin===true?`/newcompetitions/${item.identifier}/common_header`:null:item.competition_status==="progressing"?`/newcompetitions/${item.identifier}/common_header`:null)} + >{item.name}{item.sub_title===null?"":{ + item.sub_title + }} + } + /> + {item.description} + + + + + ) + + } + />} + + {datas===undefined?'none':datas.task_count >20 ?
+ + + +
:""} + + { + datas===undefined?"":datas && datas.length===0? :"" + } + + + + + + + + ) + } +} +export default CompetitionsIndex; \ No newline at end of file diff --git a/public/react/src/modules/competitions/competitimain/Competitionsindex.css b/public/react/src/modules/competitions/Competitimain/Competitionsindex.css similarity index 72% rename from public/react/src/modules/competitions/competitimain/Competitionsindex.css rename to public/react/src/modules/competitions/Competitimain/Competitionsindex.css index 608bc05fd..c711859c9 100644 --- a/public/react/src/modules/competitions/competitimain/Competitionsindex.css +++ b/public/react/src/modules/competitions/Competitimain/Competitionsindex.css @@ -1,12 +1,4 @@ -.courses-head{ - width: 100%; - height: 300px; - background-image: url(./courses.jpg); - background-color: #081C4B; - background-size: cover; - background-position: center; - background-repeat: no-repeat; -} +.teamsLayout{background: transparent !important;} .competitionstitle{ height:50px !important; @@ -22,7 +14,16 @@ background: #fff; width: 1200px; } - +.CompetitionsList{ + position: relative; + max-height: 210px; +} +.competitonimg{ + position: absolute; + right: -5px; + width: 80px; + top: 20px; +} .ant-menu-horizontal { border-bottom:none !important; @@ -104,6 +105,26 @@ .competitionsrelative{ position: absolute; - /*top: 28px;*/ + top: 28px; } +.CompetitionsList:hover{ + /*box-shadow: 0 2px 6px rgba(51,51,51,.09);*/ + box-shadow:3px 4px 10px 2px rgba(229,229,229,0.5); + opacity: 1; + border-radius: 2px; +} +.endedfont{ + color:#000 !important; +} +.zhezhaos{ + + height: 200px; + overflow: hidden; + position: relative; + border: 1px solid rgb(235, 237, 240); + border-radius: 2px; + padding: 48px; + text-align: center; + background: rgb(250, 250, 250); +} \ No newline at end of file diff --git a/public/react/src/modules/competitions/Competition_teams/Competitionteams.css b/public/react/src/modules/competitions/Competition_teams/Competitionteams.css new file mode 100644 index 000000000..af1f40aba --- /dev/null +++ b/public/react/src/modules/competitions/Competition_teams/Competitionteams.css @@ -0,0 +1,53 @@ +.teamsLayout{background: transparent !important;} +.teamsLayout .teamsLayoutitle{ + font-size:18px; + font-family:PingFangSC-Semibold,PingFang SC; + font-weight:600; + color:rgba(5,16,26,1); + line-height:25px; + margin-top: 10px; + margin-bottom: 10px; +} +.teamsLayoutTable .ant-table-bordered .ant-table-thead > tr > th, .ant-table-bordered .ant-table-tbody > tr > td { + border-right: 1px solid transparent !important; +} + +.teamsLayoutTable .ant-table-body .ant-table-thead > tr> th:nth-last-child(1){ + border-right: 1px solid #e8e8e8 !important; +} + +.teamsLayoutTable .ant-table-body .ant-table-tbody > tr> td:nth-last-child(1){ + border-right: 1px solid #e8e8e8 !important; +} + +.teamsLayoutTable .ant-table-bordered .ant-table-thead > tr > th{ + background:#EEEEEE; + font-size: 14px; + font-family: PingFangSC-Regular,PingFang SC; + font-weight: 400; + color: rgba(102,102,102,1); + line-height: 20px; +} + +.teamsLayoutTable .ant-table-bordered .ant-table-tbody > tr > th{ + background:#EEEEEE; + font-size:14px; + font-family:PingFangSC-Regular,PingFang SC; + font-weight:400; + color:rgba(5,16,26,1); + line-height:20px; +} + +.teamsLayout .mt40{ + margin-top: 40px !important; +} + +.teamsLayoutheji{ + color: #878787; + font-size: 16px; +} + +.teamsLayoucolor-orange { + color: #ff6800!important; + font-size: 16px; +} \ No newline at end of file diff --git a/public/react/src/modules/competitions/Competition_teams/Competitionteams.js b/public/react/src/modules/competitions/Competition_teams/Competitionteams.js new file mode 100644 index 000000000..34b1d97fc --- /dev/null +++ b/public/react/src/modules/competitions/Competition_teams/Competitionteams.js @@ -0,0 +1,245 @@ +import React, { Component } from 'react'; +import { Breadcrumb,Layout,Table, Divider, Tag,Badge} from 'antd'; + +import axios from 'axios'; + +import NoneData from "../../courses/shixunHomework/shixunHomework"; + +import './Competitionteams.css'; +const { Header, Footer, Sider, Content } = Layout; + +class Competitionteams extends Component{ + constructor(props) { + super(props) + this.state={ + shixundata: undefined, + coursedata:undefined, + } + } + + componentDidMount(){ + window.document.title = '竞赛'; + + this.getshixundata(); + this.getcoursedata(); + } + + getshixundata=()=>{ + + const Url =`/competitions/${this.props.match.params.identifier}/competition_teams/${this.props.match.params.competition_team_id}/shixun_detail.json`; + axios.get(Url).then((response) => { + if(response.status===200){ + // let data={ + // shixuns: [ + // { + // creator: "黄井泉", // 创建者 + // shixun_name: "单链表的学习与应用(I)", // 实训名称 + // shixun_identifier: "mnf6b7z3", + // forked: false, // false:原创 + // myshixuns_count: 179, // 学习人数 + // forked_myshixun_count: 0, // 被fork发布的学习人数 + // valid_count: 82, // 有效作品数 + // score: 1320 // 应用值 + // } + // ], + // shixun_count: 1, // 实训总计 + // total_myshixun_count: 179, // 学习人数总计 + // total_forked_myshixun_count: 0, // 被fork发布的学习人数总计 + // total_valid_count: 82, // 有效作品数总计 + // total_shixun_score: 1320 // 应用值总计 + // } + let data=response.data; + + let newarr=data.shixuns; + + let newobj={ + creator:"合计:", + shixun_name:data.shixun_count, + myshixuns_count:data.total_myshixun_count, + forked_myshixun_count:data.total_forked_myshixun_count, + valid_count:data.total_valid_count, + score:data.total_shixun_score + } + newarr.push(newobj) + + this.setState({ + shixundata:newarr + }) + + + } + }) + .catch(function (error) { + console.log(error); + }); + + + + + } + + getcoursedata=()=>{ + const Url =`/competitions/${this.props.match.params.identifier}/competition_teams/${this.props.match.params.competition_team_id}/course_detail.json`; + + axios.get(Url).then((response) => { + if(response.status===200){ + // let data={ + // courses: [ + // { + // creator: "周海芳", // 创建者 + // creator_login: "Nancy", // login + // course_name: "大学计算机基础2018年秋季", + // course_id: 1502, + // students_count: 122, // 学生数量 + // shixun_homework_count: 8, // 发布的实训作业数量 + // valid_count: 977, // 有效作品数 + // score: 29810 // 应用值 + // } + // ], + // total_course_count: 1, // 课堂总计 + // total_students_count: 122, // 学生数总计 + // total_shixun_homework_count: 8, // 实训作业数总计 + // total_valid_count: 977, // 有效作品数总计 + // total_course_score: 29810 // 应用值总计 + // } + + let data=response.data; + + let newarr=data.courses; + + let newobj={ + creator:"合计:", + course_name:data.total_course_count, + students_count:data.total_students_count, + shixun_homework_count:data.total_shixun_homework_count, + valid_count:data.total_valid_count, + score:data.total_course_score + } + newarr.push(newobj) + + this.setState({ + coursedata:newarr + }) + + } + }) + .catch(function (error) { + console.log(error); + }); + + + } + + render() { + + const shixuncolumns = [ + { + title: '创建者', + dataIndex: 'creator', + key: 'creator', + render: (text, record) =>
{text}
, + }, + { + title: '名称', + dataIndex: 'shixun_name', + key: 'shixun_name', + render: (text, record) => +
{text}{record.forked===true?:""}
, + }, + { + title: '学习人数', + dataIndex: 'myshixuns_count', + key: 'myshixuns_count', + render: (text, record) =>
{text}
, + }, + { + title: '被fork发布的学习人数', + dataIndex: 'forked_myshixun_count', + key: 'forked_myshixun_count', + render: (text, record) =>
{text}
, + }, + { + title: '有效作品数', + dataIndex: 'valid_count', + key: 'valid_count', + render: (text, record) =>
{text}
, + }, + { + title: '应用值', + dataIndex: 'score', + key: 'score', + render: (text, record) =>
{text}
, + }, + ]; + + const coursecolumns = [ + { + title: '创建者', + dataIndex: 'creator', + key: 'creator', + render: (text, record) =>
{text}
, + }, + { + title: '名称', + dataIndex: 'course_name', + key: 'course_name', + render: (text, record) =>
{text}
, + }, + { + title: '学习人数', + dataIndex: 'students_count', + key: 'students_count', + render: (text, record) =>
{text}
, + }, + { + title: '被fork发布的学习人数', + dataIndex: 'shixun_homework_count', + key: 'shixun_homework_count', + render: (text, record) =>
{text}
, + }, + { + title: '有效作品数', + dataIndex: 'valid_count', + key: 'valid_count', + render: (text, record) =>
{text}
, + }, + { + title: '应用值', + dataIndex: 'score', + key: 'score', + render: (text, record) =>
{text}
, + }, + ]; + + + console.log(this.state.shixundata) + return ( + +
+ + 全国高校计算机大赛战 + 报名 + 战队详情 + + + + + 实训项目 + +
').addClass('cw').text('#')); + } + + while (currentDate.isBefore(viewDate.clone().endOf('w'))) { + row.append($('').addClass('dow').text(currentDate.format('dd'))); + currentDate.add(1, 'd'); + } + widget.find('.datepicker-days thead').append(row); + }, + + isInDisabledDates = function (testDate) { + return options.disabledDates[testDate.format('YYYY-MM-DD')] === true; + }, + + isInEnabledDates = function (testDate) { + return options.enabledDates[testDate.format('YYYY-MM-DD')] === true; + }, + + isInDisabledHours = function (testDate) { + return options.disabledHours[testDate.format('H')] === true; + }, + + isInEnabledHours = function (testDate) { + return options.enabledHours[testDate.format('H')] === true; + }, + + isValid = function (targetMoment, granularity) { + if (!targetMoment.isValid()) { + return false; + } + if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) { + return false; + } + if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) { + return false; + } + if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) { + return false; + } + if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) { + return false; + } + if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) { + return false; + } + if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) { + return false; + } + if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) { + return false; + } + if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) { + var found = false; + $.each(options.disabledTimeIntervals, function () { + if (targetMoment.isBetween(this[0], this[1])) { + found = true; + return false; + } + }); + if (found) { + return false; + } + } + return true; + }, + + fillMonths = function () { + var spans = [], + monthsShort = viewDate.clone().startOf('y').startOf('d'); + while (monthsShort.isSame(viewDate, 'y')) { + spans.push($('').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM'))); + monthsShort.add(1, 'M'); + } + widget.find('.datepicker-months td').empty().append(spans); + }, + + updateMonths = function () { + var monthsView = widget.find('.datepicker-months'), + monthsViewHeader = monthsView.find('th'), + months = monthsView.find('tbody').find('span'); + + monthsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevYear); + monthsViewHeader.eq(1).attr('title', options.tooltips.selectYear); + monthsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextYear); + + monthsView.find('.disabled').removeClass('disabled'); + + if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) { + monthsViewHeader.eq(0).addClass('disabled'); + } + + monthsViewHeader.eq(1).text(viewDate.year()); + + if (!isValid(viewDate.clone().add(1, 'y'), 'y')) { + monthsViewHeader.eq(2).addClass('disabled'); + } + + months.removeClass('active'); + if (date.isSame(viewDate, 'y') && !unset) { + months.eq(date.month()).addClass('active'); + } + + months.each(function (index) { + if (!isValid(viewDate.clone().month(index), 'M')) { + $(this).addClass('disabled'); + } + }); + }, + + updateYears = function () { + var yearsView = widget.find('.datepicker-years'), + yearsViewHeader = yearsView.find('th'), + startYear = viewDate.clone().subtract(5, 'y'), + endYear = viewDate.clone().add(6, 'y'), + html = ''; + + yearsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevDecade); + yearsViewHeader.eq(1).attr('title', options.tooltips.selectDecade); + yearsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextDecade); + + yearsView.find('.disabled').removeClass('disabled'); + + if (options.minDate && options.minDate.isAfter(startYear, 'y')) { + yearsViewHeader.eq(0).addClass('disabled'); + } + + yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year()); + + if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) { + yearsViewHeader.eq(2).addClass('disabled'); + } + + while (!startYear.isAfter(endYear, 'y')) { + html += '' + startYear.year() + ''; + startYear.add(1, 'y'); + } + + yearsView.find('td').html(html); + }, + + updateDecades = function () { + var decadesView = widget.find('.datepicker-decades'), + decadesViewHeader = decadesView.find('th'), + startDecade = moment({ y: viewDate.year() - (viewDate.year() % 100) - 1 }), + endDecade = startDecade.clone().add(100, 'y'), + startedAt = startDecade.clone(), + minDateDecade = false, + maxDateDecade = false, + endDecadeYear, + html = ''; + + decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury); + decadesViewHeader.eq(2).find('span').attr('title', options.tooltips.nextCentury); + + decadesView.find('.disabled').removeClass('disabled'); + + if (startDecade.isSame(moment({ y: 1900 })) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) { + decadesViewHeader.eq(0).addClass('disabled'); + } + + decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year()); + + if (startDecade.isSame(moment({ y: 2000 })) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) { + decadesViewHeader.eq(2).addClass('disabled'); + } + + while (!startDecade.isAfter(endDecade, 'y')) { + endDecadeYear = startDecade.year() + 12; + minDateDecade = options.minDate && options.minDate.isAfter(startDecade, 'y') && options.minDate.year() <= endDecadeYear; + maxDateDecade = options.maxDate && options.maxDate.isAfter(startDecade, 'y') && options.maxDate.year() <= endDecadeYear; + html += '' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + ''; + startDecade.add(12, 'y'); + } + html += ''; //push the dangling block over, at least this way it's even + + decadesView.find('td').html(html); + decadesViewHeader.eq(1).text((startedAt.year() + 1) + '-' + (startDecade.year())); + }, + + fillDate = function () { + var daysView = widget.find('.datepicker-days'), + daysViewHeader = daysView.find('th'), + currentDate, + html = [], + row, + clsNames = [], + i; + + if (!hasDate()) { + return; + } + + daysViewHeader.eq(0).find('span').attr('title', options.tooltips.prevMonth); + daysViewHeader.eq(1).attr('title', options.tooltips.selectMonth); + daysViewHeader.eq(2).find('span').attr('title', options.tooltips.nextMonth); + + daysView.find('.disabled').removeClass('disabled'); + daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat)); + + if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) { + daysViewHeader.eq(0).addClass('disabled'); + } + if (!isValid(viewDate.clone().add(1, 'M'), 'M')) { + daysViewHeader.eq(2).addClass('disabled'); + } + + currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d'); + + for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks) + if (currentDate.weekday() === 0) { + row = $('
' + currentDate.week() + '' + currentDate.date() + '
' + currentHour.format(use24Hours ? 'HH' : 'hh') + '
' + currentMinute.format('mm') + '
' + currentSecond.format('ss') + '
<%= myshixun.id %> + <%= myshixun.identifier %> <% current_task = myshixun.last_executable_task || myshixun.last_task %> <%= link_to "/myshixuns/#{myshixun.identifier}/stages/#{current_task.identifier}", target: '_blank' do %> - <%= myshixun.identifier %> - <% end %> - - <%= link_to "/shixuns/#{myshixun.shixun.identifier}", target: '_blank' do %> <%= overflow_hidden_span myshixun.shixun.name, width: 280 %> <% end %>
姓名单位部门<%= sort_tag('学习关卡数', name: 'study_challenge_count', path: admins_user_statistics_path) %><%= sort_tag('完成关卡数', name: 'finish_challenge_count', path: admins_user_statistics_path) %><%= sort_tag('学习实训数', name: 'study_shixun_count', path: admins_user_statistics_path) %><%= sort_tag('完成实训数', name: 'finish_shixun_count', path: admins_user_statistics_path) %>单位部门学习关卡数<%#= sort_tag('学习关卡数', name: 'study_challenge_count', path: admins_user_statistics_path) %>完成关卡数<%#= sort_tag('完成关卡数', name: 'finish_challenge_count', path: admins_user_statistics_path) %><%= sort_tag('学习实训数', name: 'study_shixun_count', path: admins_user_statistics_path) %><%= sort_tag('完成实训数', name: 'finish_shixun_count', path: admins_user_statistics_path) %>评测次数实战时间
<%= user.display_extra_data(:finish_challenge_count) %> <%= user.display_extra_data(:study_shixun_count) %> <%= user.display_extra_data(:finish_shixun_count) %><%= user.display_extra_data(:evaluate_count) %><%= Util.display_cost_time(user.display_extra_data(:cost_time)) || '--' %>
+ + 翻转课堂 + +
+ + + + + + + + + ) + } +} +export default Competitionteams; \ No newline at end of file diff --git a/public/react/src/modules/competitions/Competitioncommon/CompetitionCommon.css b/public/react/src/modules/competitions/Competitioncommon/CompetitionCommon.css new file mode 100644 index 000000000..5f6a96173 --- /dev/null +++ b/public/react/src/modules/competitions/Competitioncommon/CompetitionCommon.css @@ -0,0 +1,216 @@ +.teamsLayout{background: transparent !important;} +.teamsLayout .ant-layout-sider{ + background: transparent !important; + flex: 0 0 180px !important; + max-width: 180px !important; + min-width: 180px !important; + width: 180px !important; +} +.teamsLayout .teamsLayoutitle{ + font-size:18px; + font-family:PingFangSC-Semibold,PingFang SC; + font-weight:600; + color:rgba(5,16,26,1); + line-height:25px; + margin-top: 10px; + margin-bottom: 10px; +} +.teamsLayoutTable .ant-table-bordered .ant-table-thead > tr > th, .ant-table-bordered .ant-table-tbody > tr > td { + border-right: 1px solid transparent !important; +} + +.teamsLayoutTable .ant-table-body .ant-table-thead > tr> th:nth-last-child(1){ + border-right: 1px solid #e8e8e8 !important; +} + +.teamsLayoutTable .ant-table-body .ant-table-tbody > tr> td:nth-last-child(1){ + border-right: 1px solid #e8e8e8 !important; +} + +.teamsLayoutTable .ant-table-bordered .ant-table-thead > tr > th{ + background:#EEEEEE; + font-size: 14px; + font-family: PingFangSC-Regular,PingFang SC; + font-weight: 400; + color: rgba(102,102,102,1); + line-height: 20px; +} + +.teamsLayoutTable .ant-table-bordered .ant-table-tbody > tr > th{ + background:#EEEEEE; + font-size:14px; + font-family:PingFangSC-Regular,PingFang SC; + font-weight:400; + color:rgba(5,16,26,1); + line-height:20px; +} + +.teamsLayout .mt40{ + margin-top: 40px !important; +} + +.teamsLayoutheji{ + color: #878787; + font-size: 16px; +} + +.teamsLayoucolor-orange { + color: #ff6800!important; + font-size: 16px; +} + +.CompetitionCommonbanner{ + padding: 20px; + background:rgba(255,255,255,1); + box-shadow:3px 2px 12px 2px rgba(0,0,0,0.05); + position: relative; +} + +.CompetitionCommonbannerfont{ + height:100%; +} + +.CompetitionCommonbannerfont .competitionbannerdiv:nth-child(1){ + max-height:100px; + font-size:25px; + font-weight:400; + color:rgba(5,16,26,1); +} + +.CompetitionCommonbannerfont .competitionbannerdiv:nth-child(2){ + max-height: 70px; + font-size:16px; + font-weight:400; + /*color:rgba(155,155,155,1);*/ + color:#05101A; +} + +.CompetitionCommonbannerfont .competitionbannerdiv:nth-child(3){ + max-height: 70px; + font-size: 16px; + font-weight: 400; + /*color: rgba(155,155,155,1);*/ + color:#05101A; +} + + + +.Competitioncolor9b{ + color: #9B9B9B; +} + +.Competitioncolor77{ + color: #777777; + font-size: 14px; +} + +.Competitioncolor516{ + font-size:24px; + color:rgba(5,16,26,1); +} + +.Competitionfontsize22{ + font-size:22px; + font-weight:500; + color:rgba(255,255,255,1); +} + +.Competitionfontsize16{ + font-size: 16px; + font-weight: 400; + color: rgba(102,102,102,1); +} + +.ant-layout-sider { + position: relative; + min-width: 0; + background: #001529; + -webkit-transition: all 0.2s; + -o-transition: all 0.2s; + transition: all 0.2s; +} + +.CompetitionMenu .ant-menu-item::after { + left: 0px !important; + right: auto; + border-right: 5px solid #4CACFF; +} + +.CompetitionMenu .ant-menu-item{ + height: 30px; + line-height: 30px; + background:none; + color:#666; +} + +.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected { + background-color: transparent; +} + +.CompetitionMenu .ant-menu-item:not(:last-child){ + margin-bottom: 40px; + background: transparent; + color:#666; +} + +.CompetitionMenu .ant-menu-item{ + font-size: 18px; +} + +.CompetitionMenu .ant-menu-item-selected { + color: rgba(76,172,255,1) !important; +} + +.CompetitionMenu{ + width: 145px; + background: transparent; + border: 1px solid rgba(239,239,239,1); + padding-top: 20px; + padding-bottom: 40px !important; +} + +.teamsLayoutleft{ + background: transparent !important; +} + +.Competitioncharts{ + font-size: 24px; + color: rgba(5,16,26,1); +} +.Competitionfirst{ + width:233px; + height:298px; + background:rgba(250,250,250,1); + box-shadow:0px 2px 8px 2px rgba(255,134,34,0.5); + border-radius:5px; +} +.Competitionsecondary{ + width:234px; + height:277px; + background:rgba(250,250,250,1); + box-shadow:0px 3px 5px 0px rgba(254,190,154,1); + border-radius:5px; +} + +.Competitionthird{ + width: 234px; + height: 270px; + background: rgba(250,250,250,1); + box-shadow: 0px 4px 5px 0px rgba(200,200,202,1); + border-radius: 5px; +} + +.Competition399{ + height:399px; +} + +.Competitiontransparent table{ + background: transparent; +} + +.Commonimg{ + position: absolute; + right: -5px; + width:93px; + top: 20px; +} \ No newline at end of file diff --git a/public/react/src/modules/competitions/Competitioncommon/CompetitionCommon.js b/public/react/src/modules/competitions/Competitioncommon/CompetitionCommon.js new file mode 100644 index 000000000..f3177cece --- /dev/null +++ b/public/react/src/modules/competitions/Competitioncommon/CompetitionCommon.js @@ -0,0 +1,174 @@ +import React, { Component } from 'react'; +import { Breadcrumb,Layout,Table, Divider, Tag,Badge,Row, Col,Button, Menu, Icon} from 'antd'; +import { Link } from 'react-router-dom'; +import axios from 'axios'; +import {markdownToHTML,getImageUrl} from 'educoder'; +import CompetitionContents from './CompetitionContents'; +import CompetitionContentsChart from './CompetitionContentsChart'; +import NoneData from "../../courses/shixunHomework/shixunHomework"; + +import './CompetitionCommon.css'; + +const { Header, Footer, Sider, Content } = Layout; + +class CompetitionCommon extends Component{ + constructor(props) { + super(props) + this.state={ + data:undefined, + bannerdata:undefined + } + } + + componentDidMount(){ + window.document.title = '竞赛'; + this.getbannerdata(); + let url=`/competitions/${this.props.match.params.identifier}.json`; + axios.get(url).then((response) => { + if(response.status===200){ + this.setState({ + bannerdata:response.data + }) + } + }).catch((error) => { + console.log(error) + }) + } + + getbannerdata=()=>{ + let url=`/competitions/${this.props.match.params.identifier}/common_header.json`; + axios.get(url).then((response) => { + if(response.status===200){ + this.setState({ + data:response.data + }) + } + }).catch((error) => { + console.log(error) + }) + + } + + getrightdata=(id,typeid)=>{ +debugger + } + + render() { + let {data,bannerdata}=this.state; + // console.log(bannerdata) + return ( + data===undefined?"":
+ + + 在线竞赛 + {data&&data.name} + + +
+ + +
+ + + + + {data&&data.name} + + + 竞赛时间: + {data&&data.start_time}~{data&&data.end_time} + + + + + +
奖金
+ +
+
浏览数
+ +
+
报名数
+ + + + +
+
¥{data&&data.bonus}
+ +
+
{data.competition_status==="nearly_published"?"--":data&&data.visits_count}
+ +
+
{data.competition_status==="nearly_published"?"--":data&&data.member_count}
+ + + + + {data.competition_status==="ended"?:} +
+ {data.competition_status==="ended"? + : + } + + {data&&data.enroll_end_time===null?"":`报名截止时间:${data&&data.enroll_end_time}`} + + + + + + + + + {data&&data.competition_modules.map((item,key)=>{ + return( + + {item.has_url===false?this.getrightdata(item.id,item.module_type)}>{item.name}:this.getrightdata(item.id,item.module_type)} + >{item.name}} + + ) + })} + + + + + + + + + + + + + + ) + } +} +export default CompetitionCommon; \ No newline at end of file diff --git a/public/react/src/modules/competitions/Competitioncommon/CompetitionContents.js b/public/react/src/modules/competitions/Competitioncommon/CompetitionContents.js new file mode 100644 index 000000000..5ba381b24 --- /dev/null +++ b/public/react/src/modules/competitions/Competitioncommon/CompetitionContents.js @@ -0,0 +1,38 @@ +import React, { Component } from 'react'; +import {Button,Layout} from 'antd'; +import axios from 'axios'; +import {markdownToHTML,getImageUrl} from 'educoder'; +import NoneData from "../../courses/shixunHomework/shixunHomework"; + +const { Header, Footer, Sider, Content } = Layout; +class CompetitionContents extends Component{ + constructor(props) { + super(props) + this.state={ + + } + } + + componentDidMount(){ + window.document.title = '竞赛'; + + } + + + + render() { + + return ( + +
+ + + +
+ + ) + } +} +export default CompetitionContents; \ No newline at end of file diff --git a/public/react/src/modules/competitions/Competitioncommon/CompetitionContentsChart.js b/public/react/src/modules/competitions/Competitioncommon/CompetitionContentsChart.js new file mode 100644 index 000000000..9d7a10f18 --- /dev/null +++ b/public/react/src/modules/competitions/Competitioncommon/CompetitionContentsChart.js @@ -0,0 +1,189 @@ +import React, { Component } from 'react'; +import {Button,Layout,Tabs,Icon, Card, Avatar, Row, Col ,Table} from 'antd'; +import axios from 'axios'; +import {markdownToHTML,getImageUrl} from 'educoder'; +import NoneData from "../../courses/shixunHomework/shixunHomework"; + +const { Header, Footer, Sider, Content } = Layout; +const { TabPane } = Tabs; +const { Meta } = Card; + +class CompetitionContents extends Component{ + constructor(props) { + super(props) + this.state={ + + } + } + + componentDidMount(){ + window.document.title = '竞赛'; + + } + + + + render() { + const operations = ; + const columns = [ + { + title: 'Name', + dataIndex: 'name', + key: 'name', + render: text => {text}, + }, + { + title: 'Age', + dataIndex: 'age', + key: 'age', + }, + { + title: 'Address', + dataIndex: 'address', + key: 'address', + }, + { + title: 'Tags', + key: 'tags', + dataIndex: 'tags', + render: tags => ( + + 123123 + + ), + }, + { + title: 'Action', + key: 'action', + render: (text, record) => ( + + Invite {record.name} + Delete + + ), + }, + { + title: 'Values', + key: 'values', + dataIndex: 'values', + render: tags => ( + + 123123 + + ), + }, + ]; + + const data = [ + { + key: '1', + name: 'John Brown', + age: 32, + address: 'New York No. 1 Lake Park', + tags: ['nice', 'developer'], + values:123 + }, + { + key: '2', + name: 'Jim Green', + age: 42, + address: 'London No. 1 Lake Park', + tags: ['loser'], + values:123 + }, + { + key: '3', + name: 'Joe Black', + age: 32, + address: 'Sidney No. 1 Lake Park', + tags: ['cool', 'teacher'], + values:123 + }, + ]; + + + return ( +
+ + + + + + + + + + + + + + + + +
+ 总排名 + + + + + + } + > + + + + + + } + > + + + + + + + } + > + + + + + + +
+ + + + + + ) + } +} +export default CompetitionContents; \ No newline at end of file diff --git a/public/react/src/modules/competitions/Competitions.js b/public/react/src/modules/competitions/Competitions.js index cc52f610f..1b8da55d7 100644 --- a/public/react/src/modules/competitions/Competitions.js +++ b/public/react/src/modules/competitions/Competitions.js @@ -4,25 +4,46 @@ import { Redirect } from 'react-router'; import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; -import Loading from '../../Loading' +import Loading from '../../Loading'; import Loadable from 'react-loadable'; -import { TPMIndexHOC } from '../tpm/TPMIndexHOC' -import { SnackbarHOC } from 'educoder' +import { TPMIndexHOC } from '../tpm/TPMIndexHOC'; +import { SnackbarHOC } from 'educoder'; //新版竞赛首页 const CompetitionsIndex = Loadable({ - loader: () => import('./competitimain/CompetitionsIndex'), + loader: () => import('./Competitimain/CompetitionsIndex'), loading: Loading, }) +//竞赛详情页 +const CompetitionCommon=Loadable({ + loader: () => import('./Competitioncommon/CompetitionCommon'), + loading: Loading, +}) + + +//战队详情 +const CompetitionTeams = Loadable({ + loader: () => import('./Competition_teams/Competitionteams'), + loading: Loading, +}) + +//团队竞赛报名 +const Registration = Loadable({ + loader: () => import('../competition/Registration'), + loading: Loading, +}); + class Competitions extends Component { constructor(props) { super(props) } componentDidMount(){ - window.document.title = '竞赛' + console.log("Competitions竞赛"); + console.log(this.props); + window.document.title = '竞赛'; } render() { @@ -31,14 +52,37 @@ class Competitions extends Component {
- {/*新版竞赛首页*/} + {/*新版竞赛战队详情*/} + () + } + > + + + {/*新版竞赛报名*/} + () + } + /> + + {/*新版竞赛详情页面*/} + () + } + > + {/*新版竞赛首页*/} () } > +
diff --git a/public/react/src/modules/competitions/competitimain/CompetitionsIndex.js b/public/react/src/modules/competitions/competitimain/CompetitionsIndex.js deleted file mode 100644 index 3e0715736..000000000 --- a/public/react/src/modules/competitions/competitimain/CompetitionsIndex.js +++ /dev/null @@ -1,191 +0,0 @@ -import React, { Component } from 'react'; -import {BrowserRouter as Router,Route,Switch} from 'react-router-dom'; -import { Menu, Icon, List, Avatar,Row, Col,Tag,Pagination} from 'antd'; -import axios from 'axios'; -import './Competitionsindex.css'; -import NoneData from "../../courses/shixunHomework/shixunHomework"; - -const { SubMenu } = Menu; - -const IconText = ({ type, text }) => ( - - - {text} - -); - -class CompetitionsIndex extends Component{ - constructor(props) { - super(props) - this.state={ - current: 'all', - datas:undefined, - page:1 - - } - } - - componentDidMount(){ - window.document.title = '竞赛'; - - let{page}=this.state; - const Url =`/competitions.json`; - axios.get(Url,{params:{ - page:page - } - }).then((response) => { - if(response.status===200){ - this.setState({ - datas:response.data.competitions, - count:response.data.count, - }) - } - }) - .catch(function (error) { - console.log(error); - }); - } - - handleClick = e => { - console.log('click ', e); - this.setState({ - current: e.key, - }); - }; - - render() { - let {datas,page,count}=this.state; - - - // bonus: 0 - // current_stage: {name: "正赛 第一阶段", start_time: "2019-10-11 00:00:00", end_time: "2019-11-01 00:00:00"} - // description: null - // end_time: "2019-11-01 00:00:00" - // enroll_end_time: "2019-10-31 00:00:00" - // id: 7 - // identifier: "gcc-annotation-2019" - // image: null - // member_count: 540 - // name: "第二届全国绿色计算系列大赛" - // nearly_published: false - // published: true - // single_stage: false - // start_time: "2019-07-01 00:00:00" - // sub_title: "代码标注组" - // visits_count: 10181 - - return ( -
-
-
-
-
-
-
-
-
- -
-
- - - 全部 - - - 即将发布 - - - 进行中 - - - 往期比赛 - - -
-
- -
- ( - 竞赛时间: 2019-08-07 24: 00~2019-09-10 24: 00, - 报名截止时间:2019-08-07 08:10, - ]} - extra={ -
- -
-
奖金
- -
-
浏览数
- -
-
报名数
- - - - -
-
¥4500
- -
-
351
- -
-
351
- - - - - } - > - {item.name}{item.sub_title===null?"":{ - item.sub_title - }} - } - /> - {item.description} - - )} - /> - -
15 ? 'block':'none' - // // } - // } - > - - - -
- - { - datas===undefined?"":datas && datas.length===0? :"" - } - - - - - - - - ) - } -} -export default CompetitionsIndex; \ No newline at end of file diff --git a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js index 86b17e802..134be31c3 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js @@ -4,13 +4,8 @@ import {Link} from 'react-router-dom'; import {BrowserRouter as Router,Route,Switch} from 'react-router-dom'; import Loadable from 'react-loadable'; import Loading from '../../../Loading'; -import { CNotificationHOC } from '../common/CNotificationHOC' -import { RouteHOC } from './common' - -import locale from 'antd/lib/date-picker/locale/zh_CN'; import { WordsBtn, MarkdownToHtml, trigger, queryString, downloadFile } from 'educoder'; import axios from 'axios'; -import Modals from '../../modals/Modals'; import CoursesListType from '../coursesPublic/CoursesListType'; import AccessoryModal from "../coursesPublic/AccessoryModal"; import PublishRightnow from './PublishRightnow' diff --git a/public/react/src/modules/courses/busyWork/PublishRightnow.js b/public/react/src/modules/courses/busyWork/PublishRightnow.js index da2054124..ff0a1bbd3 100644 --- a/public/react/src/modules/courses/busyWork/PublishRightnow.js +++ b/public/react/src/modules/courses/busyWork/PublishRightnow.js @@ -1,7 +1,8 @@ import React,{ Component } from "react"; import { Input,Checkbox,Menu,Pagination } from "antd"; -import HomeworkModal from '../coursesPublic/HomeworkModal' +import HomeworkModal from '../coursesPublic/HomeworkModal'; +import OneSelfOrderModal from "../coursesPublic/OneSelfOrderModal"; import axios from 'axios' import moment from 'moment' import { getNextHalfHourOfMoment } from 'educoder' @@ -32,9 +33,12 @@ class PublishRightnow extends Component{ } homeworkstart=()=>{ - const isPublish = this.props.isPublish; + const isPublish = this.props.isPublish; + const isPublishtype = this.props.isPublishtype; + let showdatatypes=isPublish===true||isPublishtype===1; + if (!this.props.checkBoxValues || this.props.checkBoxValues.length == 0) { - this.props.showNotification(`请先选择要立即${isPublish ? "发布" : "截止"}的作业`) + this.props.showNotification(`请先选择要立即${showdatatypes? "发布" : "截止"}的作业`) return; } @@ -42,27 +46,30 @@ class PublishRightnow extends Component{ } - showDialog = () => { + showDialog = (course_groups) => { const isPublish = this.props.isPublish; + const isPublishtype = this.props.isPublishtype; const dateFormat = 'YYYY-MM-DD HH:mm'; - - // getNextHalfHourOfMoment + let showdatatype=isPublish===true&&isPublishtype===undefined; + let showdatatypes=isPublish===true||isPublishtype===1; + // getNextHalfHourOfMoment const startMoment = (moment()); this.setState({ - modalname: isPublish ? "立即发布" : "立即截止", - modaltype:1, - visible:true, - Topval: isPublish ? "学生将立即收到作业" : "学生将不能再提交作品", + modalname: showdatatypes ? "立即发布" : "立即截止", + modaltype:course_groups.length> 0 ? 1 : 2, + visible:showdatatype?false:true, + OneSelftype:showdatatype?true:false, + Topval:showdatatypes ? "学生将立即收到作业" : "学生将不能再提交作品", // Botvalleft: isPublish ? "暂不发布" : "暂不截止", - Botval: this.props.fromListPage ? (isPublish ? "本操作只对“未发布”的分班有效" : "本操作只对“提交中”的分班有效") : '', - starttime: isPublish ? `发布时间:${startMoment.format(dateFormat)}` : '', - starttimes:isPublish ? `${startMoment.format(dateFormat)}` : '', - endtime: isPublish ? `截止时间:${startMoment.add(1, 'months').add(1, 'hours').minutes(0).format(dateFormat)}` : '', - Cancelname:isPublish ? "暂不发布" : "暂不截止", - Savesname:isPublish ? "立即发布" : "立即截止", + Botval: this.props.fromListPage ? (showdatatypes ? "本操作只对“未发布”的分班有效" : "本操作只对“提交中”的分班有效") : '', + starttime: showdatatypes? `发布时间:${startMoment.format(dateFormat)}` : '', + starttimes:showdatatypes? `${startMoment.format(dateFormat)}` : '', + endtime:showdatatypes ? `截止时间:${startMoment.add(1, 'months').add(1, 'hours').minutes(0).format(dateFormat)}` : '', + Cancelname:showdatatypes ? "暂不发布" : "暂不截止", + Savesname:showdatatypes ? "立即发布" : "立即截止", Cancel:this.homeworkhide, Saves:this.homeworkstartend, - typs:isPublish ? "start" : "end", + typs:showdatatypes ? "start" : "end", }) } homeworkhide=()=>{ @@ -70,6 +77,7 @@ class PublishRightnow extends Component{ modalname:undefined, modaltype:undefined, visible:false, + OneSelftype:false, Topval:undefined, Topvalright:undefined, Botvalleft:undefined, @@ -106,19 +114,30 @@ class PublishRightnow extends Component{ this.props.showNotification('请至少选择一个分班'); return; } - + let data={} + if(arg_group_ids.length===0){ + data = { + homework_ids: this.props.checkBoxValues, + end_time: endtime==="Invalid date"?undefined:endtime, + } + }else{ + data={ + homework_ids: this.props.checkBoxValues, + group_ids: group_ids, + group_end_times:endtime, + detail:true + } + } + const isPublishtype = this.props.isPublishtype; + let showdatatypes=isPublish===true||isPublishtype===1; let coursesId=this.props.match.params.coursesId; - const url = `/courses/${coursesId}/homework_commons/${isPublish ? "publish_homework" : "end_homework"}.json` - axios.post(url, { - group_ids, - homework_ids: this.props.checkBoxValues, - all_check: 0, - end_time:endtime==="Invalid date"?undefined:endtime - }) + const url = `/courses/${coursesId}/homework_commons/${showdatatypes ? "publish_homework" : "end_homework"}.json` + axios.post(url, data) .then((response) => { if (response.data.status == 0) { - this.props.showNotification(isPublish ? "立即发布成功" : "立即截止成功") + this.homeworkhide() + this.props.showNotification(showdatatypes ? "立即发布成功" : "立即截止成功") this.props.doWhenSuccess && this.props.doWhenSuccess() this.setState({ visible : false }) this.props.action && this.props.action() @@ -134,13 +153,16 @@ class PublishRightnow extends Component{ // } // } fetchCourseGroups = () => { + const isPublish = this.props.isPublish; + const isPublishtype = this.props.isPublishtype; + let showdatatypes=isPublish===true||isPublishtype===1; let coursesId=this.props.match.params.coursesId; // TODO 这里要改成单选作业,接口使用这个 https://www.showdoc.cc/127895880302646?page_id=2035541497546668 // /homework_commons/:id/publish_groups.json let url = `/courses/${coursesId}/all_course_groups.json` if (this.props.checkBoxValues.length == 1) { const isPublish = this.props.isPublish; - url = `/homework_commons/${this.props.checkBoxValues[0]}/${ isPublish ? 'publish_groups' : 'end_groups'}.json` + url = `/homework_commons/${this.props.checkBoxValues[0]}/${ showdatatypes ? 'publish_groups' : 'end_groups'}.json` } axios.get(url, { @@ -150,9 +172,10 @@ class PublishRightnow extends Component{ this.setState({ visible : false }) return; } - this.showDialog() + this.showDialog(response.data.course_groups) this.setState({ course_groups: response.data.course_groups, + starttimesend:response.data.end_time===undefined||response.data.end_time===null||response.data.end_time===""?undefined:response.data.end_time, }) }) .catch(function (error) { @@ -162,6 +185,8 @@ class PublishRightnow extends Component{ render(){ const isPublish = this.props.isPublish; + const isPublishtype = this.props.isPublishtype; + let showdatatypes=isPublish===true||isPublishtype===1; let{ Topvalright, @@ -184,6 +209,7 @@ class PublishRightnow extends Component{ const { showActionButton } = this.props return(
+ {/*立即截止*/} {visible===true?:""} - { showActionButton && { isPublish ? "立即发布" : "立即截止" } } + {/*立即发布*/} + {this.state.OneSelftype===true?:""} + { showActionButton && { showdatatypes ? "立即发布" : "立即截止" } }
) } diff --git a/public/react/src/modules/courses/busyWork/commonWork.js b/public/react/src/modules/courses/busyWork/commonWork.js index f6a989354..d07513c50 100644 --- a/public/react/src/modules/courses/busyWork/commonWork.js +++ b/public/react/src/modules/courses/busyWork/commonWork.js @@ -431,7 +431,9 @@ class commonWork extends Component{ > + isPublish={true} + isPublishtype={1} + doWhenSuccess={this.doWhenSuccess} fromListPage={true}> { mainList && mainList.course_identity < 5 && mainList.homeworks.length>0 &&
diff --git a/public/react/src/modules/courses/coursesPublic/HomeworkModal.js b/public/react/src/modules/courses/coursesPublic/HomeworkModal.js index ee19745c9..69eb937ff 100644 --- a/public/react/src/modules/courses/coursesPublic/HomeworkModal.js +++ b/public/react/src/modules/courses/coursesPublic/HomeworkModal.js @@ -235,10 +235,14 @@ class HomeworkModal extends Component{ @@ -251,7 +255,7 @@ class HomeworkModal extends Component{
  • item.id); - this.shixunhomeworkedit(arr); + if(this.props.course_groups!=undefined) { + let arr = this.props.course_groups.map(item => item.id); + let newarr = []; + let course_groups = this.props.course_groups; + course_groups.map((item, key) => { + if (item.end_time === null) { + // if(this.props.starttimesend===undefined){ + // item.end_time = moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm"); + // }else{ + // item.end_time = moment(handleDateString(this.props.starttimesend)).format("YYYY-MM-DD HH:mm"); + // } + item.end_time = moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm"); + newarr.push(item) + } else { + newarr.push(item) + } + }) + this.setState({ + course_groups: newarr + }) + this.shixunhomeworkedit(arr); + } } if(this.props.starttimes===undefined||this.props.starttimes===""||this.props.starttimes===null){ - this.setState({ - endtime:moment(moment(handleDateString(this.props.staytime)).add(1, 'months')).format("YYYY-MM-DD HH:mm") - }) + if(this.props.starttimesend===undefined){ + this.setState({ + endtime:moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm") + }) + }else{ + this.setState({ + endtime:moment(handleDateString(this.props.starttimesend)).format("YYYY-MM-DD HH:mm") + }) + } + }else{ - this.setState({ - endtime:moment(handleDateString(this.props.starttimes)).format("YYYY-MM-DD HH:mm") - }) + if(this.props.starttimesend===undefined){ + this.setState({ + endtime:moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm") + }) + }else{ + this.setState({ + endtime:moment(handleDateString(this.props.starttimesend)).format("YYYY-MM-DD HH:mm") + }) + } } } componentDidUpdate=(prevProps)=>{ - // if(prevProps.visible!=this.props.visible){ - // - // if(this.props.course_groups!=undefined){ - // let arr=this.props.course_groups.map(item => item.id); - // this.shixunhomeworkedit(arr); - // } - // } + if(prevProps.course_groups!=this.props.course_groups){ - if(this.props.course_groups!=undefined){ - let arr=this.props.course_groups.map(item => item.id); - this.shixunhomeworkedit(arr); - } + if(this.props.course_groups!=undefined){ + let arr=this.props.course_groups.map(item => item.id); + let newarr=[]; + let course_groups=this.props.course_groups; + course_groups.map((item,key)=>{ + if(item.end_time===null){ + item.end_time = moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm"); + newarr.push(item) + }else{ + newarr.push(item) + } + }) + this.setState({ + course_groups:newarr + }) + this.shixunhomeworkedit(arr); + } } + + if(prevProps.starttimes!=this.props.starttimes){ if(this.props.starttimes===undefined||this.props.starttimes===""||this.props.starttimes===null){ - this.setState({ - endtime:moment(moment(handleDateString(this.props.staytime)).add(1, 'months')).format("YYYY-MM-DD HH:mm") - }) + if(this.props.starttimesend===undefined){ + this.setState({ + endtime:moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm") + }) + }else{ + this.setState({ + endtime:moment(handleDateString(this.props.starttimesend)).format("YYYY-MM-DD HH:mm") + }) + } + }else{ - this.setState({ - endtime:moment(handleDateString(this.props.starttimes)).format("YYYY-MM-DD HH:mm") - }) + if(this.props.starttimesend===undefined){ + this.setState({ + endtime:moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm") + }) + }else{ + this.setState({ + endtime:moment(handleDateString(this.props.starttimesend)).format("YYYY-MM-DD HH:mm") + }) + } } } } @@ -101,50 +157,140 @@ class OneSelfOrderModal extends Component{ } + onChangeTimeendlist=(date, dateString,id)=>{ + let {course_groups,endtimetypeid}=this.state; + if(endtimetypeid===id){ + if(date!=null){ + this.setState({ + endtimetypeid:undefined + }) + } + if(moment(dateString,"YYYY-MM-DD HH:mm") <= moment(this.props.starttime,"YYYY-MM-DD HH:mm")){}else{ + if(date!=null){ + this.setState({ + endtimetypeid:undefined + }) + } + } + } + let arr=course_groups; + + arr.map((item,key)=>{ + if(item.id===id){ + item.end_time=date===null?"":moment(handleDateString(dateString)).format('YYYY-MM-DD HH:mm') + } + }) + + this.setState({ + course_groups:arr + }) + + } + propsSaves=(ds,endtime)=>{ + let {course_groups}=this.state; - if(ds.length ===0&&endtime === ""){ + if(this.props.typs=="end"){ this.props.Saves() }else{ - if(this.props.typs!="end"){ - if(endtime === ""||endtime===undefined||endtime===null){ + if(this.props.typs!="end"){ + if(!endtime){ this.setState({ endtimetype:true, endtimetypevalue:"截止时间不能为空" }) return } - - if(moment(endtime,"YYYY-MM-DD HH:mm") <= moment(this.props.starttimes,"YYYY-MM-DD HH:mm")){ + if(moment(endtime,"YYYY-MM-DD HH:mm") <= moment(this.props.starttime,"YYYY-MM-DD HH:mm")){ this.setState({ endtimetype:true, - endtimetypevalue:"必须晚于发布时间" + endtimetypevalue:"必须晚于当前时间" }) return } } - this.props.Saves(ds,moment(handleDateString(endtime),"YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm")) - } + + let type=false + if(course_groups===undefined||course_groups.length===0){ + this.props.Saves(ds,moment(handleDateString(endtime),"YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm")) + }else{ + let arr=[] + ds.map((item,key)=>{ + course_groups.map((items,key)=>{ + if(item===items.id){ + if(!items.end_time){ + type=true + this.setState({ + endtimetype:true, + endtimetypeid:items.id, + endtimetypevalue:"截止时间不能为空" + }) + return + + // arr.push(moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm")) + }else{ + if(moment(items.end_time,"YYYY-MM-DD HH:mm") <= moment(this.props.starttime,"YYYY-MM-DD HH:mm")){ + this.setState({ + endtimetype:true, + endtimetypevalue:"必须晚于当前时间" + }) + return + } + arr.push(items.end_time) + } + } + }) + }) + + if(type===false){ + this.props.Saves(ds,arr) + } + + } + } } - render(){ - let {group_ids,endtime}=this.state; - let {course_groups}=this.props; + Checkboxtype=(e)=>{ - // console.log(this.props.starttimes) - // console.log(endtime) - // console.log(this.props.starttimes) - // console.log(this.state.endtime) + let {course_groups}=this.state; - // console.log(this.props.starttime,this.props.endtime) - // TODO course_groups为空时的处理 + let arr=[]; + if(e.target.checked==true){ + course_groups.map((item,key)=>{ + arr.push(item.id) + }) + }else{ + arr=[] + } + this.setState({ + Checkboxtype:e.target.checked, + group_ids:arr + }) + } - // let endtimelist=this.props.starttimes===undefined||this.props.starttimes===""?"":moment(handleDateString(endtime)).add(1,'months') + render(){ + let {group_ids,endtime,course_groups}=this.state; + console.log(this.props.modaltype) + let course_groupstype=course_groups===undefined||course_groups.length===0; + // TODO course_groups为空时的处理 return(
    + { this.props.OneSelftype===true? - {datas===undefined?"":
  • } diff --git a/public/react/src/modules/ecs/EcSetting/reachCalculationInfo/index.scss b/public/react/src/modules/ecs/EcSetting/reachCalculationInfo/index.scss index 56a260b5e..324d88ea5 100644 --- a/public/react/src/modules/ecs/EcSetting/reachCalculationInfo/index.scss +++ b/public/react/src/modules/ecs/EcSetting/reachCalculationInfo/index.scss @@ -31,6 +31,9 @@ .font-18 { font-size: 18px!important; } +.font-26 { + font-size: 26px!important; +} .fl { float: left!important; } diff --git a/public/react/src/modules/forums/MemoDetail.js b/public/react/src/modules/forums/MemoDetail.js index cc206713b..7578eea6e 100644 --- a/public/react/src/modules/forums/MemoDetail.js +++ b/public/react/src/modules/forums/MemoDetail.js @@ -22,7 +22,7 @@ import {ImageLayerOfCommentHOC} from '../page/layers/ImageLayerOfCommentHOC' import MemoDetailKEEditor from './MemoDetailKEEditor' import MemoDetailMDEditor from './MemoDetailMDEditor' -import { bytesToSize, CBreadcrumb } from 'educoder' +import { bytesToSize, CBreadcrumb ,htmlEncode} from 'educoder' import { Tooltip } from 'antd' // import CBreadcrumb from '../courses/common/CBreadcrumb' @@ -246,6 +246,8 @@ class MemoDetail extends Component { if (commentContent) { commentContent = commentContent.replace(/(\n

    \n\t
    \n<\/p>)*$/g,''); } + + commentContent=htmlEncode(commentContent) axios.post(url, { parent_id: id, content: commentContent @@ -491,6 +493,7 @@ class MemoDetail extends Component { const url = `/memos/reply.json`; let { comments } = this.state; const user = this._getUser(); + content=htmlEncode(content) axios.post(url, { parent_id: memo.id, content: content diff --git a/public/react/src/modules/home/shixunsHome.js b/public/react/src/modules/home/shixunsHome.js index bad776b89..4db39a310 100644 --- a/public/react/src/modules/home/shixunsHome.js +++ b/public/react/src/modules/home/shixunsHome.js @@ -111,7 +111,7 @@ class ShixunsHome extends Component { } const MyRate = ({ defaultValue, ...rest }) => { let myValue = defaultValue; - console.log(myValue-Math.floor(myValue)) + // console.log(myValue-Math.floor(myValue)) // if (myValue < Math.ceil(myValue)) { // myValue = Math.floor(myValue) + 0.5; // } diff --git a/public/react/src/modules/message/js/MessagChat.js b/public/react/src/modules/message/js/MessagChat.js index 34494a256..e320ff3a3 100644 --- a/public/react/src/modules/message/js/MessagChat.js +++ b/public/react/src/modules/message/js/MessagChat.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import "../css/messagemy.css" -import {getImageUrl,markdownToHTML} from 'educoder'; +import {getImageUrl,markdownToHTML,htmlEncode} from 'educoder'; import { Modal,Input,Icon,Tooltip,Spin} from 'antd'; import axios from 'axios'; import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; @@ -417,6 +417,7 @@ class MessagChat extends Component{ let contents=this.messageRef.current.getValue().trim(); const query = this.props.location.search; let target_ids = query.split('?target_ids='); + contents=htmlEncode(contents) let url = `/users/${this.props.match.params.userid}/private_messages.json`; axios.post(url, { target_id: target_ids[1], diff --git a/public/react/src/modules/message/messagemodal/WriteaprivateletterModal.js b/public/react/src/modules/message/messagemodal/WriteaprivateletterModal.js index dfa27ba9a..da0af0448 100644 --- a/public/react/src/modules/message/messagemodal/WriteaprivateletterModal.js +++ b/public/react/src/modules/message/messagemodal/WriteaprivateletterModal.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import { Modal,Input,Icon,Tooltip,Spin} from 'antd'; import axios from 'axios'; // import '../../modules/user/common.css'; -import {getImageUrl} from 'educoder'; +import {getImageUrl,htmlEncode} from 'educoder'; //完善个人资料 class WriteaprivateletterModal extends Component { @@ -58,6 +58,7 @@ class WriteaprivateletterModal extends Component { //发送私信 SendprivatemessageAPI=(idvalue,contentvalue)=>{ const url =`/users/${this.props.current_user.user_id}/private_messages.json` + contentvalue=htmlEncode(contentvalue) let data={ target_id:idvalue, content:contentvalue, diff --git a/public/stylesheets/css/iconfont.css b/public/stylesheets/css/iconfont.css index 142b620bd..87991b38e 100644 --- a/public/stylesheets/css/iconfont.css +++ b/public/stylesheets/css/iconfont.css @@ -1,10 +1,8 @@ @font-face {font-family: "iconfont"; - src: url('iconfont.eot?t=1571281327367'); /* IE9 */ - src: url('iconfont.eot?t=1571281327367#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), - url('iconfont.woff?t=1571281327367') format('woff'), - url('iconfont.ttf?t=1571281327367') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ - url('iconfont.svg?t=1571281327367#iconfont') format('svg'); /* iOS 4.1- */ + src: url('iconfont.eot?t=1571756926538'); /* IE9 */ + src: url('iconfont.eot?t=1571756926538#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), + url('iconfont.woff?t=1571756926538') format('woff'), + url('iconfont.ttf?t=1571756926538') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('iconfont.svg?t=1571756926538#iconfont') format('svg'); /* iOS 4.1- */ } .iconfont { @@ -715,6 +713,10 @@ content: "\e669"; } +.icon-fuzhi1:before { + content: "\e800"; +} + .icon-gengduo1:before { content: "\e7f9"; } @@ -887,3 +889,19 @@ content: "\e6be"; } +.icon-detectionx:before { + content: "\e6c1"; +} + +.icon-communityx:before { + content: "\e6c2"; +} + +.icon-hostingx2:before { + content: "\e6c3"; +} + +.icon-projectx:before { + content: "\e6c4"; +} + diff --git a/public/stylesheets/educoder/iconfont/demo_index.html b/public/stylesheets/educoder/iconfont/demo_index.html index 26baf8ac7..a8b8e705f 100644 --- a/public/stylesheets/educoder/iconfont/demo_index.html +++ b/public/stylesheets/educoder/iconfont/demo_index.html @@ -1079,8 +1079,14 @@

    下降
    &#xe669;
    - -
  • + +
  • + +
    复制
    +
    &#xe800;
    +
  • + +
  • 更多
    &#xe7f9;
    @@ -1337,7 +1343,31 @@
    nenghaofenxi@1x
    &#xe6be;
  • - + +
  • + +
    detection@1x
    +
    &#xe6c1;
    +
  • + +
  • + +
    community@1x
    +
    &#xe6c2;
    +
  • + +
  • + +
    hosting@1x
    +
    &#xe6c3;
    +
  • + +
  • + +
    project@1x
    +
    &#xe6c4;
    +
  • +

    Unicode 引用

    @@ -2962,8 +2992,17 @@
    .icon-xiajiang
    - -
  • + +
  • + +
    + 复制 +
    +
    .icon-fuzhi1 +
    +
  • + +
  • 更多 @@ -3349,7 +3388,43 @@
    .icon-nenghaofenxix
  • - + +
  • + +
    + detection@1x +
    +
    .icon-detectionx +
    +
  • + +
  • + +
    + community@1x +
    +
    .icon-communityx +
    +
  • + +
  • + +
    + hosting@1x +
    +
    .icon-hostingx2 +
    +
  • + +
  • + +
    + project@1x +
    +
    .icon-projectx +
    +
  • +

    font-class 引用

    @@ -4778,8 +4853,16 @@
    下降
    #icon-xiajiang
    - -
  • + +
  • + +
    复制
    +
    #icon-fuzhi1
    +
  • + +
  • @@ -5122,6 +5205,38 @@
    nenghaofenxi@1x
    #icon-nenghaofenxix
  • + +
  • + +
    detection@1x
    +
    #icon-detectionx
    +
  • + +
  • + +
    community@1x
    +
    #icon-communityx
    +
  • + +
  • + +
    hosting@1x
    +
    #icon-hostingx2
    +
  • + +
  • + +
    project@1x
    +
    #icon-projectx
    +
  • diff --git a/public/stylesheets/educoder/iconfont/iconfont.css b/public/stylesheets/educoder/iconfont/iconfont.css index 142b620bd..87991b38e 100644 --- a/public/stylesheets/educoder/iconfont/iconfont.css +++ b/public/stylesheets/educoder/iconfont/iconfont.css @@ -1,10 +1,8 @@ @font-face {font-family: "iconfont"; - src: url('iconfont.eot?t=1571281327367'); /* IE9 */ - src: url('iconfont.eot?t=1571281327367#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), - url('iconfont.woff?t=1571281327367') format('woff'), - url('iconfont.ttf?t=1571281327367') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ - url('iconfont.svg?t=1571281327367#iconfont') format('svg'); /* iOS 4.1- */ + src: url('iconfont.eot?t=1571756926538'); /* IE9 */ + src: url('iconfont.eot?t=1571756926538#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), + url('iconfont.woff?t=1571756926538') format('woff'), + url('iconfont.ttf?t=1571756926538') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('iconfont.svg?t=1571756926538#iconfont') format('svg'); /* iOS 4.1- */ } .iconfont { @@ -715,6 +713,10 @@ content: "\e669"; } +.icon-fuzhi1:before { + content: "\e800"; +} + .icon-gengduo1:before { content: "\e7f9"; } @@ -887,3 +889,19 @@ content: "\e6be"; } +.icon-detectionx:before { + content: "\e6c1"; +} + +.icon-communityx:before { + content: "\e6c2"; +} + +.icon-hostingx2:before { + content: "\e6c3"; +} + +.icon-projectx:before { + content: "\e6c4"; +} + diff --git a/public/stylesheets/educoder/iconfont/iconfont.eot b/public/stylesheets/educoder/iconfont/iconfont.eot index d26e316a6..f0e5fbf01 100644 Binary files a/public/stylesheets/educoder/iconfont/iconfont.eot and b/public/stylesheets/educoder/iconfont/iconfont.eot differ diff --git a/public/stylesheets/educoder/iconfont/iconfont.js b/public/stylesheets/educoder/iconfont/iconfont.js index 49cca2424..06afba4fe 100644 --- a/public/stylesheets/educoder/iconfont/iconfont.js +++ b/public/stylesheets/educoder/iconfont/iconfont.js @@ -1 +1 @@ -!function(z){var c,h='',l=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss");if(l&&!z.__iconfont__svg__cssinject__){z.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var l=function(){document.removeEventListener("DOMContentLoaded",l,!1),c()};document.addEventListener("DOMContentLoaded",l,!1)}else document.attachEvent&&(a=c,i=z.document,t=!1,(o=function(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(o,50)}h()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,h())});function h(){t||(t=!0,a())}var a,i,t,o}(function(){var c,l;(c=document.createElement("div")).innerHTML=h,h=null,(l=c.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",function(c,l){l.firstChild?function(c,l){l.parentNode.insertBefore(c,l)}(c,l.firstChild):l.appendChild(c)}(l,document.body))})}(window); \ No newline at end of file +!function(o){var c,h='',l=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss");if(l&&!o.__iconfont__svg__cssinject__){o.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var l=function(){document.removeEventListener("DOMContentLoaded",l,!1),c()};document.addEventListener("DOMContentLoaded",l,!1)}else document.attachEvent&&(a=c,i=o.document,t=!1,(z=function(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(z,50)}h()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,h())});function h(){t||(t=!0,a())}var a,i,t,z}(function(){var c,l;(c=document.createElement("div")).innerHTML=h,h=null,(l=c.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",function(c,l){l.firstChild?function(c,l){l.parentNode.insertBefore(c,l)}(c,l.firstChild):l.appendChild(c)}(l,document.body))})}(window); \ No newline at end of file diff --git a/public/stylesheets/educoder/iconfont/iconfont.json b/public/stylesheets/educoder/iconfont/iconfont.json index 1a21d0726..2cfdd7e3d 100644 --- a/public/stylesheets/educoder/iconfont/iconfont.json +++ b/public/stylesheets/educoder/iconfont/iconfont.json @@ -1230,6 +1230,13 @@ "unicode": "e669", "unicode_decimal": 58985 }, + { + "icon_id": "5255211", + "name": "复制", + "font_class": "fuzhi1", + "unicode": "e800", + "unicode_decimal": 59392 + }, { "icon_id": "5291605", "name": "更多", @@ -1530,6 +1537,34 @@ "font_class": "nenghaofenxix", "unicode": "e6be", "unicode_decimal": 59070 + }, + { + "icon_id": "11408531", + "name": "detection@1x", + "font_class": "detectionx", + "unicode": "e6c1", + "unicode_decimal": 59073 + }, + { + "icon_id": "11409495", + "name": "community@1x", + "font_class": "communityx", + "unicode": "e6c2", + "unicode_decimal": 59074 + }, + { + "icon_id": "11409771", + "name": "hosting@1x", + "font_class": "hostingx2", + "unicode": "e6c3", + "unicode_decimal": 59075 + }, + { + "icon_id": "11410432", + "name": "project@1x", + "font_class": "projectx", + "unicode": "e6c4", + "unicode_decimal": 59076 } ] } diff --git a/public/stylesheets/educoder/iconfont/iconfont.svg b/public/stylesheets/educoder/iconfont/iconfont.svg index e9aa3e2f9..f2f298f58 100644 --- a/public/stylesheets/educoder/iconfont/iconfont.svg +++ b/public/stylesheets/educoder/iconfont/iconfont.svg @@ -544,7 +544,12 @@ Created by iconfont - + + + + @@ -673,8 +678,26 @@ Created by iconfont - + + + + + + + + + + + - + diff --git a/public/stylesheets/educoder/iconfont/iconfont.ttf b/public/stylesheets/educoder/iconfont/iconfont.ttf index bf316a765..cef43d726 100644 Binary files a/public/stylesheets/educoder/iconfont/iconfont.ttf and b/public/stylesheets/educoder/iconfont/iconfont.ttf differ diff --git a/public/stylesheets/educoder/iconfont/iconfont.woff b/public/stylesheets/educoder/iconfont/iconfont.woff index b06206850..27daa6142 100644 Binary files a/public/stylesheets/educoder/iconfont/iconfont.woff and b/public/stylesheets/educoder/iconfont/iconfont.woff differ diff --git a/public/stylesheets/educoder/iconfont/iconfont.woff2 b/public/stylesheets/educoder/iconfont/iconfont.woff2 index 374af4f2a..0bbea822f 100644 Binary files a/public/stylesheets/educoder/iconfont/iconfont.woff2 and b/public/stylesheets/educoder/iconfont/iconfont.woff2 differ