parent
8e4bc5bffa
commit
e15e24b369
@ -0,0 +1,66 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-dashboards-index-page').length > 0) {
|
||||
// 月新增用户
|
||||
var monthChart = echarts.init(document.getElementById('month-active-user'));
|
||||
monthChart.setOption({
|
||||
tooltip: {
|
||||
show: "true",
|
||||
trigger: 'item',
|
||||
formatter: '{c0}',
|
||||
backgroundColor: 'rgba(0,0,0,0.7)', // 背景
|
||||
padding: [8, 10], //内边距
|
||||
extraCssText: 'box-shadow: 0 0 3px rgba(255, 255, 255, 0.4);', //添加阴影
|
||||
axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
}
|
||||
},
|
||||
series : [
|
||||
{
|
||||
name: '访问来源',
|
||||
type: 'pie',
|
||||
radius: '55%',
|
||||
data: []
|
||||
}
|
||||
]
|
||||
});
|
||||
monthChart.showLoading();
|
||||
$.get('/admins/dashboards/month_active_user.json').done(function(data){
|
||||
monthChart.setOption({
|
||||
series: [
|
||||
{ data: data.data }
|
||||
]
|
||||
});
|
||||
|
||||
monthChart.hideLoading();
|
||||
});
|
||||
|
||||
|
||||
// 近七天评测次数
|
||||
// var evaluateChart = echarts.init(document.getElementById('evaluate-pie'));
|
||||
// evaluateChart.setOption({
|
||||
// tooltip: {
|
||||
// show: "true",
|
||||
// trigger: 'item',
|
||||
// formatter: '{c0}',
|
||||
// backgroundColor: 'rgba(0,0,0,0.7)', // 背景
|
||||
// padding: [8, 10], //内边距
|
||||
// extraCssText: 'box-shadow: 0 0 3px rgba(255, 255, 255, 0.4);', //添加阴影
|
||||
// axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
||||
// type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
// }
|
||||
// },
|
||||
// xAxis: { type: 'category', boundaryGap: false, data: [] },
|
||||
// yAxis: { type: 'value' },
|
||||
// series: [{ data: [], type: 'line', areaStyle: {} }]
|
||||
// });
|
||||
// evaluateChart.showLoading();
|
||||
// $.get('/admins/dashboards/evaluate.json').done(function(data){
|
||||
// evaluateChart.setOption({
|
||||
// xAxis: { data: data.names },
|
||||
// series: [{ data: data.data }]
|
||||
// });
|
||||
//
|
||||
// evaluateChart.hideLoading();
|
||||
// });
|
||||
}
|
||||
});
|
@ -0,0 +1,173 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-departments-index-page').length > 0) {
|
||||
var $searchContainer = $('.department-list-form');
|
||||
var $searchForm = $searchContainer.find('form.search-form');
|
||||
var $list = $('.department-list-container');
|
||||
|
||||
$searchContainer.on('change', '.form-check-input', function(){
|
||||
$searchForm.find('input[type="submit"]').trigger('click');
|
||||
});
|
||||
|
||||
// ============== 新建部门 ===============
|
||||
var $modal = $('.modal.admin-create-department-modal');
|
||||
var $form = $modal.find('form.admin-create-department-form');
|
||||
var $departmentNameInput = $form.find('input[name="department_name"]');
|
||||
var $schoolSelect = $modal.find('.school-select');
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
school_id: {
|
||||
required: true
|
||||
},
|
||||
department_name: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
school_id: {
|
||||
required: '请选择所属单位'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// modal ready fire
|
||||
$modal.on('show.bs.modal', function () {
|
||||
$departmentNameInput.val('');
|
||||
$schoolSelect.select2('val', ' ');
|
||||
});
|
||||
|
||||
// ************** 学校选择 *************
|
||||
var matcherFunc = function(params, data){
|
||||
if ($.trim(params.term) === '') {
|
||||
return data;
|
||||
}
|
||||
if (typeof data.text === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data.name && data.name.indexOf(params.term) > -1) {
|
||||
var modifiedData = $.extend({}, data, true);
|
||||
return modifiedData;
|
||||
}
|
||||
|
||||
// Return `null` if the term should not be displayed
|
||||
return null;
|
||||
};
|
||||
|
||||
var defineSchoolSelect = function(schools) {
|
||||
$schoolSelect.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: '请选择所属单位',
|
||||
minimumInputLength: 1,
|
||||
data: schools,
|
||||
templateResult: function (item) {
|
||||
if(!item.id || item.id === '') return item.text;
|
||||
return item.name;
|
||||
},
|
||||
templateSelection: function(item){
|
||||
if (item.id) {
|
||||
$('#school_id').val(item.id);
|
||||
}
|
||||
return item.name || item.text;
|
||||
},
|
||||
matcher: matcherFunc
|
||||
});
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '/api/schools/for_option.json',
|
||||
dataType: 'json',
|
||||
type: 'GET',
|
||||
success: function(data) {
|
||||
defineSchoolSelect(data.schools);
|
||||
}
|
||||
});
|
||||
|
||||
$modal.on('click', '.submit-btn', function(){
|
||||
$form.find('.error').html('');
|
||||
|
||||
if ($form.valid()) {
|
||||
var url = $form.data('url');
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
url: url,
|
||||
data: $form.serialize(),
|
||||
success: function(){
|
||||
$.notify({ message: '创建成功' });
|
||||
$modal.modal('hide');
|
||||
|
||||
setTimeout(function(){
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
},
|
||||
error: function(res){
|
||||
var data = res.responseJSON;
|
||||
$form.find('.error').html(data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ============= 添加部门管理员 ==============
|
||||
var $addMemberModal = $('.admin-add-department-member-modal');
|
||||
var $addMemberForm = $addMemberModal.find('.admin-add-department-member-form');
|
||||
var $memberSelect = $addMemberModal.find('.department-member-select');
|
||||
var $departmentIdInput = $addMemberForm.find('input[name="department_id"]')
|
||||
|
||||
$addMemberModal.on('show.bs.modal', function(event){
|
||||
var $link = $(event.relatedTarget);
|
||||
var departmentId = $link.data('department-id');
|
||||
$departmentIdInput.val(departmentId);
|
||||
|
||||
$memberSelect.select2('val', ' ');
|
||||
});
|
||||
|
||||
$memberSelect.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: '请输入要添加的管理员姓名',
|
||||
multiple: true,
|
||||
minimumInputLength: 1,
|
||||
ajax: {
|
||||
delay: 500,
|
||||
url: '/admins/users',
|
||||
dataType: 'json',
|
||||
data: function(params){
|
||||
return { name: params.term };
|
||||
},
|
||||
processResults: function(data){
|
||||
return { results: data.users }
|
||||
}
|
||||
},
|
||||
templateResult: function (item) {
|
||||
if(!item.id || item.id === '') return item.text;
|
||||
return item.real_name;
|
||||
},
|
||||
templateSelection: function(item){
|
||||
if (item.id) {
|
||||
}
|
||||
return item.real_name || item.text;
|
||||
}
|
||||
});
|
||||
|
||||
$addMemberModal.on('click', '.submit-btn', function(){
|
||||
$addMemberForm.find('.error').html('');
|
||||
|
||||
var departmentId = $departmentIdInput.val();
|
||||
var memberIds = $memberSelect.val();
|
||||
if (departmentId && memberIds && memberIds.length > 0) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'script',
|
||||
url: '/admins/departments/' + departmentId + '/department_member',
|
||||
data: { user_ids: memberIds }
|
||||
});
|
||||
} else {
|
||||
$addMemberModal.modal('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,20 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-library-applies-index-page').length > 0) {
|
||||
var $searchFrom = $('.library-applies-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,19 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-mirror-repositories-edit-page, body.admins-mirror-repositories-update-page').length > 0) {
|
||||
var $form = $('form.edit-mirror');
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
"mirror_repository[type_name]": {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$form.submit(function(e){
|
||||
if(!$form.valid()){ e.preventDefault(); }
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,4 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-mirror-repositories-index-page').length > 0) {
|
||||
}
|
||||
});
|
@ -0,0 +1,33 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-mirror-scripts-edit-page, body.admins-mirror-scripts-update-page, body.admins-mirror-scripts-new-page, body.admins-mirror-scripts-create-page').length > 0) {
|
||||
var $form = $('form.script-form');
|
||||
|
||||
// codemirror编辑器
|
||||
var scriptEditor = CodeMirror.fromTextArea(document.getElementById('mirror_script_script'), {
|
||||
lineNumbers: true,
|
||||
mode: 'shell',
|
||||
theme: "default",
|
||||
indentUnit: 4, //代码缩进为一个tab的距离
|
||||
matchBrackets: true,
|
||||
autoRefresh: true,
|
||||
smartIndent: true,//智能换行
|
||||
styleActiveLine: true,
|
||||
lint: true
|
||||
});
|
||||
scriptEditor.setSize('auto', '600px');
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
"mirror_script[script_type]": {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$form.submit(function(e){
|
||||
if(!$form.valid()){ e.preventDefault(); }
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,32 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-choose-mirror-modal', function(){
|
||||
var $modal = $('.modal.admin-choose-mirror-modal');
|
||||
var $form = $modal.find('form.admin-choose-mirror-form');
|
||||
|
||||
var validateForm = function(){
|
||||
var checkedValue = $form.find('input[name="mirror_number"]:checked').val();
|
||||
|
||||
if(checkedValue == undefined){
|
||||
$modal.find('.error').html('必须选择一种镜像保存!');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$modal.on('click', '.submit-btn', function(){
|
||||
$form.find('.error').html('');
|
||||
var url = $form.attr('action');
|
||||
|
||||
if (validateForm()) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'script',
|
||||
url: url,
|
||||
data: $form.serialize(),
|
||||
}).done(function(){
|
||||
$modal.modal('hide');
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
@ -0,0 +1,34 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-department-modal', function(){
|
||||
var $modal = $('.modal.admin-edit-department-modal');
|
||||
var $form = $modal.find('form.admin-edit-department-form');
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
'department[name]': {
|
||||
required: true,
|
||||
maxlength: 20
|
||||
},
|
||||
'department[host_count]': {
|
||||
digits: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$modal.on('click', '.submit-btn', function(){
|
||||
$form.find('.error').html('');
|
||||
var url = $form.attr('action');
|
||||
|
||||
if ($form.valid()) {
|
||||
$.ajax({
|
||||
method: 'PATCH',
|
||||
dataType: 'script',
|
||||
url: url,
|
||||
data: $form.serialize()
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
@ -0,0 +1,110 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
var $modal = $('.modal.admin-merge-department-modal');
|
||||
if ($modal.length > 0) {
|
||||
var $form = $modal.find('form.admin-merge-department-form');
|
||||
var $schoolIdInput = $form.find('input[name="school_id"]');
|
||||
var $originDepartmentIdInput = $form.find('input[name="origin_department_id"]');
|
||||
var $departmentSelect = $modal.find('.department-select');
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
department_id: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
department_id: {
|
||||
required: '请选择部门'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ************** 学校选择 *************
|
||||
var matcherFunc = function(params, data){
|
||||
if ($.trim(params.term) === '') {
|
||||
return data;
|
||||
}
|
||||
if (typeof data.text === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data.name && data.name.indexOf(params.term) > -1) {
|
||||
var modifiedData = $.extend({}, data, true);
|
||||
return modifiedData;
|
||||
}
|
||||
|
||||
// Return `null` if the term should not be displayed
|
||||
return null;
|
||||
};
|
||||
|
||||
var defineDepartmentSelect = function(departments) {
|
||||
$departmentSelect.empty();
|
||||
|
||||
$departmentSelect.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: '请选择所属部门',
|
||||
data: departments,
|
||||
templateResult: function (item) {
|
||||
if(!item.id || item.id === '') return item.text;
|
||||
return item.name;
|
||||
},
|
||||
templateSelection: function(item){
|
||||
if (item.id) {
|
||||
$form.find('#department_id').val(item.id);
|
||||
}
|
||||
return item.name || item.text;
|
||||
},
|
||||
matcher: matcherFunc
|
||||
});
|
||||
$departmentSelect.select2('val', ' ');
|
||||
};
|
||||
|
||||
// modal ready fire
|
||||
$modal.on('show.bs.modal', function (event) {
|
||||
var $link = $(event.relatedTarget);
|
||||
|
||||
var schoolId = $link.data('schoolId');
|
||||
|
||||
$schoolIdInput.val(schoolId);
|
||||
$originDepartmentIdInput.val($link.data('departmentId'));
|
||||
|
||||
$.ajax({
|
||||
url: '/api/schools/' + schoolId + '/departments/for_option.json',
|
||||
dataType: 'json',
|
||||
type: 'GET',
|
||||
success: function(data) {
|
||||
defineDepartmentSelect(data.departments);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$modal.on('click', '.submit-btn', function(){
|
||||
$form.find('.error').html('');
|
||||
|
||||
if ($form.valid()) {
|
||||
var url = $form.data('url');
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
url: url,
|
||||
data: $form.serialize(),
|
||||
success: function(){
|
||||
$.notify({ message: '操作成功' });
|
||||
$modal.modal('hide');
|
||||
|
||||
setTimeout(function(){
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
},
|
||||
error: function(res){
|
||||
var data = res.responseJSON;
|
||||
$form.find('.error').html(data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,89 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
var $modal = $('.modal.admin-replace-mirror-modal');
|
||||
if ($modal.length > 0) {
|
||||
var $form = $modal.find('form.admin-replace-mirror-form');
|
||||
var $mirrorIdInput = $modal.find('.modal-body input[name="mirror_id"]');
|
||||
var $mirrorSelect = $modal.find('.new-mirror-select');
|
||||
|
||||
var setMirror = function(id, name){
|
||||
$mirrorIdInput.val(id);
|
||||
$form.find('.mirror-id-container').html(id);
|
||||
$form.find('.mirror-name-container').html(name);
|
||||
}
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
new_mirror_id: {
|
||||
required: true
|
||||
},
|
||||
},
|
||||
messages: {
|
||||
new_mirror_id: {
|
||||
required: '请选择新镜像'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// modal ready fire
|
||||
$modal.on('show.bs.modal', function (event) {
|
||||
var $link = $(event.relatedTarget);
|
||||
|
||||
var mirrorId = $link.data('id');
|
||||
var mirrorName = $link.data('name');
|
||||
|
||||
setMirror(mirrorId, mirrorName);
|
||||
$mirrorSelect.select2('val', ' ');
|
||||
});
|
||||
$modal.on('hide.bs.modal', function () {
|
||||
setMirror('', '');
|
||||
$mirrorSelect.select2('val', ' ');
|
||||
$('#new_mirror_id-error').remove();
|
||||
});
|
||||
|
||||
$mirrorSelect.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: '输入要合并的镜像名',
|
||||
minimumInputLength: 1,
|
||||
ajax: {
|
||||
url: '/admins/mirror_repositories/for_select',
|
||||
dataType: 'json',
|
||||
data: function(params){
|
||||
return { keyword: params.term };
|
||||
},
|
||||
processResults: function(data){
|
||||
return { results: data.mirrors }
|
||||
}
|
||||
},
|
||||
templateResult: function (item) {
|
||||
if(!item.id || item.id === '') return item.text;
|
||||
return item.name;
|
||||
},
|
||||
templateSelection: function(item){
|
||||
if (item.id) {
|
||||
$('#new_mirror_id-error').remove();
|
||||
$('#new_mirror_id').val(item.id);
|
||||
}
|
||||
return item.name || item.text;
|
||||
}
|
||||
});
|
||||
|
||||
$modal.on('click', '.submit-btn', function(){
|
||||
$form.find('.error').html('');
|
||||
|
||||
if ($form.valid()) {
|
||||
var url = $form.data('url');
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'script',
|
||||
url: url,
|
||||
data: $form.serialize(),
|
||||
}).done(function(){
|
||||
$modal.modal('hide');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,62 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
var $modal = $('.modal.admin-upload-file-modal');
|
||||
if ($modal.length > 0) {
|
||||
var $form = $modal.find('form.admin-upload-file-form')
|
||||
var $sourceIdInput = $modal.find('input[name="source_id"]');
|
||||
var $sourceTypeInput = $modal.find('input[name="source_type"]');
|
||||
|
||||
$modal.on('show.bs.modal', function(event){
|
||||
var $link = $(event.relatedTarget);
|
||||
var sourceId = $link.data('sourceId');
|
||||
var sourceType = $link.data('sourceType');
|
||||
|
||||
$sourceIdInput.val(sourceId);
|
||||
$sourceTypeInput.val(sourceType);
|
||||
|
||||
$modal.find('.upload-file-input').trigger('click');
|
||||
});
|
||||
|
||||
$modal.find('.upload-file-input').on('change', function(e){
|
||||
var file = $(this)[0].files[0];
|
||||
|
||||
if(file){
|
||||
$modal.find('.file-names').html(file.name);
|
||||
$modal.find('.submit-btn').trigger('click');
|
||||
}
|
||||
})
|
||||
|
||||
var formValid = function(){
|
||||
if($form.find('input[name="file"]').val() == undefined || $form.find('input[name="file"]').val().length == 0){
|
||||
$form.find('.error').html('请选择文件');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
$modal.on('click', '.submit-btn', function(){
|
||||
$form.find('.error').html('');
|
||||
|
||||
if (formValid()) {
|
||||
var formDataString = $form.serialize();
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
url: '/admins/files?' + formDataString,
|
||||
data: new FormData($form[0]),
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function(data){
|
||||
$.notify({ message: '上传成功' });
|
||||
$modal.trigger('upload:success', data);
|
||||
$modal.modal('hide');
|
||||
},
|
||||
error: function(res){
|
||||
var data = res.responseJSON;
|
||||
$form.find('.error').html(data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,20 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-project-package-applies-index-page').length > 0) {
|
||||
var $searchFrom = $('.project-package-applies-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('all');
|
||||
|
||||
if($link.data('value') === 'all'){
|
||||
$searchFrom.find('.status-filter').show();
|
||||
} else {
|
||||
$searchFrom.find('.status-filter').hide();
|
||||
$searchFrom.find('select[name="status"]').val('pending');
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
@ -0,0 +1,44 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-shixun-settings-index-page').length > 0) {
|
||||
let searchContainer = $(".shixun-settings-list-form");
|
||||
let searchForm = $("form.search-form",searchContainer);
|
||||
|
||||
searchContainer.on('change', '.shixun-settings-select', function(){
|
||||
searchForm.find('input[type="submit"]').trigger('click');
|
||||
});
|
||||
|
||||
//导出
|
||||
searchContainer.on('click',"#shixun-settings-export",function () {
|
||||
window.location.href = "/admins/shixun_settings.xls?" + searchForm.serialize();
|
||||
});
|
||||
|
||||
$(".shixun-settings-list-container").on("change", '.shixun-setting-form', function () {
|
||||
var s_id = $(this).attr("data-id");
|
||||
var s_value = $(this).val();
|
||||
var s_name = $(this).attr("name");
|
||||
var json = {};
|
||||
var s_index = $(this).parent("td").siblings(".shixun-line-no").text();
|
||||
json[s_name] = s_value;
|
||||
json["page_no"] = s_index;
|
||||
$.ajax({
|
||||
url: "/admins/shixun_settings/" + s_id,
|
||||
type: "PUT",
|
||||
dataType:'script',
|
||||
data: json
|
||||
})
|
||||
});
|
||||
|
||||
$("select#settings-tag-choosed").select2({
|
||||
placeholder: "请选择分类",
|
||||
allowClear: true
|
||||
});
|
||||
|
||||
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
|
||||
var $imageElement = $('.shixun-image-' + data.source_id);
|
||||
$imageElement.attr('src', data.url);
|
||||
$imageElement.show();
|
||||
$imageElement.next().html('重新上传');
|
||||
})
|
||||
}
|
||||
});
|
||||
|
@ -0,0 +1,14 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if($('body.admins-shixuns-index-page').length > 0){
|
||||
$('select#tag-choosed').select2({
|
||||
placeholder: "请选择分类",
|
||||
allowClear: true
|
||||
});
|
||||
|
||||
let search_form = $(".search-form");
|
||||
//导出
|
||||
$(".shixuns-list-form").on("click","#shixuns-export",function () {
|
||||
window.location.href = "/admins/shixuns.xls?" + search_form.serialize();
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,20 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-video-applies-index-page').length > 0) {
|
||||
var $searchFrom = $('.video-applies-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('all');
|
||||
|
||||
if($link.data('value') === 'all'){
|
||||
$searchFrom.find('.status-filter').show();
|
||||
} else {
|
||||
$searchFrom.find('.status-filter').hide();
|
||||
$searchFrom.find('select[name="status"]').val('pending');
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
@ -0,0 +1,21 @@
|
||||
//= require rails-ujs
|
||||
//= require turbolinks
|
||||
//= require jquery3
|
||||
//= require popper
|
||||
//= require bootstrap-sprockets
|
||||
|
||||
//= require echarts
|
||||
|
||||
//= require_tree ./colleges
|
||||
|
||||
Turbolinks.setProgressBarDelay(200);
|
||||
|
||||
$(document).on('turbolinks:load', function() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
$('[data-toggle="popover"]').popover();
|
||||
})
|
||||
|
||||
$(document).on("turbolinks:before-cache", function () {
|
||||
$('[data-toggle="tooltip"]').tooltip('hide');
|
||||
$('[data-toggle="popover"]').popover('hide');
|
||||
});
|
@ -0,0 +1,156 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if($('body.colleges-statistics-page').length > 0) {
|
||||
var $statisticBody = $('.statistics-body');
|
||||
var $statisticBase = $('.statistic-base');
|
||||
var schoolId = $statisticBody.data('id');
|
||||
var $statisticCourse = $statisticBody.find('.statistic-course')
|
||||
var $shixunChart = $statisticBody.find('.shixun-chart');
|
||||
|
||||
$.get('/colleges/' + schoolId + '/shixun_time', function(data){
|
||||
$statisticBase.find('.shixun-time').html("<span>" + data.shixun_time + "</span>天");
|
||||
});
|
||||
$.get('/colleges/' + schoolId + '/shixun_report_count', function(data){
|
||||
$statisticBase.find('.shixun-report-count').html("<span>" + data.shixun_report_count + "</span>个");
|
||||
});
|
||||
|
||||
$.ajax({ url: '/colleges/' + schoolId + '/course_statistics', method: 'GET', dataType: 'script' });
|
||||
$.ajax({ url: '/colleges/' + schoolId + '/teachers', method: 'GET', dataType: 'script' });
|
||||
|
||||
var initShixunChart = function(names, data){
|
||||
var shixunChart = echarts.init(document.getElementById('shixun-chart'));
|
||||
var options = {
|
||||
series : [
|
||||
{
|
||||
name: '访问来源',
|
||||
type: 'pie',
|
||||
radius: '55%',
|
||||
data: data
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
shixunChart.setOption(options);
|
||||
};
|
||||
$.get('/colleges/' + schoolId + '/shixun_chart_data', function(data){
|
||||
$statisticBody.find('.shixun-chart-loading').hide();
|
||||
if (data.data.length > 0) {
|
||||
$shixunChart.css('height', '400px').css('width', '100%');
|
||||
initShixunChart(data.names, data.data);
|
||||
} else {
|
||||
$statisticBody.find('.shixun-chart-empty').show();
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({ url: '/colleges/' + schoolId + '/student_shixun', method: 'GET', dataType: 'script' });
|
||||
|
||||
var initHotEvaluating = function(names, values){
|
||||
var Color = ['#962e66', '#623363', '#CCCCCC', '#9A9A9A', '#FF8080', '#FF80C2', '#B980FF', '#80B9FF', '#6FE9FF', '#4DE8B4', '#F8EF63', '#FFB967'];
|
||||
|
||||
var option = {
|
||||
backgroundColor: '#fff',
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '10%',
|
||||
containLabel: true
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
show: "true",
|
||||
trigger: 'item',
|
||||
formatter: '{c0}',
|
||||
backgroundColor: 'rgba(0,0,0,0.7)', // 背景
|
||||
padding: [8, 10], //内边距
|
||||
extraCssText: 'box-shadow: 0 0 3px rgba(255, 255, 255, 0.4);', //添加阴影
|
||||
axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#CCCCCC'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
lineStyle: {
|
||||
color: '#CCCCCC'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#656565',
|
||||
fontWeight: 'normal',
|
||||
fontSize: '12'
|
||||
},
|
||||
formatter: '{value}'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#cccccc'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitArea: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
inside: false,
|
||||
textStyle: {
|
||||
color: '#656565',
|
||||
fontWeight: 'normal',
|
||||
fontSize: '12'
|
||||
}
|
||||
},
|
||||
data: names
|
||||
},
|
||||
series: [{
|
||||
name: '',
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
show: true,
|
||||
color: function(params) {
|
||||
return Color[params.dataIndex]
|
||||
},
|
||||
barBorderRadius: 50,
|
||||
borderWidth: 0,
|
||||
borderColor: '#333'
|
||||
}
|
||||
},
|
||||
barGap: '0%',
|
||||
barCategoryGap: '50%',
|
||||
data: values
|
||||
}
|
||||
|
||||
]
|
||||
};
|
||||
var myChart = echarts.init(document.getElementById('hot-chart'));
|
||||
myChart.setOption(option);
|
||||
}
|
||||
|
||||
$.get('/colleges/' + schoolId + '/student_hot_evaluations', function(data){
|
||||
$statisticBody.find('.hot-chart-loading').hide();
|
||||
if (data.names.length > 0) {
|
||||
$statisticBody.find('.hot-chart').css('height', '400px').css('width', '100%');
|
||||
initHotEvaluating(data.names.reverse(), data.values.reverse());
|
||||
} else {
|
||||
$statisticBody.find('.hot-chart-empty').show();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
@ -0,0 +1,2 @@
|
||||
// Place all the behaviors and hooks related to the matching controller here.
|
||||
// All this logic will automatically be available in application.js.
|
@ -0,0 +1,7 @@
|
||||
.admins-dashboards-index-page {
|
||||
.pie-statistic {
|
||||
.pie {
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
.admins-departments-index-page {
|
||||
.department-list-table {
|
||||
.member-container {
|
||||
.member-user {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.member-user-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
padding: 2px 5px;
|
||||
margin: 2px 2px;
|
||||
border: 1px solid #91D5FF;
|
||||
background-color: #E6F7FF;
|
||||
color: #91D5FF;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
.admins-library-applies-index-page {
|
||||
.library-applies-list-container {
|
||||
span {
|
||||
&.apply-status-agreed { color: #28a745; }
|
||||
&.apply-status-refused { color: #dc3545; }
|
||||
&.apply-status-processed { color: #6c757d; }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
.admins-project-package-applies-index-page {
|
||||
.project-package-applies-list-container {
|
||||
span {
|
||||
&.apply-status-agreed { color: #28a745; }
|
||||
&.apply-status-refused { color: #dc3545; }
|
||||
&.apply-status-processed { color: #6c757d; }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
.admins-shixuns-index-page{
|
||||
.shixuns-list-container{
|
||||
.shixuns-status-1 { color: #6c757d; }
|
||||
.shixuns-status-2 { color: #28a745; }
|
||||
.shixuns-status-3 { color: #dc3545; }
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
.admins-shixun-settings-index-page {
|
||||
input[type="checkbox"]{
|
||||
font-size:18px;
|
||||
}
|
||||
.select2 input::-webkit-input-placeholder{
|
||||
color:#ccc;
|
||||
}
|
||||
.select2 .select2-selection__choice{
|
||||
border: 1px solid #eee !important;
|
||||
}
|
||||
.setting-chosen{
|
||||
font-weight: 400;
|
||||
font-size: 10px;
|
||||
color:#333;
|
||||
}
|
||||
|
||||
.shixun-setting-image {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
.admins-video-applies-index-page {
|
||||
.video-applies-list-container {
|
||||
span {
|
||||
&.apply-status-agreed { color: #28a745; }
|
||||
&.apply-status-refused { color: #dc3545; }
|
||||
&.apply-status-processed { color: #6c757d; }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
@import "bootstrap";
|
||||
@import "font-awesome-sprockets";
|
||||
@import "font-awesome";
|
||||
|
||||
@import "common";
|
||||
|
||||
@import "colleges/*";
|
||||
|
||||
|
||||
.navbar-dark .navbar-nav .nav-link {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
font-size: 16px;
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
.colleges-statistics-page {
|
||||
.college-body-container {
|
||||
.statistic-header {
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
background-image: url('/images/educoder/statistics.jpg');
|
||||
background-size: 100% 100%;
|
||||
|
||||
&-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-title {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #4CACFF;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
&-content {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
&-item {
|
||||
margin-bottom: 22px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
|
||||
&-label {
|
||||
color: #989898;
|
||||
}
|
||||
|
||||
&-content {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.statistic-box {
|
||||
border: unset;
|
||||
box-shadow: 0px 0px 9px rgba(174, 175, 177, 0.2);
|
||||
}
|
||||
|
||||
.statistic-base {
|
||||
&-title {
|
||||
padding: 2rem 1.25rem;
|
||||
background: #fff;
|
||||
border-bottom: unset;
|
||||
}
|
||||
|
||||
&-table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&-item {
|
||||
padding: 0;
|
||||
|
||||
&-label {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
color: #686868;
|
||||
background: #F5F5F5;
|
||||
border-top: 1px solid #EBEBEB;
|
||||
border-bottom: 1px solid #EBEBEB;
|
||||
}
|
||||
|
||||
&-content {
|
||||
height: 100px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
line-height: 100px;
|
||||
|
||||
span {
|
||||
margin-right: 5px;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.statistic-container {
|
||||
padding: 0;
|
||||
background: #fff;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 0px 9px rgba(174, 175, 177, 0.2);
|
||||
|
||||
.statistic-label {
|
||||
padding: 2rem 1.25rem;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.statistic-table {
|
||||
overflow-x: scroll;
|
||||
table.course-table { min-width: 1100px; }
|
||||
table.teacher-rank-table { min-width: 640px; }
|
||||
}
|
||||
|
||||
table th {
|
||||
background: #F5F5F5;
|
||||
border-color: #EBEBEB;
|
||||
}
|
||||
|
||||
&.statistic-course {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
&.statistic-teacher-rank, &.statistic-student-rank {
|
||||
min-height: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
.statistic-chart {
|
||||
padding: 0 20px;
|
||||
height: 400px;
|
||||
|
||||
.shixun-chart-loading, .shixun-chart-empty, .hot-chart-loading, .hot-chart-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
body {
|
||||
font-size: 14px;
|
||||
background: #efefef;
|
||||
}
|
||||
|
||||
a {
|
||||
&:hover {
|
||||
text-decoration: unset;
|
||||
}
|
||||
}
|
||||
|
||||
textarea.danger, input.danger {
|
||||
border-color: #dc3545!important;
|
||||
}
|
||||
|
||||
label.error {
|
||||
color: #dc3545!important;
|
||||
}
|
||||
|
||||
input.form-control {
|
||||
font-size: 14px;
|
||||
}
|
||||
.input-group-prepend {
|
||||
.input-group-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.font-12 { font-size: 12px !important; }
|
||||
.font-14 { font-size: 14px !important; }
|
||||
.font-16 { font-size: 16px !important; }
|
||||
.font-18 { font-size: 18px !important; }
|
@ -0,0 +1,3 @@
|
||||
// Place all the styles related to the homework_banks controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
@ -1 +1 @@
|
||||
.select2-container--bootstrap4 .select2-selection--single{height:calc(1.5em + .75rem + 2px)!important}.select2-container--bootstrap4 .select2-selection--single .select2-selection__placeholder{color:#757575;line-height:calc(1.5em + .75rem)}.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow{position:absolute;top:50%;right:3px;width:20px}.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b{top:60%;border-color:#343a40 transparent transparent;border-style:solid;border-width:5px 4px 0;width:0;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute}.select2-container--bootstrap4 .select2-selection--single .select2-selection__rendered{line-height:calc(1.5em + .75rem)}.select2-search--dropdown .select2-search__field{border:1px solid #ced4da;border-radius:.25rem}.select2-results__message{color:#6c757d}.select2-container--bootstrap4 .select2-selection--multiple{min-height:calc(1.5em + .75rem + 2px)!important}.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered{-webkit-box-sizing:border-box;box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice{color:#343a40;border:1px solid #bdc6d0;border-radius:.2rem;padding:0 5px 0 0;cursor:pointer;float:left;margin-top:.3em;margin-right:5px}.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove{color:#bdc6d0;font-weight:700;margin-left:3px;margin-right:1px;padding-right:3px;padding-left:3px;float:left}.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove:hover{color:#343a40}.select2-container{display:block}.select2-container :focus{outline:0}.input-group .select2-container--bootstrap4{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.input-group-prepend~.select2-container--bootstrap4 .select2-selection{border-top-left-radius:0;border-bottom-left-radius:0}.select2-container--bootstrap4 .select2-selection{border:1px solid #ced4da;border-radius:.25rem;width:100%}.select2-container--bootstrap4.select2-container--focus .select2-selection{border-color:#17a2b8;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.select2-container--bootstrap4.select2-container--focus.select2-container--open .select2-selection{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--bootstrap4.select2-container--disabled.select2-container--focus .select2-selection,.select2-container--bootstrap4.select2-container--disabled .select2-selection{background-color:#e9ecef;cursor:not-allowed;border-color:#ced4da;-webkit-box-shadow:none;box-shadow:none}.select2-container--bootstrap4.select2-container--disabled.select2-container--focus .select2-search__field,.select2-container--bootstrap4.select2-container--disabled .select2-search__field{background-color:transparent}form.was-validated select:invalid~.select2-container--bootstrap4 .select2-selection,select.is-invalid~.select2-container--bootstrap4 .select2-selection{border-color:#dc3545}form.was-validated select:valid~.select2-container--bootstrap4 .select2-selection,select.is-valid~.select2-container--bootstrap4 .select2-selection{border-color:#28a745}.select2-container--bootstrap4 .select2-dropdown{border-color:#ced4da;border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--bootstrap4 .select2-dropdown.select2-dropdown--above{border-top:1px solid #ced4da;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.select2-container--bootstrap4 .select2-dropdown .select2-results__option[aria-selected=true]{background-color:#e9ecef}.select2-container--bootstrap4 .select2-results__option--highlighted,.select2-container--bootstrap4 .select2-results__option--highlighted.select2-results__option[aria-selected=true]{background-color:#007bff;color:#f8f9fa}.select2-container--bootstrap4 .select2-results__option[role=group]{padding:0}.select2-container--bootstrap4 .select2-results>.select2-results__options{max-height:15em;overflow-y:auto}.select2-container--bootstrap4 .select2-results__group{padding:6px;display:list-item;color:#6c757d}.select2-container--bootstrap4 .select2-selection__clear{width:1.2em;height:1.2em;line-height:1.15em;padding-left:.3em;margin-top:.5em;border-radius:100%;background-color:#6c757d;color:#f8f9fa;float:right;margin-right:.3em}.select2-container--bootstrap4 .select2-selection__clear:hover{background-color:#343a40}
|
||||
.select2-container--bootstrap4 .select2-selection--single{height:calc(1.5em + .75rem + 2px)!important}.select2-container--bootstrap4 .select2-selection--single .select2-selection__placeholder{color:#757575;line-height:calc(1.5em + .75rem)}.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow{position:absolute;top:50%;right:3px;width:20px}.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b{top:60%;border-color:#343a40 transparent transparent;border-style:solid;border-width:5px 4px 0;width:0;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute}.select2-container--bootstrap4 .select2-selection--single .select2-selection__rendered{line-height:calc(1.5em + .75rem)}.select2-search--dropdown .select2-search__field{border:1px solid #ced4da;border-radius:.25rem}.select2-results__message{color:#6c757d}.select2-container--bootstrap4 .select2-selection--multiple{min-height:calc(1.5em + .75rem + 2px)!important}.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered{-webkit-box-sizing:border-box;box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice{color:#343a40;border:1px solid #bdc6d0;border-radius:.2rem;padding:0 5px 0 0;cursor:pointer;float:left;margin-top:.3em;margin-right:5px}.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove{color:#bdc6d0;font-weight:700;margin-left:3px;margin-right:1px;padding-right:3px;padding-left:3px;float:left}.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove:hover{color:#343a40}.select2-container{display:block}.select2-container :focus{outline:0}.input-group .select2-container--bootstrap4{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.input-group-prepend~.select2-container--bootstrap4 .select2-selection{border-top-left-radius:0;border-bottom-left-radius:0}.select2-container--bootstrap4 .select2-selection{border:1px solid #ced4da;border-radius:.25rem;width:100%}.select2-container--bootstrap4.select2-container--focus .select2-selection{border-color:#17a2b8;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.select2-container--bootstrap4.select2-container--focus.select2-container--open .select2-selection{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--bootstrap4.select2-container--disabled.select2-container--focus .select2-selection,.select2-container--bootstrap4.select2-container--disabled .select2-selection{background-color:#e9ecef;cursor:not-allowed;border-color:#ced4da;-webkit-box-shadow:none;box-shadow:none}.select2-container--bootstrap4.select2-container--disabled.select2-container--focus .select2-search__field,.select2-container--bootstrap4.select2-container--disabled .select2-search__field{background-color:transparent}form.was-validated select:invalid~.select2-container--bootstrap4 .select2-selection,select.is-invalid~.select2-container--bootstrap4 .select2-selection{border-color:#dc3545}form.was-validated select:valid~.select2-container--bootstrap4 .select2-selection,select.is-valid~.select2-container--bootstrap4 .select2-selection{border-color:#28a745}.select2-container--bootstrap4 .select2-dropdown{border-color:#ced4da;border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--bootstrap4 .select2-dropdown.select2-dropdown--above{border-top:1px solid #ced4da;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.select2-container--bootstrap4 .select2-dropdown .select2-results__option[aria-selected=true]{background-color:#e9ecef}.select2-container--bootstrap4 .select2-results__option--highlighted,.select2-container--bootstrap4 .select2-results__option--highlighted.select2-results__option[aria-selected=true]{background-color:#007bff;color:#f8f9fa}.select2-container--bootstrap4 .select2-results__option[role=group]{padding:0}.select2-container--bootstrap4 .select2-results>.select2-results__options{max-height:15em;overflow-y:auto}.select2-container--bootstrap4 .select2-results__group{padding:6px;display:list-item;color:#6c757d}.select2-container--bootstrap4 .select2-selection__clear{width:1.2em;height:1.2em;line-height:1.15em;padding-left:.3em;margin-top:.5em;border-radius:100%;background-color:#ccc;color:#f8f9fa;float:right;margin-right:.3em}.select2-container--bootstrap4 .select2-selection__clear:hover{background-color:#343a40}
|
@ -0,0 +1,11 @@
|
||||
class Admins::ChooseMirrorRepositoriesController < Admins::BaseController
|
||||
def new
|
||||
@mirror = MirrorRepository.find(params[:mirror_id])
|
||||
@new_mirror = MirrorOperationRecord.where(mirror_repository_id: @mirror.id, status: 1, user_id: -1).first
|
||||
end
|
||||
|
||||
def create
|
||||
mirror = MirrorRepository.find(params[:mirror_id])
|
||||
Admins::ChooseMirrorService.call(mirror, current_user, params[:mirror_number])
|
||||
end
|
||||
end
|
@ -1,4 +1,51 @@
|
||||
class Admins::DashboardsController < Admins::BaseController
|
||||
def index
|
||||
@active_user_count = User.where(last_login_on: today).count
|
||||
@weekly_active_user_count = User.where(last_login_on: current_week).count
|
||||
@month_active_user_count = User.where(last_login_on: current_month).count
|
||||
|
||||
@new_user_count = User.where(created_on: current_month).count
|
||||
end
|
||||
|
||||
def month_active_user
|
||||
count = UserExtension.where(created_at: current_month).group(:identity).count
|
||||
|
||||
data = [
|
||||
{ value: count['teacher'].to_i, name: '老师' },
|
||||
{ value: count['student'].to_i, name: '学生' },
|
||||
{ value: count['professional'].to_i, name: '专业人士' },
|
||||
{ value: count[nil].to_i, name: '未选职业' },
|
||||
]
|
||||
|
||||
render_ok(data: data)
|
||||
end
|
||||
|
||||
def evaluate
|
||||
names = []
|
||||
data = []
|
||||
|
||||
1.upto(7) do |i|
|
||||
date = i.days.ago
|
||||
names.unshift(date.strftime('%Y-%m-%d'))
|
||||
|
||||
count = Output.where(created_at: date.beginning_of_day..date.end_of_day).count
|
||||
data.unshift(count)
|
||||
end
|
||||
|
||||
render_ok(names: names, data: data)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def today
|
||||
Time.now.beginning_of_day..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def current_week
|
||||
7.days.ago.beginning_of_day..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def current_month
|
||||
30.days.ago.beginning_of_day..Time.now.end_of_day
|
||||
end
|
||||
end
|
@ -0,0 +1,20 @@
|
||||
class Admins::DepartmentMembersController < Admins::BaseController
|
||||
|
||||
helper_method :current_department
|
||||
|
||||
def create
|
||||
Admins::AddDepartmentMemberService.call(current_department, params)
|
||||
current_department.reload
|
||||
end
|
||||
|
||||
def destroy
|
||||
@member = current_department.department_members.find_by(user_id: params[:user_id])
|
||||
@member.destroy! if @member.present?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_department
|
||||
@_current_department ||= Department.find(params[:department_id])
|
||||
end
|
||||
end
|
@ -0,0 +1,95 @@
|
||||
class Admins::DepartmentsController < Admins::BaseController
|
||||
|
||||
helper_method :current_department
|
||||
|
||||
def index
|
||||
params[:sort_by] ||= 'created_at'
|
||||
params[:sort_direction] ||= 'desc'
|
||||
|
||||
departments = Admins::DepartmentQuery.call(params)
|
||||
|
||||
@departments = paginate departments.preload(:school, :member_users)
|
||||
|
||||
department_ids = @departments.map(&:id)
|
||||
@users_count = UserExtension.where(department_id: department_ids).group(:department_id).count
|
||||
@professional_auth_count = UserExtension.where(department_id: department_ids)
|
||||
.joins(:user).where(users: { professional_certification: true })
|
||||
.group(:department_id).count
|
||||
end
|
||||
|
||||
def create
|
||||
department_name = params[:department_name].to_s.strip
|
||||
school = School.find(params[:school_id])
|
||||
|
||||
return render_error('部门名称重复') if school.departments.exists?(name: department_name)
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
department = school.departments.create!(name: department_name, is_auth: 1)
|
||||
ApplyAddDepartment.create!(school_id: school.id, status: 1, name: department.name,
|
||||
department_id: department.id, user_id: current_user.id)
|
||||
end
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
identifier = update_params.delete(:identifier).presence
|
||||
if identifier && Department.where.not(id: current_department.id).exists?(identifier: identifier)
|
||||
return render_error('统计链接重复', type: :notify)
|
||||
end
|
||||
|
||||
current_department.update!(update_params.merge(identifier: identifier))
|
||||
end
|
||||
|
||||
def destroy
|
||||
ActiveRecord::Base.transaction do
|
||||
current_department.apply_add_departments.update_all(status: 2)
|
||||
|
||||
user_ids = current_department.user_extensions.pluck(:user_id)
|
||||
if user_ids.present?
|
||||
DeleteDepartmentNotifyJob.perform_later(current_department.id, 0, user_ids)
|
||||
current_department.soft_delete!
|
||||
else
|
||||
current_department.destroy!
|
||||
end
|
||||
end
|
||||
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
def merge
|
||||
return render_error('请选择其它部门') if params[:origin_department_id].to_s == params[:department_id].to_s
|
||||
|
||||
origin_department = Department.find(params[:origin_department_id])
|
||||
to_department = Department.find(params[:department_id])
|
||||
|
||||
return render_error('部门所属单位不相同') if origin_department.school_id != to_department.school_id
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
origin_department.apply_add_departments.delete_all
|
||||
|
||||
origin_department.user_extensions.update_all(department_id: to_department.id)
|
||||
|
||||
if to_department.identifier.blank? && origin_department.identifier.present?
|
||||
to_department.update!(identifier: origin_department.identifier)
|
||||
end
|
||||
|
||||
origin_department.destroy!
|
||||
end
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_department
|
||||
@_current_department ||= Department.find(params[:id])
|
||||
end
|
||||
|
||||
def update_params
|
||||
params.require(:department).permit(:name, :identifier, :host_count)
|
||||
end
|
||||
end
|
@ -0,0 +1,54 @@
|
||||
class Admins::FilesController < Admins::BaseController
|
||||
before_action :convert_file!, only: [:create]
|
||||
|
||||
def create
|
||||
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
|
||||
|
||||
Util.write_file(@file, file_path)
|
||||
|
||||
render_ok(source_id: params[:source_id], source_type: params[:source_type].to_s, url: file_url)
|
||||
rescue StandardError => ex
|
||||
logger_error(ex)
|
||||
render_error('上传失败')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def convert_file!
|
||||
max_size = 10 * 1024 * 1024 # 10M
|
||||
if params[:file].class == ActionDispatch::Http::UploadedFile
|
||||
@file = params[:file]
|
||||
render_error('请上传文件') if @file.size.zero?
|
||||
render_error('文件大小超过限制') if @file.size > max_size
|
||||
else
|
||||
file = params[:file].to_s.strip
|
||||
return render_error('请上传正确的图片') if file.blank?
|
||||
@file = Util.convert_base64_image(file, max_size: max_size)
|
||||
end
|
||||
rescue Base64ImageConverter::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
def file_path
|
||||
@_file_path ||= begin
|
||||
case params[:source_type].to_s
|
||||
when 'Shixun' then
|
||||
disk_filename('Shixun', params[:source_id])
|
||||
else
|
||||
disk_filename(params[:source_type].to_s, params[:source_id].to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def disk_filename(type, id)
|
||||
File.join(storage_path, type.to_s, id.to_s)
|
||||
end
|
||||
|
||||
def storage_path
|
||||
@_storage_path ||= File.join(Rails.root, 'public', 'images', 'avatars')
|
||||
end
|
||||
|
||||
def file_url
|
||||
File.join('/images/avatars/', params[:source_type].to_s, params[:source_id].to_s)
|
||||
end
|
||||
end
|
@ -0,0 +1,25 @@
|
||||
class Admins::LibraryAppliesController < Admins::BaseController
|
||||
def index
|
||||
params[:status] ||= 'pending'
|
||||
applies = Admins::LibraryApplyQuery.call(params)
|
||||
|
||||
@library_applies = paginate applies.preload(library: :user)
|
||||
end
|
||||
|
||||
def agree
|
||||
Libraries::AgreeApplyService.new(current_library_apply, current_user).call
|
||||
render_success_js
|
||||
end
|
||||
|
||||
def refuse
|
||||
Libraries::RefuseApplyService.new(current_library_apply, current_user, reason: params[:reason]).call
|
||||
|
||||
render_success_js
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_library_apply
|
||||
@_current_library_apply ||= LibraryApply.find(params[:id])
|
||||
end
|
||||
end
|
@ -0,0 +1,97 @@
|
||||
class Admins::MirrorRepositoriesController < Admins::BaseController
|
||||
before_action :check_shixun_mirrors!, only: [:index]
|
||||
|
||||
def index
|
||||
mirrors = MirrorRepository.all
|
||||
mirrors = mirrors.reorder(status: :desc, main_type: :desc, type_name: :asc)
|
||||
|
||||
@mirrors = paginate mirrors.includes(:mirror_scripts)
|
||||
@error_mirror_names = MirrorRepository.where(status: 5).pluck(:name)
|
||||
end
|
||||
|
||||
def new
|
||||
@mirror = MirrorRepository.new
|
||||
end
|
||||
|
||||
def create
|
||||
@mirror = MirrorRepository.new
|
||||
Admins::SaveMirrorRepositoryService.call(@mirror, current_user, form_params)
|
||||
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_path(@mirror)
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
flash.now[:danger] = '保存失败'
|
||||
render 'new'
|
||||
rescue Admins::SaveMirrorRepositoryService::Error => ex
|
||||
flash.now[:danger] = ex.message
|
||||
render 'new'
|
||||
end
|
||||
|
||||
def edit
|
||||
@mirror = current_mirror
|
||||
end
|
||||
|
||||
def update
|
||||
@mirror = current_mirror
|
||||
|
||||
Admins::SaveMirrorRepositoryService.call(current_mirror, current_user, form_params)
|
||||
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_path(current_mirror)
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
flash.now[:danger] = '保存失败'
|
||||
render 'edit'
|
||||
rescue Admins::SaveMirrorRepositoryService::Error => ex
|
||||
flash.now[:danger] = ex.message
|
||||
render 'edit'
|
||||
end
|
||||
|
||||
def destroy
|
||||
return render_js_error('该状态下不允许删除') unless current_mirror.deletable?
|
||||
|
||||
current_mirror.destroy!
|
||||
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
def for_select
|
||||
mirrors = MirrorRepository.all
|
||||
|
||||
keyword = params[:keyword].to_s.strip
|
||||
mirrors = mirrors.where('name LIKE ?', "%#{keyword}%") if keyword.present?
|
||||
|
||||
@mirrors = paginate mirrors
|
||||
|
||||
render_ok(count: @mirrors.total_count, mirrors: @mirrors.as_json(only: %i[id name]))
|
||||
end
|
||||
|
||||
def merge
|
||||
origin_mirror = MirrorRepository.find(params[:mirror_id])
|
||||
mirror = MirrorRepository.find(params[:new_mirror_id])
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
origin_mirror.update!(name: mirror.name, mirrorID: mirror.mirrorID)
|
||||
mirror.destroy!
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_mirror
|
||||
@_current_mirror ||= MirrorRepository.find(params[:id])
|
||||
end
|
||||
|
||||
def form_params
|
||||
columns = %i[type_name main_type time_limit resource_limit cpu_limit memory_limit description status]
|
||||
params.require(:mirror_repository).permit(*columns)
|
||||
end
|
||||
|
||||
def check_shixun_mirrors!
|
||||
return
|
||||
return unless request.format.html?
|
||||
|
||||
Admins::CheckShixunMirrorsService.call
|
||||
rescue Admins::CheckShixunMirrorsService::Error => e
|
||||
internal_server_error(e.message)
|
||||
end
|
||||
end
|
@ -0,0 +1,59 @@
|
||||
class Admins::MirrorScriptsController < Admins::BaseController
|
||||
helper_method :current_mirror
|
||||
|
||||
def index
|
||||
scripts = current_mirror.mirror_scripts.order(updated_at: :desc)
|
||||
@scripts = paginate scripts
|
||||
end
|
||||
|
||||
def new
|
||||
@script = current_mirror.mirror_scripts.new
|
||||
end
|
||||
|
||||
def create
|
||||
@script = current_mirror.mirror_scripts.new(form_params)
|
||||
|
||||
if @script.save
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_mirror_script_path(current_mirror, @script)
|
||||
else
|
||||
flash[:danger] = '保存失败'
|
||||
render 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@script = current_script
|
||||
end
|
||||
|
||||
def update
|
||||
@script = current_script
|
||||
|
||||
if @script.update(form_params)
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_mirror_script_path(current_mirror, @script)
|
||||
else
|
||||
flash[:danger] = '保存失败'
|
||||
render 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
current_script.destroy!
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_script
|
||||
@_current_script ||= current_mirror.mirror_scripts.find(params[:id])
|
||||
end
|
||||
|
||||
def current_mirror
|
||||
@_current_mirror ||= MirrorRepository.find(params[:mirror_repository_id])
|
||||
end
|
||||
|
||||
def form_params
|
||||
params.require(:mirror_script).permit(:script_type, :description, :script)
|
||||
end
|
||||
end
|
@ -0,0 +1,14 @@
|
||||
class Admins::MyshixunsController < Admins::BaseController
|
||||
def index
|
||||
params[:sort_by] = params[:sort_by].presence || 'created_at'
|
||||
params[:sort_direction] = params[:sort_direction].presence || 'desc'
|
||||
|
||||
myshixuns = Admins::MyshixunQuery.call(params)
|
||||
|
||||
@myshixuns = paginate myshixuns.includes(:last_executable_task, :last_task, shixun: :user, user: { user_extension: :school })
|
||||
|
||||
myshixun_ids = @myshixuns.map(&:id)
|
||||
@finish_game_count = Game.where(myshixun_id: myshixun_ids, status: 2).group(:myshixun_id).count
|
||||
@total_score = Game.where(myshixun_id: myshixun_ids, status: 2).where('final_score > 0').group(:myshixun_id).sum(:final_score)
|
||||
end
|
||||
end
|
@ -0,0 +1,37 @@
|
||||
class Admins::ProjectPackageAppliesController < Admins::BaseController
|
||||
before_action :current_apply,only: [:agree,:refuse]
|
||||
|
||||
def index
|
||||
params[:status] ||= 'pending'
|
||||
status = params[:status]
|
||||
if status == 'all'
|
||||
status = %w(agreed refused)
|
||||
end
|
||||
package_applies = ProjectPackageApply.where(status: status)
|
||||
keyword = params[:keyword].to_s.strip || ""
|
||||
if keyword.present?
|
||||
package_applies = package_applies.joins(:project_package).where("project_packages.title like ?","%#{keyword}%")
|
||||
end
|
||||
@package_applies = paginate package_applies.includes(project_package: { creator: :user_extension })
|
||||
end
|
||||
|
||||
def agree
|
||||
ProjectPackages::AgreeApplyService.new(current_apply).call
|
||||
render_success_js
|
||||
rescue ProjectPackages::AgreeApplyService::Error => e
|
||||
render json: { status: -1, message: e.message }
|
||||
end
|
||||
|
||||
def refuse
|
||||
ProjectPackages::RefuseApplyService.new(current_apply, reason: params[:reason]).call
|
||||
render_success_js
|
||||
rescue ProjectPackages::RefuseApplyService::Error => e
|
||||
render json: { status: -1, message: e.message }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_apply
|
||||
@_current_apply ||= ProjectPackageApply.find(params[:id])
|
||||
end
|
||||
end
|
@ -0,0 +1,97 @@
|
||||
class Admins::ShixunSettingsController < Admins::BaseController
|
||||
|
||||
def index
|
||||
params[:sort_by] = params[:sort_by].presence || 'created_on'
|
||||
params[:sort_direction] = params[:sort_direction].presence || 'desc'
|
||||
|
||||
shixun_settings = Admins::ShixunSettingsQuery.call(params)
|
||||
@editing_shixuns = shixun_settings.where(status:0).size
|
||||
@pending_shixuns = shixun_settings.where(status:1).size
|
||||
@processed_shixuns = shixun_settings.where(status:2).size
|
||||
@closed_shixuns = shixun_settings.where(status:3).size
|
||||
|
||||
@sort_json = {
|
||||
can_copy: params[:can_copy].present? ? params[:can_copy] : false,
|
||||
webssh: params[:webssh].present? ? params[:webssh] : "0",
|
||||
hidden: params[:hidden].present? ? params[:hidden] : false,
|
||||
homepage_show: params[:homepage_show].present? ? params[:homepage_show] : false,
|
||||
task_pass: params[:task_pass].present? ? params[:task_pass] : false,
|
||||
code_hidden: params[:code_hidden].present? ? params[:code_hidden] : false
|
||||
}
|
||||
|
||||
@shixuns_type_check = MirrorRepository.pluck(:type_name,:id)
|
||||
@shixun_tags = TagRepertoire.order("name asc").pluck(:name,:id)
|
||||
@params_page = params[:page] || 1
|
||||
@shixun_settings = paginate shixun_settings.preload(:user,:tag_repertoires)
|
||||
|
||||
respond_to do |format|
|
||||
format.js
|
||||
format.html
|
||||
format.xls{
|
||||
filename = "实训详情_#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}.xls"
|
||||
send_data(shixun_list_xls(shixun_settings), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename))
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def update
|
||||
@shixun = Shixun.find_by(id:params[:id])
|
||||
@page_no = params[:page_no] || "1"
|
||||
@shixun_tags = TagRepertoire.order("name asc").pluck(:name,:id)
|
||||
tag_ids = params[:tag_repertoires]
|
||||
if tag_ids.present?
|
||||
@shixun&.shixun_tag_repertoires.delete_all
|
||||
tag_repertoire_ids = @shixun&.tag_repertoires&.pluck(:id)
|
||||
tag_ids.each do |id|
|
||||
unless tag_repertoire_ids.include?(id)
|
||||
tag_repertoire = @shixun.shixun_tag_repertoires.new(shixun_id:@shixun.id,tag_repertoire_id:id)
|
||||
tag_repertoire.save
|
||||
end
|
||||
end
|
||||
else
|
||||
unless @shixun.update_attributes(setting_params)
|
||||
redirect_to admins_shixun_settings_path
|
||||
flash[:danger] = "更新失败"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def shixun_list_xls shixuns
|
||||
xls_report = StringIO.new
|
||||
book = Spreadsheet::Workbook.new
|
||||
sheet1 = book.create_worksheet :name => "sheet"
|
||||
blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10
|
||||
sheet1.row(0).default_format = blue
|
||||
sheet1.row(0).concat(["实训ID","实训名称","技术平台", "Fork源", "实践任务","选择题任务","挑战人数", "通关人数", "状态","创建者", "单位", "职业", "关卡序号","关卡名称","技能标签"])
|
||||
count_row = 1
|
||||
shixuns.find_each do |shixun|
|
||||
sheet1[count_row, 0] = shixun.identifier
|
||||
sheet1[count_row, 1] = shixun.name
|
||||
sheet1[count_row, 2] = shixun.shixun_main_name
|
||||
sheet1[count_row, 3] = shixun.fork_identifier
|
||||
sheet1[count_row, 4] = shixun.challenges.practice_type.count
|
||||
sheet1[count_row, 5] = shixun.challenges.choose_type.count
|
||||
sheet1[count_row, 6] = shixun.myshixuns.count
|
||||
sheet1[count_row, 7] = shixun.myshixuns.finished.count
|
||||
sheet1[count_row, 8] = shixun.shixun_status
|
||||
sheet1[count_row, 9] = shixun.owner.show_real_name
|
||||
sheet1[count_row, 10] = shixun.owner.school_name
|
||||
sheet1[count_row, 11] = shixun.owner.identity
|
||||
shixun.challenges.each do |challenge|
|
||||
sheet1[count_row, 12] = "第#{challenge.position}关"
|
||||
sheet1[count_row, 13] = challenge.subject
|
||||
sheet1[count_row, 14] = challenge.tags_show
|
||||
count_row += 1
|
||||
end
|
||||
count_row += 1
|
||||
end
|
||||
book.write xls_report
|
||||
xls_report.string
|
||||
end
|
||||
|
||||
def setting_params
|
||||
params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,:code_hidden,:id,tag_repertoires:[])
|
||||
end
|
||||
end
|
@ -0,0 +1,64 @@
|
||||
class Admins::ShixunsController < Admins::BaseController
|
||||
|
||||
def index
|
||||
params[:sort_by] = params[:sort_by].presence || 'created_on'
|
||||
params[:sort_direction] = params[:sort_direction].presence || 'desc'
|
||||
shixuns = Admins::ShixunQuery.call(params)
|
||||
@editing_shixuns = shixuns.where(status:0).size
|
||||
@pending_shixuns = shixuns.where(status:1).size
|
||||
@processed_shixuns = shixuns.where(status:2).size
|
||||
@closed_shixuns = shixuns.where(status:3).size
|
||||
@shixuns_type_check = MirrorRepository.pluck(:type_name,:id)
|
||||
@params_page = params[:page] || 1
|
||||
@shixuns = paginate shixuns.preload(:user,:challenges)
|
||||
|
||||
respond_to do |format|
|
||||
format.js
|
||||
format.html
|
||||
format.xls{
|
||||
filename = "实训详情_#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}.xls"
|
||||
send_data(shixun_list_xls(shixuns), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename))
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
Shixun.find(params[:id]).destroy!
|
||||
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
private
|
||||
def shixun_list_xls shixuns
|
||||
xls_report = StringIO.new
|
||||
book = Spreadsheet::Workbook.new
|
||||
sheet1 = book.create_worksheet :name => "sheet"
|
||||
blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10
|
||||
sheet1.row(0).default_format = blue
|
||||
sheet1.row(0).concat(["实训ID","实训名称","技术平台", "Fork源", "实践任务","选择题任务","挑战人数", "通关人数", "状态","创建者", "单位", "职业", "关卡序号","关卡名称","技能标签"])
|
||||
count_row = 1
|
||||
shixuns.find_each do |shixun|
|
||||
sheet1[count_row, 0] = shixun.identifier
|
||||
sheet1[count_row, 1] = shixun.name
|
||||
sheet1[count_row, 2] = shixun.shixun_main_name
|
||||
sheet1[count_row, 3] = shixun.fork_identifier
|
||||
sheet1[count_row, 4] = shixun.challenges.practice_type.count
|
||||
sheet1[count_row, 5] = shixun.challenges.choose_type.count
|
||||
sheet1[count_row, 6] = shixun.myshixuns.count
|
||||
sheet1[count_row, 7] = shixun.myshixuns.finished.count
|
||||
sheet1[count_row, 8] = shixun.shixun_status
|
||||
sheet1[count_row, 9] = shixun.owner.show_real_name
|
||||
sheet1[count_row, 10] = shixun.owner.school_name
|
||||
sheet1[count_row, 11] = shixun.owner.identity
|
||||
shixun.challenges.each do |challenge|
|
||||
sheet1[count_row, 12] = "第#{challenge.position}关"
|
||||
sheet1[count_row, 13] = challenge.subject
|
||||
sheet1[count_row, 14] = challenge.tags_show
|
||||
count_row += 1
|
||||
end
|
||||
count_row += 1
|
||||
end
|
||||
book.write xls_report
|
||||
xls_report.string
|
||||
end
|
||||
end
|
@ -0,0 +1,41 @@
|
||||
class Admins::VideoAppliesController < Admins::BaseController
|
||||
|
||||
def index
|
||||
params[:status] ||= 'pending'
|
||||
status = params[:status]
|
||||
if status == 'all'
|
||||
status = %w(agreed refused)
|
||||
end
|
||||
|
||||
applies = VideoApply.where(status: status).order('video_applies.updated_at desc')
|
||||
|
||||
search = params[:keyword].to_s.strip
|
||||
if search.present?
|
||||
applies = applies.joins(:video)
|
||||
.where('videos.title like :search', search: "%#{search}%")
|
||||
end
|
||||
|
||||
@video_applies = paginate applies.includes(video: { user: :user_extension })
|
||||
end
|
||||
|
||||
def agree
|
||||
Videos::AgreeApplyService.new(current_video_apply, current_user).call
|
||||
render_success_js
|
||||
rescue Videos::AgreeApplyService::Error => e
|
||||
render json: { status: -1, message: e.message }
|
||||
end
|
||||
|
||||
def refuse
|
||||
Videos::RefuseApplyService.new(current_video_apply, current_user, reason: params[:reason]).call
|
||||
render_success_js
|
||||
rescue Videos::RefuseApplyService::Error => e
|
||||
render json: { status: -1, message: e.message }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_video_apply
|
||||
@_current_video_apply ||= VideoApply.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,171 @@
|
||||
class CollegesController < ApplicationController
|
||||
include Admins::PaginateHelper
|
||||
|
||||
layout 'college'
|
||||
|
||||
before_action :require_login
|
||||
before_action :check_college_present!
|
||||
before_action :check_manage_permission!
|
||||
|
||||
helper_method :current_school, :current_college
|
||||
|
||||
def statistics
|
||||
# 教师、学生总数
|
||||
count_statistic = UserExtension.where(school_id: current_school.id)
|
||||
.select('SUM(IF(identity=0, 1, 0)) AS teachers_count, SUM(IF(identity=1, 1, 0)) AS students_count').first
|
||||
@teachers_count = count_statistic['teachers_count']
|
||||
@students_count = count_statistic['students_count']
|
||||
|
||||
# 课堂总数
|
||||
@courses_count = Course.where(school_id: current_school.id, is_delete: 0).where.not(id: 1309).count
|
||||
# 实训总数
|
||||
@shixuns_count = Shixun.visible.joins('left join user_extensions on user_extensions.user_id = shixuns.user_id')
|
||||
.where(user_extensions: { school_id: current_school.id }).count
|
||||
end
|
||||
|
||||
def shixun_time
|
||||
time_sum = Game.joins('left join user_extensions on user_extensions.user_id = games.user_id')
|
||||
.where(user_extensions: { school_id: current_school.id }).sum(:cost_time)
|
||||
shixun_time_sum = (time_sum / (24 * 60 * 60.0)).ceil
|
||||
|
||||
render json: { shixun_time: shixun_time_sum }
|
||||
end
|
||||
|
||||
def shixun_report_count
|
||||
shixun_report_count = StudentWork.where(work_status: [1, 2]).where('myshixun_id != 0')
|
||||
.joins('left join user_extensions on user_extensions.user_id = student_works.user_id')
|
||||
.where(user_extensions: { school_id: current_school.id }).count
|
||||
render json: { shixun_report_count: shixun_report_count }
|
||||
end
|
||||
|
||||
def teachers
|
||||
@teachers = User.find_by_sql("SELECT users.id, users.login, users.lastname, users.firstname, users.nickname, IFNULL((SELECT count(shixuns.id) FROM shixuns where shixuns.user_id =users.id group by shixuns.user_id), 0) AS publish_shixun_count,
|
||||
(SELECT count(c.id) FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.role in (1,2,3) and c.school_id = #{current_school.id} AND m.user_id=users.id AND c.is_delete = 0) as course_count
|
||||
FROM `users`, user_extensions ue where users.id=ue.user_id and ue.identity=0 and ue.school_id=#{current_school.id} ORDER BY publish_shixun_count desc, course_count desc, id desc LIMIT 10")
|
||||
# ).order("publish_shixun_count desc, experience desc").limit(10)
|
||||
@teachers =
|
||||
@teachers.map do |teacher|
|
||||
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.role in (1,2,3) AND m.user_id=#{teacher.id} AND c.is_delete = 0 and c.school_id = #{current_school.id}")
|
||||
course_count = course_ids.size
|
||||
homeworks = HomeworkCommon.where(:homework_type => 4, :course_id => course_ids.map(&:id))
|
||||
un_shixun_work_count = homeworks.where("publish_time > '#{Time.now}' or publish_time is null").count
|
||||
shixun_work_count = homeworks.size - un_shixun_work_count
|
||||
student_count = StudentsForCourse.where(:course_id => course_ids.map(&:id)).count
|
||||
myshixun_ids = StudentWork.select("myshixun_id").where("homework_common_id in (#{homeworks.map(&:id).join(',').strip == "" ? -1 : homeworks.map(&:id).join(',')}) and myshixun_id is not null")
|
||||
complete_myshixun = Myshixun.select("id").where(:status => 1, :id => myshixun_ids.map(&:myshixun_id)).size
|
||||
all_myshixun = Myshixun.select("id").where(:id => myshixun_ids.map(&:myshixun_id)).size
|
||||
complete_rate = all_myshixun == 0 ? 0 : ((complete_myshixun * 100) / all_myshixun).try(:round, 2).to_f
|
||||
real_name = teacher.show_real_name
|
||||
teacher = teacher.attributes.dup.merge({
|
||||
real_name: real_name,
|
||||
course_count: course_count,
|
||||
shixun_work_count: shixun_work_count,
|
||||
un_shixun_work_count: un_shixun_work_count,
|
||||
student_count: student_count,
|
||||
complete_rate: complete_rate
|
||||
}).to_json
|
||||
JSON.parse(teacher)
|
||||
end
|
||||
end
|
||||
|
||||
def shixun_chart_data
|
||||
shixun_ids = HomeworkCommonsShixun.joins(homework_common: :course).where(courses: {school_id: current_school.id, is_delete: 0}).where('courses.id != 1309').pluck('distinct shixun_id')
|
||||
shixun_count_map = ShixunTagRepertoire.joins(:tag_repertoire).where(shixun_id: shixun_ids).group('tag_repertoires.name').order('count_shixun_id desc').count(:shixun_id)
|
||||
|
||||
names = []
|
||||
data = []
|
||||
shixun_count_map.each do |name, count|
|
||||
break if names.size == 9
|
||||
|
||||
names << name
|
||||
data << { value: count, name: name }
|
||||
end
|
||||
|
||||
if shixun_count_map.keys.size > 9
|
||||
other_count = shixun_count_map.values[9..-1].reduce(:+)
|
||||
names << 'Others'
|
||||
data << { name: 'Others', value: other_count }
|
||||
end
|
||||
|
||||
render json: { names: names, data: data }
|
||||
end
|
||||
|
||||
# 在线课堂
|
||||
def course_statistics
|
||||
courses = Course.where(school_id: current_school.id, is_delete: 0).where.not(id: 1309)
|
||||
|
||||
courses = courses.left_joins(practice_homeworks: { student_works: { myshixun: :games } })
|
||||
.select('courses.id, courses.name, courses.is_end, sum(games.evaluate_count) evaluating_count')
|
||||
.group('courses.id').order('is_end asc, evaluating_count desc')
|
||||
|
||||
params[:per_page] = 8
|
||||
@courses = paginate courses
|
||||
|
||||
course_ids = @courses.map(&:id)
|
||||
@student_count = StudentsForCourse.where(course_id: course_ids).group(:course_id).count
|
||||
@shixun_work_count = HomeworkCommon.where(homework_type: 4, course_id: course_ids).group(:course_id).count
|
||||
@attachment_count = Attachment.where(container_id: course_ids, container_type: 'Course').group(:container_id).count
|
||||
@message_count = Message.joins(:board).where(boards: { parent_id: 0, course_id: course_ids }).group('boards.course_id').count
|
||||
@active_time = CourseActivity.where(course_id: course_ids).group(:course_id).maximum(:created_at)
|
||||
@exercise_count = Exercise.where(course_id: course_ids).group(:course_id).count
|
||||
@poll_count = Poll.where(course_id: course_ids).group(:course_id).count
|
||||
@other_work_count = HomeworkCommon.where(homework_type: [1,3], course_id: course_ids).group(:course_id).count
|
||||
end
|
||||
|
||||
# 学生实训
|
||||
def student_shixun
|
||||
@students = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).includes(:user_extension).order('experience desc').limit(10)
|
||||
|
||||
student_ids = @students.map(&:id)
|
||||
@shixun_count = Myshixun.where(user_id: student_ids).group(:user_id).count
|
||||
@study_shixun_count = Myshixun.where(user_id: student_ids, status: 0).group(:user_id).count
|
||||
end
|
||||
|
||||
def student_hot_evaluations
|
||||
games = Game.joins(:myshixun).joins('join shixun_tag_repertoires str on str.shixun_id = myshixuns.shixun_id')
|
||||
games = games.joins('join tag_repertoires tr on tr.id = str.tag_repertoire_id')
|
||||
games = games.joins("join user_extensions ue on ue.user_id = myshixuns.user_id and ue.school_id = #{current_school.id}")
|
||||
evaluate_count_map = games.group('tr.name').reorder('sum_games_evaluate_count desc').limit(10).sum('games.evaluate_count')
|
||||
|
||||
render json: { names: evaluate_count_map.keys, values: evaluate_count_map.values }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def require_login
|
||||
return if User.current.logged?
|
||||
|
||||
redirect_to "/login?back_url=#{CGI::escape(request.fullpath)}"
|
||||
end
|
||||
|
||||
def check_college_present!
|
||||
return if current_college.present?
|
||||
|
||||
redirect_to '/404'
|
||||
end
|
||||
|
||||
def check_manage_permission!
|
||||
return if can_manage_college?
|
||||
|
||||
redirect_to '/403'
|
||||
end
|
||||
|
||||
def can_manage_college?
|
||||
return true if current_user.admin_or_business? # 超级管理员|运营
|
||||
return true if current_college.is_a?(Department) && current_college.member?(current_user) # 部门管理员
|
||||
return true if current_user.is_teacher? && current_user.school_id == current_school.id # 学校老师
|
||||
return true if current_school.customer_id && current_user.partner&.partner_customers&.exists?(customer_id: current_school.customer_id)
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def current_school
|
||||
current_college.is_a?(School) ? current_college : current_college.school
|
||||
end
|
||||
|
||||
def current_college
|
||||
@_current_college ||= begin
|
||||
Department.find_by(identifier: params[:id]) || School.find_by(id: params[:id])
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,129 @@
|
||||
#encoding: UTF-8
|
||||
class ExerciseBanksController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :find_bank, except: [:choose_shixun]
|
||||
before_action :bank_admin, only: [:update]
|
||||
before_action :commit_shixun_present, only: [:commit_shixun]
|
||||
|
||||
def show
|
||||
@exercise_questions = @bank.exercise_bank_questions&.includes(:exercise_bank_choices, :exercise_bank_shixun_challenges,
|
||||
:exercise_bank_standard_answers).order("question_number ASC")
|
||||
|
||||
if @bank.container_type == "Exercise"
|
||||
get_exercise_question_count
|
||||
else
|
||||
get_poll_question_count
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
tip_exception("标题不能为空!") if params[:exercise_name].blank?
|
||||
@bank.update_attributes!(name: params[:exercise_name], description: params[:exercise_description])
|
||||
normal_status(0,"更新成功")
|
||||
end
|
||||
|
||||
def choose_shixun
|
||||
search = params[:search]
|
||||
type = params[:type]
|
||||
# 超级管理员用户显示所有未隐藏的实训、非管理员显示所有已发布的实训(对本单位公开且未隐藏未关闭)
|
||||
if current_user.admin?
|
||||
@shixuns = Shixun.unhidden
|
||||
else
|
||||
none_shixun_ids = ShixunSchool.where("school_id != #{current_user.school_id}").pluck(:shixun_id)
|
||||
|
||||
@shixuns = Shixun.where.not(id: none_shixun_ids).unhidden
|
||||
end
|
||||
|
||||
# 实训的所有标签
|
||||
@tags = TagRepertoire.select([:id, :name]).joins(:shixuns).where(shixuns: {id: @shixuns}).distinct
|
||||
|
||||
if params[:search] && params[:search].strip != ""
|
||||
@shixuns = @shixuns.joins(:user).where("shixuns.name like ? or concat(users.lastname, users.firstname) like ?",
|
||||
"%#{search}%", "%#{search}%").distinct
|
||||
end
|
||||
|
||||
unless type.blank? || type == "all"
|
||||
@shixuns = @shixuns.joins(:shixun_tag_repertoires).where(shixun_tag_repertoires: {tag_repertoire_id: type}).distinct
|
||||
end
|
||||
|
||||
@shixuns = @shixuns.select([:id, :name, :status, :myshixuns_count, :identifier, :user_id, :trainee])
|
||||
@total_count = @shixuns.size
|
||||
|
||||
## 分页参数
|
||||
page = params[:page] || 1
|
||||
@shixuns = @shixuns.reorder("shixuns.created_at desc").includes(:challenges, user: [user_extension: :school]).page(page).per(10)
|
||||
end
|
||||
|
||||
#确认实训的选择
|
||||
def commit_shixun
|
||||
@shixun_challenges = @shixun.challenges
|
||||
@shixun_challenges_count = @shixun_challenges.size
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_bank
|
||||
@bank = ExerciseBank.find_by!(id: params[:id])
|
||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? ||
|
||||
(current_user.certification_teacher? && @bank.is_public)
|
||||
end
|
||||
|
||||
def bank_admin
|
||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin?
|
||||
end
|
||||
|
||||
#判断实训是否已选择
|
||||
def commit_shixun_present
|
||||
question_shixun_ids = @exercise.exercise_bank_questions.pluck(:shixun_id).reject(&:blank?)
|
||||
shixun_id = params[:shixun_id]
|
||||
@shixun = Shixun.find_by(id: shixun_id)
|
||||
if shixun_id.present? && question_shixun_ids.include?(shixun_id)
|
||||
normal_status(-1,"该实训已选择!")
|
||||
elsif @shixun.blank?
|
||||
normal_status(-1,"该实训不存在!")
|
||||
end
|
||||
end
|
||||
|
||||
def get_exercise_question_count
|
||||
@exercise_ques_count = @exercise_questions.size # 全部的题目数
|
||||
@exercise_ques_scores = @exercise_questions.pluck(:question_score).sum
|
||||
|
||||
#单选题的数量及分数
|
||||
exercise_single_ques = @exercise_questions.find_by_custom("question_type", Exercise::SINGLE)
|
||||
@exercise_single_ques_count = exercise_single_ques.size
|
||||
@exercise_single_ques_scores = exercise_single_ques.pluck(:question_score).sum
|
||||
|
||||
#多选题的数量及分数
|
||||
exercise_double_ques = @exercise_questions.find_by_custom("question_type", Exercise::MULTIPLE)
|
||||
@exercise_double_ques_count = exercise_double_ques.size
|
||||
@exercise_double_ques_scores = exercise_double_ques.pluck(:question_score).sum
|
||||
|
||||
# 判断题数量及分数
|
||||
exercise_ques_judge = @exercise_questions.find_by_custom("question_type", Exercise::JUDGMENT)
|
||||
@exercise_ques_judge_count = exercise_ques_judge.size
|
||||
@exercise_ques_judge_scores = exercise_ques_judge.pluck(:question_score).sum
|
||||
|
||||
#填空题数量及分数
|
||||
exercise_ques_null = @exercise_questions.find_by_custom("question_type", Exercise::COMPLETION)
|
||||
@exercise_ques_null_count = exercise_ques_null.size
|
||||
@exercise_ques_null_scores = exercise_ques_null.pluck(:question_score).sum
|
||||
|
||||
#简答题数量及分数
|
||||
exercise_ques_main = @exercise_questions.find_by_custom("question_type", Exercise::SUBJECTIVE)
|
||||
@exercise_ques_main_count = exercise_ques_main.size
|
||||
@exercise_ques_main_scores = exercise_ques_main.pluck(:question_score).sum
|
||||
|
||||
#实训题数量及分数
|
||||
exercise_ques_shixun = @exercise_questions.find_by_custom("question_type", Exercise::PRACTICAL)
|
||||
@exercise_ques_shixun_count = exercise_ques_shixun.size
|
||||
@exercise_ques_shixun_scores = exercise_ques_shixun.pluck(:question_score).sum
|
||||
end
|
||||
|
||||
def get_poll_question_count
|
||||
@poll_questions_count = @exercise_questions&.size # 全部的题目数
|
||||
@poll_question_singles = @exercise_questions.find_by_custom("question_type", 1).size # 单选题
|
||||
@poll_question_doubles = @exercise_questions.find_by_custom("question_type", 2).size # 多选题
|
||||
@poll_question_mains = @exercise_questions.find_by_custom("question_type", 3).size #主观题
|
||||
end
|
||||
|
||||
end
|
@ -0,0 +1,40 @@
|
||||
class GtopicBanksController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :find_bank
|
||||
before_action :bank_admin, only: [:edit, :update]
|
||||
|
||||
def show
|
||||
@bank_attachments = @bank.attachments
|
||||
end
|
||||
|
||||
def edit
|
||||
@attachments = @bank.attachments
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
@bank.update_attributes(gtopic_bank_params)
|
||||
Attachment.associate_container(params[:attachment_ids], @bank.id, @bank.class) if params[:attachment_ids]
|
||||
normal_status(0, "更新成功")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_bank
|
||||
@bank = GtopicBank.find_by!(id: params[:id])
|
||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? ||
|
||||
(current_user.certification_teacher? && @bank.is_public)
|
||||
end
|
||||
|
||||
def bank_admin
|
||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin?
|
||||
end
|
||||
|
||||
def gtopic_bank_params
|
||||
tip_exception("name参数不能为空") if params[:gtopic_bank][:name].blank?
|
||||
tip_exception("description参数不能为空") if params[:gtopic_bank][:description].blank?
|
||||
params.require(:gtopic_bank).permit(:name, :topic_type, :topic_source, :topic_property_first, :description,
|
||||
:topic_property_second, :source_unit, :topic_repeat, :province, :city)
|
||||
end
|
||||
end
|
@ -0,0 +1,69 @@
|
||||
class HomeworkBanksController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :find_bank
|
||||
before_action :bank_params, only: [:update]
|
||||
before_action :bank_admin, only: [:update, :destroy, :set_public]
|
||||
|
||||
def show
|
||||
@bank_attachments = @bank.attachments.where(attachtype: 1)
|
||||
@reference_attachments = @bank.attachments.where(attachtype: 2)
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
if @bank.homework_type == 1
|
||||
@bank.update_attributes(name: params[:name], description: params[:description], reference_answer: params[:reference_answer])
|
||||
elsif @bank.homework_type == 3
|
||||
@bank.update_attributes(name: params[:name], description: params[:description], reference_answer: params[:reference_answer],
|
||||
base_on_project: params[:base_on_project], min_num: params[:min_num], max_num: params[:max_num])
|
||||
end
|
||||
|
||||
# 作业描述的附件
|
||||
Attachment.associate_container(params[:attachment_ids], @bank.id, @bank.class) if params[:attachment_ids]
|
||||
# 作业参考答案的附件
|
||||
Attachment.associate_container(params[:reference_attachment_ids], @bank.id, @bank.class, 2) if params[:reference_attachment_ids]
|
||||
|
||||
normal_status(0, "更新成功")
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
ActiveRecord::Base.transaction do
|
||||
@bank.homework_commons.update_all(homework_bank_id: nil)
|
||||
@bank.destroy!
|
||||
normal_status("删除成功")
|
||||
end
|
||||
end
|
||||
|
||||
def set_public
|
||||
@bank.update_attributes(is_public: 1)
|
||||
normal_status("更新成功")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_bank
|
||||
@bank = HomeworkBank.find_by!(id: params[:id])
|
||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? ||
|
||||
(current_user.certification_teacher? && @bank.is_public)
|
||||
end
|
||||
|
||||
def bank_admin
|
||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin?
|
||||
end
|
||||
|
||||
def bank_params
|
||||
tip_exception("name参数不能为空") if params[:homework_bank][:name].blank?
|
||||
tip_exception("description参数不能为空") if params[:homework_bank][:description].blank?
|
||||
if @bank.homework_type == 3
|
||||
tip_exception("base_on_project参数不能为空") if params[:homework_bank][:base_on_project].nil?
|
||||
tip_exception("min_num参数不能为空") if params[:homework_bank][:min_num].blank?
|
||||
tip_exception("max_num参数不能为空") if params[:homework_bank][:max_num].blank?
|
||||
tip_exception("最小人数不能小于1") if params[:homework_bank][:min_num].to_i < 1
|
||||
tip_exception("最大人数不能小于最小人数") if params[:homework_bank][:max_num].to_i < params[:homework_bank][:min_num].to_i
|
||||
end
|
||||
params.require(:homework_bank).permit(:name, :description, :reference_answer) if @bank.homework_type == 1
|
||||
params.require(:homework_bank).permit(:name, :description, :reference_answer, :min_num, :max_num, :base_on_project) if @bank.homework_type == 3
|
||||
end
|
||||
|
||||
end
|
@ -0,0 +1,49 @@
|
||||
class TaskBanksController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :find_bank
|
||||
before_action :bank_admin, only: [:update]
|
||||
|
||||
def show
|
||||
@bank_attachments = @bank.attachments
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
@bank.update_attributes(gtask_bank_params)
|
||||
Attachment.associate_container(params[:attachment_ids], @bank.id, @bank.class) if params[:attachment_ids]
|
||||
normal_status(0, "更新成功")
|
||||
rescue Exception => e
|
||||
uid_logger(e.message)
|
||||
tip_exception(e.message)
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_bank
|
||||
@bank = GtaskBank.find_by!(id: params[:id])
|
||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? ||
|
||||
(current_user.certification_teacher? && @bank.is_public)
|
||||
end
|
||||
|
||||
def bank_admin
|
||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin?
|
||||
end
|
||||
|
||||
def gtask_bank_params
|
||||
tip_exception("name参数不能为空") if params[:gtask_bank][:name].blank?
|
||||
tip_exception("description参数不能为空") if params[:gtask_bank][:description].blank?
|
||||
if @bank.homework_type == 3
|
||||
tip_exception("base_on_project参数不能为空") if params[:gtask_bank][:base_on_project].nil?
|
||||
tip_exception("min_num参数不能为空") if params[:gtask_bank][:min_num].blank?
|
||||
tip_exception("max_num参数不能为空") if params[:gtask_bank][:max_num].blank?
|
||||
tip_exception("最小人数不能小于1") if params[:gtask_bank][:min_num].to_i < 1
|
||||
tip_exception("最大人数不能小于最小人数") if params[:gtask_bank][:max_num].to_i < params[:gtask_bank][:min_num].to_i
|
||||
end
|
||||
params.require(:gtask_bank).permit(:name, :description) if @bank.task_type == 1
|
||||
params.require(:gtask_bank).permit(:name, :description, :min_num, :max_num, :base_on_project) if @bank.task_type == 2
|
||||
end
|
||||
end
|
@ -0,0 +1,23 @@
|
||||
module Admins::MirrorRepositoriesHelper
|
||||
def mirror_type_tag(mirror)
|
||||
case mirror.main_type
|
||||
when '1' then '<i class="fa fa-star text-success font-16" aria-hidden="true" data-toggle="tooltip" data-title="主类别"></i>'.html_safe
|
||||
when '0' then '<i class="fa fa-star text-secondary font-16" aria-hidden="true" data-toggle="tooltip" data-title="子类别"></i>'.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
def mirror_status_tag(mirror)
|
||||
case mirror.status
|
||||
when 0
|
||||
'<i class="fa fa-check-circle text-secondary font-16" data-toggle="tooltip" data-title="未发布"></i>'.html_safe
|
||||
when 1
|
||||
'<i class="fa fa-check-circle text-success font-16" data-toggle="tooltip" data-title="已发布"></i>'.html_safe
|
||||
when 2, 3
|
||||
'<i class="fa fa-exclamation-circle text-danger font-16" data-toggle="tooltip" data-title="被修改"></i>'.html_safe
|
||||
when 4
|
||||
'<i class="fa fa-times-circle text-danger font-18" data-toggle="tooltip" data-title="被删除"></i>'.html_safe
|
||||
when 5
|
||||
'<i class="fa fa-exclamation-circle text-warning font-16" data-toggle="tooltip" data-title="子节点异常"></i>'.html_safe
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,2 @@
|
||||
module ExerciseBankQuestionsHelper
|
||||
end
|
@ -0,0 +1,2 @@
|
||||
module HomeworkBanksHelper
|
||||
end
|
@ -0,0 +1,21 @@
|
||||
# 删除部门 消息通知
|
||||
class DeleteDepartmentNotifyJob < ApplicationJob
|
||||
queue_as :notify
|
||||
|
||||
def perform(department_id, operator_id, user_ids)
|
||||
department = Department.unscoped.find_by(id: department_id)
|
||||
return if department.blank? || user_ids.blank?
|
||||
|
||||
attrs = %i[ user_id trigger_user_id container_id container_type tiding_type status created_at updated_at]
|
||||
|
||||
same_attrs = {
|
||||
trigger_user_id: operator_id, container_id: department.id, container_type: 'Department',
|
||||
status: 4, tiding_type: 'System'
|
||||
}
|
||||
Tiding.bulk_insert(*attrs) do |worker|
|
||||
user_ids.each do |user_id|
|
||||
worker.add same_attrs.merge(user_id: user_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,10 @@
|
||||
class Customer < ApplicationRecord
|
||||
default_scope { order(created_at: :desc) }
|
||||
|
||||
belongs_to :school
|
||||
|
||||
has_many :partner_customers, dependent: :destroy
|
||||
has_many :partners, through: :partner_customers
|
||||
|
||||
has_many :users
|
||||
end
|
@ -1,4 +1,7 @@
|
||||
class ExerciseBankChoice < ApplicationRecord
|
||||
belongs_to :exercise_bank_question
|
||||
has_many :exercise_bank_standard_answers
|
||||
|
||||
scope :find_choice_custom, lambda {|k,v| where("#{k} = ?",v)} #根据传入的参数查找问题
|
||||
scope :left_choice_choose, lambda {|k,v| where("#{k} > ?",v)} #根据传入的参数查找问题
|
||||
end
|
@ -1,3 +1,5 @@
|
||||
class Partner < ApplicationRecord
|
||||
belongs_to :school, optional: true
|
||||
|
||||
has_many :users
|
||||
end
|
||||
|
@ -0,0 +1,4 @@
|
||||
class PartnerCustomer < ApplicationRecord
|
||||
belongs_to :partner
|
||||
belongs_to :customer
|
||||
end
|
@ -0,0 +1,32 @@
|
||||
class Admins::DepartmentQuery < ApplicationQuery
|
||||
include CustomSortable
|
||||
|
||||
attr_reader :params
|
||||
|
||||
sort_columns :created_at, default_by: :created_at, default_direction: :desc
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
departments = Department.where(is_auth: true).without_deleted
|
||||
|
||||
keyword = params[:keyword].to_s.strip
|
||||
if keyword.present?
|
||||
departments = departments.joins(:school)
|
||||
.where('schools.name LIKE :keyword OR departments.name LIKE :keyword', keyword: "%#{keyword}%")
|
||||
end
|
||||
|
||||
if params[:with_member].to_s == 'true'
|
||||
subquery = DepartmentMember.where('department_id = departments.id').select('1 AS one').to_sql
|
||||
departments = departments.where("EXISTS(#{subquery})")
|
||||
end
|
||||
|
||||
if params[:with_identifier].to_s == 'true'
|
||||
departments = departments.where.not(identifier: nil).where.not(identifier: '')
|
||||
end
|
||||
|
||||
custom_sort(departments, params[:sort_by], params[:sort_direction])
|
||||
end
|
||||
end
|
@ -0,0 +1,29 @@
|
||||
class Admins::LibraryApplyQuery < ApplicationQuery
|
||||
include CustomSortable
|
||||
|
||||
attr_reader :params
|
||||
|
||||
sort_columns :updated_at, default_by: :updated_at, default_direction: :desc
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
status =
|
||||
case params[:status]
|
||||
when 'processed' then %w(agreed refused)
|
||||
else params[:status]
|
||||
end
|
||||
applies = LibraryApply.where(status: status) if status.present?
|
||||
|
||||
# 关键字模糊查询
|
||||
keyword = params[:keyword].to_s.strip
|
||||
if keyword.present?
|
||||
applies = applies.joins(:library)
|
||||
.where('title LIKE :keyword OR uuid LIKE :keyword', keyword: "%#{keyword}%")
|
||||
end
|
||||
|
||||
custom_sort(applies, params[:sort_by], params[:sort_direction])
|
||||
end
|
||||
end
|
@ -0,0 +1,26 @@
|
||||
class Admins::MyshixunQuery < ApplicationQuery
|
||||
include CustomSortable
|
||||
|
||||
attr_reader :params
|
||||
|
||||
sort_columns :created_at, default_by: :created_at, default_direction: :desc
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
objs = Myshixun.all
|
||||
|
||||
keyword = params[:keyword].to_s.strip
|
||||
if keyword.present?
|
||||
like_sql = 'users.login LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword OR '\
|
||||
'schools.name LIKE :keyword OR shixuns.name LIKE :keyword OR CONCAT(teacher.lastname, teacher.firstname) Like :keyword'
|
||||
objs = objs.joins(:shixun, user: { user_extension: :school })
|
||||
.joins('JOIN users teacher ON teacher.id = shixuns.user_id')
|
||||
.where(like_sql, keyword: "%#{keyword}%")
|
||||
end
|
||||
|
||||
custom_sort(objs, params[:sort_by], params[:sort_direction])
|
||||
end
|
||||
end
|
@ -0,0 +1,48 @@
|
||||
class Admins::ShixunQuery < ApplicationQuery
|
||||
include CustomSortable
|
||||
|
||||
attr_reader :params
|
||||
|
||||
sort_columns :created_at, default_by: :created_at, default_direction: :desc
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
all_shixuns = Shixun.all
|
||||
status =
|
||||
case params[:status]
|
||||
when "editing" then [0]
|
||||
when "pending" then [1]
|
||||
when "processed" then [2]
|
||||
when "closed" then [3]
|
||||
else
|
||||
[0,1,2,3]
|
||||
end
|
||||
|
||||
all_shixuns = all_shixuns.where(status: status) if status.present?
|
||||
|
||||
if params[:tag].present?
|
||||
all_shixuns = all_shixuns.joins(:mirror_repositories).where("mirror_repositories.id = ?",params[:tag].to_i)
|
||||
end
|
||||
|
||||
# 关键字模糊查询
|
||||
keyword = params[:keyword].to_s.strip
|
||||
if keyword.present?
|
||||
search_type = params[:search_type] || "0"
|
||||
case search_type
|
||||
when "0"
|
||||
all_shixuns = all_shixuns.joins(:user)
|
||||
.where('CONCAT(lastname, firstname) like :keyword', keyword: "%#{keyword}%")
|
||||
when "1"
|
||||
all_shixuns = all_shixuns.where('name like :keyword', keyword: "%#{keyword}%")
|
||||
else
|
||||
all_shixuns = all_shixuns.joins(user: {user_extension: :school}).where('schools.name LIKE ?', "%#{keyword}%")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
custom_sort(all_shixuns, params[:sort_by], params[:sort_direction])
|
||||
end
|
||||
end
|
@ -0,0 +1,54 @@
|
||||
class Admins::ShixunSettingsQuery < ApplicationQuery
|
||||
include CustomSortable
|
||||
|
||||
attr_reader :params
|
||||
|
||||
sort_columns :created_at, default_by: :created_at, default_direction: :desc
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
all_shixuns = Shixun.all
|
||||
status =
|
||||
case params[:status]
|
||||
when "editing" then [0]
|
||||
when "pending" then [1]
|
||||
when "processed" then [2]
|
||||
when "closed" then [3]
|
||||
else
|
||||
[0,1,2,3]
|
||||
end
|
||||
|
||||
all_shixuns = all_shixuns.where(status: status) if status.present?
|
||||
|
||||
if params[:tag].present?
|
||||
all_shixuns = all_shixuns.joins(:mirror_repositories).where("mirror_repositories.id = ?",params[:tag].to_i)
|
||||
end
|
||||
|
||||
# 关键字模糊查询
|
||||
keyword = params[:keyword].to_s.strip
|
||||
if keyword.present?
|
||||
search_type = params[:search_type] || "0"
|
||||
case search_type
|
||||
when "0"
|
||||
all_shixuns = all_shixuns.joins(:user)
|
||||
.where('CONCAT(lastname, firstname) like :keyword', keyword: "%#{keyword}%")
|
||||
when "1"
|
||||
all_shixuns = all_shixuns.where('name like :keyword', keyword: "%#{keyword}%")
|
||||
else
|
||||
all_shixuns = all_shixuns.joins(user: {user_extension: :school}).where('schools.name LIKE ?', "%#{keyword}%")
|
||||
end
|
||||
end
|
||||
|
||||
all_shixuns = all_shixuns.where(can_copy: params[:can_copy]) if params[:can_copy]
|
||||
all_shixuns = all_shixuns.where(webssh: params[:webssh]) if params[:webssh]
|
||||
all_shixuns = all_shixuns.where(hidden: params[:hidden]) if params[:hidden]
|
||||
all_shixuns = all_shixuns.where(homepage_show: params[:homepage_show]) if params[:homepage_show]
|
||||
all_shixuns = all_shixuns.where(task_pass: params[:task_pass]) if params[:task_pass]
|
||||
all_shixuns = all_shixuns.where(code_hidden: params[:code_hidden]) if params[:code_hidden]
|
||||
|
||||
custom_sort(all_shixuns, params[:sort_by], params[:sort_direction])
|
||||
end
|
||||
end
|
@ -0,0 +1,20 @@
|
||||
class Admins::AddDepartmentMemberService < ApplicationService
|
||||
|
||||
attr_reader :department, :params
|
||||
|
||||
def initialize(department, params)
|
||||
@department = department
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
columns = %i[]
|
||||
DepartmentMember.bulk_insert(*columns) do |worker|
|
||||
Array.wrap(params[:user_ids]).compact.each do |user_id|
|
||||
next if department.department_members.exists?(user_id: user_id)
|
||||
|
||||
worker.add(department_id: department.id, user_id: user_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue