Merge branch 'dev_local' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_local

dev_local_2
jingquan huang 5 years ago
commit 1ea42891e9

@ -1,6 +1,7 @@
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function() {
if ($('body.admins-identity-authentications-index-page').length > 0) { if ($('body.admins-identity-authentications-index-page').length > 0) {
var $searchFrom = $('.identity-authentication-list-form'); var $searchFrom = $('.identity-authentication-list-form');
$searchFrom.find('select[name="status"]').val('pending');
$searchFrom.on('click', '.search-form-tab', function(){ $searchFrom.on('click', '.search-form-tab', function(){
var $link = $(this); var $link = $(this);
@ -12,6 +13,7 @@ $(document).on('turbolinks:load', function() {
$searchFrom.find('.status-filter').show(); $searchFrom.find('.status-filter').show();
} else { } else {
$searchFrom.find('.status-filter').hide(); $searchFrom.find('.status-filter').hide();
$searchFrom.find('select[name="status"]').val('pending');
} }
}); });
} }

@ -1,6 +1,7 @@
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function() {
if ($('body.admins-professional-authentications-index-page').length > 0) { if ($('body.admins-professional-authentications-index-page').length > 0) {
var $searchFrom = $('.professional-authentication-list-form'); var $searchFrom = $('.professional-authentication-list-form');
$searchFrom.find('select[name="status"]').val('pending');
$searchFrom.on('click', '.search-form-tab', function(){ $searchFrom.on('click', '.search-form-tab', function(){
var $link = $(this); var $link = $(this);
@ -12,6 +13,7 @@ $(document).on('turbolinks:load', function() {
$searchFrom.find('.status-filter').show(); $searchFrom.find('.status-filter').show();
} else { } else {
$searchFrom.find('.status-filter').hide(); $searchFrom.find('.status-filter').hide();
$searchFrom.find('select[name="status"]').val('pending');
} }
}); });
} }

@ -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');
}
});
}
})

@ -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');
}
});
}
})

@ -1,403 +1,403 @@
/*! /*!
* jQuery cxSelect * jQuery cxSelect
* @name jquery.cxselect.js * @name jquery.cxselect.js
* @version 1.4.1 * @version 1.4.1
* @date 2016-11-02 * @date 2016-11-02
* @author ciaoca * @author ciaoca
* @email ciaoca@gmail.com * @email ciaoca@gmail.com
* @site https://github.com/ciaoca/cxSelect * @site https://github.com/ciaoca/cxSelect
* @license Released under the MIT license * @license Released under the MIT license
*/ */
(function(factory) { (function(factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
define(['jquery'], factory); define(['jquery'], factory);
} else { } else {
factory(window.jQuery || window.Zepto || window.$); factory(window.jQuery || window.Zepto || window.$);
}; };
}(function($) { }(function($) {
var cxSelect = function() { var cxSelect = function() {
var self = this; var self = this;
var dom, settings, callback; var dom, settings, callback;
// 分配参数 // 分配参数
for (var i = 0, l = arguments.length; i < l; i++) { for (var i = 0, l = arguments.length; i < l; i++) {
if (cxSelect.isJquery(arguments[i]) || cxSelect.isZepto(arguments[i])) { if (cxSelect.isJquery(arguments[i]) || cxSelect.isZepto(arguments[i])) {
dom = arguments[i]; dom = arguments[i];
} else if (cxSelect.isElement(arguments[i])) { } else if (cxSelect.isElement(arguments[i])) {
dom = $(arguments[i]); dom = $(arguments[i]);
} else if (typeof arguments[i] === 'function') { } else if (typeof arguments[i] === 'function') {
callback = arguments[i]; callback = arguments[i];
} else if (typeof arguments[i] === 'object') { } else if (typeof arguments[i] === 'object') {
settings = arguments[i]; settings = arguments[i];
}; };
}; };
var api = new cxSelect.init(dom, settings); var api = new cxSelect.init(dom, settings);
if (typeof callback === 'function') { if (typeof callback === 'function') {
callback(api); callback(api);
}; };
return api; return api;
}; };
cxSelect.isElement = function(o){ cxSelect.isElement = function(o){
if (o && (typeof HTMLElement === 'function' || typeof HTMLElement === 'object') && o instanceof HTMLElement) { if (o && (typeof HTMLElement === 'function' || typeof HTMLElement === 'object') && o instanceof HTMLElement) {
return true; return true;
} else { } else {
return (o && o.nodeType && o.nodeType === 1) ? true : false; return (o && o.nodeType && o.nodeType === 1) ? true : false;
}; };
}; };
cxSelect.isJquery = function(o){ cxSelect.isJquery = function(o){
return (o && o.length && (typeof jQuery === 'function' || typeof jQuery === 'object') && o instanceof jQuery) ? true : false; return (o && o.length && (typeof jQuery === 'function' || typeof jQuery === 'object') && o instanceof jQuery) ? true : false;
}; };
cxSelect.isZepto = function(o){ cxSelect.isZepto = function(o){
return (o && o.length && (typeof Zepto === 'function' || typeof Zepto === 'object') && Zepto.zepto.isZ(o)) ? true : false; return (o && o.length && (typeof Zepto === 'function' || typeof Zepto === 'object') && Zepto.zepto.isZ(o)) ? true : false;
}; };
cxSelect.getIndex = function(n, required) { cxSelect.getIndex = function(n, required) {
return required ? n : n - 1; return required ? n : n - 1;
}; };
cxSelect.getData = function(data, space) { cxSelect.getData = function(data, space) {
if (typeof space === 'string' && space.length) { if (typeof space === 'string' && space.length) {
space = space.split('.'); space = space.split('.');
for (var i = 0, l = space.length; i < l; i++) { for (var i = 0, l = space.length; i < l; i++) {
data = data[space[i]]; data = data[space[i]];
}; };
}; };
return data; return data;
}; };
cxSelect.init = function(dom, settings) { cxSelect.init = function(dom, settings) {
var self = this; var self = this;
if (!cxSelect.isJquery(dom) && !cxSelect.isZepto(dom)) {return}; if (!cxSelect.isJquery(dom) && !cxSelect.isZepto(dom)) {return};
var theSelect = { var theSelect = {
dom: { dom: {
box: dom box: dom
} }
}; };
self.attach = cxSelect.attach.bind(theSelect); self.attach = cxSelect.attach.bind(theSelect);
self.detach = cxSelect.detach.bind(theSelect); self.detach = cxSelect.detach.bind(theSelect);
self.setOptions = cxSelect.setOptions.bind(theSelect); self.setOptions = cxSelect.setOptions.bind(theSelect);
self.clear = cxSelect.clear.bind(theSelect); self.clear = cxSelect.clear.bind(theSelect);
theSelect.changeEvent = function() { theSelect.changeEvent = function() {
cxSelect.selectChange.call(theSelect, this.className); cxSelect.selectChange.call(theSelect, this.className);
}; };
theSelect.settings = $.extend({}, $.cxSelect.defaults, settings, { theSelect.settings = $.extend({}, $.cxSelect.defaults, settings, {
url: theSelect.dom.box.data('url'), url: theSelect.dom.box.data('url'),
emptyStyle: theSelect.dom.box.data('emptyStyle'), emptyStyle: theSelect.dom.box.data('emptyStyle'),
required: theSelect.dom.box.data('required'), required: theSelect.dom.box.data('required'),
firstTitle: theSelect.dom.box.data('firstTitle'), firstTitle: theSelect.dom.box.data('firstTitle'),
firstValue: theSelect.dom.box.data('firstValue'), firstValue: theSelect.dom.box.data('firstValue'),
jsonSpace: theSelect.dom.box.data('jsonSpace'), jsonSpace: theSelect.dom.box.data('jsonSpace'),
jsonName: theSelect.dom.box.data('jsonName'), jsonName: theSelect.dom.box.data('jsonName'),
jsonValue: theSelect.dom.box.data('jsonValue'), jsonValue: theSelect.dom.box.data('jsonValue'),
jsonSub: theSelect.dom.box.data('jsonSub') jsonSub: theSelect.dom.box.data('jsonSub')
}); });
var _dataSelects = theSelect.dom.box.data('selects'); var _dataSelects = theSelect.dom.box.data('selects');
if (typeof _dataSelects === 'string' && _dataSelects.length) { if (typeof _dataSelects === 'string' && _dataSelects.length) {
theSelect.settings.selects = _dataSelects.split(','); theSelect.settings.selects = _dataSelects.split(',');
}; };
self.setOptions(); self.setOptions();
self.attach(); self.attach();
// 使用独立接口获取数据 // 使用独立接口获取数据
if (!theSelect.settings.url && !theSelect.settings.data) { if (!theSelect.settings.url && !theSelect.settings.data) {
cxSelect.start.apply(theSelect); cxSelect.start.apply(theSelect);
// 设置自定义数据 // 设置自定义数据
} else if ($.isArray(theSelect.settings.data)) { } else if ($.isArray(theSelect.settings.data)) {
cxSelect.start.call(theSelect, theSelect.settings.data); cxSelect.start.call(theSelect, theSelect.settings.data);
// 设置 URL通过 Ajax 获取数据 // 设置 URL通过 Ajax 获取数据
} else if (typeof theSelect.settings.url === 'string' && theSelect.settings.url.length) { } else if (typeof theSelect.settings.url === 'string' && theSelect.settings.url.length) {
$.getJSON(theSelect.settings.url, function(json) { $.getJSON(theSelect.settings.url, function(json) {
cxSelect.start.call(theSelect, json); cxSelect.start.call(theSelect, json);
}); });
}; };
}; };
// 设置参数 // 设置参数
cxSelect.setOptions = function(opts) { cxSelect.setOptions = function(opts) {
var self = this; var self = this;
if (opts) { if (opts) {
$.extend(self.settings, opts); $.extend(self.settings, opts);
}; };
// 初次或重设选择器组 // 初次或重设选择器组
if (!$.isArray(self.selectArray) || !self.selectArray.length || (opts && opts.selects)) { if (!$.isArray(self.selectArray) || !self.selectArray.length || (opts && opts.selects)) {
self.selectArray = []; self.selectArray = [];
if ($.isArray(self.settings.selects) && self.settings.selects.length) { if ($.isArray(self.settings.selects) && self.settings.selects.length) {
var _tempSelect; var _tempSelect;
for (var i = 0, l = self.settings.selects.length; i < l; i++) { for (var i = 0, l = self.settings.selects.length; i < l; i++) {
_tempSelect = self.dom.box.find('select.' + self.settings.selects[i]); _tempSelect = self.dom.box.find('select.' + self.settings.selects[i]);
if (!_tempSelect || !_tempSelect.length) {break}; if (!_tempSelect || !_tempSelect.length) {break};
self.selectArray.push(_tempSelect); self.selectArray.push(_tempSelect);
}; };
}; };
}; };
if (opts) { if (opts) {
if (!$.isArray(opts.data) && typeof opts.url === 'string' && opts.url.length) { if (!$.isArray(opts.data) && typeof opts.url === 'string' && opts.url.length) {
$.getJSON(self.settings.url, function(json) { $.getJSON(self.settings.url, function(json) {
cxSelect.start.call(self, json); cxSelect.start.call(self, json);
}); });
} else { } else {
cxSelect.start.call(self, opts.data); cxSelect.start.call(self, opts.data);
}; };
}; };
}; };
// 绑定 // 绑定
cxSelect.attach = function() { cxSelect.attach = function() {
var self = this; var self = this;
if (!self.attachStatus) { if (!self.attachStatus) {
self.dom.box.on('change', 'select', self.changeEvent); self.dom.box.on('change', 'select', self.changeEvent);
}; };
if (typeof self.attachStatus === 'boolean') { if (typeof self.attachStatus === 'boolean') {
cxSelect.start.call(self); cxSelect.start.call(self);
}; };
self.attachStatus = true; self.attachStatus = true;
}; };
// 移除绑定 // 移除绑定
cxSelect.detach = function() { cxSelect.detach = function() {
var self = this; var self = this;
self.dom.box.off('change', 'select', self.changeEvent); self.dom.box.off('change', 'select', self.changeEvent);
self.attachStatus = false; self.attachStatus = false;
}; };
// 清空选项 // 清空选项
cxSelect.clear = function(index) { cxSelect.clear = function(index) {
var self = this; var self = this;
var _style = { var _style = {
display: '', display: '',
visibility: '' visibility: ''
}; };
index = isNaN(index) ? 0 : index; index = isNaN(index) ? 0 : index;
// 清空后面的 select // 清空后面的 select
for (var i = index, l = self.selectArray.length; i < l; i++) { for (var i = index, l = self.selectArray.length; i < l; i++) {
self.selectArray[i].empty().prop('disabled', true); self.selectArray[i].empty().prop('disabled', true);
if (self.settings.emptyStyle === 'none') { if (self.settings.emptyStyle === 'none') {
_style.display = 'none'; _style.display = 'none';
} else if (self.settings.emptyStyle === 'hidden') { } else if (self.settings.emptyStyle === 'hidden') {
_style.visibility = 'hidden'; _style.visibility = 'hidden';
}; };
self.selectArray[i].css(_style); self.selectArray[i].css(_style);
}; };
}; };
cxSelect.start = function(data) { cxSelect.start = function(data) {
var self = this; var self = this;
if ($.isArray(data)) { if ($.isArray(data)) {
self.settings.data = cxSelect.getData(data, self.settings.jsonSpace); self.settings.data = cxSelect.getData(data, self.settings.jsonSpace);
}; };
if (!self.selectArray.length) {return}; if (!self.selectArray.length) {return};
// 保存默认值 // 保存默认值
for (var i = 0, l = self.selectArray.length; i < l; i++) { 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) { 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()); 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)) { if (self.settings.data || (typeof self.selectArray[0].data('url') === 'string' && self.selectArray[0].data('url').length)) {
cxSelect.getOptionData.call(self, 0); cxSelect.getOptionData.call(self, 0);
} else { } else {
self.selectArray[0].prop('disabled', false).css({ self.selectArray[0].prop('disabled', false).css({
'display': '', 'display': '',
'visibility': '' 'visibility': ''
}); });
}; };
}; };
// 获取选项数据 // 获取选项数据
cxSelect.getOptionData = function(index) { cxSelect.getOptionData = function(index) {
var self = this; var self = this;
if (typeof index !== 'number' || isNaN(index) || index < 0 || index >= self.selectArray.length) {return}; if (typeof index !== 'number' || isNaN(index) || index < 0 || index >= self.selectArray.length) {return};
var _indexPrev = index - 1; var _indexPrev = index - 1;
var _select = self.selectArray[index]; var _select = self.selectArray[index];
var _selectData; var _selectData;
var _valueIndex; var _valueIndex;
var _dataUrl = _select.data('url'); var _dataUrl = _select.data('url');
var _jsonSpace = typeof _select.data('jsonSpace') === 'undefined' ? self.settings.jsonSpace : _select.data('jsonSpace'); var _jsonSpace = typeof _select.data('jsonSpace') === 'undefined' ? self.settings.jsonSpace : _select.data('jsonSpace');
var _query = {}; var _query = {};
var _queryName; var _queryName;
var _selectName; var _selectName;
var _selectValue; var _selectValue;
cxSelect.clear.call(self, index); cxSelect.clear.call(self, index);
// 使用独立接口 // 使用独立接口
if (typeof _dataUrl === 'string' && _dataUrl.length) { if (typeof _dataUrl === 'string' && _dataUrl.length) {
if (index > 0) { if (index > 0) {
for (var i = 0, j = 1; i < index; i++, j++) { for (var i = 0, j = 1; i < index; i++, j++) {
_queryName = self.selectArray[j].data('queryName'); _queryName = self.selectArray[j].data('queryName');
_selectName = self.selectArray[i].attr('name'); _selectName = self.selectArray[i].attr('name');
_selectValue = self.selectArray[i].val(); _selectValue = self.selectArray[i].val();
if (typeof _queryName === 'string' && _queryName.length) { if (typeof _queryName === 'string' && _queryName.length) {
_query[_queryName] = _selectValue; _query[_queryName] = _selectValue;
} else if (typeof _selectName === 'string' && _selectName.length) { } else if (typeof _selectName === 'string' && _selectName.length) {
_query[_selectName] = _selectValue; _query[_selectName] = _selectValue;
}; };
}; };
}; };
$.getJSON(_dataUrl, _query, function(json) { $.getJSON(_dataUrl, _query, function(json) {
_selectData = cxSelect.getData(json, _jsonSpace); _selectData = cxSelect.getData(json, _jsonSpace);
cxSelect.buildOption.call(self, index, _selectData); cxSelect.buildOption.call(self, index, _selectData);
}); });
// 使用整合数据 // 使用整合数据
} else if (self.settings.data && typeof self.settings.data === 'object') { } else if (self.settings.data && typeof self.settings.data === 'object') {
_selectData = self.settings.data; _selectData = self.settings.data;
for (var i = 0; i < index; i++) { 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); _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) { if (typeof _selectData[_valueIndex] === 'object' && $.isArray(_selectData[_valueIndex][self.settings.jsonSub]) && _selectData[_valueIndex][self.settings.jsonSub].length) {
_selectData = _selectData[_valueIndex][self.settings.jsonSub]; _selectData = _selectData[_valueIndex][self.settings.jsonSub];
} else { } else {
_selectData = null; _selectData = null;
break; break;
}; };
}; };
cxSelect.buildOption.call(self, index, _selectData); cxSelect.buildOption.call(self, index, _selectData);
}; };
}; };
// 构建选项列表 // 构建选项列表
cxSelect.buildOption = function(index, data) { cxSelect.buildOption = function(index, data) {
var self = this; var self = this;
var _select = self.selectArray[index]; var _select = self.selectArray[index];
var _required = typeof _select.data('required') === 'boolean' ? _select.data('required') : self.settings.required; 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 _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 _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 _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'); var _jsonValue = typeof _select.data('jsonValue') === 'undefined' ? self.settings.jsonValue : _select.data('jsonValue');
if (!$.isArray(data)) {return}; if (!$.isArray(data)) {return};
var _html = !_required ? '<option value="' + String(_firstValue) + '">' + String(_firstTitle) + '</option>' : ''; var _html = !_required ? '<option value="' + String(_firstValue) + '">' + String(_firstTitle) + '</option>' : '';
// 区分标题、值的数据 // 区分标题、值的数据
if (typeof _jsonName === 'string' && _jsonName.length) { if (typeof _jsonName === 'string' && _jsonName.length) {
// 无值字段时使用标题作为值 // 无值字段时使用标题作为值
if (typeof _jsonValue !== 'string' || !_jsonValue.length) { if (typeof _jsonValue !== 'string' || !_jsonValue.length) {
_jsonValue = _jsonName; _jsonValue = _jsonName;
}; };
for (var i = 0, l = data.length; i < l; i++) { for (var i = 0, l = data.length; i < l; i++) {
_html += '<option value="' + String(data[i][_jsonValue]) + '">' + String(data[i][_jsonName]) + '</option>'; _html += '<option value="' + String(data[i][_jsonValue]) + '">' + String(data[i][_jsonName]) + '</option>';
}; };
// 数组即为值的数据 // 数组即为值的数据
} else { } else {
for (var i = 0, l = data.length; i < l; i++) { for (var i = 0, l = data.length; i < l; i++) {
_html += '<option value="' + String(data[i]) + '">' + String(data[i]) + '</option>'; _html += '<option value="' + String(data[i]) + '">' + String(data[i]) + '</option>';
}; };
}; };
_select.html(_html).prop('disabled', false).css({ _select.html(_html).prop('disabled', false).css({
'display': '', 'display': '',
'visibility': '' 'visibility': ''
}); });
// 初次加载设置默认值 // 初次加载设置默认值
if (typeof _select.attr('data-value') === 'string') { if (typeof _select.attr('data-value') === 'string') {
_select.val(String(_select.attr('data-value'))).removeAttr('data-value'); _select.val(String(_select.attr('data-value'))).removeAttr('data-value');
if (_select[0].selectedIndex < 0) { if (_select[0].selectedIndex < 0) {
_select[0].options[0].selected = true; _select[0].options[0].selected = true;
}; };
}; };
if (_required || _select[0].selectedIndex > 0) { if (_required || _select[0].selectedIndex > 0) {
_select.trigger('change'); _select.trigger('change');
}; };
}; };
// 改变选择时的处理 // 改变选择时的处理
cxSelect.selectChange = function(name) { cxSelect.selectChange = function(name) {
var self = this; var self = this;
if (typeof name !== 'string' || !name.length) {return}; if (typeof name !== 'string' || !name.length) {return};
var index; var index;
name = name.replace(/\s+/g, ','); name = name.replace(/\s+/g, ',');
name = ',' + name + ','; name = ',' + name + ',';
// 获取当前 select 位置 // 获取当前 select 位置
for (var i = 0, l = self.selectArray.length; i < l; i++) { for (var i = 0, l = self.selectArray.length; i < l; i++) {
if (name.indexOf(',' + self.settings.selects[i] + ',') > -1) { if (name.indexOf(',' + self.settings.selects[i] + ',') > -1) {
index = i; index = i;
break; break;
}; };
}; };
if (typeof index === 'number' && index > -1) { if (typeof index === 'number' && index > -1) {
index += 1; index += 1;
cxSelect.getOptionData.call(self, index); cxSelect.getOptionData.call(self, index);
}; };
}; };
$.cxSelect = function() { $.cxSelect = function() {
return cxSelect.apply(this, arguments); return cxSelect.apply(this, arguments);
}; };
// 默认值 // 默认值
$.cxSelect.defaults = { $.cxSelect.defaults = {
selects: [], // 下拉选框组 selects: [], // 下拉选框组
url: null, // 列表数据文件路径URL或数组数据 url: null, // 列表数据文件路径URL或数组数据
data: null, // 自定义数据 data: null, // 自定义数据
emptyStyle: null, // 无数据状态显示方式 emptyStyle: null, // 无数据状态显示方式
required: false, // 是否为必选 required: false, // 是否为必选
firstTitle: '请选择', // 第一个选项的标题 firstTitle: '请选择', // 第一个选项的标题
firstValue: '', // 第一个选项的值 firstValue: '', // 第一个选项的值
jsonSpace: '', // 数据命名空间 jsonSpace: '', // 数据命名空间
jsonName: 'n', // 数据标题字段名称 jsonName: 'n', // 数据标题字段名称
jsonValue: '', // 数据值字段名称 jsonValue: '', // 数据值字段名称
jsonSub: 's' // 子集数据字段名称 jsonSub: 's' // 子集数据字段名称
}; };
$.fn.cxSelect = function(settings, callback) { $.fn.cxSelect = function(settings, callback) {
this.each(function(i) { this.each(function(i) {
$.cxSelect(this, settings, callback); $.cxSelect(this, settings, callback);
}); });
return this; return this;
}; };
})); }));

