diff --git a/app/assets/javascripts/admins/identity_authentications/index.js b/app/assets/javascripts/admins/identity_authentications/index.js index 2da644ec2..91ce5c7ec 100644 --- a/app/assets/javascripts/admins/identity_authentications/index.js +++ b/app/assets/javascripts/admins/identity_authentications/index.js @@ -1,6 +1,7 @@ $(document).on('turbolinks:load', function() { if ($('body.admins-identity-authentications-index-page').length > 0) { var $searchFrom = $('.identity-authentication-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -12,6 +13,7 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } diff --git a/app/assets/javascripts/admins/professional_authentications/index.js b/app/assets/javascripts/admins/professional_authentications/index.js index 769a6b2fc..82a1da5af 100644 --- a/app/assets/javascripts/admins/professional_authentications/index.js +++ b/app/assets/javascripts/admins/professional_authentications/index.js @@ -1,6 +1,7 @@ $(document).on('turbolinks:load', function() { if ($('body.admins-professional-authentications-index-page').length > 0) { var $searchFrom = $('.professional-authentication-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -12,6 +13,7 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } diff --git a/app/assets/javascripts/admins/shixun_authorizations/index.js b/app/assets/javascripts/admins/shixun_authorizations/index.js new file mode 100644 index 000000000..b98354c65 --- /dev/null +++ b/app/assets/javascripts/admins/shixun_authorizations/index.js @@ -0,0 +1,20 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-shixun-authorizations-index-page').length > 0) { + var $searchFrom = $('.shixun-authorization-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); + + $searchFrom.on('click', '.search-form-tab', function(){ + var $link = $(this); + + $searchFrom.find('input[name="keyword"]').val(''); + $searchFrom.find('select[name="status"]').val('processed'); + + if($link.data('value') === 'processed'){ + $searchFrom.find('.status-filter').show(); + } else { + $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); + } + }); + } +}) \ No newline at end of file diff --git a/app/assets/javascripts/admins/subject_authorizations/index.js b/app/assets/javascripts/admins/subject_authorizations/index.js new file mode 100644 index 000000000..bfba16fc1 --- /dev/null +++ b/app/assets/javascripts/admins/subject_authorizations/index.js @@ -0,0 +1,20 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-subject-authorizations-index-page').length > 0) { + var $searchFrom = $('.subject-authorization-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); + + $searchFrom.on('click', '.search-form-tab', function(){ + var $link = $(this); + + $searchFrom.find('input[name="keyword"]').val(''); + $searchFrom.find('select[name="status"]').val('processed'); + + if($link.data('value') === 'processed'){ + $searchFrom.find('.status-filter').show(); + } else { + $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); + } + }); + } +}) \ No newline at end of file diff --git a/app/assets/javascripts/bootstrap-notify.js b/app/assets/javascripts/bootstrap-notify.js old mode 100755 new mode 100644 diff --git a/app/assets/javascripts/bootstrap-notify.min.js b/app/assets/javascripts/bootstrap-notify.min.js old mode 100755 new mode 100644 diff --git a/app/assets/javascripts/i18n/select2-i18n.zh-CN.js b/app/assets/javascripts/i18n/select2-i18n.zh-CN.js old mode 100755 new mode 100644 diff --git a/app/assets/javascripts/jquery.cxselect.js b/app/assets/javascripts/jquery.cxselect.js old mode 100755 new mode 100644 index 9bd674664..aeb3c17dd --- a/app/assets/javascripts/jquery.cxselect.js +++ b/app/assets/javascripts/jquery.cxselect.js @@ -1,403 +1,403 @@ -/*! - * jQuery cxSelect - * @name jquery.cxselect.js - * @version 1.4.1 - * @date 2016-11-02 - * @author ciaoca - * @email ciaoca@gmail.com - * @site https://github.com/ciaoca/cxSelect - * @license Released under the MIT license - */ -(function(factory) { - if (typeof define === 'function' && define.amd) { - define(['jquery'], factory); - } else { - factory(window.jQuery || window.Zepto || window.$); - }; -}(function($) { - var cxSelect = function() { - var self = this; - var dom, settings, callback; - - // 分配参数 - for (var i = 0, l = arguments.length; i < l; i++) { - if (cxSelect.isJquery(arguments[i]) || cxSelect.isZepto(arguments[i])) { - dom = arguments[i]; - } else if (cxSelect.isElement(arguments[i])) { - dom = $(arguments[i]); - } else if (typeof arguments[i] === 'function') { - callback = arguments[i]; - } else if (typeof arguments[i] === 'object') { - settings = arguments[i]; - }; - }; - - var api = new cxSelect.init(dom, settings); - - if (typeof callback === 'function') { - callback(api); - }; - - return api; - }; - - cxSelect.isElement = function(o){ - if (o && (typeof HTMLElement === 'function' || typeof HTMLElement === 'object') && o instanceof HTMLElement) { - return true; - } else { - return (o && o.nodeType && o.nodeType === 1) ? true : false; - }; - }; - - cxSelect.isJquery = function(o){ - return (o && o.length && (typeof jQuery === 'function' || typeof jQuery === 'object') && o instanceof jQuery) ? true : false; - }; - - cxSelect.isZepto = function(o){ - return (o && o.length && (typeof Zepto === 'function' || typeof Zepto === 'object') && Zepto.zepto.isZ(o)) ? true : false; - }; - - cxSelect.getIndex = function(n, required) { - return required ? n : n - 1; - }; - - cxSelect.getData = function(data, space) { - if (typeof space === 'string' && space.length) { - space = space.split('.'); - for (var i = 0, l = space.length; i < l; i++) { - data = data[space[i]]; - }; - }; - return data; - }; - - cxSelect.init = function(dom, settings) { - var self = this; - - if (!cxSelect.isJquery(dom) && !cxSelect.isZepto(dom)) {return}; - - var theSelect = { - dom: { - box: dom - } - }; - - self.attach = cxSelect.attach.bind(theSelect); - self.detach = cxSelect.detach.bind(theSelect); - self.setOptions = cxSelect.setOptions.bind(theSelect); - self.clear = cxSelect.clear.bind(theSelect); - - theSelect.changeEvent = function() { - cxSelect.selectChange.call(theSelect, this.className); - }; - - theSelect.settings = $.extend({}, $.cxSelect.defaults, settings, { - url: theSelect.dom.box.data('url'), - emptyStyle: theSelect.dom.box.data('emptyStyle'), - required: theSelect.dom.box.data('required'), - firstTitle: theSelect.dom.box.data('firstTitle'), - firstValue: theSelect.dom.box.data('firstValue'), - jsonSpace: theSelect.dom.box.data('jsonSpace'), - jsonName: theSelect.dom.box.data('jsonName'), - jsonValue: theSelect.dom.box.data('jsonValue'), - jsonSub: theSelect.dom.box.data('jsonSub') - }); - - var _dataSelects = theSelect.dom.box.data('selects'); - - if (typeof _dataSelects === 'string' && _dataSelects.length) { - theSelect.settings.selects = _dataSelects.split(','); - }; - - self.setOptions(); - self.attach(); - - // 使用独立接口获取数据 - if (!theSelect.settings.url && !theSelect.settings.data) { - cxSelect.start.apply(theSelect); - - // 设置自定义数据 - } else if ($.isArray(theSelect.settings.data)) { - cxSelect.start.call(theSelect, theSelect.settings.data); - - // 设置 URL,通过 Ajax 获取数据 - } else if (typeof theSelect.settings.url === 'string' && theSelect.settings.url.length) { - $.getJSON(theSelect.settings.url, function(json) { - cxSelect.start.call(theSelect, json); - }); - }; - }; - - // 设置参数 - cxSelect.setOptions = function(opts) { - var self = this; - - if (opts) { - $.extend(self.settings, opts); - }; - - // 初次或重设选择器组 - if (!$.isArray(self.selectArray) || !self.selectArray.length || (opts && opts.selects)) { - self.selectArray = []; - - if ($.isArray(self.settings.selects) && self.settings.selects.length) { - var _tempSelect; - - for (var i = 0, l = self.settings.selects.length; i < l; i++) { - _tempSelect = self.dom.box.find('select.' + self.settings.selects[i]); - - if (!_tempSelect || !_tempSelect.length) {break}; - - self.selectArray.push(_tempSelect); - }; - }; - }; - - if (opts) { - if (!$.isArray(opts.data) && typeof opts.url === 'string' && opts.url.length) { - $.getJSON(self.settings.url, function(json) { - cxSelect.start.call(self, json); - }); - - } else { - cxSelect.start.call(self, opts.data); - }; - }; - }; - - // 绑定 - cxSelect.attach = function() { - var self = this; - - if (!self.attachStatus) { - self.dom.box.on('change', 'select', self.changeEvent); - }; - - if (typeof self.attachStatus === 'boolean') { - cxSelect.start.call(self); - }; - - self.attachStatus = true; - }; - - // 移除绑定 - cxSelect.detach = function() { - var self = this; - self.dom.box.off('change', 'select', self.changeEvent); - self.attachStatus = false; - }; - - // 清空选项 - cxSelect.clear = function(index) { - var self = this; - var _style = { - display: '', - visibility: '' - }; - - index = isNaN(index) ? 0 : index; - - // 清空后面的 select - for (var i = index, l = self.selectArray.length; i < l; i++) { - self.selectArray[i].empty().prop('disabled', true); - - if (self.settings.emptyStyle === 'none') { - _style.display = 'none'; - } else if (self.settings.emptyStyle === 'hidden') { - _style.visibility = 'hidden'; - }; - - self.selectArray[i].css(_style); - }; - }; - - cxSelect.start = function(data) { - var self = this; - - if ($.isArray(data)) { - self.settings.data = cxSelect.getData(data, self.settings.jsonSpace); - }; - - if (!self.selectArray.length) {return}; - - // 保存默认值 - for (var i = 0, l = self.selectArray.length; i < l; i++) { - if (typeof self.selectArray[i].attr('data-value') !== 'string' && self.selectArray[i][0].options.length) { - self.selectArray[i].attr('data-value', self.selectArray[i].val()); - }; - }; - - if (self.settings.data || (typeof self.selectArray[0].data('url') === 'string' && self.selectArray[0].data('url').length)) { - cxSelect.getOptionData.call(self, 0); - } else { - self.selectArray[0].prop('disabled', false).css({ - 'display': '', - 'visibility': '' - }); - }; - }; - - // 获取选项数据 - cxSelect.getOptionData = function(index) { - var self = this; - - if (typeof index !== 'number' || isNaN(index) || index < 0 || index >= self.selectArray.length) {return}; - - var _indexPrev = index - 1; - var _select = self.selectArray[index]; - var _selectData; - var _valueIndex; - var _dataUrl = _select.data('url'); - var _jsonSpace = typeof _select.data('jsonSpace') === 'undefined' ? self.settings.jsonSpace : _select.data('jsonSpace'); - var _query = {}; - var _queryName; - var _selectName; - var _selectValue; - - cxSelect.clear.call(self, index); - - // 使用独立接口 - if (typeof _dataUrl === 'string' && _dataUrl.length) { - if (index > 0) { - for (var i = 0, j = 1; i < index; i++, j++) { - _queryName = self.selectArray[j].data('queryName'); - _selectName = self.selectArray[i].attr('name'); - _selectValue = self.selectArray[i].val(); - - if (typeof _queryName === 'string' && _queryName.length) { - _query[_queryName] = _selectValue; - } else if (typeof _selectName === 'string' && _selectName.length) { - _query[_selectName] = _selectValue; - }; - }; - }; - - $.getJSON(_dataUrl, _query, function(json) { - _selectData = cxSelect.getData(json, _jsonSpace); - - cxSelect.buildOption.call(self, index, _selectData); - }); - - // 使用整合数据 - } else if (self.settings.data && typeof self.settings.data === 'object') { - _selectData = self.settings.data; - - for (var i = 0; i < index; i++) { - _valueIndex = cxSelect.getIndex(self.selectArray[i][0].selectedIndex, typeof self.selectArray[i].data('required') === 'boolean' ? self.selectArray[i].data('required') : self.settings.required); - - if (typeof _selectData[_valueIndex] === 'object' && $.isArray(_selectData[_valueIndex][self.settings.jsonSub]) && _selectData[_valueIndex][self.settings.jsonSub].length) { - _selectData = _selectData[_valueIndex][self.settings.jsonSub]; - } else { - _selectData = null; - break; - }; - }; - - cxSelect.buildOption.call(self, index, _selectData); - }; - }; - - // 构建选项列表 - cxSelect.buildOption = function(index, data) { - var self = this; - - var _select = self.selectArray[index]; - var _required = typeof _select.data('required') === 'boolean' ? _select.data('required') : self.settings.required; - var _firstTitle = typeof _select.data('firstTitle') === 'undefined' ? self.settings.firstTitle : _select.data('firstTitle'); - var _firstValue = typeof _select.data('firstValue') === 'undefined' ? self.settings.firstValue : _select.data('firstValue'); - var _jsonName = typeof _select.data('jsonName') === 'undefined' ? self.settings.jsonName : _select.data('jsonName'); - var _jsonValue = typeof _select.data('jsonValue') === 'undefined' ? self.settings.jsonValue : _select.data('jsonValue'); - - if (!$.isArray(data)) {return}; - - var _html = !_required ? '' : ''; - - // 区分标题、值的数据 - if (typeof _jsonName === 'string' && _jsonName.length) { - // 无值字段时使用标题作为值 - if (typeof _jsonValue !== 'string' || !_jsonValue.length) { - _jsonValue = _jsonName; - }; - - for (var i = 0, l = data.length; i < l; i++) { - _html += ''; - }; - - // 数组即为值的数据 - } else { - for (var i = 0, l = data.length; i < l; i++) { - _html += ''; - }; - }; - - _select.html(_html).prop('disabled', false).css({ - 'display': '', - 'visibility': '' - }); - - // 初次加载设置默认值 - if (typeof _select.attr('data-value') === 'string') { - _select.val(String(_select.attr('data-value'))).removeAttr('data-value'); - - if (_select[0].selectedIndex < 0) { - _select[0].options[0].selected = true; - }; - }; - - if (_required || _select[0].selectedIndex > 0) { - _select.trigger('change'); - }; - - }; - - // 改变选择时的处理 - cxSelect.selectChange = function(name) { - var self = this; - - if (typeof name !== 'string' || !name.length) {return}; - - var index; - - name = name.replace(/\s+/g, ','); - name = ',' + name + ','; - - // 获取当前 select 位置 - for (var i = 0, l = self.selectArray.length; i < l; i++) { - if (name.indexOf(',' + self.settings.selects[i] + ',') > -1) { - index = i; - break; - }; - }; - - if (typeof index === 'number' && index > -1) { - index += 1; - cxSelect.getOptionData.call(self, index); - }; - }; - - $.cxSelect = function() { - return cxSelect.apply(this, arguments); - }; - - // 默认值 - $.cxSelect.defaults = { - selects: [], // 下拉选框组 - url: null, // 列表数据文件路径(URL)或数组数据 - data: null, // 自定义数据 - emptyStyle: null, // 无数据状态显示方式 - required: false, // 是否为必选 - firstTitle: '请选择', // 第一个选项的标题 - firstValue: '', // 第一个选项的值 - jsonSpace: '', // 数据命名空间 - jsonName: 'n', // 数据标题字段名称 - jsonValue: '', // 数据值字段名称 - jsonSub: 's' // 子集数据字段名称 - }; - - $.fn.cxSelect = function(settings, callback) { - this.each(function(i) { - $.cxSelect(this, settings, callback); - }); - return this; - }; -})); +/*! + * jQuery cxSelect + * @name jquery.cxselect.js + * @version 1.4.1 + * @date 2016-11-02 + * @author ciaoca + * @email ciaoca@gmail.com + * @site https://github.com/ciaoca/cxSelect + * @license Released under the MIT license + */ +(function(factory) { + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } else { + factory(window.jQuery || window.Zepto || window.$); + }; +}(function($) { + var cxSelect = function() { + var self = this; + var dom, settings, callback; + + // 分配参数 + for (var i = 0, l = arguments.length; i < l; i++) { + if (cxSelect.isJquery(arguments[i]) || cxSelect.isZepto(arguments[i])) { + dom = arguments[i]; + } else if (cxSelect.isElement(arguments[i])) { + dom = $(arguments[i]); + } else if (typeof arguments[i] === 'function') { + callback = arguments[i]; + } else if (typeof arguments[i] === 'object') { + settings = arguments[i]; + }; + }; + + var api = new cxSelect.init(dom, settings); + + if (typeof callback === 'function') { + callback(api); + }; + + return api; + }; + + cxSelect.isElement = function(o){ + if (o && (typeof HTMLElement === 'function' || typeof HTMLElement === 'object') && o instanceof HTMLElement) { + return true; + } else { + return (o && o.nodeType && o.nodeType === 1) ? true : false; + }; + }; + + cxSelect.isJquery = function(o){ + return (o && o.length && (typeof jQuery === 'function' || typeof jQuery === 'object') && o instanceof jQuery) ? true : false; + }; + + cxSelect.isZepto = function(o){ + return (o && o.length && (typeof Zepto === 'function' || typeof Zepto === 'object') && Zepto.zepto.isZ(o)) ? true : false; + }; + + cxSelect.getIndex = function(n, required) { + return required ? n : n - 1; + }; + + cxSelect.getData = function(data, space) { + if (typeof space === 'string' && space.length) { + space = space.split('.'); + for (var i = 0, l = space.length; i < l; i++) { + data = data[space[i]]; + }; + }; + return data; + }; + + cxSelect.init = function(dom, settings) { + var self = this; + + if (!cxSelect.isJquery(dom) && !cxSelect.isZepto(dom)) {return}; + + var theSelect = { + dom: { + box: dom + } + }; + + self.attach = cxSelect.attach.bind(theSelect); + self.detach = cxSelect.detach.bind(theSelect); + self.setOptions = cxSelect.setOptions.bind(theSelect); + self.clear = cxSelect.clear.bind(theSelect); + + theSelect.changeEvent = function() { + cxSelect.selectChange.call(theSelect, this.className); + }; + + theSelect.settings = $.extend({}, $.cxSelect.defaults, settings, { + url: theSelect.dom.box.data('url'), + emptyStyle: theSelect.dom.box.data('emptyStyle'), + required: theSelect.dom.box.data('required'), + firstTitle: theSelect.dom.box.data('firstTitle'), + firstValue: theSelect.dom.box.data('firstValue'), + jsonSpace: theSelect.dom.box.data('jsonSpace'), + jsonName: theSelect.dom.box.data('jsonName'), + jsonValue: theSelect.dom.box.data('jsonValue'), + jsonSub: theSelect.dom.box.data('jsonSub') + }); + + var _dataSelects = theSelect.dom.box.data('selects'); + + if (typeof _dataSelects === 'string' && _dataSelects.length) { + theSelect.settings.selects = _dataSelects.split(','); + }; + + self.setOptions(); + self.attach(); + + // 使用独立接口获取数据 + if (!theSelect.settings.url && !theSelect.settings.data) { + cxSelect.start.apply(theSelect); + + // 设置自定义数据 + } else if ($.isArray(theSelect.settings.data)) { + cxSelect.start.call(theSelect, theSelect.settings.data); + + // 设置 URL,通过 Ajax 获取数据 + } else if (typeof theSelect.settings.url === 'string' && theSelect.settings.url.length) { + $.getJSON(theSelect.settings.url, function(json) { + cxSelect.start.call(theSelect, json); + }); + }; + }; + + // 设置参数 + cxSelect.setOptions = function(opts) { + var self = this; + + if (opts) { + $.extend(self.settings, opts); + }; + + // 初次或重设选择器组 + if (!$.isArray(self.selectArray) || !self.selectArray.length || (opts && opts.selects)) { + self.selectArray = []; + + if ($.isArray(self.settings.selects) && self.settings.selects.length) { + var _tempSelect; + + for (var i = 0, l = self.settings.selects.length; i < l; i++) { + _tempSelect = self.dom.box.find('select.' + self.settings.selects[i]); + + if (!_tempSelect || !_tempSelect.length) {break}; + + self.selectArray.push(_tempSelect); + }; + }; + }; + + if (opts) { + if (!$.isArray(opts.data) && typeof opts.url === 'string' && opts.url.length) { + $.getJSON(self.settings.url, function(json) { + cxSelect.start.call(self, json); + }); + + } else { + cxSelect.start.call(self, opts.data); + }; + }; + }; + + // 绑定 + cxSelect.attach = function() { + var self = this; + + if (!self.attachStatus) { + self.dom.box.on('change', 'select', self.changeEvent); + }; + + if (typeof self.attachStatus === 'boolean') { + cxSelect.start.call(self); + }; + + self.attachStatus = true; + }; + + // 移除绑定 + cxSelect.detach = function() { + var self = this; + self.dom.box.off('change', 'select', self.changeEvent); + self.attachStatus = false; + }; + + // 清空选项 + cxSelect.clear = function(index) { + var self = this; + var _style = { + display: '', + visibility: '' + }; + + index = isNaN(index) ? 0 : index; + + // 清空后面的 select + for (var i = index, l = self.selectArray.length; i < l; i++) { + self.selectArray[i].empty().prop('disabled', true); + + if (self.settings.emptyStyle === 'none') { + _style.display = 'none'; + } else if (self.settings.emptyStyle === 'hidden') { + _style.visibility = 'hidden'; + }; + + self.selectArray[i].css(_style); + }; + }; + + cxSelect.start = function(data) { + var self = this; + + if ($.isArray(data)) { + self.settings.data = cxSelect.getData(data, self.settings.jsonSpace); + }; + + if (!self.selectArray.length) {return}; + + // 保存默认值 + for (var i = 0, l = self.selectArray.length; i < l; i++) { + if (typeof self.selectArray[i].attr('data-value') !== 'string' && self.selectArray[i][0].options.length) { + self.selectArray[i].attr('data-value', self.selectArray[i].val()); + }; + }; + + if (self.settings.data || (typeof self.selectArray[0].data('url') === 'string' && self.selectArray[0].data('url').length)) { + cxSelect.getOptionData.call(self, 0); + } else { + self.selectArray[0].prop('disabled', false).css({ + 'display': '', + 'visibility': '' + }); + }; + }; + + // 获取选项数据 + cxSelect.getOptionData = function(index) { + var self = this; + + if (typeof index !== 'number' || isNaN(index) || index < 0 || index >= self.selectArray.length) {return}; + + var _indexPrev = index - 1; + var _select = self.selectArray[index]; + var _selectData; + var _valueIndex; + var _dataUrl = _select.data('url'); + var _jsonSpace = typeof _select.data('jsonSpace') === 'undefined' ? self.settings.jsonSpace : _select.data('jsonSpace'); + var _query = {}; + var _queryName; + var _selectName; + var _selectValue; + + cxSelect.clear.call(self, index); + + // 使用独立接口 + if (typeof _dataUrl === 'string' && _dataUrl.length) { + if (index > 0) { + for (var i = 0, j = 1; i < index; i++, j++) { + _queryName = self.selectArray[j].data('queryName'); + _selectName = self.selectArray[i].attr('name'); + _selectValue = self.selectArray[i].val(); + + if (typeof _queryName === 'string' && _queryName.length) { + _query[_queryName] = _selectValue; + } else if (typeof _selectName === 'string' && _selectName.length) { + _query[_selectName] = _selectValue; + }; + }; + }; + + $.getJSON(_dataUrl, _query, function(json) { + _selectData = cxSelect.getData(json, _jsonSpace); + + cxSelect.buildOption.call(self, index, _selectData); + }); + + // 使用整合数据 + } else if (self.settings.data && typeof self.settings.data === 'object') { + _selectData = self.settings.data; + + for (var i = 0; i < index; i++) { + _valueIndex = cxSelect.getIndex(self.selectArray[i][0].selectedIndex, typeof self.selectArray[i].data('required') === 'boolean' ? self.selectArray[i].data('required') : self.settings.required); + + if (typeof _selectData[_valueIndex] === 'object' && $.isArray(_selectData[_valueIndex][self.settings.jsonSub]) && _selectData[_valueIndex][self.settings.jsonSub].length) { + _selectData = _selectData[_valueIndex][self.settings.jsonSub]; + } else { + _selectData = null; + break; + }; + }; + + cxSelect.buildOption.call(self, index, _selectData); + }; + }; + + // 构建选项列表 + cxSelect.buildOption = function(index, data) { + var self = this; + + var _select = self.selectArray[index]; + var _required = typeof _select.data('required') === 'boolean' ? _select.data('required') : self.settings.required; + var _firstTitle = typeof _select.data('firstTitle') === 'undefined' ? self.settings.firstTitle : _select.data('firstTitle'); + var _firstValue = typeof _select.data('firstValue') === 'undefined' ? self.settings.firstValue : _select.data('firstValue'); + var _jsonName = typeof _select.data('jsonName') === 'undefined' ? self.settings.jsonName : _select.data('jsonName'); + var _jsonValue = typeof _select.data('jsonValue') === 'undefined' ? self.settings.jsonValue : _select.data('jsonValue'); + + if (!$.isArray(data)) {return}; + + var _html = !_required ? '' : ''; + + // 区分标题、值的数据 + if (typeof _jsonName === 'string' && _jsonName.length) { + // 无值字段时使用标题作为值 + if (typeof _jsonValue !== 'string' || !_jsonValue.length) { + _jsonValue = _jsonName; + }; + + for (var i = 0, l = data.length; i < l; i++) { + _html += ''; + }; + + // 数组即为值的数据 + } else { + for (var i = 0, l = data.length; i < l; i++) { + _html += ''; + }; + }; + + _select.html(_html).prop('disabled', false).css({ + 'display': '', + 'visibility': '' + }); + + // 初次加载设置默认值 + if (typeof _select.attr('data-value') === 'string') { + _select.val(String(_select.attr('data-value'))).removeAttr('data-value'); + + if (_select[0].selectedIndex < 0) { + _select[0].options[0].selected = true; + }; + }; + + if (_required || _select[0].selectedIndex > 0) { + _select.trigger('change'); + }; + + }; + + // 改变选择时的处理 + cxSelect.selectChange = function(name) { + var self = this; + + if (typeof name !== 'string' || !name.length) {return}; + + var index; + + name = name.replace(/\s+/g, ','); + name = ',' + name + ','; + + // 获取当前 select 位置 + for (var i = 0, l = self.selectArray.length; i < l; i++) { + if (name.indexOf(',' + self.settings.selects[i] + ',') > -1) { + index = i; + break; + }; + }; + + if (typeof index === 'number' && index > -1) { + index += 1; + cxSelect.getOptionData.call(self, index); + }; + }; + + $.cxSelect = function() { + return cxSelect.apply(this, arguments); + }; + + // 默认值 + $.cxSelect.defaults = { + selects: [], // 下拉选框组 + url: null, // 列表数据文件路径(URL)或数组数据 + data: null, // 自定义数据 + emptyStyle: null, // 无数据状态显示方式 + required: false, // 是否为必选 + firstTitle: '请选择', // 第一个选项的标题 + firstValue: '', // 第一个选项的值 + jsonSpace: '', // 数据命名空间 + jsonName: 'n', // 数据标题字段名称 + jsonValue: '', // 数据值字段名称 + jsonSub: 's' // 子集数据字段名称 + }; + + $.fn.cxSelect = function(settings, callback) { + this.each(function(i) { + $.cxSelect(this, settings, callback); + }); + return this; + }; +})); diff --git a/app/assets/javascripts/jquery.cxselect.min.js b/app/assets/javascripts/jquery.cxselect.min.js old mode 100755 new mode 100644 index 54549a920..9aabba447 --- a/app/assets/javascripts/jquery.cxselect.min.js +++ b/app/assets/javascripts/jquery.cxselect.min.js @@ -1,11 +1,11 @@ -/*! - * jQuery cxSelect - * @name jquery.cxselect.js - * @version 1.4.1 - * @date 2016-11-02 - * @author ciaoca - * @email ciaoca@gmail.com - * @site https://github.com/ciaoca/cxSelect - * @license Released under the MIT license - */ +/*! + * jQuery cxSelect + * @name jquery.cxselect.js + * @version 1.4.1 + * @date 2016-11-02 + * @author ciaoca + * @email ciaoca@gmail.com + * @site https://github.com/ciaoca/cxSelect + * @license Released under the MIT license + */ !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(window.jQuery||window.Zepto||window.$)}(function(a){var b=function(){var d,e,f,g,h,i;for(g=0,h=arguments.length;h>g;g++)b.isJquery(arguments[g])||b.isZepto(arguments[g])?d=arguments[g]:b.isElement(arguments[g])?d=a(arguments[g]):"function"==typeof arguments[g]?f=arguments[g]:"object"==typeof arguments[g]&&(e=arguments[g]);return i=new b.init(d,e),"function"==typeof f&&f(i),i};b.isElement=function(a){return a&&("function"==typeof HTMLElement||"object"==typeof HTMLElement)&&a instanceof HTMLElement?!0:a&&a.nodeType&&1===a.nodeType?!0:!1},b.isJquery=function(a){return a&&a.length&&("function"==typeof jQuery||"object"==typeof jQuery)&&a instanceof jQuery?!0:!1},b.isZepto=function(a){return a&&a.length&&("function"==typeof Zepto||"object"==typeof Zepto)&&Zepto.zepto.isZ(a)?!0:!1},b.getIndex=function(a,b){return b?a:a-1},b.getData=function(a,b){if("string"==typeof b&&b.length){b=b.split(".");for(var c=0,d=b.length;d>c;c++)a=a[b[c]]}return a},b.init=function(c,d){var f,g,e=this;(b.isJquery(c)||b.isZepto(c))&&(f={dom:{box:c}},e.attach=b.attach.bind(f),e.detach=b.detach.bind(f),e.setOptions=b.setOptions.bind(f),e.clear=b.clear.bind(f),f.changeEvent=function(){b.selectChange.call(f,this.className)},f.settings=a.extend({},a.cxSelect.defaults,d,{url:f.dom.box.data("url"),emptyStyle:f.dom.box.data("emptyStyle"),required:f.dom.box.data("required"),firstTitle:f.dom.box.data("firstTitle"),firstValue:f.dom.box.data("firstValue"),jsonSpace:f.dom.box.data("jsonSpace"),jsonName:f.dom.box.data("jsonName"),jsonValue:f.dom.box.data("jsonValue"),jsonSub:f.dom.box.data("jsonSub")}),g=f.dom.box.data("selects"),"string"==typeof g&&g.length&&(f.settings.selects=g.split(",")),e.setOptions(),e.attach(),f.settings.url||f.settings.data?a.isArray(f.settings.data)?b.start.call(f,f.settings.data):"string"==typeof f.settings.url&&f.settings.url.length&&a.getJSON(f.settings.url,function(a){b.start.call(f,a)}):b.start.apply(f))},b.setOptions=function(c){var e,f,g,d=this;if(c&&a.extend(d.settings,c),(!a.isArray(d.selectArray)||!d.selectArray.length||c&&c.selects)&&(d.selectArray=[],a.isArray(d.settings.selects)&&d.settings.selects.length))for(f=0,g=d.settings.selects.length;g>f&&(e=d.dom.box.find("select."+d.settings.selects[f]),e&&e.length);f++)d.selectArray.push(e);c&&(!a.isArray(c.data)&&"string"==typeof c.url&&c.url.length?a.getJSON(d.settings.url,function(a){b.start.call(d,a)}):b.start.call(d,c.data))},b.attach=function(){var a=this;a.attachStatus||a.dom.box.on("change","select",a.changeEvent),"boolean"==typeof a.attachStatus&&b.start.call(a),a.attachStatus=!0},b.detach=function(){var a=this;a.dom.box.off("change","select",a.changeEvent),a.attachStatus=!1},b.clear=function(a){var d,e,b=this,c={display:"",visibility:""};for(a=isNaN(a)?0:a,d=a,e=b.selectArray.length;e>d;d++)b.selectArray[d].empty().prop("disabled",!0),"none"===b.settings.emptyStyle?c.display="none":"hidden"===b.settings.emptyStyle&&(c.visibility="hidden"),b.selectArray[d].css(c)},b.start=function(c){var e,f,d=this;if(a.isArray(c)&&(d.settings.data=b.getData(c,d.settings.jsonSpace)),d.selectArray.length){for(e=0,f=d.selectArray.length;f>e;e++)"string"!=typeof d.selectArray[e].attr("data-value")&&d.selectArray[e][0].options.length&&d.selectArray[e].attr("data-value",d.selectArray[e].val());d.settings.data||"string"==typeof d.selectArray[0].data("url")&&d.selectArray[0].data("url").length?b.getOptionData.call(d,0):d.selectArray[0].prop("disabled",!1).css({display:"",visibility:""})}},b.getOptionData=function(c){var f,g,h,i,j,k,l,m,n,o,p,d=this;if(!("number"!=typeof c||isNaN(c)||0>c||c>=d.selectArray.length))if(f=d.selectArray[c],i=f.data("url"),j="undefined"==typeof f.data("jsonSpace")?d.settings.jsonSpace:f.data("jsonSpace"),k={},b.clear.call(d,c),"string"==typeof i&&i.length){if(c>0)for(o=0,p=1;c>o;o++,p++)l=d.selectArray[p].data("queryName"),m=d.selectArray[o].attr("name"),n=d.selectArray[o].val(),"string"==typeof l&&l.length?k[l]=n:"string"==typeof m&&m.length&&(k[m]=n);a.getJSON(i,k,function(a){g=b.getData(a,j),b.buildOption.call(d,c,g)})}else if(d.settings.data&&"object"==typeof d.settings.data){for(g=d.settings.data,o=0;c>o;o++){if(h=b.getIndex(d.selectArray[o][0].selectedIndex,"boolean"==typeof d.selectArray[o].data("required")?d.selectArray[o].data("required"):d.settings.required),"object"!=typeof g[h]||!a.isArray(g[h][d.settings.jsonSub])||!g[h][d.settings.jsonSub].length){g=null;break}g=g[h][d.settings.jsonSub]}b.buildOption.call(d,c,g)}},b.buildOption=function(b,c){var k,l,m,d=this,e=d.selectArray[b],f="boolean"==typeof e.data("required")?e.data("required"):d.settings.required,g="undefined"==typeof e.data("firstTitle")?d.settings.firstTitle:e.data("firstTitle"),h="undefined"==typeof e.data("firstValue")?d.settings.firstValue:e.data("firstValue"),i="undefined"==typeof e.data("jsonName")?d.settings.jsonName:e.data("jsonName"),j="undefined"==typeof e.data("jsonValue")?d.settings.jsonValue:e.data("jsonValue");if(a.isArray(c)){if(k=f?"":'","string"==typeof i&&i.length)for("string"==typeof j&&j.length||(j=i),l=0,m=c.length;m>l;l++)k+='";else for(l=0,m=c.length;m>l;l++)k+='";e.html(k).prop("disabled",!1).css({display:"",visibility:""}),"string"==typeof e.attr("data-value")&&(e.val(String(e.attr("data-value"))).removeAttr("data-value"),e[0].selectedIndex<0&&(e[0].options[0].selected=!0)),(f||e[0].selectedIndex>0)&&e.trigger("change")}},b.selectChange=function(a){var d,e,f,c=this;if("string"==typeof a&&a.length){for(a=a.replace(/\s+/g,","),a=","+a+",",e=0,f=c.selectArray.length;f>e;e++)if(a.indexOf(","+c.settings.selects[e]+",")>-1){d=e;break}"number"==typeof d&&d>-1&&(d+=1,b.getOptionData.call(c,d))}},a.cxSelect=function(){return b.apply(this,arguments)},a.cxSelect.defaults={selects:[],url:null,data:null,emptyStyle:null,required:!1,firstTitle:"请选择",firstValue:"",jsonSpace:"",jsonName:"n",jsonValue:"",jsonSub:"s"},a.fn.cxSelect=function(b,c){return this.each(function(){a.cxSelect(this,b,c)}),this}}); \ No newline at end of file diff --git a/app/assets/javascripts/jquery.validate.js b/app/assets/javascripts/jquery.validate.js index 70297bd5c..d025319db 100644 --- a/app/assets/javascripts/jquery.validate.js +++ b/app/assets/javascripts/jquery.validate.js @@ -1,21 +1,21 @@ -/*! - * jQuery Validation Plugin v1.19.1 - * - * https://jqueryvalidation.org/ - * - * Copyright (c) 2019 Jörn Zaefferer - * Released under the MIT license - */ -(function( factory ) { - if ( typeof define === "function" && define.amd ) { - define( ["jquery"], factory ); - } else if (typeof module === "object" && module.exports) { - module.exports = factory( require( "jquery" ) ); - } else { - factory( jQuery ); - } -}(function( $ ) { - +/*! + * jQuery Validation Plugin v1.19.1 + * + * https://jqueryvalidation.org/ + * + * Copyright (c) 2019 Jörn Zaefferer + * Released under the MIT license + */ +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + define( ["jquery"], factory ); + } else if (typeof module === "object" && module.exports) { + module.exports = factory( require( "jquery" ) ); + } else { + factory( jQuery ); + } +}(function( $ ) { + $.extend( $.fn, { // https://jqueryvalidation.org/validate/ @@ -1610,7 +1610,7 @@ $.extend( $.validator, { } } ); - + // Ajax mode: abort // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() @@ -1646,5 +1646,5 @@ if ( $.ajaxPrefilter ) { return ajax.apply( this, arguments ); }; } -return $; +return $; })); \ No newline at end of file diff --git a/app/assets/javascripts/select2.js b/app/assets/javascripts/select2.js old mode 100755 new mode 100644 diff --git a/app/assets/javascripts/select2.min.js b/app/assets/javascripts/select2.min.js old mode 100755 new mode 100644 diff --git a/app/assets/stylesheets/admins/daily-school-statistics.scss b/app/assets/stylesheets/admins/daily_school_statistics.scss similarity index 100% rename from app/assets/stylesheets/admins/daily-school-statistics.scss rename to app/assets/stylesheets/admins/daily_school_statistics.scss diff --git a/app/assets/stylesheets/admins/identity-authentications.scss b/app/assets/stylesheets/admins/identity_authentications.scss similarity index 100% rename from app/assets/stylesheets/admins/identity-authentications.scss rename to app/assets/stylesheets/admins/identity_authentications.scss diff --git a/app/assets/stylesheets/admins/professional-authentications.scss b/app/assets/stylesheets/admins/professional_authentications.scss similarity index 100% rename from app/assets/stylesheets/admins/professional-authentications.scss rename to app/assets/stylesheets/admins/professional_authentications.scss diff --git a/app/assets/stylesheets/admins/school-statistics.scss b/app/assets/stylesheets/admins/school_statistics.scss similarity index 100% rename from app/assets/stylesheets/admins/school-statistics.scss rename to app/assets/stylesheets/admins/school_statistics.scss diff --git a/app/assets/stylesheets/admins/shixun_authorizations.scss b/app/assets/stylesheets/admins/shixun_authorizations.scss new file mode 100644 index 000000000..05bcbc2bb --- /dev/null +++ b/app/assets/stylesheets/admins/shixun_authorizations.scss @@ -0,0 +1,9 @@ +.admins-shixun-authorizations-index-page { + .shixun-authorization-list-container { + span { + &.apply-status-1 { color: #28a745; } + &.apply-status-2 { color: #dc3545; } + &.apply-status-3 { color: #6c757d; } + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/admins/subject_authorizations.scss b/app/assets/stylesheets/admins/subject_authorizations.scss new file mode 100644 index 000000000..f16c30151 --- /dev/null +++ b/app/assets/stylesheets/admins/subject_authorizations.scss @@ -0,0 +1,9 @@ +.admins-subject-authorizations-index-page { + .subject-authorization-list-container { + span { + &.apply-status-1 { color: #28a745; } + &.apply-status-2 { color: #dc3545; } + &.apply-status-3 { color: #6c757d; } + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/select2-bootstrap4.min.scss b/app/assets/stylesheets/select2-bootstrap4.min.scss old mode 100755 new mode 100644 diff --git a/app/assets/stylesheets/select2.min.scss b/app/assets/stylesheets/select2.min.scss old mode 100755 new mode 100644 diff --git a/app/controllers/admins/shixun_authorizations_controller.rb b/app/controllers/admins/shixun_authorizations_controller.rb new file mode 100644 index 000000000..31bd5faf7 --- /dev/null +++ b/app/controllers/admins/shixun_authorizations_controller.rb @@ -0,0 +1,48 @@ +class Admins::ShixunAuthorizationsController < Admins::BaseController + def index + params[:status] ||= 'pending' + + applies = ApplyAction.where(container_type: 'ApplyShixun') + + status = + case params[:status] + when 'pending' then 0 + when 'processed' then [1, 2] + when 'agreed' then 1 + when 'refused' then 2 + else 0 + end + applies = applies.where(status: status) if status.present? + + # 关键字模糊查询 + keyword = params[:keyword].to_s.strip + if keyword.present? + applies = applies.joins('JOIN shixuns ON shixuns.id = apply_actions.container_id') + .where('shixuns.name LIKE :keyword', keyword: "%#{keyword}%") + end + + applies = applies.order(updated_at: :desc) + + @applies = paginate applies.includes(user: :user_extension) + + shixun_ids = @applies.map(&:container_id) + @shixun_map = Shixun.where(id: shixun_ids).each_with_object({}) { |s, h| h[s.id] = s } + end + + def agree + Admins::ShixunAuths::AgreeApplyService.call(current_apply, current_user) + render_success_js + end + + def refuse + Admins::ShixunAuths::RefuseApplyService.call(current_apply, current_user, params) + + render_success_js + end + + private + + def current_apply + @_current_apply ||= ApplyAction.where(container_type: 'ApplyShixun').find(params[:id]) + end +end \ No newline at end of file diff --git a/app/controllers/admins/subject_authorizations_controller.rb b/app/controllers/admins/subject_authorizations_controller.rb new file mode 100644 index 000000000..3d3733fa4 --- /dev/null +++ b/app/controllers/admins/subject_authorizations_controller.rb @@ -0,0 +1,49 @@ +class Admins::SubjectAuthorizationsController < Admins::BaseController + def index + params[:status] ||= 'pending' + + applies = ApplyAction.where(container_type: 'ApplySubject') + + status = + case params[:status] + when 'pending' then 0 + when 'processed' then [1, 2] + when 'agreed' then 1 + when 'refused' then 2 + else 0 + end + applies = applies.where(status: status) if status.present? + + # 关键字模糊查询 + keyword = params[:keyword].to_s.strip + if keyword.present? + applies = applies.joins('JOIN subjects ON subjects.id = apply_actions.container_id') + .where('subjects.name LIKE :keyword', keyword: "%#{keyword}%") + end + + applies = applies.order(updated_at: :desc) + + @applies = paginate applies.includes(user: :user_extension) + + subject_ids = @applies.map(&:container_id) + @subject_map = Subject.where(id: subject_ids).each_with_object({}) { |s, h| h[s.id] = s } + @challenge_count_map = Challenge.joins(shixun: :stage_shixuns).where(st: 0, stage_shixuns: { subject_id: subject_ids}).group('subject_id').count + end + + def agree + Admins::SubjectAuths::AgreeApplyService.call(current_apply, current_user) + render_success_js + end + + def refuse + Admins::SubjectAuths::RefuseApplyService.call(current_apply, current_user, params) + + render_success_js + end + + private + + def current_apply + @_current_apply ||= ApplyAction.where(container_type: 'ApplySubject').find(params[:id]) + end +end \ No newline at end of file diff --git a/app/controllers/challenges_controller.rb b/app/controllers/challenges_controller.rb index 9e87d3799..0f6532372 100644 --- a/app/controllers/challenges_controller.rb +++ b/app/controllers/challenges_controller.rb @@ -74,6 +74,7 @@ class ChallengesController < ApplicationController ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id) end end + @challenge.update_column(:score, @challenge.challenge_chooses.sum(:score)) end rescue Exception => e raise ActiveRecord::Rollback @@ -95,6 +96,7 @@ class ChallengesController < ApplicationController @challenge.update_column(:modify_time, Time.now) end @challenge_choose.update_attributes(chooce_params) + @challenge.update_column(:score, @challenge.challenge_chooses.sum(:score)) # 单选多选题的更新 category = @challenge_choose.standard_answer.length > 1 ? 2 : 1 @challenge_choose.update_column(:category, category) @@ -208,6 +210,9 @@ class ChallengesController < ApplicationController # 测试集的 @shixun.myshixuns.update_all(:system_tip => 0) end + if params[:challenge][:show_type].to_i == -1 + @challenge.update_attributes(picture_path: nil, web_route: nil, expect_picture_path: nil, original_picture_path: nil) + end # 关卡评测执行文件如果被修改,需要修改脚本内容 script = modify_shixun_script @shixun, @shixun.evaluate_script @shixun.shixun_info.update_column(:evaluate_script, script) diff --git a/app/controllers/concerns/admins/error_rescue_handler.rb b/app/controllers/concerns/admins/error_rescue_handler.rb index b1e29d5ce..ceb810f36 100644 --- a/app/controllers/concerns/admins/error_rescue_handler.rb +++ b/app/controllers/concerns/admins/error_rescue_handler.rb @@ -2,7 +2,7 @@ module Admins::ErrorRescueHandler extend ActiveSupport::Concern included do - rescue_from Exception, Educoder::TipException do |e| + rescue_from Exception do |e| raise e if Rails.env.development? Util.logger_error e diff --git a/app/controllers/concerns/admins/render_helper.rb b/app/controllers/concerns/admins/render_helper.rb index 3651f892b..0ccc16a09 100644 --- a/app/controllers/concerns/admins/render_helper.rb +++ b/app/controllers/concerns/admins/render_helper.rb @@ -28,7 +28,7 @@ module Admins::RenderHelper def internal_server_error respond_to do |format| format.html { render 'admins/shared/500' } - format.js { render_js_error(message) } + format.js { render_js_error('系统错误') } format.json { render status: 500, json: { message: '系统错误' } } end end diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb index c7a598a43..0064914d3 100644 --- a/app/controllers/games_controller.rb +++ b/app/controllers/games_controller.rb @@ -13,8 +13,8 @@ class GamesController < ApplicationController def show uid_logger("--games show start") # 防止评测中途ajaxE被取消;3改成0是为了处理首次进入下一关的问题 - @game.update_attribute(:status, 0) if @game.status == 1 - @game.update_attributes(status: 0, open_time: Time.now) if @game.status == 3 + update_game_parameter(@game) + game_challenge = Challenge.base_attrs.find(@game.challenge_id) # 选择题类型的实训关卡总分 @@ -739,7 +739,7 @@ class GamesController < ApplicationController experience = 0 game_status = @game.status had_done = @game.had_done - game_challenge = Challenge.select([:id, :score, :position, :shixun_id, :web_route]).find(@game.challenge_id) + game_challenge = Challenge.select([:id, :score, :position, :shixun_id, :web_route, :show_type]).find(@game.challenge_id) if params[:resubmit].blank? # 非重新评测 if game_status == 2 # 通关 @@ -765,9 +765,10 @@ class GamesController < ApplicationController testset_detail max_query_index.to_i, game_challenge # 处理生成图片类型文件 - picture = (@game.picture_path.nil? ? 0 : @game.id) + picture = (game_challenge.show_type.to_i == -1 || @game.picture_path.nil?) ? 0 : @game.id # 针对web类型的实训 web_route = game_challenge.try(:web_route) + mirror_name = @shixun.mirror_name e_record = EvaluateRecord.where(:identifier => sec_key).first @@ -964,4 +965,13 @@ class GamesController < ApplicationController nil end end + + # 更新关卡状态和一些学习进度 + def update_game_parameter game + game.update_attribute(:status, 0) if game.status == 1 + game.update_attributes(status: 0, open_time: Time.now) if game.status == 3 + # 开启实训更新myshixuns的时间,方便跟踪用于的学习进度。 + game.myshixun.update_column(:updated_at, Time.now) + end + end diff --git a/app/controllers/subjects_controller.rb b/app/controllers/subjects_controller.rb index a62707536..5b926ee48 100644 --- a/app/controllers/subjects_controller.rb +++ b/app/controllers/subjects_controller.rb @@ -101,8 +101,9 @@ class SubjectsController < ApplicationController @tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq # 用户获取的实训标签 # @user_tags = @subject.shixuns.map(&:user_tags_name).flatten.uniq - @user_tags = user_shixun_tags challenge_ids, @user.id - @my_subject_progress = @subject.my_subject_progress + + # 用户进展 + user_subject_progress(challenge_ids) end def new @@ -436,4 +437,33 @@ class SubjectsController < ApplicationController tip_exception("403", "") end end + + # 用户进展和获取的标签 + def user_subject_progress challenge_ids + pass_games = Game.select(:id, :cost_time, :challenge_id).where(status: 2, user_id: current_user.id, challenge_id: challenge_ids) if current_user.logged? + @all_score = Challenge.where(id: challenge_ids).sum(:score) + + # 如果没有通关的,没必要再继续统计了 + if pass_games.blank? + @my_score = 0 + @learned = 0 + @time = 0 + @user_tags = [] + else + pass_challenge_ids = pass_games.map(&:challenge_id) + subject_challenge_count = @subject.shixuns.sum(:challenges_count) + # 用户通关获得的标签 + @user_tags = ChallengeTag.where(challenge_id: pass_challenge_ids).pluck(:name) + # 用户学习进度 + @learned = + subject_challenge_count == 0 ? 0 : + ((pass_challenge_ids.size.to_f / subject_challenge_count).round(2) * 100).to_i + # 用户通关分数 + @my_score = Challenge.where(id: pass_challenge_ids).pluck(:score).sum + @time = pass_games.map(&:cost_time).sum + end + + + end + end diff --git a/app/models/apply_action.rb b/app/models/apply_action.rb index 2d31f394d..54bdaa396 100644 --- a/app/models/apply_action.rb +++ b/app/models/apply_action.rb @@ -1,8 +1,16 @@ # 申请消息 class ApplyAction < ApplicationRecord + belongs_to :user + has_many :tidings, :as => :container, :dependent => :destroy after_create :send_tiding + def status_text + I18n.t!("apply_action.status.#{status}") + rescue I18n::MissingTranslationData + nil + end + def send_tiding if container_type == 'TrialAuthorization' && status == 1 tidings.create(user_id: user_id, trigger_user_id: 0, status: 1, viewed: 0, tiding_type: 'System', diff --git a/app/models/challenge.rb b/app/models/challenge.rb index adb54fae9..8087fd6ab 100644 --- a/app/models/challenge.rb +++ b/app/models/challenge.rb @@ -40,16 +40,18 @@ class Challenge < ApplicationRecord ## 选择题总分 def choose_score - self.challenge_chooses.pluck(:score).sum + self.score + #self.challenge_chooses.pluck(:score).sum end # 关卡总分 def all_score - if self.st == 1 - self.choose_score - else - self.score - end + self.score + # if self.st == 1 + # self.choose_score + # else + # self.score + # end end # 开启挑战 diff --git a/app/models/game.rb b/app/models/game.rb index d81b794a5..d7c68dd5f 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -31,7 +31,7 @@ class Game < ApplicationRecord # 根据得分比例来算实际得分(试卷、实训作业) def real_score score - ((final_score < 0 ? 0 : final_score).to_f / challenge.all_score) * score + ((final_score < 0 ? 0 : final_score).to_f / challenge.score) * score end # 判断实训是否全部通关 diff --git a/app/models/shixun.rb b/app/models/shixun.rb index 81b444c0a..d61ba45b9 100644 --- a/app/models/shixun.rb +++ b/app/models/shixun.rb @@ -192,11 +192,7 @@ class Shixun < ApplicationRecord # 实训关卡的总分(由于大部分是实践题,因此没关联查choose表) # 提前加载问题:由于选择题比较少,所以几乎不会触发选择题的查询,所以没必要提前载入choose_score def all_score - sum = 0 - challenges.each do |challenge| - sum += challenge.st == 0 ? challenge.score : challenge.choose_score - end - sum + self.challenges.pluck(:score).sum end ### fork 数量 diff --git a/app/models/subject.rb b/app/models/subject.rb index 7b671cfb1..4b7f4dbcd 100644 --- a/app/models/subject.rb +++ b/app/models/subject.rb @@ -83,7 +83,7 @@ class Subject < ApplicationRecord def my_subject_progress my_challenge_count = Game.joins(:challenge).where(user_id: User.current.id, status: 2, challenges: {shixun_id: shixuns.published_closed}). - pluck(:challenge_id).uniq.size + pluck(:challenge_id).uniq.size count = self.subject_challenge_count == 0 ? 0 : ((my_challenge_count.to_f / self.subject_challenge_count).round(2) * 100).to_i end diff --git a/app/services/admins/shixun_auths/agree_apply_service.rb b/app/services/admins/shixun_auths/agree_apply_service.rb new file mode 100644 index 000000000..4734e03bb --- /dev/null +++ b/app/services/admins/shixun_auths/agree_apply_service.rb @@ -0,0 +1,43 @@ +class Admins::ShixunAuths::AgreeApplyService < ApplicationService + attr_reader :apply, :user, :shixun + + def initialize(apply, user) + @apply = apply + @user = user + @shixun = Shixun.find(apply.container_id) + end + + def call + ActiveRecord::Base.transaction do + apply.update!(status: 1, dealer_id: user.id) + shixun.update!(status: 2, publish_time: Time.now) + + # 奖励金币、经验 + reward_grade_and_experience! + + deal_tiding! + end + end + + private + + def reward_grade_and_experience! + score = shixun.all_score + shixun_creator = shixun.user + + RewardGradeService.call(shixun_creator, container_id: shixun.id, container_type: 'shixunPublish', score: score) + + Experience.create!(user_id: shixun_creator.id, container_id: shixun.id, container_type: 'shixunPublish', score: score) + shixun_creator.update_column(:experience, shixun_creator.experience.to_i + score) + end + + def deal_tiding! + apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1) + + Tiding.create!(user_id: apply.user_id, trigger_user_id: 0, + container_id: apply.id, container_type: 'ApplyAction', + parent_container_id: apply.container_id, parent_container_type: apply.container_type, + belong_container_id: apply.container_id, belong_container_type: 'Shixun', + status: 1, tiding_type: 'System') + end +end \ No newline at end of file diff --git a/app/services/admins/shixun_auths/refuse_apply_service.rb b/app/services/admins/shixun_auths/refuse_apply_service.rb new file mode 100644 index 000000000..49416a2b0 --- /dev/null +++ b/app/services/admins/shixun_auths/refuse_apply_service.rb @@ -0,0 +1,35 @@ +class Admins::ShixunAuths::RefuseApplyService < ApplicationService + attr_reader :apply, :user, :shixun, :params + + def initialize(apply, user, params) + @apply = apply + @user = user + @shixun = Shixun.find(apply.container_id) + @params = params + end + + def call + ActiveRecord::Base.transaction do + shixun.update!(status: 0) + apply.update!(status: 2, reason: reason, dealer_id: user.id) + + deal_tiding! + end + end + + private + + def reason + params[:reason].to_s.strip + end + + def deal_tiding! + apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1) + + Tiding.create!(user_id: apply.user_id, trigger_user_id: 0, + container_id: apply.id, container_type: 'ApplyAction', + parent_container_id: apply.container_id, parent_container_type: apply.container_type, + belong_container_id: apply.container_id, belong_container_type: 'Shixun', + status: 2, tiding_type: 'System') + end +end \ No newline at end of file diff --git a/app/services/admins/subject_auths/agree_apply_service.rb b/app/services/admins/subject_auths/agree_apply_service.rb new file mode 100644 index 000000000..465e3e903 --- /dev/null +++ b/app/services/admins/subject_auths/agree_apply_service.rb @@ -0,0 +1,30 @@ +class Admins::SubjectAuths::AgreeApplyService < ApplicationService + attr_reader :apply, :user, :subject + + def initialize(apply, user) + @apply = apply + @user = user + @subject = Subject.find(apply.container_id) + end + + def call + ActiveRecord::Base.transaction do + apply.update!(status: 1, dealer_id: user.id) + subject.update!(status: 2, publish_time: Time.now) + + deal_tiding! + end + end + + private + + def deal_tiding! + apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1) + + Tiding.create!(user_id: apply.user_id, trigger_user_id: 0, + container_id: apply.id, container_type: 'ApplyAction', + parent_container_id: apply.container_id, parent_container_type: apply.container_type, + belong_container_id: apply.container_id, belong_container_type: 'Subject', + status: 1, tiding_type: 'System') + end +end \ No newline at end of file diff --git a/app/services/admins/subject_auths/refuse_apply_service.rb b/app/services/admins/subject_auths/refuse_apply_service.rb new file mode 100644 index 000000000..f51d55185 --- /dev/null +++ b/app/services/admins/subject_auths/refuse_apply_service.rb @@ -0,0 +1,35 @@ +class Admins::SubjectAuths::RefuseApplyService < ApplicationService + attr_reader :apply, :user, :subject, :params + + def initialize(apply, user, params) + @apply = apply + @user = user + @subject = Subject.find(apply.container_id) + @params = params + end + + def call + ActiveRecord::Base.transaction do + subject.update!(status: 0) + apply.update!(status: 2, reason: reason, dealer_id: user.id) + + deal_tiding! + end + end + + private + + def reason + params[:reason].to_s.strip + end + + def deal_tiding! + apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1) + + Tiding.create!(user_id: apply.user_id, trigger_user_id: 0, + container_id: apply.id, container_type: 'ApplyAction', + parent_container_id: apply.container_id, parent_container_type: apply.container_type, + belong_container_id: apply.container_id, belong_container_type: 'Subject', + status: 2, tiding_type: 'System') + end +end \ No newline at end of file diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb index 2be899ebd..ab30e8bd3 100644 --- a/app/views/admins/shared/_sidebar.html.erb +++ b/app/views/admins/shared/_sidebar.html.erb @@ -41,6 +41,8 @@ <%= sidebar_item_group('#apply-review-submenu', '审核', icon: 'gavel') do %>
头像 | +创建者 | +实训名称 | +任务数 | +时间 | + <% if is_processed %> +拒绝原因 | +状态 | + <% else %> +操作 | + <% end %> +
---|---|---|---|---|---|---|---|
+ <%= link_to "/users/#{user.login}", class: 'shixun-authorization-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %> + + <% end %> + | +<%= user.real_name %> | ++ <%= link_to "/shixuns/#{shixun.identifier}", target: '_blank' do %> + <%= overflow_hidden_span shixun.name, width: 300 %> + <% end %> + | +<%= shixun.challenges_count %> | +<%= apply.updated_at.strftime('%Y-%m-%d %H:%M') %> | + + <% if is_processed %> +<%= overflow_hidden_span apply.reason, width: 140 %> | +<%= apply.status_text %> | + <% else %> ++ <%= agree_link '同意', agree_admins_shixun_authorization_path(apply, element: ".shixun-authorization-#{apply.id}"), 'data-confirm': '确认审核通过?' %> + <%= javascript_void_link('拒绝', class: 'action refuse-action', + data: { + toggle: 'modal', target: '.admin-common-refuse-modal', id: apply.id, + url: refuse_admins_shixun_authorization_path(apply, element: ".shixun-authorization-#{apply.id}") + }) %> + | + <% end %> +
头像 | +创建者 | +实践课程名称 | +阶段数 | +实训数 | +关卡数 | +时间 | + <% if is_processed %> +拒绝原因 | +状态 | + <% else %> +操作 | + <% end %> +
---|---|---|---|---|---|---|---|---|---|
+ <%= link_to "/users/#{user.login}", class: 'subject-authorization-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %> + + <% end %> + | +<%= user.real_name %> | ++ <%= link_to "/paths/#{subject.id}", target: '_blank' do %> + <%= overflow_hidden_span subject.name, width: 300 %> + <% end %> + | +<%= subject.stages_count %> | +<%= subject.shixuns_count %> | +<%= challenge_count_map.fetch(subject.id, 0) %> | +<%= apply.updated_at.strftime('%Y-%m-%d %H:%M') %> | + + <% if is_processed %> +<%= overflow_hidden_span apply.reason, width: 140 %> | +<%= apply.status_text %> | + <% else %> ++ <%= agree_link '同意', agree_admins_subject_authorization_path(apply, element: ".subject-authorization-#{apply.id}"), 'data-confirm': '确认审核通过?' %> + <%= javascript_void_link('拒绝', class: 'action refuse-action', + data: { + toggle: 'modal', target: '.admin-common-refuse-modal', id: apply.id, + url: refuse_admins_subject_authorization_path(apply, element: ".subject-authorization-#{apply.id}") + }) %> + | + <% end %> +
{ return( -
-
+
+
{
item.is_pdf && item.is_pdf == true ?
- {item.title}
+ 暂时还没有相关数据哦! 暂时还没有相关数据哦! 暂时还没有相关数据哦! 选择的{moduleName}发送到指定课堂
- 选择的{moduleName}发送到指定课堂
+
-
-
+ 暂时还没有相关数据哦! 暂时还没有相关数据哦!
- {
+
-
-
+
+
-
-
+
+
- 点击或拖拽文件到这里上传
- 单个文件最大150MB
-
- {errorTip}
-
+ 点击或拖拽文件到这里上传
+ 单个文件最大150MB
+ 实训已经更新了,正在为您重置! 本实训的开启时间:{shixunsmessage} */}
- {/*知道了*/}
- {/* 实训已经更新了,正在为您重置! 本实训的开启时间:{shixunsmessage} */}
+ {/*知道了*/}
+ {/*
- {datas&&datas.category_name===undefined||datas&&datas.category_name===null?datas&&datas.main_category_name:datas&&datas.category_name+" 作业列表"}
- {/* 实训作业*/}
+ {/*{datas&&datas.category_name===undefined||datas&&datas.category_name===null?datas&&datas.main_category_name:datas&&datas.category_name+" 作业列表"}*/}
+ 实训作业
+
暂时还没有相关数据哦! 暂时还没有相关数据哦!
-
+
this.eventStop(event)}>
+
{checkBox}
{
@@ -283,16 +287,15 @@ class Fileslistitem extends Component{
{this.props.isAdmin?
-
-
+ this.eventStop(event)}>
开启时间之前不能挑战
-
开启时间之前不能挑战
+