File diff suppressed because one or more lines are too long

@ -1,21 +1,21 @@
/*! /*!
* jQuery Validation Plugin v1.19.1 * jQuery Validation Plugin v1.19.1
* *
* https://jqueryvalidation.org/ * https://jqueryvalidation.org/
* *
* Copyright (c) 2019 Jörn Zaefferer * Copyright (c) 2019 Jörn Zaefferer
* Released under the MIT license * Released under the MIT license
*/ */
(function( factory ) { (function( factory ) {
if ( typeof define === "function" && define.amd ) { if ( typeof define === "function" && define.amd ) {
define( ["jquery"], factory ); define( ["jquery"], factory );
} else if (typeof module === "object" && module.exports) { } else if (typeof module === "object" && module.exports) {
module.exports = factory( require( "jquery" ) ); module.exports = factory( require( "jquery" ) );
} else { } else {
factory( jQuery ); factory( jQuery );
} }
}(function( $ ) { }(function( $ ) {
$.extend( $.fn, { $.extend( $.fn, {
// https://jqueryvalidation.org/validate/ // https://jqueryvalidation.org/validate/
@ -1610,7 +1610,7 @@ $.extend( $.validator, {
} }
} ); } );
// Ajax mode: abort // Ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); // 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() // 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 ajax.apply( this, arguments );
}; };
} }
return $; return $;
})); }));

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

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

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

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

@ -74,6 +74,7 @@ class ChallengesController < ApplicationController
ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id) ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id)
end end
end end
@challenge.update_column(:score, @challenge.challenge_chooses.sum(:score))
end end
rescue Exception => e rescue Exception => e
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
@ -95,6 +96,7 @@ class ChallengesController < ApplicationController
@challenge.update_column(:modify_time, Time.now) @challenge.update_column(:modify_time, Time.now)
end end
@challenge_choose.update_attributes(chooce_params) @challenge_choose.update_attributes(chooce_params)
@challenge.update_column(:score, @challenge.challenge_chooses.sum(:score))
# 单选多选题的更新 # 单选多选题的更新
category = @challenge_choose.standard_answer.length > 1 ? 2 : 1 category = @challenge_choose.standard_answer.length > 1 ? 2 : 1
@challenge_choose.update_column(:category, category) @challenge_choose.update_column(:category, category)
@ -208,6 +210,9 @@ class ChallengesController < ApplicationController
# 测试集的 # 测试集的
@shixun.myshixuns.update_all(:system_tip => 0) @shixun.myshixuns.update_all(:system_tip => 0)
end 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 script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script) @shixun.shixun_info.update_column(:evaluate_script, script)

@ -2,7 +2,7 @@ module Admins::ErrorRescueHandler
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
rescue_from Exception, Educoder::TipException do |e| rescue_from Exception do |e|
raise e if Rails.env.development? raise e if Rails.env.development?
Util.logger_error e Util.logger_error e

@ -28,7 +28,7 @@ module Admins::RenderHelper
def internal_server_error def internal_server_error
respond_to do |format| respond_to do |format|
format.html { render 'admins/shared/500' } format.html { render 'admins/shared/500' }
format.js { render_js_error(message) } format.js { render_js_error('系统错误') }
format.json { render status: 500, json: { message: '系统错误' } } format.json { render status: 500, json: { message: '系统错误' } }
end end
end end

@ -13,8 +13,8 @@ class GamesController < ApplicationController
def show def show
uid_logger("--games show start") uid_logger("--games show start")
# 防止评测中途ajaxE被取消;3改成0是为了处理首次进入下一关的问题 # 防止评测中途ajaxE被取消;3改成0是为了处理首次进入下一关的问题
@game.update_attribute(:status, 0) if @game.status == 1 update_game_parameter(@game)
@game.update_attributes(status: 0, open_time: Time.now) if @game.status == 3
game_challenge = Challenge.base_attrs.find(@game.challenge_id) game_challenge = Challenge.base_attrs.find(@game.challenge_id)
# 选择题类型的实训关卡总分 # 选择题类型的实训关卡总分
@ -739,7 +739,7 @@ class GamesController < ApplicationController
experience = 0 experience = 0
game_status = @game.status game_status = @game.status
had_done = @game.had_done 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 params[:resubmit].blank? # 非重新评测
if game_status == 2 # 通关 if game_status == 2 # 通关
@ -765,9 +765,10 @@ class GamesController < ApplicationController
testset_detail max_query_index.to_i, game_challenge 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类型的实训
web_route = game_challenge.try(:web_route) web_route = game_challenge.try(:web_route)
mirror_name = @shixun.mirror_name mirror_name = @shixun.mirror_name
e_record = EvaluateRecord.where(:identifier => sec_key).first e_record = EvaluateRecord.where(:identifier => sec_key).first
@ -964,4 +965,13 @@ class GamesController < ApplicationController
nil nil
end end
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 end

@ -101,8 +101,9 @@ class SubjectsController < ApplicationController
@tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq @tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq
# 用户获取的实训标签 # 用户获取的实训标签
# @user_tags = @subject.shixuns.map(&:user_tags_name).flatten.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 end
def new def new
@ -436,4 +437,33 @@ class SubjectsController < ApplicationController
tip_exception("403", "") tip_exception("403", "")
end end
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 end

@ -1,8 +1,16 @@
# 申请消息 # 申请消息
class ApplyAction < ApplicationRecord class ApplyAction < ApplicationRecord
belongs_to :user
has_many :tidings, :as => :container, :dependent => :destroy has_many :tidings, :as => :container, :dependent => :destroy
after_create :send_tiding after_create :send_tiding
def status_text
I18n.t!("apply_action.status.#{status}")
rescue I18n::MissingTranslationData
nil
end
def send_tiding def send_tiding
if container_type == 'TrialAuthorization' && status == 1 if container_type == 'TrialAuthorization' && status == 1
tidings.create(user_id: user_id, trigger_user_id: 0, status: 1, viewed: 0, tiding_type: 'System', tidings.create(user_id: user_id, trigger_user_id: 0, status: 1, viewed: 0, tiding_type: 'System',

@ -40,16 +40,18 @@ class Challenge < ApplicationRecord
## 选择题总分 ## 选择题总分
def choose_score def choose_score
self.challenge_chooses.pluck(:score).sum self.score
#self.challenge_chooses.pluck(:score).sum
end end
# 关卡总分 # 关卡总分
def all_score def all_score
if self.st == 1 self.score
self.choose_score # if self.st == 1
else # self.choose_score
self.score # else
end # self.score
# end
end end
# 开启挑战 # 开启挑战

@ -31,7 +31,7 @@ class Game < ApplicationRecord
# 根据得分比例来算实际得分(试卷、实训作业) # 根据得分比例来算实际得分(试卷、实训作业)
def real_score score 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 end
# 判断实训是否全部通关 # 判断实训是否全部通关

@ -192,11 +192,7 @@ class Shixun < ApplicationRecord
# 实训关卡的总分(由于大部分是实践题,因此没关联查choose表) # 实训关卡的总分(由于大部分是实践题,因此没关联查choose表)
# 提前加载问题由于选择题比较少所以几乎不会触发选择题的查询所以没必要提前载入choose_score # 提前加载问题由于选择题比较少所以几乎不会触发选择题的查询所以没必要提前载入choose_score
def all_score def all_score
sum = 0 self.challenges.pluck(:score).sum
challenges.each do |challenge|
sum += challenge.st == 0 ? challenge.score : challenge.choose_score
end
sum
end end
### fork 数量 ### fork 数量

@ -83,7 +83,7 @@ class Subject < ApplicationRecord
def my_subject_progress def my_subject_progress
my_challenge_count = Game.joins(:challenge).where(user_id: User.current.id, status: 2, challenges: {shixun_id: shixuns.published_closed}). 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 count = self.subject_challenge_count == 0 ? 0 : ((my_challenge_count.to_f / self.subject_challenge_count).round(2) * 100).to_i
end end

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

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

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

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

@ -41,6 +41,8 @@
<%= sidebar_item_group('#apply-review-submenu', '审核', icon: 'gavel') do %> <%= sidebar_item_group('#apply-review-submenu', '审核', icon: 'gavel') do %>
<li><%= sidebar_item(admins_identity_authentications_path, '实名认证', icon: 'id-card-o', controller: 'admins-identity_authentications') %></li> <li><%= sidebar_item(admins_identity_authentications_path, '实名认证', icon: 'id-card-o', controller: 'admins-identity_authentications') %></li>
<li><%= sidebar_item(admins_professional_authentications_path, '职业认证', icon: 'drivers-license', controller: 'admins-professional_authentications') %></li> <li><%= sidebar_item(admins_professional_authentications_path, '职业认证', icon: 'drivers-license', controller: 'admins-professional_authentications') %></li>
<li><%= sidebar_item(admins_shixun_authorizations_path, '实训发布', icon: 'object-ungroup', controller: 'admins-shixun_authorizations') %></li>
<li><%= sidebar_item(admins_subject_authorizations_path, '实践课程发布', icon: 'object-group', controller: 'admins-subject_authorizations') %></li>
<% end %> <% end %>
</li> </li>

@ -4,4 +4,7 @@ setTimeout(function() {
if ($('.admin-alert-container button.close').length > 0) { if ($('.admin-alert-container button.close').length > 0) {
$('.admin-alert-container button.close').trigger('click'); $('.admin-alert-container button.close').trigger('click');
} }
}, 2000) }, 5000)
$(".admin-body-container").animate({
scrollTop: 0
}, 200);

@ -0,0 +1,32 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('实训发布') %>
<% end %>
<div class="box search-form-container flex-column mb-0 pb-0 shixun-authorization-list-form">
<ul class="nav nav-tabs w-100 search-form-tabs">
<li class="nav-item">
<%= link_to '待审批', admins_shixun_authorizations_path(status: :pending), remote: true, 'data-value': 'pending',
class: "nav-link search-form-tab #{params[:status] == 'pending' ? 'active' : ''}" %>
</li>
<li class="nav-item">
<%= link_to '已审批', admins_shixun_authorizations_path(status: :processed), remote: true, 'data-value': 'processed',
class: "nav-link search-form-tab #{params[:status] != 'pending' ? 'active' : ''}" %>
</li>
</ul>
<%= form_tag(admins_shixun_authorizations_path(unsafe_params), method: :get, class: 'form-inline search-form justify-content-end mt-3', remote: true) do %>
<div class="form-group status-filter" style="<%= params[:status] != 'pending' ? '' : 'display: none;' %>">
<label for="status">审核状态:</label>
<% status_options = [['全部', 'processed'], ['已同意', 'agreed'], ['已拒绝', 'refused']] %>
<%= select_tag(:status, options_for_select(status_options), class: 'form-control') %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '实训名称检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3') %>
<% end %>
</div>
<div class="box shixun-authorization-list-container">
<%= render(partial: 'admins/shixun_authorizations/shared/list', locals: { applies: @applies, shixun_map: @shixun_map }) %>
</div>
<%= render(partial: 'admins/shared/admin_common_refuse_modal') %>

@ -0,0 +1 @@
$('.shixun-authorization-list-container').html("<%= j( render partial: 'admins/shixun_authorizations/shared/list', locals: { applies: @applies, shixun_map: @shixun_map } ) %>");

@ -0,0 +1,60 @@
<% is_processed = params[:status].to_s != 'pending' %>
<table class="table table-hover text-center shixun-authorization-list-table">
<thead class="thead-light">
<tr>
<th width="8%">头像</th>
<th width="14%">创建者</th>
<th width="28%" class="text-left">实训名称</th>
<th width="12%">任务数</th>
<th width="16%">时间</th>
<% if is_processed %>
<th width="14%">拒绝原因</th>
<th width="8%">状态</th>
<% else %>
<th width="22%">操作</th>
<% end %>
</tr>
</thead>
<tbody>
<% if applies.present? %>
<% applies.each do |apply| %>
<% user = apply.user %>
<% shixun = shixun_map[apply.container_id] %>
<tr class="shixun-authorization-item shixun-authorization-<%= apply.id %>">
<td>
<%= link_to "/users/#{user.login}", class: 'shixun-authorization-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %>
<img src="/images/<%= url_to_avatar(user) %>" class="rounded-circle" width="40" height="40" />
<% end %>
</td>
<td><%= user.real_name %></td>
<td class="text-left">
<%= link_to "/shixuns/#{shixun.identifier}", target: '_blank' do %>
<%= overflow_hidden_span shixun.name, width: 300 %>
<% end %>
</td>
<td><%= shixun.challenges_count %></td>
<td><%= apply.updated_at.strftime('%Y-%m-%d %H:%M') %></td>
<% if is_processed %>
<td class="text-secondary"><%= overflow_hidden_span apply.reason, width: 140 %></td>
<td><span class="apply-status-<%= apply.status %>"><%= apply.status_text %></span></td>
<% else %>
<td class="action-container">
<%= 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}")
}) %>
</td>
<% end %>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: applies } %>

@ -0,0 +1,33 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('实践课程发布') %>
<% end %>
<div class="box search-form-container flex-column mb-0 pb-0 subject-authorization-list-form">
<ul class="nav nav-tabs w-100 search-form-tabs">
<li class="nav-item">
<%= link_to '待审批', admins_subject_authorizations_path(status: :pending), remote: true, 'data-value': 'pending',
class: "nav-link search-form-tab #{params[:status] == 'pending' ? 'active' : ''}" %>
</li>
<li class="nav-item">
<%= link_to '已审批', admins_subject_authorizations_path(status: :processed), remote: true, 'data-value': 'processed',
class: "nav-link search-form-tab #{params[:status] != 'pending' ? 'active' : ''}" %>
</li>
</ul>
<%= form_tag(admins_subject_authorizations_path(unsafe_params), method: :get, class: 'form-inline search-form justify-content-end mt-3', remote: true) do %>
<div class="form-group status-filter" style="<%= params[:status] != 'pending' ? '' : 'display: none;' %>">
<label for="status">审核状态:</label>
<% status_options = [['全部', 'processed'], ['已同意', 'agreed'], ['已拒绝', 'refused']] %>
<%= select_tag(:status, options_for_select(status_options), class: 'form-control') %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '实训课程名称检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3') %>
<% end %>
</div>
<div class="box subject-authorization-list-container">
<%= render(partial: 'admins/subject_authorizations/shared/list',
locals: { applies: @applies, subject_map: @subject_map, challenge_count_map: @challenge_count_map }) %>
</div>
<%= render(partial: 'admins/shared/admin_common_refuse_modal') %>

@ -0,0 +1 @@
$('.subject-authorization-list-container').html("<%= j( render partial: 'admins/subject_authorizations/shared/list', locals: { applies: @applies, subject_map: @subject_map, challenge_count_map: @challenge_count_map } ) %>");

@ -0,0 +1,64 @@
<% is_processed = params[:status].to_s != 'pending' %>
<table class="table table-hover text-center subject-authorization-list-table">
<thead class="thead-light">
<tr>
<th width="8%">头像</th>
<th width="10%">创建者</th>
<th width="28%" class="text-left">实践课程名称</th>
<th width="6%">阶段数</th>
<th width="6%">实训数</th>
<th width="6%">关卡数</th>
<th width="14%">时间</th>
<% if is_processed %>
<th width="14%">拒绝原因</th>
<th width="8%">状态</th>
<% else %>
<th width="22%">操作</th>
<% end %>
</tr>
</thead>
<tbody>
<% if applies.present? %>
<% applies.each do |apply| %>
<% user = apply.user %>
<% subject = subject_map[apply.container_id] %>
<tr class="subject-authorization-item subject-authorization-<%= apply.id %>">
<td>
<%= link_to "/users/#{user.login}", class: 'subject-authorization-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %>
<img src="/images/<%= url_to_avatar(user) %>" class="rounded-circle" width="40" height="40" />
<% end %>
</td>
<td><%= user.real_name %></td>
<td class="text-left">
<%= link_to "/paths/#{subject.id}", target: '_blank' do %>
<%= overflow_hidden_span subject.name, width: 300 %>
<% end %>
</td>
<td><%= subject.stages_count %></td>
<td><%= subject.shixuns_count %></td>
<td><%= challenge_count_map.fetch(subject.id, 0) %></td>
<td><%= apply.updated_at.strftime('%Y-%m-%d %H:%M') %></td>
<% if is_processed %>
<td class="text-secondary"><%= overflow_hidden_span apply.reason, width: 140 %></td>
<td><span class="apply-status-<%= apply.status %>"><%= apply.status_text %></span></td>
<% else %>
<td class="action-container">
<%= 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}")
}) %>
</td>
<% end %>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: applies } %>

@ -13,7 +13,7 @@ if @challenges.present?
json.position challenge.position json.position challenge.position
json.st challenge.st json.st challenge.st
json.name challenge.subject json.name challenge.subject
json.score challenge.all_score json.score challenge.score
json.passed_count challenge.user_passed_count json.passed_count challenge.user_passed_count
json.playing_count challenge.playing_count json.playing_count challenge.playing_count
json.name_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) json.name_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)

@ -20,10 +20,20 @@ if question.question_type <= 2 #当为选择题或判断题时,只显示选
#TODO: 旧版本来一个题只有一个标准答案的新版又做成了一个题有多个标准答案exercise_choice_id存放的是标准答案的位置.. #TODO: 旧版本来一个题只有一个标准答案的新版又做成了一个题有多个标准答案exercise_choice_id存放的是标准答案的位置..
standard_answer_b = standard_answers_array.join("").include?(a.choice_position.to_s) standard_answer_b = standard_answers_array.join("").include?(a.choice_position.to_s)
user_answer_b = user_answer.include?(a.id) user_answer_b = user_answer.include?(a.id)
choice_text = a.choice_text
if question.question_type == 2
if choice_text == "对"
choice_text = "正确"
end
if choice_text == "错"
choice_text = "错误"
end
end
json.c_position (index+1) if ex_choice_random_boolean #当选项随机时,选项位置以此为准,否则不出现 json.c_position (index+1) if ex_choice_random_boolean #当选项随机时,选项位置以此为准,否则不出现
json.choice_id a.id json.choice_id a.id
# json.choice_text (edit_type.present? || question.question_type == 2) ? a.choice_text : "#{(index+65).chr}.#{a.choice_text}" # json.choice_text (edit_type.present? || question.question_type == 2) ? a.choice_text : "#{(index+65).chr}.#{a.choice_text}"
json.choice_text a.choice_text
json.choice_text choice_text
json.choice_position a.choice_position json.choice_position a.choice_position
if exercise_type == 1 || exercise_type == 4 #1为教师编辑/预览 试卷或问题2为空白试卷即标准答案和用户答案都不显示3为用户开始答题的显示4为老师评阅试卷或学生在截止后查看试卷 if exercise_type == 1 || exercise_type == 4 #1为教师编辑/预览 试卷或问题2为空白试卷即标准答案和用户答案都不显示3为用户开始答题的显示4为老师评阅试卷或学生在截止后查看试卷
json.standard_boolean standard_answer_b json.standard_boolean standard_answer_b
@ -36,6 +46,14 @@ if question.question_type <= 2 #当为选择题或判断题时,只显示选
if exercise_type == 1 || exercise_type == 4 #1为老师4为试卷截止且答案公开的情况 if exercise_type == 1 || exercise_type == 4 #1为老师4为试卷截止且答案公开的情况
json.standard_answer standard_answers_array json.standard_answer standard_answers_array
if question.question_type == 2 #返回答案的文字
standard_text = standard_answers_array.first.to_i == 1 ? "正确" : "错误"
else
array_text_answer = []
standard_answers_array.each{|a| array_text_answer.push((a+64).chr)}
standard_text = array_text_answer.join("")
end
json.standard_answer_show standard_text
end end
if exercise_type == 3 || exercise_type == 4 if exercise_type == 3 || exercise_type == 4
json.user_answer user_answer json.user_answer user_answer

@ -14,8 +14,8 @@ end
# 我的进展 # 我的进展
json.progress do json.progress do
json.my_score @subject.my_subject_score json.my_score @my_score
json.all_score @subject.all_score json.all_score @all_score
json.learned @subject.my_subject_progress json.learned @learned
json.time @subject.my_consume_time json.time @time
end end

@ -55,6 +55,8 @@ Rails.application.configure do
# Suppress logger output for asset requests. # Suppress logger output for asset requests.
config.assets.quiet = true config.assets.quiet = true
# config.assets.prefix = '/dev-assets'
# Raises error for missing translations # Raises error for missing translations
# config.action_view.raise_on_missing_translations = true # config.action_view.raise_on_missing_translations = true

@ -11,4 +11,4 @@ Rails.application.config.assets.paths << Rails.root.join('node_modules')
# Precompile additional assets. # Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets # application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added. # folder are already added.
Rails.application.config.assets.precompile += %w( admin.js admin.scss ) Rails.application.config.assets.precompile += %w( admin.js admin.css )

@ -0,0 +1,7 @@
zh-CN:
apply_action:
status:
'0': '待处理'
'1': '已同意'
'2': '已拒绝'
'3': '已撤销'

@ -774,6 +774,18 @@ Rails.application.routes.draw do
post :refuse post :refuse
end end
end end
resources :shixun_authorizations, only: [:index] do
member do
post :agree
post :refuse
end
end
resources :subject_authorizations, only: [:index] do
member do
post :agree
post :refuse
end
end
end end
#git 认证回调 #git 认证回调

@ -0,0 +1,10 @@
class ModifyChallnegeScoreForChoose < ActiveRecord::Migration[5.2]
def change
challenges = Challenge.where(st: 1)
challenges.find_each do |c|
puts(c.id)
score = c.challenge_chooses.sum(:score)
c.update_column(:score, score)
end
end
end

@ -0,0 +1 @@
{"files":{"admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js":{"logical_path":"admin.js","mtime":"2019-08-26T15:21:11+08:00","size":907839,"digest":"6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d","integrity":"sha256-ZXXxOZlT+xk1wDenuL0oxK/we3C+2bQfr2iZqJr0tX0="},"admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css":{"logical_path":"admin.css","mtime":"2019-08-26T15:21:47+08:00","size":655571,"digest":"8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5","integrity":"sha256-iisDy4oFXcY/RUQ7MEyudzgjMb66VbFXCz08iqQkQtU="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-08-21T15:10:12+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js":{"logical_path":"application.js","mtime":"2019-08-26T15:21:11+08:00","size":1042232,"digest":"a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533","integrity":"sha256-o6TzVJ1oZwVyuwdwDIWprBHlNu3HP+9udIlyO/U15TM="},"application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css":{"logical_path":"application.css","mtime":"2019-08-26T15:21:47+08:00","size":1182859,"digest":"a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46","integrity":"sha256-p1CLiOtqaaWzAWAr3cFHRc7AmFPqfZHG+uhWuW54j0Y="}},"assets":{"admin.js":"admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js","admin.css":"admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js","application.css":"application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css"}}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

@ -30,7 +30,8 @@ module.exports = {
// You may want 'eval' instead if you prefer to see the compiled output in DevTools. // You may want 'eval' instead if you prefer to see the compiled output in DevTools.
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
// devtool: "cheap-module-eval-source-map", // devtool: "cheap-module-eval-source-map",
// 开启调试 // 开启调试
devtool: "source-map", // 开启调试
// These are the "entry points" to our application. // These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle. // 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. // The first two entry points enable "hot" CSS and auto-refreshes for JS.

@ -119,7 +119,7 @@ em.vertical-line{display: inline-block;width: 2px;background: #999;height: 10px}
.tag-green .tag-name{display: block;width: auto; .tag-green .tag-name{display: block;width: auto;
/*background-image: url("/images/educoder/tag1.png");*/ /*background-image: url("/images/educoder/tag1.png");*/
background: rgba(000,000,000,0.56); background: rgba(000,000,000,0.56);
border: 1px solid #fff; border: 1px solid rgba(255,255,255,0.56);
border-radius: 3px; border-radius: 3px;
font-size: 12px; font-size: 12px;
/*opacity: 0.56;*/ /*opacity: 0.56;*/
@ -446,8 +446,8 @@ table.text-file{}
/*-------------------------------实训路径-------------------------------*/ /*-------------------------------实训路径-------------------------------*/
.path-head{width: 100%;height: 300px;background-image: url("/images/educoder/path.png"); .path-head{width: 100%;height: 300px;background-image: url("/images/educoder/path.png");
background-color: #081C4B; background-color: #000a4f;
background-size: cover; /*background-size: cover;*/
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
} }

@ -236,8 +236,7 @@ $(function(){
if(dragging) { if(dragging) {
clickX = e.pageX || e.originalEvent.touches[0].pageX;; clickX = e.pageX || e.originalEvent.touches[0].pageX;;
if(clickX > leftOffset+0&&clickX<leftOffset+1600) { if(clickX > leftOffset+0&&clickX<leftOffset+1600) {
console.log('resize') // console.log('resize')
//console.log(1);
lab.css('left', clickX - 7 - leftOffset + 'px'); lab.css('left', clickX - 7 - leftOffset + 'px');
$("#game_left_contents").width( clickX-leftOffset + 'px'); $("#game_left_contents").width( clickX-leftOffset + 'px');
nextW2 = clickX-leftOffset; nextW2 = clickX-leftOffset;
@ -314,10 +313,16 @@ $(function(){
window.top.__updateWebsshRows && window.top.__updateWebsshRows(rows) window.top.__updateWebsshRows && window.top.__updateWebsshRows(rows)
} }
window.refresh_editor_monaco = function(height) { window.refresh_editor_monaco = function(height) {
console.log('refresh_editor_monaco')
if (window.editor_monaco) { if (window.editor_monaco) {
height && $('#codetab_con_1').height(height) height && $('#codetab_con_1').height(height)
window.editor_monaco.layout(); window.editor_monaco.layout();
} }
// if ($('#game_operate_action').width() < 720) {
// $('#game_operate_action .time_limit').hide()
// } else {
// $('#game_operate_action .time_limit').show()
// }
} }
// end; // end;
//解決IE瀏覽器大小改變時webssh佈局變亂。 //解決IE瀏覽器大小改變時webssh佈局變亂。

@ -195,7 +195,30 @@ function generateNewIndexJsp() {
let cdnHost = 'https://shixun.educoder.net' let cdnHost = 'https://shixun.educoder.net'
cdnHost = 'https://ali-cdn.educoder.net' cdnHost = 'https://ali-cdn.educoder.net'
cdnHost = '' cdnHost = ''
var result = data.replace('/js/js_min_all.js', `${cdnHost}/react/build/js/js_min_all.js?v=${newVersion}`)
var mainRegex = /<script type="text\/javascript" src="\/react\/build\/.\/static\/js\/main.([a-zA-Z0-9]{8,}).js"><\/script>/
var matchResult = data.match(mainRegex)
var code = `
<script>
(function() {
var _host = '/react/build/'
/**/
if (window.location.host == 'pre-newweb.educoder.net') {
_host = 'https://testali-cdn.educoder.net/react/build/'
} else if (window.location.host == 'www.educoder.net') {
_host = 'https://ali-cdn.educoder.net/react/build/'
}
document.write('<script type="text/javascript" src="' + _host + 'js/js_min_all.js"><\\/script>');
document.write('<script type="text/javascript" src="' + _host + 'static/js/main.${matchResult[1]}.js"><\\/script>');
})()
</script>
`
var jsMinAllRegex = /<script type="text\/javascript" src="\/js\/js_min_all.js"><\/script>/
// <script type="text/javascript" src="/js/js_min_all.js"></script>
var result = data
.replace(jsMinAllRegex, code)
// .replace('/js/js_min_all.js', `${cdnHost}/react/build/js/js_min_all.js?v=${newVersion}`)
// .replace('/js/js_min_all_2.js', `${cdnHost}/react/build/js/js_min_all_2.js?v=${newVersion}`) // .replace('/js/js_min_all_2.js', `${cdnHost}/react/build/js/js_min_all_2.js?v=${newVersion}`)
// ${cdnHost} 加了cdn后这个文件里的字体文件加载会有跨域的报错 ../fonts/fontawesome-webfont.eot // ${cdnHost} 加了cdn后这个文件里的字体文件加载会有跨域的报错 ../fonts/fontawesome-webfont.eot
@ -204,10 +227,11 @@ function generateNewIndexJsp() {
.replace('/css/iconfont.css', `${cdnHost}/react/build/css/iconfont.css?v=${newVersion}`) .replace('/css/iconfont.css', `${cdnHost}/react/build/css/iconfont.css?v=${newVersion}`)
.replace(/\/js\/create_kindeditor.js/g, `${cdnHost}/react/build/js/create_kindeditor.js?v=${newVersion}`) .replace(/\/js\/create_kindeditor.js/g, `${cdnHost}/react/build/js/create_kindeditor.js?v=${newVersion}`)
.replace(mainRegex, '')
// .replace('/react/build/./static/css/main', `${cdnHost}/react/build/./static/css/main`) // .replace('/react/build/./static/css/main', `${cdnHost}/react/build/./static/css/main`)
// .replace('/react/build/./static/js/main', `${cdnHost}/react/build/./static/js/main`) // .replace('/react/build/./static/js/main', `${cdnHost}/react/build/./static/js/main`)
.replace(/https:\/\/testeduplus2.educoder.net/g, ''); // .replace(/https:\/\/testeduplus2.educoder.net/g, '');
// .replace(/http:\/\/testbdweb.educoder.net/g, ''); // .replace(/http:\/\/testbdweb.educoder.net/g, '');
// .replace('/css/css_min_all.css', '/react/build/css/css_min_all.css'); // .replace('/css/css_min_all.css', '/react/build/css/css_min_all.css');

@ -55,6 +55,10 @@ html, body {
.markdown-body p { .markdown-body p {
white-space: pre-wrap; white-space: pre-wrap;
} }
/* https://www.educoder.net/courses/2346/group_homeworks/34405/question */
.renderAsHtml.markdown-body p {
white-space: inherit;
}
/* resize */ /* resize */
.editormd .CodeMirror { .editormd .CodeMirror {
border-right: none !important; border-right: none !important;

@ -1,4 +1,5 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import './public-path';
import logo from './logo.svg'; import logo from './logo.svg';
import './App.css'; import './App.css';
import {LocaleProvider} from 'antd' import {LocaleProvider} from 'antd'

@ -9,6 +9,7 @@ export function markdownToHTML(oldContent, selector) {
window.$('#md_div').html('') window.$('#md_div').html('')
// markdown to html // markdown to html
if (selector && oldContent && oldContent.startsWith('<p')) { // 普通html处理 if (selector && oldContent && oldContent.startsWith('<p')) { // 普通html处理
window.$('#' + selector).addClass('renderAsHtml')
window.$('#' + selector).html(oldContent) window.$('#' + selector).html(oldContent)
} else { } else {
try { try {

@ -1,4 +1,5 @@
import React,{ Component } from "react"; import React,{ Component } from "react";
import { ConditionToolTip } from 'educoder'
class AttachmentsList extends Component{ class AttachmentsList extends Component{
constructor(props){ constructor(props){
@ -11,15 +12,19 @@ class AttachmentsList extends Component{
{ {
attachments.map((item,key)=>{ attachments.map((item,key)=>{
return( return(
<p key={key}> <p key={key} className="clearfix mb3">
<a className="color-grey"> <a className="color-grey fl">
<i className="font-14 color-green iconfont icon-fujian mr8"></i> <i className="font-14 color-green iconfont icon-fujian mr8"></i>
</a> </a>
{ {
item.is_pdf && item.is_pdf == true ? item.is_pdf && item.is_pdf == true ?
<a href={item.url} className="mr12" length="58" target="_blank">{item.title}</a> <ConditionToolTip title={item.title} condition={item.title && item.title.length > 30 }>
<a href={item.url} className="mr12 fl task-hide" length="58" target="_blank" style={{"maxWidth":"432px"}}>{item.title}</a>
</ConditionToolTip>
: :
<a href={item.url} className="mr12" length="58">{item.title}</a> <ConditionToolTip title={item.title} condition={item.title && item.title.length > 30 }>
<a href={item.url} className="mr12 fl task-hide" length="58" style={{"maxWidth":"432px"}}>{item.title}</a>
</ConditionToolTip>
} }
<span className="color-grey mt2 color-grey-6 font-12">{item.filesize}</span> <span className="color-grey mt2 color-grey-6 font-12">{item.filesize}</span>
</p> </p>

@ -129,12 +129,16 @@ class Fileslistitem extends Component{
.catch(function (error) { .catch(function (error) {
console.log(error); console.log(error);
}); });
} }
eventStop = (event) =>{
event.stopPropagation()
}
render(){ render(){
const { checkBox, const { checkBox,
discussMessage, discussMessage,index
} = this.props; } = this.props;
return( return(
@ -190,9 +194,9 @@ class Fileslistitem extends Component{
white-space:nowrap white-space:nowrap
} }
`}</style> `}</style>
<div className="clearfix ds pr contentSection"> <div className="clearfix ds pr contentSection" style={{cursor : this.props.isAdmin ? "pointer" : "default"}} onClick={() => window.$(`.sourceitem${index} input`).click() }>
<h6> <h6 onClick={(event)=>this.eventStop(event)}>
<span className="fl mr12 mt3"> <span className={`sourceitem${index} fl mr12 mt3`}>
{checkBox} {checkBox}
</span> </span>
{ {
@ -283,16 +287,15 @@ class Fileslistitem extends Component{
</span> </span>
</span> </span>
{this.props.isAdmin? {this.props.isAdmin?
<span className={"fr mrf2 mr10"}> <span className={"fr mrf2 mr10"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr"> <WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue" <a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a> onClick={()=>this.settingList()}>设置</a>
</WordsBtn> </WordsBtn>
</span>:""} </span>:""}
{this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login? {this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login?
<span className={"fr mrf2 mr10"}> <span className={"fr mrf2 mr10"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr"> <WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue" <a className="btn colorblue"

@ -10,6 +10,8 @@ import Selectsetting from "../coursesPublic/SelectSetting";
import HomeworkModal from "../coursesPublic/HomeworkModal"; import HomeworkModal from "../coursesPublic/HomeworkModal";
import Fileslistitem from './Fileslistitem'; import Fileslistitem from './Fileslistitem';
import Titlesearchsection from '../common/titleSearch/TitleSearchSection'; import Titlesearchsection from '../common/titleSearch/TitleSearchSection';
import NoneData from "../coursesPublic/NoneData";
import _ from 'lodash'
import './style.css'; import './style.css';
import '../css/members.css'; import '../css/members.css';
import moment from 'moment'; import moment from 'moment';
@ -474,7 +476,16 @@ class Fileslists extends Component{
} }
onItemClick = (item) => {
const checkBoxValues = this.state.checkBoxValues.slice(0);
const index = checkBoxValues.indexOf(item.id);
if (index != -1) {
_.remove(checkBoxValues, (listItem)=> listItem === item.id)
} else {
checkBoxValues.push(item.id);
}
this.onCheckBoxChange(checkBoxValues)
}
PaginationTask=(page)=>{ PaginationTask=(page)=>{
let {search,order,selectpage,checkAllValue,checkBoxValues}=this.state; let {search,order,selectpage,checkAllValue,checkBoxValues}=this.state;
@ -787,7 +798,7 @@ class Fileslists extends Component{
showSearchInput={true} showSearchInput={true}
></Titlesearchsection> ></Titlesearchsection>
{this.props.isAdmin()? <div className="mt20 edu-back-white padding20-30" style={{display:this.props.isAdmin()||this.props.isStudent()?"":"none"}}> {this.props.isAdmin()? files===undefined?'' :files.length===0? "":<div className="mt20 edu-back-white padding20-30" style={{display:this.props.isAdmin()||this.props.isStudent()?"":"none"}}>
<div className="clearfix"> <div className="clearfix">
{this.props.isAdmin()? <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>:""} {this.props.isAdmin()? <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>:""}
<div className="studentList_operation_ul"> <div className="studentList_operation_ul">
@ -897,7 +908,7 @@ class Fileslists extends Component{
{ files&&files.map((item, index) => { { files&&files.map((item, index) => {
return ( return (
<div className="mt20 edu-back-white padding02010" key={index}> <div className="mt20 edu-back-white padding02010" key={index} onClick={()=>this.onItemClick(item)}>
<div className="clearfix"> <div className="clearfix">
<div key={index}> <div key={index}>
<Fileslistitem <Fileslistitem
@ -909,7 +920,8 @@ class Fileslists extends Component{
checkBox={this.props.isAdmin()?<Checkbox value={item.id} key={item.id}></Checkbox>:""} checkBox={this.props.isAdmin()?<Checkbox value={item.id} key={item.id}></Checkbox>:""}
Settingtypes={(id)=>this.Settingtypes(id)} Settingtypes={(id)=>this.Settingtypes(id)}
coursesId={this.props.match.params.coursesId} coursesId={this.props.match.params.coursesId}
updatafiledfun={()=>this.updatafiled()} updatafiledfun={()=>this.updatafiled()}
index={index}
></Fileslistitem> ></Fileslistitem>
</div> </div>
</div> </div>
@ -948,21 +960,23 @@ class Fileslists extends Component{
/>:""} />:""}
</div> </div>
<div className="alltask edu-back-white" {
style={ files===undefined?'' :files.length===0?<NoneData></NoneData>:""
{ }
display: files===undefined?'none' :files.length===0? 'block' : 'none'
}
}
>
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src="/images/educoder/nodata.png" />
<p className="edu-nodata-p mb20">暂时还没有相关数据哦</p></div>
</div>
</React.Fragment> </React.Fragment>
) )
} }
} }
export default Fileslists; export default Fileslists;
{/*<div className="alltask"*/}
{/*style={*/}
{/*{*/}
{/*display: files===undefined?'none' :files.length===0? 'block' : 'none'*/}
{/*}*/}
{/*}*/}
{/*>*/}
{/*<div className="edu-tab-con-box clearfix edu-txt-center">*/}
{/*<img className="edu-nodata-img mb20" src="/images/educoder/nodata.png" />*/}
{/*<p className="edu-nodata-p mb20">暂时还没有相关数据哦!</p></div>*/}
{/*</div>*/}

@ -376,10 +376,15 @@ class BoardsNew extends Component{
dropdownRender={menu => ( dropdownRender={menu => (
<div> <div>
{menu} {menu}
<Divider style={{ margin: '4px 0' }} /> {
<div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}> isAdmin &&
<Icon type="plus" /> 添加目录 <React.Fragment>
</div> <Divider style={{ margin: '4px 0' }} />
<div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}>
<Icon type="plus" /> 添加目录
</div>
</React.Fragment>
}
</div> </div>
)} )}
> >

@ -24,7 +24,7 @@ import '../../forums/RightSection.css'
import './TopicDetail.css' import './TopicDetail.css'
import '../common/courseMessage.css' import '../common/courseMessage.css'
import { Pagination, Tooltip } from 'antd' import { Pagination, Tooltip } from 'antd'
import { bytesToSize, ConditionToolTip, markdownToHTML, MarkdownToHtml } from 'educoder' import { bytesToSize, ConditionToolTip, markdownToHTML, MarkdownToHtml , setImagesUrl } from 'educoder'
import SendToCourseModal from '../coursesPublic/modal/SendToCourseModal' import SendToCourseModal from '../coursesPublic/modal/SendToCourseModal'
import CBreadcrumb from '../common/CBreadcrumb' import CBreadcrumb from '../common/CBreadcrumb'
import { generateComments, generateChildComments, _findById, handleContentBeforeCreateNew, addNewComment import { generateComments, generateChildComments, _findById, handleContentBeforeCreateNew, addNewComment
@ -57,6 +57,7 @@ class TopicDetail extends Component {
pageCount: 1, pageCount: 1,
comments: [], comments: [],
goldRewardDialogOpen: false, goldRewardDialogOpen: false,
author:undefined
} }
} }
componentDidMount() { componentDidMount() {
@ -85,7 +86,8 @@ class TopicDetail extends Component {
memo: Object.assign({}, { memo: Object.assign({}, {
...response.data.data, ...response.data.data,
replies_count: response.data.data.total_replies_count replies_count: response.data.data.total_replies_count
}, {...this.state.memo}) }, {...this.state.memo}),
author:response.data.data.author
}, () => { }, () => {
}) })
@ -514,7 +516,7 @@ class TopicDetail extends Component {
render() { render() {
const { match, history } = this.props const { match, history } = this.props
const { recommend_shixun, current_user,author_info } = this.props; const { recommend_shixun, current_user,author_info } = this.props;
const { memo, comments, hasMoreComments, goldRewardDialogOpen, pageCount, total_count } = this.state; const { memo, comments, hasMoreComments, goldRewardDialogOpen, pageCount, total_count , author } = this.state;
const messageId = match.params.topicId const messageId = match.params.topicId
if (this.state.memoLoading || !current_user) { if (this.state.memoLoading || !current_user) {
return <div className="edu-back-white" id="forum_index_list"></div> return <div className="edu-back-white" id="forum_index_list"></div>
@ -599,51 +601,54 @@ class TopicDetail extends Component {
} }
</div> </div>
<div className="color-grey-9 clearfix"> <div className="df mt20">
<span className="fl" style={{marginTop: "2px"}}>{moment(memo.created_on).fromNow()} 发布</span> <img src={setImagesUrl(`/images/${author && author.image_url}`)} className="radius mr10 mt2" width="40px" height="40px"/>
<div className="fr"> <div className="flex1">
<div className="color-grey-9 lineh-20">
</div> <span class="color-grey-3 mr20 fl" style={{"fontWeight":"400"}}>{author && author.name}</span>
</div> <span className="fl">{moment(memo.created_on).fromNow()} 发布</span>
</div>
<div className="color-grey-9 clearfix">
<span className="fl" style={{marginTop: '4px'}}> <div className="color-grey-9 clearfix">
{/* { current_user.admin && <Tooltip title={ "" }> <span className="fl" style={{marginTop: '4px'}}>
<span className="noteDetailNum rightline cdefault" style={{padding: '0 4px', cursor: 'pointer'}}> {/* { current_user.admin && <Tooltip title={ "" }>
<i className="iconfont icon-jiangli mr5" onClick={this.showRewardDialog}></i> <span className="noteDetailNum rightline cdefault" style={{padding: '0 4px', cursor: 'pointer'}}>
</span> <i className="iconfont icon-jiangli mr5" onClick={this.showRewardDialog}></i>
</Tooltip> } */}
<Tooltip title={"浏览数"}>
<span className={`noteDetailNum `} style={{paddingLeft: '0px'}}>
<i className="iconfont icon-liulanyan mr5"></i>
<span style={{ top: "1px", position: "relative" }}>{memo.visits || '1'}</span>
</span>
</Tooltip>
{ !!memo.total_replies_count &&
<Tooltip title={"回复数"}>
<a href="javascript:void(0)" className="noteDetailNum">
<i className="iconfont icon-huifu1 mr5" onClick={this.showCommentInput}></i>
<span style={{ top: "2px", position: "relative" }}>{ memo.total_replies_count }</span>
</a>
</Tooltip>
}
{!!memo.praises_count &&
<Tooltip title={"点赞数"}>
<span className={`noteDetailNum `} style={{}}>
<i className="iconfont icon-dianzan-xian mr5"></i>
<span style={{ top: "2px", position: "relative" }}>{ memo.praises_count }</span>
</span> </span>
</Tooltip> </Tooltip> } */}
<Tooltip title={"浏览数"}>
<span className={`noteDetailNum `} style={{paddingLeft: '0px'}}>
<i className="iconfont icon-liulanyan mr5"></i>
<span style={{ top: "1px", position: "relative" }}>{memo.visits || '1'}</span>
</span>
</Tooltip>
{ !!memo.total_replies_count &&
<Tooltip title={"回复数"}>
<a href="javascript:void(0)" className="noteDetailNum">
<i className="iconfont icon-huifu1 mr5" onClick={this.showCommentInput}></i>
<span style={{ top: "2px", position: "relative" }}>{ memo.total_replies_count }</span>
</a>
</Tooltip>
} }
</span> {!!memo.total_praises_count &&
<div className="fr"> <Tooltip title={"点赞数"}>
{/* || current_user.user_id === author_info.user_id */} <span className={`noteDetailNum `} style={{}}>
<a className={`task-hide fr return_btn color-grey-6 ${ current_user && (isAdmin <i className="iconfont icon-dianzan-xian mr5"></i>
) ? '': 'no_mr'} `} onClick={() => this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id})) } > <span style={{ top: "2px", position: "relative" }}>{ memo.total_praises_count }</span>
返回 </span>
</a> </Tooltip>
</div> }
</span>
<div className="fr">
{/* || current_user.user_id === author_info.user_id */}
<a className={`task-hide fr return_btn color-grey-6 ${ current_user && (isAdmin
) ? '': 'no_mr'} `} onClick={() => this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id})) } >
返回
</a>
</div>
</div>
</div> </div>
</div>
</div> </div>

@ -363,9 +363,9 @@ class Boards extends Component{
<FilesListItem></FilesListItem> */} <FilesListItem></FilesListItem> */}
{isAdmin && <div className="mt20 edu-back-white padding20-30"> {messages&&messages.length == 0?"": isAdmin && <div className="mt20 edu-back-white padding20-30">
<div className="clearfix"> <div className="clearfix">
{isAdmin && <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>} {isAdmin&&<Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>}
<div className="studentList_operation_ul"> <div className="studentList_operation_ul">
{ !!isAdmin && { !!isAdmin &&
<React.Fragment> <React.Fragment>

@ -15,7 +15,7 @@ import WorkDetailPageHeader from './common/WorkDetailPageHeader'
import CommonWorkAppraiseReply from './reply/CommonWorkAppraiseReply' import CommonWorkAppraiseReply from './reply/CommonWorkAppraiseReply'
import Example from './TestHooks' import Example from './TestHooks'
import CommonWorkAppraiseReviseAttachments from './CommonWorkAppraiseReviseAttachments' import CommonWorkAppraiseReviseAttachments from './CommonWorkAppraiseReviseAttachments'
import LeaderIcon from './common/LeaderIcon'
const { Option} = Select; const { Option} = Select;
const CheckboxGroup = Checkbox.Group; const CheckboxGroup = Checkbox.Group;
const confirm = Modal.confirm; const confirm = Modal.confirm;
@ -88,6 +88,14 @@ class CommonWorkAppraise extends Component{
console.log(error) console.log(error)
}) })
} }
componentDidUpdate(prevProps, prevState) {
if (this.props.match.params.studentWorkId != prevProps.match.params.studentWorkId) {
this.getWork();
this.getReviseAttachments()
this.commonWorkAppraiseReply && this.commonWorkAppraiseReply.fetchAllComments()
}
}
componentDidMount() { componentDidMount() {
this.getWork(); this.getWork();
this.getReviseAttachments() this.getReviseAttachments()
@ -156,12 +164,13 @@ class CommonWorkAppraise extends Component{
attachments, homework_id, project_info, work_members, is_evaluation, attachments, homework_id, project_info, work_members, is_evaluation,
description, update_user_name, update_time, commit_time, author_name, description, update_user_name, update_time, commit_time, author_name,
revise_attachments, revise_reason, atta_update_user, atta_update_time, atta_update_user_login, revise_attachments, revise_reason, atta_update_user, atta_update_time, atta_update_user_login,
Modalstype,Modalstopval,ModalCancel,ModalSave,loadtype Modalstype,Modalstopval,ModalCancel,ModalSave,loadtype, is_leader_work
} =this.state; } =this.state;
let courseId=this.props.match.params.coursesId; let courseId=this.props.match.params.coursesId;
let category_id=this.props.match.params.category_id; let category_id=this.props.match.params.category_id;
let studentWorkId=this.props.match.params.studentWorkId; let studentWorkId=this.props.match.params.studentWorkId;
const isAdmin = this.props.isAdmin()
return( return(
<WorkDetailPageHeader <WorkDetailPageHeader
{...this.props} {...this.state} {...this.props} {...this.state}
@ -251,12 +260,27 @@ class CommonWorkAppraise extends Component{
{is_evaluation != true && work_members && !!work_members.length && <div className={"stud-class-set bor-top-greyE edu-back-white padding20-30"}> {is_evaluation != true && work_members && !!work_members.length && <div className={"stud-class-set bor-top-greyE edu-back-white padding20-30"}>
<div className={"color-grey-6 mb10"}> <div className={"color-grey-6 mb10"}>
其他组员 全部组员
</div> </div>
<div className={"ml20"}> <div className={"ml20 color-grey-6"}>
{work_members.map((item, index) => { <div className="">
return item.user_name + ' ' 当前组员{author_name} {is_leader_work && <LeaderIcon small={true} ></LeaderIcon>}
})} </div>
<div>
其他组员
{work_members.map((item, index) => {
return <React.Fragment>
{isAdmin ?
<a className={`color-blue ${index == 0 ? '' : 'ml10'}`} href="javascript:void(0)"
onClick={() => this.props.toWorkDetailPage(this.props.match.params, null, item.work_id)}
>
{item.user_name}
</a> : <span className={`${index == 0 ? '' : 'ml10'}`} >{item.user_name}</span>}
{item.is_leader && <LeaderIcon small={true} ></LeaderIcon>}
</React.Fragment>
})}
</div>
</div> </div>
</div> </div>
} }
@ -266,6 +290,7 @@ class CommonWorkAppraise extends Component{
{/* task_type={datalist&&datalist.task_type} */} {/* task_type={datalist&&datalist.task_type} */}
<CommonWorkAppraiseReply {...this.props} task_id={studentWorkId} <CommonWorkAppraiseReply {...this.props} task_id={studentWorkId}
onReplySuccess={this.onReplySuccess} {...this.state} onReplySuccess={this.onReplySuccess} {...this.state}
wrappedComponentRef={(ref) => {this.commonWorkAppraiseReply = ref}}
></CommonWorkAppraiseReply> ></CommonWorkAppraiseReply>
</div> </div>

@ -15,7 +15,7 @@ import WorkDetailPageHeader from './common/WorkDetailPageHeader'
import PublishRightnow from './PublishRightnow' import PublishRightnow from './PublishRightnow'
import ModulationModal from "../coursesPublic/ModulationModal"; import ModulationModal from "../coursesPublic/ModulationModal";
import AccessoryModal from "../coursesPublic/AccessoryModal"; import AccessoryModal from "../coursesPublic/AccessoryModal";
import LeaderIcon from './common/LeaderIcon'
const { Option} = Select; const { Option} = Select;
const CheckboxGroup = Checkbox.Group; const CheckboxGroup = Checkbox.Group;
const confirm = Modal.confirm; const confirm = Modal.confirm;
@ -97,7 +97,12 @@ function buildColumns(that, student_works, studentData) {
}} title={text && text.length > 5 ? text : ''}> }} title={text && text.length > 5 ? text : ''}>
{/* <Tooltip placement="bottom" title={text}> {/* <Tooltip placement="bottom" title={text}>
</Tooltip> */} </Tooltip> */}
{text} {record.is_leader ?
<div style={{ display: 'flex', 'flex-direction': 'column', 'align-items': 'center'}}>
<div >{text}</div>
<LeaderIcon></LeaderIcon>
</div>
: <React.Fragment>{text}</React.Fragment>}
</div> </div>
), ),
}] }]

@ -91,7 +91,7 @@ class CommonWorkQuestion extends Component{
{/* 内容区 */} {/* 内容区 */}
<div className="padding40 memoContent new_li"> <div className="padding40 memoContent new_li">
<MarkdownToHtml content={description} selector="work_content"></MarkdownToHtml> <MarkdownToHtml content={description} selector="work_content" className="mb10"></MarkdownToHtml>
{ attachments && attachments.map((item) => { { attachments && attachments.map((item) => {
return ( <div className="color-grey"> return ( <div className="color-grey">

@ -128,7 +128,7 @@ class UseBank extends Component{
}) })
} }
onSave = () => { onSave = () => {
debugger
const { checkBoxValues } = this.state; const { checkBoxValues } = this.state;
const { object_type } = this.props const { object_type } = this.props
if(checkBoxValues.length==0){ if(checkBoxValues.length==0){

@ -0,0 +1,19 @@
import React,{Component} from "React";
export default function LeaderIcon(props = {}) {
let icon = null;
if (props.small) {
icon = <div className="font-8 blueFull Actionbtn" style={{
height: '14px',
'line-height': '14px',
width: '24px',
padding: 0,
'margin-top': '-2px',
'margin-left': '2px',
'vertical-align': 'middle', }}>组长</div>
} else {
icon = <div className="font-8 blueFull Actionbtn" style={{ height: '16px', 'line-height': '16px', width: '30px'}}>组长</div>
}
return icon
}

@ -85,8 +85,7 @@ class WorkDetailPageHeader extends Component{
background: #fff; background: #fff;
} }
.workDetailPageHeader .summaryname { .workDetailPageHeader .summaryname {
line-height: 20px; line-height:30px
margin-top: 13px;
} }
`}</style> `}</style>
<CBreadcrumb items={[ <CBreadcrumb items={[
@ -99,18 +98,18 @@ class WorkDetailPageHeader extends Component{
// { name: childModuleName } // { name: childModuleName }
]}></CBreadcrumb> ]}></CBreadcrumb>
<div style={{ width:'100%',height:'52px'}} > <div className="clearfix mt20 mb20" >
<span className=" fl color-black summaryname" style={{height: 'auto'}}> <span className=" fl color-black summaryname">
{homework_name} {homework_name}
{/* <Link to={"/courses/"+courseId+"/graduation"+"/graduation_tasks/"}>{homework_name}</Link> */} {/* <Link to={"/courses/"+courseId+"/graduation"+"/graduation_tasks/"}>{homework_name}</Link> */}
</span> </span>
<CoursesListType <CoursesListType
typelist={homework_status} typelist={homework_status}
typesylename={"mt12"} typesylename={"mt3"}
/> />
{category && <a className="color-grey-6 fr font-16 ml30 mt7 mr20" onClick={this.goback} style={{ marginRight: '26px'}}>返回</a>} {category && <a className="color-grey-6 fr font-16 ml30 mr30 lineh-25" onClick={this.goback}>返回</a>}
{this.props.update_atta && {this.props.update_atta &&
<React.Fragment> <React.Fragment>

@ -143,7 +143,9 @@ class commonWork extends Component{
this.setState({ this.setState({
order:e.key==="all"?"":e.key, order:e.key==="all"?"":e.key,
page:1, page:1,
isSpin:true isSpin:true,
checkBoxValues:[],
checkAll:false
}) })
let {search}=this.state; let {search}=this.state;
this.getList(1,search,e.key==="all"?"":e.key); this.getList(1,search,e.key==="all"?"":e.key);

@ -750,7 +750,8 @@ class Coursesleftnav extends Component{
{/*分班*/} {/*分班*/}
{item.type==="course_group"?<div onClick={e=>this.Navmodalnames(e,2,"course_group",item.id)}>添加分班</div>:""} {item.type==="course_group"?<div onClick={e=>this.Navmodalnames(e,2,"course_group",item.id)}>添加分班</div>:""}
{/*分班*/} {/*分班*/}
{item.type==="course_group"?<div onClick={e=>this.Navmodalnames(e,5,"editname",item.id,item.name)}>重命名</div>: <div onClick={e=>this.Navmodalnames(e,3,"editname",item.id,item.name)}></div>} {/*{item.type==="course_group"? :""}*/}
<div onClick={e=>this.Navmodalnames(e,3,"editname",item.id,item.name)}>重命名</div>
<div onClick={e=>this.edithidden(e,item.id)}>隐藏</div> <div onClick={e=>this.edithidden(e,item.id)}>隐藏</div>
<div onClick={e=>this.editSetup(e,item.id)}>置顶</div> <div onClick={e=>this.editSetup(e,item.id)}>置顶</div>

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import {getImageUrl} from 'educoder'; import { getImageUrl , getUrl } from 'educoder';
class NoneData extends Component{ class NoneData extends Component{
constructor(props) { constructor(props) {
@ -9,7 +9,20 @@ class NoneData extends Component{
const { style } = this.props; const { style } = this.props;
return( return(
<div className="edu-tab-con-box clearfix edu-txt-center" style={style}> <div className="edu-tab-con-box clearfix edu-txt-center" style={style}>
<img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/> <style>
{`
.edu-tab-con-box{
padding:100px 0px;
}
.ant-modal-body .edu-tab-con-box{
padding:0px!important;
}
img.edu-nodata-img{
margin: 40px auto 20px;
}
`}
</style>
<img className="edu-nodata-img mb20" src={getUrl("/images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb20">暂时还没有相关数据哦</p> <p className="edu-nodata-p mb20">暂时还没有相关数据哦</p>
</div> </div>
) )

@ -180,11 +180,13 @@ class PathModal extends Component{
}else{ }else{
// this.homeworkstart // this.homeworkstart
//调用立即发布弹窗 //调用立即发布弹窗
// this.props.showNotification(response.data.message)
this.props.hidecouseShixunModal(); this.props.hidecouseShixunModal();
this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids) this.props.updataleftNavfun()
// this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids)
// this.props.showNotification("选用成功") // this.props.showNotification("选用成功")
// this.props.showNotification(response.data.message) // this.props.showNotification(response.data.message)
// this.props.homeworkupdatalists(Coursename,page,order); this.props.homeworkupdatalists(this.props.Coursename,this.props.page,this.props.order);
} }
// if(response.status===200) { // if(response.status===200) {

@ -186,7 +186,8 @@ class ShixunModal extends Component{
// this.props.showNotification(response.data.message) // this.props.showNotification(response.data.message)
}else{ }else{
this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids) // this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids)
this.props.homeworkupdatalists(this.props.Coursename,this.props.page,this.props.order);
this.props.hidecouseShixunModal() this.props.hidecouseShixunModal()
} }
this.setState({ this.setState({

@ -1,209 +1,209 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { Modal, Checkbox, Input, Spin} from "antd"; import { Modal, Checkbox, Input, Spin} from "antd";
import axios from 'axios' import axios from 'axios'
import ModalWrapper from "../../common/ModalWrapper" import ModalWrapper from "../../common/ModalWrapper"
import InfiniteScroll from 'react-infinite-scroller'; import InfiniteScroll from 'react-infinite-scroller';
const Search = Input.Search const Search = Input.Search
const pageCount = 15; const pageCount = 15;
class SendToCourseModal extends Component{ class SendToCourseModal extends Component{
constructor(props){ constructor(props){
super(props); super(props);
this.state={ this.state={
checkBoxValues: [], checkBoxValues: [],
course_lists: [], course_lists: [],
course_lists_after_filter: [], course_lists_after_filter: [],
searchValue: '', searchValue: '',
hasMore: true, hasMore: true,
loading: false, loading: false,
page: 1 page: 1
} }
} }
fetchCourseList = (arg_page) => { fetchCourseList = (arg_page) => {
const page = arg_page || this.state.page; const page = arg_page || this.state.page;
// search=''& // search=''&
let url = `/courses/mine.json?page=${page}&page_size=${pageCount}` let url = `/courses/mine.json?page=${page}&page_size=${pageCount}`
const searchValue = this.state.searchValue.trim() const searchValue = this.state.searchValue.trim()
if (searchValue) { if (searchValue) {
url += `&search=${searchValue}` url += `&search=${searchValue}`
} }
this.setState({ loading: true }) this.setState({ loading: true })
axios.get(url, { axios.get(url, {
}) })
.then((response) => { .then((response) => {
if (!response.data.data || response.data.data.length == 0) { if (!response.data.data || response.data.data.length == 0) {
this.setState({ this.setState({
course_lists: page == 1 ? [] : this.state.course_lists, course_lists: page == 1 ? [] : this.state.course_lists,
page, page,
loading: false, loading: false,
hasMore: false, hasMore: false,
}) })
} else { } else {
this.setState({ this.setState({
course_lists: page == 1 ? response.data.data : this.state.course_lists.concat(response.data.data), course_lists: page == 1 ? response.data.data : this.state.course_lists.concat(response.data.data),
course_lists_after_filter: response.data.data, course_lists_after_filter: response.data.data,
page, page,
loading: false, loading: false,
hasMore: response.data.data.length == pageCount hasMore: response.data.data.length == pageCount
}) })
} }
}) })
.catch(function (error) { .catch(function (error) {
console.log(error); console.log(error);
}); });
} }
componentDidMount() { componentDidMount() {
setTimeout(() => { setTimeout(() => {
this.fetchCourseList() this.fetchCourseList()
}, 500) }, 500)
} }
setVisible = (visible) => { setVisible = (visible) => {
this.refs.modalWrapper.setVisible(visible) this.refs.modalWrapper.setVisible(visible)
if (visible == false) { if (visible == false) {
this.setState({ this.setState({
checkBoxValues: [] checkBoxValues: []
}) })
} }
} }
onSendOk = () => { onSendOk = () => {
if (!this.state.checkBoxValues || this.state.checkBoxValues.length == 0) { if (!this.state.checkBoxValues || this.state.checkBoxValues.length == 0) {
this.props.showNotification('请先选择要发送至的课堂') this.props.showNotification('请先选择要发送至的课堂')
return; return;
} }
if(this.props.url==="/files/bulk_send.json"){ if(this.props.url==="/files/bulk_send.json"){
axios.post("/files/bulk_send.json", { axios.post("/files/bulk_send.json", {
course_id:this.props.match.params.coursesId, course_id:this.props.match.params.coursesId,
ids: this.props.selectedMessageIds, ids: this.props.selectedMessageIds,
to_course_ids: this.state.checkBoxValues to_course_ids: this.state.checkBoxValues
}) })
.then((response) => { .then((response) => {
if (response.data.status == 0) { if (response.data.status == 0) {
this.setVisible(false) this.setVisible(false)
this.props.gobackonSend(response.data.message) this.props.gobackonSend(response.data.message)
} }
}) })
.catch(function (error) { .catch(function (error) {
console.log(error); console.log(error);
}); });
}else{ }else{
const bid = this.props.match.params.boardId const bid = this.props.match.params.boardId
const url = `/boards/${bid}/messages/bulk_send.json` const url = `/boards/${bid}/messages/bulk_send.json`
axios.post(url, { axios.post(url, {
ids: this.props.selectedMessageIds, ids: this.props.selectedMessageIds,
to_course_ids: this.state.checkBoxValues to_course_ids: this.state.checkBoxValues
}) })
.then((response) => { .then((response) => {
if (response.data.status == 0) { if (response.data.status == 0) {
this.setVisible(false) this.setVisible(false)
this.props.showNotification('发送成功') this.props.showNotification('发送成功')
} }
}) })
.catch(function (error) { .catch(function (error) {
console.log(error); console.log(error);
}); });
} }
} }
onOk = () => { onOk = () => {
const { course_lists, checkBoxValues } = this.state const { course_lists, checkBoxValues } = this.state
this.onSendOk() this.onSendOk()
// this.props.onOk && this.props.onOk(checkBoxValues) // this.props.onOk && this.props.onOk(checkBoxValues)
// this.refs.modalWrapper.setVisible(false) // this.refs.modalWrapper.setVisible(false)
} }
onCheckBoxChange = (checkBoxValues) => { onCheckBoxChange = (checkBoxValues) => {
this.setState({ this.setState({
checkBoxValues: checkBoxValues checkBoxValues: checkBoxValues
}) })
} }
onSearchChange = (e) => { onSearchChange = (e) => {
this.setState({ this.setState({
searchValue: e.target.value searchValue: e.target.value
}) })
} }
handleInfiniteOnLoad = () => { handleInfiniteOnLoad = () => {
console.log('loadmore...') console.log('loadmore...')
this.fetchCourseList(this.state.page + 1) this.fetchCourseList(this.state.page + 1)
} }
onSearch = () => { onSearch = () => {
// const course_lists_after_filter = this.state.course_lists.filter( item => item.name.indexOf(this.state.searchValue) != -1 ) // const course_lists_after_filter = this.state.course_lists.filter( item => item.name.indexOf(this.state.searchValue) != -1 )
// this.setState({ course_lists_after_filter }) // this.setState({ course_lists_after_filter })
this.fetchCourseList(1) this.fetchCourseList(1)
} }
render(){ render(){
const { course_lists, checkBoxValues, searchValue, loading, hasMore } = this.state const { course_lists, checkBoxValues, searchValue, loading, hasMore } = this.state
const { moduleName } = this.props const { moduleName } = this.props
return( return(
<ModalWrapper <ModalWrapper
ref="modalWrapper" ref="modalWrapper"
title={`发送${moduleName}`} title={`发送${moduleName}`}
{...this.props } {...this.props }
onOk={this.onOk} onOk={this.onOk}
> >
<style> <style>
{` {`
.demo-loading-container { .demo-loading-container {
position: absolute; position: absolute;
bottom: 93px; bottom: 93px;
width: 82%; width: 82%;
text-align: center; text-align: center;
}`} }`}
</style> </style>
<p className="color-grey-6 mb20 edu-txt-center" style={{ fontWeight: "bold" }} >选择的{moduleName}发送到<span className="color-orange-tip">指定课堂</span></p> <p className="color-grey-6 mb20 edu-txt-center" style={{ fontWeight: "bold" }} >选择的{moduleName}发送到<span className="color-orange-tip">指定课堂</span></p>
<Search <Search
className="mb14" className="mb14"
value={searchValue} value={searchValue}
placeholder="请输入课堂名称进行搜索" placeholder="请输入课堂名称进行搜索"
onChange={this.onSearchChange} onChange={this.onSearchChange}
onSearch={this.onSearch} onSearch={this.onSearch}
></Search> ></Search>
<div> <div>
{/* https://github.com/CassetteRocks/react-infinite-scroller/issues/70 */} {/* https://github.com/CassetteRocks/react-infinite-scroller/issues/70 */}
<div className="edu-back-skyblue padding15" style={{"height":"300px", overflowY: "scroll", overflowAnchor: 'none' }}> <div className="edu-back-skyblue padding15" style={{"height":"300px", overflowY: "scroll", overflowAnchor: 'none' }}>
<InfiniteScroll <InfiniteScroll
threshold={10} threshold={10}
initialLoad={false} initialLoad={false}
pageStart={0} pageStart={0}
loadMore={this.handleInfiniteOnLoad} loadMore={this.handleInfiniteOnLoad}
hasMore={!loading && hasMore} hasMore={!loading && hasMore}
useWindow={false} useWindow={false}
> >
<Checkbox.Group style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={checkBoxValues}> <Checkbox.Group style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={checkBoxValues}>
{ course_lists && course_lists.map( course => { { course_lists && course_lists.map( course => {
return ( return (
<p className="clearfix mb7" key={course.id}> <p className="clearfix mb7" key={course.id}>
<Checkbox className="fl" value={course.id} key={course.id}></Checkbox> <Checkbox className="fl" value={course.id} key={course.id}></Checkbox>
<span className="fl with45"><label className="task-hide fl" style={{"maxWidth":"208px;"}}>{course.name}</label></span> <span className="fl with45"><label className="task-hide fl" style={{"maxWidth":"208px;"}}>{course.name}</label></span>
</p> </p>
) )
}) } }) }
</Checkbox.Group> </Checkbox.Group>
{loading && hasMore && ( {loading && hasMore && (
<div className="demo-loading-container"> <div className="demo-loading-container">
<Spin /> <Spin />
</div> </div>
)} )}
{/* TODO */} {/* TODO */}
{/* { {/* {
!hasMore && <div>没有更多了</div> !hasMore && <div>没有更多了</div>
} */} } */}
</InfiniteScroll> </InfiniteScroll>
</div> </div>
</div> </div>
</ModalWrapper> </ModalWrapper>
) )
} }
} }
export default SendToCourseModal; export default SendToCourseModal;

@ -1,80 +1,80 @@
.studentList_operation_ul{ .studentList_operation_ul{
color: #999; color: #999;
font-size: 12px; font-size: 12px;
float: right; float: right;
margin-top: 2px; margin-top: 2px;
} }
.studentList_operation_ul li{ .studentList_operation_ul li{
float: left; float: left;
padding:0px 20px; padding:0px 20px;
position: relative; position: relative;
cursor: pointer; cursor: pointer;
flex: 0 0 26px; flex: 0 0 26px;
line-height: 26px; line-height: 26px;
} }
.studentList_operation_ul li.li_line:after{ .studentList_operation_ul li.li_line:after{
position: absolute; position: absolute;
content: ''; content: '';
width: 1px; width: 1px;
height: 12px; height: 12px;
background-color: #EDEDED; background-color: #EDEDED;
right: 0px; right: 0px;
top:6px; top:6px;
} }
.studentList_operation_ul li:last-child{ .studentList_operation_ul li:last-child{
padding-right: 0px; padding-right: 0px;
} }
.studentList_operation_ul li:last-child:after{ .studentList_operation_ul li:last-child:after{
width: 0px; width: 0px;
} }
/* 基础的下拉列表、列如排序等 */ /* 基础的下拉列表、列如排序等 */
.drop_down_normal li{ .drop_down_normal li{
padding: 0px 20px; padding: 0px 20px;
height: 34px; height: 34px;
line-height: 34px; line-height: 34px;
min-width: 96px; min-width: 96px;
color: #333; color: #333;
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
width: 100%; width: 100%;
} }
.stu_table table{ .stu_table table{
line-height: 1.2; line-height: 1.2;
} }
.stu_table .classesName{ .stu_table .classesName{
display: block; display: block;
max-width: 428px; max-width: 428px;
} }
.stu_table .ant-table-thead > tr > th{ .stu_table .ant-table-thead > tr > th{
padding:21px 16px; padding:21px 16px;
border-bottom: none; border-bottom: none;
} }
.stu_table .ant-table-tbody tr:last-child td{ .stu_table .ant-table-tbody tr:last-child td{
border-bottom: none; border-bottom: none;
} }
.stu_table table .ant-table-tbody > tr:hover:not(.ant-table-expanded-row) > td{ .stu_table table .ant-table-tbody > tr:hover:not(.ant-table-expanded-row) > td{
background-color: #fff; background-color: #fff;
} }
.stu_head{ .stu_head{
padding-bottom: 15px; padding-bottom: 15px;
} }
.ant-modal-body{ .ant-modal-body{
padding:30px 40px; padding:30px 40px;
} }
.color-dark-21{ .color-dark-21{
color: #212121; color: #212121;
} }
.tabletd { .tabletd {
background-color:#E6F7FF; background-color:#E6F7FF;
} }
.yslminheigth{ .yslminheigth{
min-height: 20px; min-height: 20px;
} }
.yslminheigths{ .yslminheigths{
min-height: 21px; min-height: 21px;
} }

@ -171,7 +171,20 @@ class Exercise extends Component{
checkAllValue: checkedValues.length == exercises.length checkAllValue: checkedValues.length == exercises.length
}) })
} }
// 全选or反选
onItemClick = (item) => {
const checkBoxValues = this.state.checkBoxValues.slice(0);
const index = checkBoxValues.indexOf(item.id);
if (index != -1) {
_.remove(checkBoxValues, (listItem)=> listItem === item.id)
} else {
checkBoxValues.push(item.id)
}
this.onCheckBoxChange(checkBoxValues)
}
// 全选or反选
onCheckAll = (e) => { onCheckAll = (e) => {
this.setState({ this.setState({
checkAllValue: e.target.checked checkAllValue: e.target.checked
@ -507,7 +520,7 @@ class Exercise extends Component{
</div> </div>
</div> </div>
<Spin size="large" spinning={this.state.isSpin}> <Spin size="large" spinning={this.state.isSpin}>
{this.props.isAdmin()?<div className="mt20 mb20 edu-back-white padding20-30"> {this.props.isAdmin()?exercises && exercises.length ===0?"":<div className="mt20 mb20 edu-back-white padding20-30">
<div className="clearfix"> <div className="clearfix">
<Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox> <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>
<div className="studentList_operation_ul"> <div className="studentList_operation_ul">
@ -559,9 +572,9 @@ class Exercise extends Component{
{...this.props} {...this.props}
{...this.state} {...this.state}
item={item} item={item}
key={key} index={key}
checkBox={<Checkbox value={item.id} key={item.id} onItemClick={this.onItemClick}
// onClick={() => this.onItemClick(item)} checkBox={<Checkbox value={item.id} key={item.id}
></Checkbox>} ></Checkbox>}
></ExerciseListItem> ></ExerciseListItem>
) )

@ -52,17 +52,17 @@ class ExerciseListItem extends Component{
}) })
} }
render(){ render(){
let{item,checkBox}=this.props; let{item,checkBox,index}=this.props;
let {coursesId,Id}=this.props.match.params let {coursesId,Id}=this.props.match.params
const IsAdmin =this.props.isAdmin(); const IsAdmin =this.props.isAdmin();
const IsStudent =this.props.isStudent(); const IsStudent =this.props.isStudent();
// console.log(this.props.current_user.user_id) // console.log(this.props.current_user.user_id)
return( return(
<div className="workList_Item" style={{padding:"30px"}}> <div className="workList_Item" style={{cursor : IsAdmin ? "pointer" : "default",padding:"30px" }} onClick={() => window.$(`.exerciseitem${index} input`).click() }>
{ {
IsAdmin && IsAdmin &&
<span className="fl mr12"> <span className={`exerciseitem${index} fl mr12`}>
{checkBox} {checkBox}
</span> </span>
} }
@ -96,20 +96,20 @@ class ExerciseListItem extends Component{
{/*<Link to={`/courses/${coursesId}/exercises/${item.id}/exercises/student_exercise_list?tab=0`} className="fl font-16 font-bd mt2 color-grey-3 task-hide" style={{"maxWidth":"600px"}}>{item.exercise_name}</Link>*/} {/*<Link to={`/courses/${coursesId}/exercises/${item.id}/exercises/student_exercise_list?tab=0`} className="fl font-16 font-bd mt2 color-grey-3 task-hide" style={{"maxWidth":"600px"}}>{item.exercise_name}</Link>*/}
{ {
this.props.isAdmin()? <a className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580" this.props.isAdmin()? <Link className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580"
title={item.exercise_name} title={item.exercise_name}
href={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</a>:"" to={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</Link>:""
} }
{ {
this.props.isStudent()? this.props.isStudent()?
<a className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580" title={item.exercise_name} href={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</a>:"" <Link className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580" title={item.exercise_name} to={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</Link>:""
} }
{ {
this.props.isNotMember()? item.lock_status === 0 ? this.props.isNotMember()? item.lock_status === 0 ?
<span className="fl mt3 font-16 font-bd color-dark comnonwidth580" title={item.exercise_name}>{item.exercise_name}</span> <span className="fl mt3 font-16 font-bd color-dark comnonwidth580" title={item.exercise_name}>{item.exercise_name}</span>
: <a className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580" title={item.exercise_name} href={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</a>:"" : <Link className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580" title={item.exercise_name} to={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</Link>:""
} }
{ {
@ -165,8 +165,8 @@ class ExerciseListItem extends Component{
{ IsAdmin &&<div className="homepagePostSetting" style={{"right":"-17px","top":"51px","display":"block","width":"100px"}}> { IsAdmin &&<div className="homepagePostSetting" style={{"right":"-17px","top":"51px","display":"block","width":"100px"}}>
<a className="btn colorblue font-16" href={`/courses/${coursesId}/exercises/${item.id}/edit`}>编辑</a> <Link className="btn colorblue font-16" to={`/courses/${coursesId}/exercises/${item.id}/edit`}>编辑</Link>
<a className="btn colorblue ml20 font-16" href={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=3`}>设置</a> <Link className="btn colorblue ml20 font-16" to={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=3`}>设置</Link>
</div> } </div> }
</p> </p>
@ -193,7 +193,7 @@ class ExerciseListItem extends Component{
<div className="homepagePostSetting" style={{"right":"0px","top":"62px","position":"absolute","display":"block"}}> <div className="homepagePostSetting" style={{"right":"0px","top":"62px","position":"absolute","display":"block"}}>
{item.current_status ===0&&item.exercise_status>1? <li> <Link className="btn colorblue font-16" to={`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`}>继续答题</Link></li>: {item.current_status ===0&&item.exercise_status>1? <li> <Link className="btn colorblue font-16" to={`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`}>继续答题</Link></li>:
item.current_status ===1&&item.exercise_status>1? <li> <Link className="btn colorblue font-16" to={`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`}>查看答题</Link></li>: item.current_status ===1&&item.exercise_status>1? <li> <Link className="btn colorblue font-16" to={`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`}>查看答题</Link></li>:
item.current_status ===2&&item.exercise_status>1? <li> <a className="btn colorblue ml20 font-16" onClick={()=>this.setgameexercise(`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`)}>开始答题</a></li>:""} item.current_status ===2&&item.exercise_status>1? <li> <a className="btn colorblue ml20 font-16" onClick={()=>this.setgameexercise(`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`)}>开始答题</a></li>:""}
</div> </div>
} }
</div> </div>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save