合并阿里云解决的问题

dev_local_2
杨树明 5 years ago
parent 8e4bc5bffa
commit e15e24b369

@ -13,15 +13,32 @@
//= require bootstrap-datepicker //= require bootstrap-datepicker
//= require bootstrap.viewer //= require bootstrap.viewer
//= require echarts
//= require lib/codemirror
//= require mode/shell/shell
//= require_tree ./i18n //= require_tree ./i18n
//= require_tree ./admins //= require_tree ./admins
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
}
});
// ******** select2 global config ******** // ******** select2 global config ********
$.fn.select2.defaults.set('theme', 'bootstrap4'); $.fn.select2.defaults.set('theme', 'bootstrap4');
$.fn.select2.defaults.set('language', 'zh-CN'); $.fn.select2.defaults.set('language', 'zh-CN');
Turbolinks.setProgressBarDelay(200); Turbolinks.setProgressBarDelay(200);
$.notifyDefaults({
type: 'success',
z_index: 9999,
delay: 2000
});
$(document).on('turbolinks:load', function(){ $(document).on('turbolinks:load', function(){
$('[data-toggle="tooltip"]').tooltip(); $('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="popover"]').popover(); $('[data-toggle="popover"]').popover();
@ -32,11 +49,18 @@ $(document).on('turbolinks:load', function(){
// flash alert提示框自动关闭 // flash alert提示框自动关闭
if($('.admin-alert-container .alert').length > 0){ if($('.admin-alert-container .alert').length > 0){
setTimeout(function(){ setTimeout(function(){
$('.admin-alert-container .alert').alert('close'); $('.admin-alert-container .alert:not(.alert-danger)').alert('close');
}, 2000); }, 2000);
setTimeout(function(){
$('.admin-alert-container .alert.alert-danger').alert('close');
}, 5000);
} }
}); });
$(document).on("turbolinks:before-cache", function () {
$('[data-toggle="tooltip"]').tooltip('hide');
$('[data-toggle="popover"]').popover('hide');
});
// var progressBar = new Turbolinks.ProgressBar(); // var progressBar = new Turbolinks.ProgressBar();
// $(document).on('ajax:send', function(event){ // $(document).on('ajax:send', function(event){

@ -27,10 +27,11 @@ $(document).on('turbolinks:load', function() {
}); });
// modal visited fire // modal visited fire
$refuseModal.on('shown.bs.modal', function(){ $refuseModal.on('shown.bs.modal', function(){
$refuseModal.find('.modal-body input[name="reason"]').focus(); $refuseModal.find('.modal-body textarea[name="reason"]').focus();
}); });
$refuseModal.on('hide.bs.modal', function () { $refuseModal.on('hide.bs.modal', function () {
$applyIdInput.val(''); $applyIdInput.val('');
$refuseModal.find('.modal-body textarea[name="reason"]').val('');
$form.data('url', ''); $form.data('url', '');
}) })

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

@ -5,7 +5,9 @@
@import "select2-bootstrap4.min"; @import "select2-bootstrap4.min";
@import "bootstrap-datepicker"; @import "bootstrap-datepicker";
@import "bootstrap-datepicker.standalone"; @import "bootstrap-datepicker.standalone";
@import "lib/codemirror";
@import "common";
@import "admins/*"; @import "admins/*";
body { body {
@ -17,20 +19,7 @@ body {
align-items: stretch; align-items: stretch;
font-size: 14px; font-size: 14px;
background: #efefef; background: #efefef;
} overflow: hidden;
a {
&:hover {
text-decoration: unset;
}
}
textarea.danger, input.danger {
border-color: #dc3545!important;
}
label.error {
color: #dc3545!important;
} }
.simple_form { .simple_form {
@ -45,6 +34,16 @@ label.error {
} }
} }
.flex-1 { input.form-control {
flex: 1; font-size: 14px;
}
.btn-default{
color: #666;
background: #e1e1e1!important;
}
.export-absolute{
right:20px;
position: absolute;
} }
.position-r{position:relative;}

@ -106,5 +106,9 @@
padding: 0.5rem 2rem; padding: 0.5rem 2rem;
} }
} }
.CodeMirror {
border: 1px solid #ced4da;
}
} }

@ -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 class Admins::DashboardsController < Admins::BaseController
def index 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
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

@ -416,7 +416,7 @@ class ApplicationController < ActionController::Base
# 实训主类别列表,自带描述 # 实训主类别列表,自带描述
def shixun_main_type def shixun_main_type
list = [] list = []
mirrors = MirrorRepository.select([:id, :type_name]).published_main_mirror mirrors = MirrorRepository.select([:id, :type_name, :description]).published_main_mirror
mirrors.try(:each) do |mirror| mirrors.try(:each) do |mirror|
list << {id: mirror.id, type_name: mirror.type_name, description: mirror.try(:description)} list << {id: mirror.id, type_name: mirror.type_name, description: mirror.try(:description)}
end end
@ -426,9 +426,9 @@ class ApplicationController < ActionController::Base
# 小类别列表 # 小类别列表
def shixun_small_type def shixun_small_type
list = [] list = []
mirrors = MirrorRepository.select([:id, :type_name]).published_small_mirror mirrors = MirrorRepository.select([:id, :type_name, :description]).published_small_mirror
mirrors.try(:each) do |mirror| mirrors.try(:each) do |mirror|
list << {id: mirror.id, type_name: mirror.type_name} list << {id: mirror.id, type_name: mirror.type_name, description: mirror.description}
end end
list list
end end

@ -234,6 +234,9 @@ class ChallengesController < ApplicationController
# {...}, ...] # {...}, ...]
#} #}
def crud_answer def crud_answer
if @challenge.challenge_answers && params[:challenge_answer].blank?
@challenge.challenge_answers.destroy_all
else
raise '参考答案不能为空' if params[:challenge_answer].empty? raise '参考答案不能为空' if params[:challenge_answer].empty?
raise '占比之和必须为100%' if params[:challenge_answer].map{|a| a[:score]}.sum != 100 raise '占比之和必须为100%' if params[:challenge_answer].map{|a| a[:score]}.sum != 100
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@ -245,7 +248,7 @@ class ChallengesController < ApplicationController
level: index+1, score: answer[:score], challenge_id: @challenge.id) level: index+1, score: answer[:score], challenge_id: @challenge.id)
end end
end end
end
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

@ -1,36 +1,34 @@
module Admins::RenderHelper module Admins::RenderHelper
extend ActiveSupport::Concern extend ActiveSupport::Concern
def render_forbidden def render_by_format(hash)
respond_to do |format| format = request.format.symbol
format.html { redirect_to '/403' } hash.key?(format) ? hash[format].call : hash[:html].call
format.json { super }
end end
def render_forbidden
render_by_format(html: -> { current_user&.business? ? render('admins/shared/403') : redirect_to('/403') },
json: -> { render status: 403, json: { messages: I18n.t('error.forbidden') } } )
end end
def render_not_found def render_not_found
respond_to do |format| render_by_format(html: -> { render 'admins/shared/404' },
format.html { render 'admins/shared/404' } js: -> { render_js_error('资源未找到') },
format.js { render_js_error('资源未找到') } json: -> { render status: 404, json: { message: '资源未找到' } })
format.json { render status: 404, json: { message: '资源未找到' } }
end
end end
def render_unprocessable_entity(message) def render_unprocessable_entity(message, type: :alert)
respond_to do |format| render_by_format(html: -> { render 'admins/shared/422' },
format.html { render 'admins/shared/422' } js: -> { render_js_error(message, type: type) },
format.js { render_js_error(message) } json: -> { render status: 422, json: { message: message } })
format.json { render status: 422, json: { message: message } }
end
end end
alias_method :render_error, :render_unprocessable_entity alias_method :render_error, :render_unprocessable_entity
def internal_server_error def internal_server_error(message = '系统错误')
respond_to do |format| @message = message
format.html { render 'admins/shared/500' } render_by_format(html: -> { render 'admins/shared/500' },
format.js { render_js_error('系统错误') } js: -> { render_js_error(message) },
format.json { render status: 500, json: { message: '系统错误' } } json: -> { render status: 500, json: { message: message } })
end
end end
def render_js_template(template, **opts) def render_js_template(template, **opts)
@ -42,7 +40,11 @@ module Admins::RenderHelper
end end
alias_method :render_success_js, :render_delete_success alias_method :render_success_js, :render_delete_success
def render_js_error(message) def render_js_error(message, type: :alert)
if type == :notify
render js: "$.notify({ message: '#{message}' },{ type: 'danger', delay: 5000 });"
else
render_js_template 'admins/shared/error', locals: { message: message } render_js_template 'admins/shared/error', locals: { message: message }
end end
end
end end

@ -10,7 +10,6 @@ module GitCommon
# ------------------------ # ------------------------
# 版本库目录结构 # 版本库目录结构
def repository def repository
logger.info("ssssssseeeeeeee#{params}")
begin begin
@repo_url = repo_url @repo_path @repo_url = repo_url @repo_path
@trees = GitService.file_tree(repo_path: @repo_path, path: @path) @trees = GitService.file_tree(repo_path: @repo_path, path: @path)
@ -44,4 +43,17 @@ module GitCommon
end end
end end
# 为版本库添加文件
def add_file
@path, message, content = params[:path].strip, params[:message], params[:content]
author_name, author_email = current_user.real_name, current_user.git_mail
Rails.logger.info(" good repo_name is #{@repo_path}")
@content = GitService.update_file(repo_path: @repo_path,
file_path: @path,
message: message.force_encoding('UTF-8'),
content: content.force_encoding('UTF-8'),
author_name: author_name,
author_email: author_email)
end
end end

@ -26,17 +26,19 @@ class CoursesController < ApplicationController
:base_info, :get_historical_courses, :create_group_by_importing_file, :base_info, :get_historical_courses, :create_group_by_importing_file,
:attahcment_category_list,:export_member_scores_excel, :duplicate_course, :attahcment_category_list,:export_member_scores_excel, :duplicate_course,
:switch_to_teacher, :switch_to_assistant, :switch_to_student, :exit_course, :switch_to_teacher, :switch_to_assistant, :switch_to_student, :exit_course,
:informs, :update_informs, :new_informs, :online_learning, :update_task_position, :tasks_list, :join_excellent_course] :informs, :update_informs, :online_learning, :update_task_position, :tasks_list,
:join_excellent_course, :export_couser_info, :export_member_act_score, :new_informs]
before_action :user_course_identity, except: [:join_excellent_course, :index, :create, :new, :apply_to_join_course, before_action :user_course_identity, except: [:join_excellent_course, :index, :create, :new, :apply_to_join_course,
:search_course_list, :get_historical_course_students, :mine, :search_slim, :board_list] :search_course_list, :get_historical_course_students, :mine, :search_slim, :board_list]
before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate, before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate,
:transfer_to_course_group, :delete_from_course, :transfer_to_course_group, :delete_from_course, :export_member_scores_excel,
:search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup, :add_teacher] :search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup,
:add_teacher, :export_couser_info, :export_member_act_score]
before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin, before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin,
:set_course_group, :create_group_by_importing_file, :update_informs, :new_informs, :set_course_group, :create_group_by_importing_file, :update_informs, :new_informs,
:update_task_position, :tasks_list] :update_task_position, :tasks_list]
before_action :teacher_or_admin_allowed, only: [:graduation_group_list, :create_graduation_group, :join_graduation_group, before_action :teacher_or_admin_allowed, only: [:graduation_group_list, :create_graduation_group, :join_graduation_group,
:change_course_teacher, :export_member_scores_excel, :course_group_list, :change_course_teacher, :course_group_list,
:teacher_application_review, :apply_teachers, :delete_course_teacher] :teacher_application_review, :apply_teachers, :delete_course_teacher]
before_action :validate_course_name, only: [:create, :update] before_action :validate_course_name, only: [:create, :update]
before_action :find_board, only: :board_list before_action :find_board, only: :board_list
@ -888,7 +890,7 @@ class CoursesController < ApplicationController
name = worksheet.cell(row, 1).to_s name = worksheet.cell(row, 1).to_s
if @course.course_groups.where(:name => name).blank? if @course.course_groups.where(:name => name).blank?
@course.course_groups << CourseGroup.new(:name => name) @course.course_groups << CourseGroup.new(:name => name, :position => @course.course_groups_count + 1)
group_count += 1 group_count += 1
end end
end end
@ -1081,44 +1083,74 @@ class CoursesController < ApplicationController
@courses= @courses.page(@page).per(@page_size) @courses= @courses.page(@page).per(@page_size)
end end
# 导出课堂信息
def export_couser_info
if params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
set_export_cookies
course_info_to_xlsx @course
filename_ = "#{current_user.real_name}_#{@course.name}_课堂信息_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{format_sheet_name filename_.strip}",template: "courses/export_course_info.xlsx.axlsx",
locals: {course_info: @course_info}
end
end
# 导出活跃度
def export_member_act_score
search = params[:search] ? "#{params[:search].strip}" : "" #用户名或学生学号id搜索
group_id = params[:group_id] #分班的班级id
@all_members = @course.students
@all_members = @all_members.where(course_group_id: group_id) unless group_id.blank?
unless search.blank?
@all_members = @all_members.joins(user: [:user_extension]).where('concat(users.lastname, users.firstname) like ? or user_extensions.student_id like ?',"%#{search}%","%#{search}%")
end
if @all_members.size == 0
normal_status(-1,"课堂暂时没有学生")
elsif params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
set_export_cookies
@all_members = student_act_score group_id, search
act_score_to_xlsx(@all_members)
filename_ = "#{current_user.real_name}_#{@course.name}_活跃度_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{format_sheet_name filename_.strip}",template: "courses/export_member_act_score.xlsx.axlsx",
locals: {activity_level:@user_activity_level}
end
end
# 导出学生成绩
def export_member_scores_excel def export_member_scores_excel
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@all_members = @course.students
search = params[:search] ? "#{params[:search].strip}" : "" #用户名或学生学号id搜索 search = params[:search] ? "#{params[:search].strip}" : "" #用户名或学生学号id搜索
group_id = params[:group_id] #分班的班级id group_id = params[:group_id] #分班的班级id
# if group_id && group_id != "0" && group_id != "-1" @all_members = @all_members.where(course_group_id: group_id) unless group_id.blank?
# @all_members = @course.students.course_find_by_ids("course_group_id",group_id) unless search.blank?
# elsif group_id && group_id == "0" # 未分班 @all_members = @all_members.joins(user: [:user_extension]).where('concat(users.lastname, users.firstname) like ? or user_extensions.student_id like ?',"%#{search}%","%#{search}%")
# @all_members = @course.course_members.ungroup_students end
# else
# @all_members = @course.students
# end
# if name.present?
# @all_members = @all_members.joins(user: [:user_extension]).where('concat(users.lastname, users.firstname) like ? or user_extensions.student_id like ?',"%#{name}%","%#{name}%")
# end
@all_members = student_act_score group_id, search
@c_homeworks = @course.homework_commons.homework_published.order("homework_commons.publish_time asc, homework_commons.created_at asc") if @all_members.length == 0
@c_exercises = @course.exercises.is_exercise_published.order("exercises.publish_time asc, exercises.created_at asc")
# @c_polls = @course.polls.publish_or_not.order("polls.publish_time asc, polls.created_at asc")
@c_tasks = @course.graduation_tasks.task_published.order("graduation_tasks.publish_time asc, graduation_tasks.created_at asc")
if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作")
elsif @all_members.size == 0
normal_status(-1,"课堂暂时没有学生") normal_status(-1,"课堂暂时没有学生")
elsif params[:export].present? && params[:export] elsif params[:export].present? && params[:export]
normal_status(0,"正在下载中") normal_status(0,"正在下载中")
else else
@c_homeworks = @course.homework_commons.homework_published.order("homework_commons.publish_time asc, homework_commons.created_at asc")
@c_exercises = @course.exercises.is_exercise_published.order("exercises.publish_time asc, exercises.created_at asc")
# @c_polls = @course.polls.publish_or_not.order("polls.publish_time asc, polls.created_at asc")
@c_tasks = @course.graduation_tasks.task_published.order("graduation_tasks.publish_time asc, graduation_tasks.created_at asc")
set_export_cookies set_export_cookies
member_to_xlsx(@course, @all_members, @c_homeworks, @c_exercises, @c_tasks) member_to_xlsx(@course, @all_members, @c_homeworks, @c_exercises, @c_tasks)
filename_ = "#{current_user.real_name}_#{@course.name}_全部成绩_#{Time.now.strftime('%Y%m%d_%H%M%S')}" filename_ = "#{current_user.real_name}_#{@course.name}_成绩_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{format_sheet_name filename_.strip}",template: "courses/export_member_scores_excel.xlsx.axlsx", render xlsx: "#{format_sheet_name filename_.strip}",template: "courses/export_member_scores_excel.xlsx.axlsx",
locals: {course_info:@course_info, activity_level:@user_activity_level, locals: {course_scores:@course_user_scores,shixun_works:@shixun_work_arrays,
course_scores:@course_user_scores,shixun_works:@shixun_work_arrays,
common_works:@common_work_arrays,group_works:@group_work_arrays,task_works:@task_work_arrays, common_works:@common_work_arrays,group_works:@group_work_arrays,task_works:@task_work_arrays,
exercise_works:@exercise_work_arrays} exercise_works:@exercise_work_arrays}
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception(e.message) tip_exception(e.message)
@ -1206,13 +1238,14 @@ class CoursesController < ApplicationController
tip_exception("开始时间不能为空") if params[:start_date].blank? tip_exception("开始时间不能为空") if params[:start_date].blank?
tip_exception("结束时间不能为空") if params[:end_date].blank? tip_exception("结束时间不能为空") if params[:end_date].blank?
tip_exception("结束时间必须晚于开始时间") if strf_date(params[:end_date]) <= strf_date(params[:start_date]) tip_exception("结束时间必须晚于开始时间") if strf_date(params[:end_date]) <= strf_date(params[:start_date])
tip_exception("开始时间和结束时间不能与往期开课时间重叠") if @course.nil? && @subject.max_course_end_date && strf_date(params[:start_date]) <= strf_date(@subject.max_course_end_date) tip_exception("开始时间和结束时间不能早于往期开课时间") if @course.nil? && @subject.max_course_end_date && strf_date(params[:start_date]) <= strf_date(@subject.max_course_end_date)
validate_start_end_date if @course.present? validate_start_end_date if @course.present?
tip_exception("开放课堂必须包含公告栏和在线学习模块") unless params[:course_module_types].include?("announcement") && params[:course_module_types].include?("online_learning") tip_exception("开放课堂必须包含公告栏和在线学习模块") unless params[:course_module_types].include?("announcement") && params[:course_module_types].include?("online_learning")
end end
tip_exception("课堂所属单位不能为空!") if params[:school].blank? tip_exception("课堂所属单位不能为空!") if params[:school].blank?
tip_exception("请至少添加一个课堂模块") if params[:course_module_types].blank? tip_exception("请至少添加一个课堂模块") if params[:course_module_types].blank?
@school = School.find_by!(name: params[:school].strip) @school = School.find_by(name: params[:school].strip)
tip_exception("所属单位不存在") unless @school.present?
end end
def validate_start_end_date def validate_start_end_date
@ -1291,13 +1324,7 @@ class CoursesController < ApplicationController
# end # end
def student_act_score group_id, search def student_act_score group_id, search
sql_select = %Q{SELECT cm.*,( sql_select = %Q{SELECT cm.*,
SELECT SUM(student_works.work_score)
FROM student_works,homework_commons
WHERE student_works.homework_common_id = homework_commons.id
AND homework_commons.course_id = #{@course.id}
AND student_works.user_id = cm.user_id
) AS score,
(SELECT max(student_id) FROM user_extensions WHERE user_extensions.user_id = cm.user_id) AS student_id, (SELECT max(student_id) FROM user_extensions WHERE user_extensions.user_id = cm.user_id) AS student_id,
(SELECT count(messages.id) FROM messages join boards on messages.board_id = boards.id WHERE boards.course_id = #{@course.id} (SELECT count(messages.id) FROM messages join boards on messages.board_id = boards.id WHERE boards.course_id = #{@course.id}
AND messages.author_id = cm.user_id and messages.parent_id is null) AS message_num, AND messages.author_id = cm.user_id and messages.parent_id is null) AS message_num,
@ -1318,52 +1345,25 @@ class CoursesController < ApplicationController
FROM course_members cm} FROM course_members cm}
if search.present? && group_id.present? if search.present? && group_id.present?
sql_select += %Q{ join users on cm.user_id = users.id sql_select += %Q{ join users on cm.user_id = users.id
joins user_extensions ue on ue.user_id = users.id join user_extensions ue on ue.user_id = users.id
WHERE cm.role = 4 and cm.course_id = #{@course.id} and cm.course_group_id = #{group_id} and WHERE cm.role = 4 and cm.course_id = #{@course.id} and cm.course_group_id = #{group_id} and
(concat(users.lastname, users.firstname) like '%#{search}%' or ue.student_id like '%#{search}%') ORDER BY score desc} (concat(users.lastname, users.firstname) like '%#{search}%' or ue.student_id like '%#{search}%')}
elsif search.present? elsif search.present?
sql_select += %Q{ join users on cm.user_id = users.id sql_select += %Q{ join users on cm.user_id = users.id
joins user_extensions ue on ue.user_id = users.id join user_extensions ue on ue.user_id = users.id
WHERE cm.role = 4 and WHERE cm.role = 4 and
(concat(users.lastname, users.firstname) like '%#{search}%' or ue.student_id like '%#{search}%') ORDER BY score desc} (concat(users.lastname, users.firstname) like '%#{search}%' or ue.student_id like '%#{search}%')}
elsif group_id.present? elsif group_id.present?
sql_select += %Q{ WHERE cm.role = 4 and cm.course_id = #{@course.id} and cm.course_group_id = #{group_id} ORDER BY score desc} sql_select += %Q{ WHERE cm.role = 4 and cm.course_id = #{@course.id} and cm.course_group_id = #{group_id}}
else else
sql_select += %Q{ WHERE cm.role = 4 and cm.course_id = #{@course.id} ORDER BY score desc} sql_select += %Q{ WHERE cm.role = 4 and cm.course_id = #{@course.id}}
end end
act_scores = CourseMember.find_by_sql(sql_select) act_scores = CourseMember.find_by_sql(sql_select)
act_scores act_scores
end end
def member_to_xlsx(course,all_members,homeworks,exercises,tasks) def course_info_to_xlsx course
#课堂的作业信息
shixun_homeworks = homeworks.search_homework_type(4) #全部实训作业
shixun_titles = shixun_homeworks.pluck(:name) + ["总得分"]
# 更新实训作业成绩
shixun_homeworks.includes(:homework_challenge_settings, :published_settings, :homework_commons_shixun).each do |homework|
homework.update_homework_work_score
end
shixun_homeworks = shixun_homeworks&.includes(score_student_works: :user)
common_homeworks = homeworks.search_homework_type(1) #全部普通作业
common_titles = common_homeworks.pluck(:name)+ ["总得分"]
common_homeworks = common_homeworks&.includes(score_student_works: :user)
group_homeworks = homeworks.search_homework_type(3) #全部分组作业
group_titles = group_homeworks.pluck(:name)+ ["总得分"]
group_homeworks = group_homeworks&.includes(score_student_works: :user)
task_titles = tasks.pluck(:name) + ["总得分"]
tasks = tasks&.includes(user: :user_extension, score_graduation_works: :user)
exercise_titles = exercises.pluck(:exercise_name) + ["总得分"]
exercises = exercises&.includes(user: :user_extension, score_exercise_users: :user)
total_user_score_array = [] #学生总成绩集合
#课堂信息 #课堂信息
@course_info = [] @course_info = []
course_info_title = "课堂信息概要" course_info_title = "课堂信息概要"
@ -1411,7 +1411,9 @@ class CoursesController < ApplicationController
end end
course_group_info = [course_group_info_head,course_group_info_body] course_group_info = [course_group_info_head,course_group_info_body]
@course_info += [course_info_title,course_main_info,course_group_info] @course_info += [course_info_title,course_main_info,course_group_info]
end
def act_score_to_xlsx all_members
#课堂活跃度 #课堂活跃度
@user_activity_level = [] @user_activity_level = []
course_user_level = [] course_user_level = []
@ -1426,8 +1428,6 @@ class CoursesController < ApplicationController
user_stu_id = u.student_id.present? ? (u.student_id.to_s + "\t") : "--" user_stu_id = u.student_id.present? ? (u.student_id.to_s + "\t") : "--"
user_school = user.school_name user_school = user.school_name
user_course_group = u.course_group_name user_course_group = u.course_group_name
user_info_array = [user_login,user_name,user_mail,user_stu_id,user_school,user_course_group] #用户的信息集合
user_work_scores = []
#课堂活跃度统计 #课堂活跃度统计
user_homeworks_num = u.homework_num.to_i #完成的作业数 user_homeworks_num = u.homework_num.to_i #完成的作业数
@ -1463,6 +1463,52 @@ class CoursesController < ApplicationController
} }
course_user_level.push(user_ac_level) course_user_level.push(user_ac_level)
#.课堂活跃度统计的集合
course_user_level = course_user_level.sort_by {|k| k[:u_13]}.reverse
@user_activity_level = [course_activity_title,user_cell_head,course_user_level]
end
end
def member_to_xlsx(course,all_members,homeworks,exercises,tasks)
#课堂的作业信息
shixun_homeworks = homeworks.search_homework_type(4) #全部实训作业
shixun_titles = shixun_homeworks.pluck(:name) + ["总得分"]
# 更新实训作业成绩
shixun_homeworks.includes(:homework_challenge_settings, :published_settings, :homework_commons_shixun).each do |homework|
homework.update_homework_work_score
end
shixun_homeworks = shixun_homeworks&.includes(score_student_works: :user)
common_homeworks = homeworks.search_homework_type(1) #全部普通作业
common_titles = common_homeworks.pluck(:name)+ ["总得分"]
common_homeworks = common_homeworks&.includes(score_student_works: :user)
group_homeworks = homeworks.search_homework_type(3) #全部分组作业
group_titles = group_homeworks.pluck(:name)+ ["总得分"]
group_homeworks = group_homeworks&.includes(score_student_works: :user)
task_titles = tasks.pluck(:name) + ["总得分"]
tasks = tasks&.includes(user: :user_extension, score_graduation_works: :user)
exercise_titles = exercises.pluck(:exercise_name) + ["总得分"]
exercises = exercises&.includes(user: :user_extension, score_exercise_users: :user)
total_user_score_array = [] #学生总成绩集合
all_members.each do |u|
#用户的基本信息
user = u.user
user_login = user.login
user_name = user.real_name
user_mail = user.mail
user_stu_id = user.student_id.present? ? (user.student_id.to_s + "\t") : "--"
user_school = user.school_name
user_course_group = u.course_group_name
user_info_array = [user_name,user_login,user_mail,user_stu_id,user_school,user_course_group] #用户的信息集合
user_work_scores = []
#学生总成绩 #学生总成绩
shixun_score = 0.0 # 实训作业的总分 shixun_score = 0.0 # 实训作业的总分
common_score = 0.0 #普通作业的总分 common_score = 0.0 #普通作业的总分
@ -1560,10 +1606,6 @@ class CoursesController < ApplicationController
total_user_score_array.push(user_work_scores) # 全部成员的集合 total_user_score_array.push(user_work_scores) # 全部成员的集合
end end
#1.课堂活跃度统计的集合
course_user_level = course_user_level.sort_by {|k| k[:u_12]}.reverse
@user_activity_level = [course_activity_title,user_cell_head,course_user_level]
#2.学生总成绩的集合 #2.学生总成绩的集合
## 作业标题的集合 ## 作业标题的集合
course_user_score_title = "学生总成绩" course_user_score_title = "学生总成绩"

@ -0,0 +1,418 @@
class ExerciseBankQuestionsController < ApplicationController
before_action :require_login, :check_auth #用户需登陆
before_action :get_exercise, only:[:create] #获取试卷
before_action :get_exercise_question, except: [:create] #获取试卷的问题及试卷
before_action :bank_admin #是否为老师
before_action :validate_params, only: [:create, :update] #传入参数的验证
def create
ActiveRecord::Base.transaction do
begin
question_options = {
:question_title => params[:question_title],
:question_type => params[:question_type].present? ? params[:question_type].to_i : 0, #默认为单选题
:question_number => @exercise.exercise_bank_questions.count + 1,
:question_score => params[:question_score].present? ? params[:question_score].to_f.round(1) : 5.0,
:shixun_id => params[:shixun_id].blank? ? "" : params[:shixun_id],
:is_ordered => params[:is_ordered] # 填空题的答案是否为一一对应关系,默认为true即为一一对应
}
@exercise_question = @exercise.exercise_bank_questions.new(question_options)
#插入问题时那么从插入的这个id以后的question_num都将要+1
if params[:insert_id].present?
insert_exercise = @exercise.exercise_bank_questions.find_by(id: params[:insert_id])
if insert_exercise.present? #如果该问题存在的话,意思是如果是第一题,那么就不存在插入
ques_num = insert_exercise.question_number.to_i
@exercise_question.question_number = ques_num + 1 #更新了问题的位置
@exercise.exercise_bank_questions.insert_question_ex(ques_num).update_all("question_number = question_number + 1")
end
end
if @exercise_question.save
#为选择题(包括单选和多选)的时候,创建问题选项
ques_type = @exercise_question.question_type
if ques_type <= Exercise::MULTIPLE
choices_array = params[:question_choices]
choices_count= choices_array.count
standard_answer = params[:standard_answers] #为数组格式,因为可能会有单选和多选,标准答案,已提前判断不能为空,
standard_answer = standard_answer.uniq.reject(&:blank?)
(1..choices_count).each do |c|
choice = choices_array[c-1] #每一个选项的内容
choice_option = {
:choice_position => c,
:choice_text => choice.strip
}
question_choices = @exercise_question.exercise_bank_choices.new(choice_option)
question_choices.save
end
#标准答案的存储,如:["1","2","3"..]等1对应A2对应B3对应C。。。
standard_answer.each do |a|
choice_id = a.to_i
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:exercise_bank_choice_id => choice_id #即为选择的位置参数
}
question_standard_answer = ExerciseBankStandardAnswer.new(standard_option)
question_standard_answer.save
if standard_answer.count > 1 && ques_type == Exercise::SINGLE #当标准答案数大于1且不为多选时修改为多选
@exercise_question.update_attribute("question_type",Exercise::MULTIPLE)
elsif standard_answer.count == 1 && ques_type == Exercise::MULTIPLE
@exercise_question.update_attribute("question_type",Exercise::SINGLE)
end
end
elsif ques_type == Exercise::JUDGMENT #这个为判断题
choices_array = params[:question_choices] #判断的选项,对/错等等
choices_count= choices_array.count
(1..choices_count).each do |c|
choice = choices_array[c-1] #每一个选项的内容
choice_option = {
:choice_position => c,
:choice_text => choice.strip
}
question_choices = @exercise_question.exercise_bank_choices.create(choice_option)
question_choices.save
end
standard_answer = params[:standard_answers] #对应选项的id
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:exercise_bank_choice_id => standard_answer.first.to_i
}
question_standard_answer = ExerciseBankStandardAnswer.new(standard_option)
question_standard_answer.save
elsif ques_type == Exercise::COMPLETION #填空题,每空的参考答案有多个,那么以位置对应
standard_answer = params[:standard_answers]
standard_answer.each do |a|
null_choice_id = a[:choice_id]
null_choice_text = a[:answer_text]
null_choice_text.each do |n|
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:exercise_bank_choice_id => null_choice_id,
:answer_text => n
}
question_standard_answer = ExerciseBankStandardAnswer.new(standard_option)
question_standard_answer.save
end
end
elsif ques_type == Exercise::SUBJECTIVE #简答题
if params[:standard_answers].present? && params[:standard_answers].reject(&:blank?).count > 0
standard_answer = params[:standard_answers]
standard_answer.each do |a|
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:answer_text => a,
}
question_standard_answer = ExerciseBankStandardAnswer.new(standard_option)
question_standard_answer.save
end
end
elsif ques_type == Exercise::PRACTICAL #实训题
shixun = Shixun.find_by(id: params[:shixun_id])
shixun_scores = params[:question_scores] #试卷有多个的分值有多个分数表,所以为分数的数组
shixun_name = params[:shixun_name] || shixun.name
question_score = 0
shixun.challenges.try(:each_with_index) do |challenge,index|
shixun_option = {
:challenge_id => challenge.id,
:shixun_id => shixun.id,
:exercise_bank_question_id => @exercise_question.id,
:position => (index + 1),
:question_score => shixun_scores[index].present? ? shixun_scores[index].to_f.round(1) : 5
}
ex_shixun_challenge = ExerciseBankShixunChallenge.create(shixun_option)
question_score += ex_shixun_challenge.question_score # 问题的分数,为各个关卡分数的总和
end
@exercise_question.update_attributes(:question_score => question_score, :shixun_name=> shixun_name)
end
end
normal_status("创建成功")
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def update
ActiveRecord::Base.transaction do
begin
# 更新试卷题目的内容
question_options = {
:question_title => params[:question_title],
:is_ordered => params[:is_ordered], # 填空题的答案是否为一一对应关系,默认为true即为一一对应
:question_score => params[:question_score].present? ? params[:question_score].to_f.round(1) : 5.0 #不可修改分数
}
choices_array = params[:question_choices]
stan_answer_params = params[:standard_answers]
standard_answer = stan_answer_params.present? ? stan_answer_params.uniq.reject(&:blank?) : []
@exercise_question.update_attributes(question_options)
#当选项存在时,可修改选项内容,但是不能更改选项的位置(即不能增删选项)
if choices_array.present?
ex_choices = @exercise_question.exercise_bank_choices
ex_choice_count = ex_choices.count
choice_array_count = choices_array.count
ex_choice_count_array = (1..ex_choice_count).to_a
choice_array_count_array = (1..choice_array_count).to_a
if ex_choice_count > choice_array_count #如果选项有减少的,那么只更新传入的,删除以前的
choice_array_count_array.each do |c|
choice = choices_array[c-1] #每一个选项的内容
exercise_choice = @exercise_question.exercise_bank_choices.find_choice_custom("choice_position",(c))
exercise_choice.update(choice_text:choice)
end
drop_ex_choice = @exercise_question.exercise_bank_choices.left_choice_choose("choice_position",(choice_array_count))
drop_ex_choice.destroy_all
else
ex_choice_count_array.each do |c|
choice = choices_array[c-1] #每一个选项的内容
exercise_choice = @exercise_question.exercise_bank_choices.find_choice_custom("choice_position",(c))
exercise_choice.update(choice_text:choice)
end
new_add_choice = choice_array_count_array - ex_choice_count_array #新传入的需新增
if new_add_choice.count > 0
new_add_choice.each do |i|
choice_option = {
:choice_position => i,
:choice_text => choices_array[i-1].strip
}
question_choices = @exercise_question.exercise_bank_choices.new(choice_option)
question_choices.save
end
end
end
end
#试卷未发布时,当标准答案存在时,可修改标准答案内容,可增删标准答案,否则只能修改标准答案,不能增删标准答案
@exercise_answers_array = @exercise_question.exercise_bank_standard_answers #问卷的全部标准答案
if standard_answer.present?
if @exercise_question.question_type <= Exercise::JUDGMENT #选择题/判断题,标准答案为一个或多个
exercise_standard_choices = @exercise_answers_array.pluck(:exercise_bank_choice_id) #问题以前的全部标准答案选项位置
if exercise_standard_choices.sort != standard_answer.sort #表示答案有更改的
common_standard_choices = standard_answer & exercise_standard_choices # 传入的标准答案的选项位置和以前的并集,即表示不用做更改的
old_left_standard_choices = exercise_standard_choices - common_standard_choices # 以前的差集共同的,剩余的表示需要删掉
new_left_standard_choices = standard_answer - common_standard_choices # 传入的标准答案差集共同的,剩余的表示需要新建
if old_left_standard_choices.count > 0
@exercise_answers_array.standard_by_ids(old_left_standard_choices).destroy_all
end
if new_left_standard_choices.count > 0 #新建标准答案
new_left_standard_choices.each do |s|
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:exercise_bank_choice_id => s.to_i #即为选择的位置参数
}
question_standard_answer = ExerciseBankStandardAnswer.new(standard_option)
question_standard_answer.save
end
end
if standard_answer.count > 1 && @exercise_question.question_type == Exercise::SINGLE #当标准答案数大于1且不为多选时修改为多选
@exercise_question.update_attribute("question_type",Exercise::MULTIPLE)
elsif standard_answer.count == 1 && @exercise_question.question_type == Exercise::MULTIPLE
@exercise_question.update_attribute("question_type",Exercise::SINGLE)
end
end
elsif @exercise_question.question_type == Exercise::COMPLETION #填空题
old_ex_answer = @exercise_question.exercise_bank_standard_answers #当前问题的全部标准答案
old_ex_answer_choice_texts = old_ex_answer.pluck(:answer_text).uniq.sort
new_ex_answer_choice_texts = standard_answer.pluck(:answer_text).sum.uniq.sort
if old_ex_answer_choice_texts != new_ex_answer_choice_texts #填空题标准答案有更改时,才会更新标准答案
new_ex_answer_choice_ids = standard_answer.map {|a| a[:choice_id]}.uniq #新传入的答案数组序号
old_ex_answer_choice_ids = old_ex_answer.pluck(:exercise_bank_choice_id).uniq #全部的答案数组序号
#删除多余的选项
if old_ex_answer_choice_ids.count > new_ex_answer_choice_ids.count #有减少的填空
delete_ex_answer_choice_ids = old_ex_answer_choice_ids - new_ex_answer_choice_ids
old_ex_answer.standard_by_ids(delete_ex_answer_choice_ids).destroy_all
end
standard_answer.each do |aa|
null_choice_id = aa[:choice_id]
null_choice_text = aa[:answer_text]
null_choice_text_count = null_choice_text.count #当前传入的答案数量
null_choice_text_count_array = (1..null_choice_text_count).to_a
ex_answer_pre = old_ex_answer.standard_by_ids(null_choice_id) #当前问题的全部答案
ex_answer_pre_count = ex_answer_pre.count
ex_answer_pre_count_array = (1..ex_answer_pre_count).to_a
if old_ex_answer_choice_ids.include?(null_choice_id) #以前的填空题答案包含有现在的填空序号
if null_choice_text_count >= ex_answer_pre_count
new_add_choice = null_choice_text_count_array - ex_answer_pre_count_array
ex_answer_pre_count_array.each do |n|
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:exercise_bank_choice_id => null_choice_id,
:answer_text => null_choice_text[n-1]
}
ex_answer_pre[n-1].update(standard_option)
end
if new_add_choice.count > 0 #表示有新增的
new_add_choice.each do |i|
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:exercise_bank_choice_id => null_choice_id,
:answer_text => null_choice_text[i-1]
}
question_standard_answer = ExerciseBankStandardAnswer.new(standard_option)
question_standard_answer.save
end
end
else
new_delete_choice = ex_answer_pre_count_array - null_choice_text_count_array
null_choice_text.each_with_index do |n,index|
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:exercise_bank_choice_id => null_choice_id,
:answer_text => n
}
ex_answer_pre[index].update(standard_option)
end
if new_delete_choice.count > 0 #表示填空题的答案有删减的
new_delete_choice.each do |d|
ex_answer_pre[d-1].destroy
end
end
end
else
null_choice_text.each do |n|
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:exercise_bank_choice_id => null_choice_id,
:answer_text => n
}
question_standard_answer = ExerciseBankStandardAnswer.new(standard_option)
question_standard_answer.save
end
end
end
end
end
end
if @exercise_question.question_type == Exercise::SUBJECTIVE #主观题
main_standard_answer = standard_answer.present? ? standard_answer.first : nil
if @exercise_answers_array.present?
@exercise_answers_array.first.update_attribute("answer_text",main_standard_answer)
else
standard_option = {
:exercise_bank_question_id => @exercise_question.id,
:answer_text => main_standard_answer,
}
question_standard_answer = ExerciseBankStandardAnswer.new(standard_option)
question_standard_answer.save
end
elsif @exercise_question.question_type == Exercise::PRACTICAL
question_score = 0
shixun_name = params[:shixun_name] || @exercise_question.shixun_name
@exercise_question.exercise_bank_shixun_challenges.each_with_index do |challenge, index|
challenge.question_score = params[:question_scores][index].to_f.round(1)
challenge.save
question_score += params[:question_scores][index].to_f.round(1)
end
@exercise_question.question_score = question_score
@exercise_question.shixun_name = shixun_name
@exercise_question.save
end
normal_status(0,"试卷更新成功")
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def up_down
ActiveRecord::Base.transaction do
begin
opr = params[:opr]
current_q_p = @exercise_question.question_number.to_i #问题的当前位置
if opr.present?
if opr.to_s == "up"
last_q_p = @exercise.exercise_bank_questions.find_by(question_number: (current_q_p - 1)) # 当前问题的前一个问题
if last_q_p.present?
@exercise_question.update_attribute('question_number', (current_q_p - 1))
last_q_p.update_attribute('question_number', current_q_p) # 重新获取当前问题的位置
normal_status(0, "问题上移成功!")
else
normal_status(-1, "移动失败,已经是第一个问题了!")
end
elsif opr.to_s == "down"
next_q_p = @exercise.exercise_bank_questions.find_by(question_number: (current_q_p + 1)) # 当前问题的前一个问题
if next_q_p.present?
@exercise_question.update_attribute('question_number', (current_q_p + 1))
next_q_p.update_attribute('question_number', current_q_p)
normal_status(0, "问题下移成功!")
else
normal_status(-1, "移动失败,已经是最后一个问题了!")
end
end
else
normal_status(-1, "移动失败,请输入参数")
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
end
end
#试卷问题的删除
def destroy
ActiveRecord::Base.transaction do
begin
question_d_id = @exercise_question.question_number.to_i #问题的当前位置
exercise_questions = @exercise.exercise_bank_questions
left_questions = exercise_questions.where("question_number > ?", question_d_id)
left_questions.update_all("question_number = question_number - 1") if left_questions
@exercise_question.destroy
normal_status(0, "删除成功")
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
end
end
private
def bank_admin
tip_exception(403, "无权限") unless @exercise.user_id == current_user.id || current_user.admin?
end
def get_exercise
@exercise = ExerciseBank.find_by!(id:params[:exercise_bank_id])
end
def get_exercise_question
@exercise_question = ExerciseBankQuestion.find_by!(id: params[:id])
@exercise = @exercise_question.exercise_bank
end
def validate_params
normal_status(-1,"题目不允许为空!") if (params[:question_title].blank? && params[:question_type].to_i != Exercise::PRACTICAL ) #除了实训题,其余题目必需有题干
normal_status(-1,"问题类型不允许为空!" ) if params[:question_type].blank?
normal_status(-1,"分值不允许为空!" ) if params[:question_score].blank? && params[:question_scores].blank? #分值的数组或参数必需存在一个
if params[:question_score].present? && params[:question_score].to_f <= 0.0 #问题类型存在,则分值不能为空,且必需大于0
normal_status(-1,"分值必需大于0")
elsif (params[:question_score].present? && params[:question_score].to_f.round(1) > 100.0) || (params[:question_scores].present? && (params[:question_scores].map{|a| a.to_f.round(1)}.max > 100.0))
normal_status(-1,"分值不能超过100分")
elsif params[:question_scores].present? && params[:question_scores].include?(0.0) #如果有负数,则自动取绝对值,#多个分数值,针对实训题的
normal_status(-1,"分值必需大于0")
elsif params[:standard_answers].present? && params[:question_choices].present? && (params[:standard_answers].count > params[:question_choices].count)
normal_status(-1,"标准答案数不能大于选项数!")
elsif [0,1,2,3].include?(params[:question_type].to_i) && (params[:standard_answers].blank? || params[:standard_answers].include?("")) #选择题/判断题/填空题 问题选项/标准答案不能为空,也不能包含空的内容
normal_status(-1,"标准答案不能为空!")
elsif params[:question_type].to_i == 2 && (params[:standard_answers].count > 1 || params[:question_choices].blank? || params[:question_choices].include?("")) #判断题的标准答案不能大于1个选项不能为空
normal_status(-1,"判断题选项不能为空/标准答案不能大于1个")
elsif params[:question_type].to_i <= 1 && (params[:question_choices].blank? || params[:question_choices].include?("") || params[:question_choices].count < 2) #选择题选项不能为空,且不能小于2
normal_status(-1,"选择题选项内容不能为空且不能少于2个")
elsif params[:question_type].to_i == 3 && (params[:standard_answers].blank? || params[:standard_answers].count > 5 ) #填空题选项最多为5个,且如果为1个的话不允许修改is_ordered
normal_status(-1,"填空题标准答案不能为空/不能超过5个")
elsif params[:question_type].to_i == 4 && params[:standard_answers].count > 2 #简单题参考答案最多为1个
normal_status(-1,"简答题的参考答案不能大于2个")
elsif params[:question_type].to_i == 5
if params[:shixun_id].blank? #实训题的id不能为空
normal_status(-1,"实训题id不能为空")
elsif params[:shixun_name].blank?
normal_status(-1,"实训题名称不能为空!")
end
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

@ -255,8 +255,8 @@ class ExerciseQuestionsController < ApplicationController
end end
elsif @exercise_question.question_type == Exercise::COMPLETION #填空题 elsif @exercise_question.question_type == Exercise::COMPLETION #填空题
old_ex_answer = @exercise_question.exercise_standard_answers #当前问题的全部标准答案 old_ex_answer = @exercise_question.exercise_standard_answers #当前问题的全部标准答案
old_ex_answer_choice_texts = old_ex_answer.pluck(:answer_text).uniq.sort old_ex_answer_choice_texts = old_ex_answer.pluck(:answer_text).sort
new_ex_answer_choice_texts = standard_answer.pluck(:answer_text).sum.uniq.sort new_ex_answer_choice_texts = standard_answer.pluck(:answer_text).sum.sort
if old_ex_answer_choice_texts != new_ex_answer_choice_texts #填空题标准答案有更改时,才会更新标准答案 if old_ex_answer_choice_texts != new_ex_answer_choice_texts #填空题标准答案有更改时,才会更新标准答案
new_ex_answer_choice_ids = standard_answer.map {|a| a[:choice_id]}.uniq #新传入的答案数组序号 new_ex_answer_choice_ids = standard_answer.map {|a| a[:choice_id]}.uniq #新传入的答案数组序号
old_ex_answer_choice_ids = old_ex_answer.pluck(:exercise_choice_id).uniq #全部的答案数组序号 old_ex_answer_choice_ids = old_ex_answer.pluck(:exercise_choice_id).uniq #全部的答案数组序号
@ -280,11 +280,12 @@ class ExerciseQuestionsController < ApplicationController
if null_choice_text_count >= ex_answer_pre_count if null_choice_text_count >= ex_answer_pre_count
new_add_choice = null_choice_text_count_array - ex_answer_pre_count_array new_add_choice = null_choice_text_count_array - ex_answer_pre_count_array
ex_answer_pre_count_array.each do |n| ex_answer_pre_count_array.each do |n|
standard_option = { @hash_symbol_null_ = {
:exercise_question_id => @exercise_question.id, :exercise_question_id => @exercise_question.id,
:exercise_choice_id => null_choice_id, :exercise_choice_id => null_choice_id,
:answer_text => null_choice_text[n-1] :answer_text => null_choice_text[n - 1]
} }
standard_option = @hash_symbol_null_
ex_answer_pre[n-1].update(standard_option) ex_answer_pre[n-1].update(standard_option)
end end
if new_add_choice.count > 0 #表示有新增的 if new_add_choice.count > 0 #表示有新增的
@ -680,8 +681,9 @@ class ExerciseQuestionsController < ApplicationController
normal_status(-1,"已发布/已截止,不允许增删答案!") normal_status(-1,"已发布/已截止,不允许增删答案!")
elsif standard_answer.present? elsif standard_answer.present?
if @exercise_question.question_type == Exercise::COMPLETION if @exercise_question.question_type == Exercise::COMPLETION
exercise_answers_text = standard_answer.map{|a| a[:answer_text]}.sum.uniq # exercise_answers_text = standard_answer.map{|a| a[:answer_text]}.sum.uniq
unless (standard_answer.count == exercise_choice_ids.count) && (standard_answers_text.count == exercise_answers_text.count) # unless (standard_answer.count == exercise_choice_ids.count) && (standard_answers_text.count == exercise_answers_text.count)
unless standard_answer.count == exercise_choice_ids.count
normal_status(-1,"已发布/已截止,不允许增删标准答案!") normal_status(-1,"已发布/已截止,不允许增删标准答案!")
end end
elsif @exercise_question.question_type == Exercise::SUBJECTIVE elsif @exercise_question.question_type == Exercise::SUBJECTIVE

@ -171,17 +171,18 @@ class FilesController < ApplicationController
begin begin
attachment_ids.each do |attachment_id| attachment_ids.each do |attachment_id|
ori = Attachment.find_by_id(attachment_id) ori = Attachment.find_by_id(attachment_id)
@course.attachments.each do |att| # 同一个资源可以多次发送到课堂
@exist = false # @course.attachments.each do |att|
if att.id == ori.id || (!att.copy_from.nil? && !ori.copy_from.nil? && att.copy_from == ori.copy_from) || att.copy_from == ori.id || att.id == ori.copy_from # @exist = false
att.created_on = Time.now # if att.id == ori.id || (!att.copy_from.nil? && !ori.copy_from.nil? && att.copy_from == ori.copy_from) || att.copy_from == ori.id || att.id == ori.copy_from
att.save # att.created_on = Time.now
@exist = true # att.save
break # @exist = true
end # break
end # end
# end
next if @exist #
# next if @exist
attach_copied_obj = ori.copy attach_copied_obj = ori.copy
attach_copied_obj.container = @course attach_copied_obj.container = @course
attach_copied_obj.created_on = Time.now attach_copied_obj.created_on = Time.now

@ -392,59 +392,6 @@ class GamesController < ApplicationController
end end
end end
# # 文件更新;数据评测记录
# # 生成重新评测认证码
# # content_modified:0 表示文件没有更新content_modified:1 表示文件有更新
# def file_update
# path = params[:path].strip unless params[:path].blank?
# myshixun = @game.myshixun
# rev = params[:rev] ? params[:rev] : "master"
# @content_modified = 0
# # params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
# # 自动保存的时候evaluate为0点评测的时候为1
# if params[:evaluate] == 1
# record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => myshixun.shixun_id, :game_id => @game.id)
# uid_logger("-- game is #{@game.id}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
# student_work_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f
# record.update_attributes!(:student_work => student_work_time)
# end
# # 远程版本库文件内容
# last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
# last_content = tran_base64_decode64(last_content)
#
# content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && params[:content].present?
# params[:content].gsub(/\t/, ' ')
# else
# params[:content]
# end
# if content != last_content
# @content_modified = 1
# code_file = @g.edit_file(myshixun.gpid, current_user.login, :content => content, :file_path => path,
# :branch_name => rev, :commit_message => params[:evaluate] == 0 ? "auto commit" : "task commit")
# uid_logger("-- file update #{code_file}")
# # REDO更新失败的处理
# raise("文件更新失败") unless code_file
# end
#
# if record.present?
# consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f
# record.update_attributes!(:file_update => consume_time)
# end
#
# # status为2说明是重新评测
# if @game.status == 2
# code = CODES.sample(8).join
# @resubmit = "#{code}_#{@myshixun.id}"
# end
#
# if content != last_content && code_file.blank?
# raise("实训平台繁忙繁忙等级81请稍后刷新并重试")
# end
# rescue Exception => e
# uid_logger("-- file update failed #{e.message}")
# raise Educoder::TipException.new("#{e.message}")
# end
# 恢复初始代码 # 恢复初始代码
# 注意path为当前打开文件的path # 注意path为当前打开文件的path
def reset_original_code def reset_original_code

@ -274,7 +274,7 @@ class GraduationWorksController < ApplicationController
@is_author = @work.user_id == current_user.id @is_author = @work.user_id == current_user.id
@work_members = @task.task_type == 1 ? [] : @task.graduation_works.where.not(user_id: @work.user_id). @work_members = @task.task_type == 1 ? [] : @task.graduation_works.where.not(user_id: @work.user_id).
where(group_id: @work.group_id).includes(:user) where(group_id: @work.group_id).includes(:user)
@attachments = @work.attachments.where.not(attachtype: 7) @attachments = @work.attachments.where("attachtype != 7 or attachtype is null")
end end
def comment_list def comment_list

@ -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,158 @@
class PollBankQuestionsController < ApplicationController
before_action :require_login, :check_auth #用户需登陆
before_action :get_poll, only:[:create] #获取试卷
before_action :get_poll_question, except: [:create] #获取试卷的问题及试卷
before_action :bank_admin #是否为老师
before_action :validates_params, only: [:create, :update] #传入参数的验证
def create
ActiveRecord::Base.transaction do
begin
poll_options = {
:question_title => params[:question_title],
:question_type => params[:question_type],
:is_necessary => params[:is_necessary].to_i,
:question_number => @poll.exercise_bank_questions.count + 1,
:max_choices => params[:max_choices] || nil,
:min_choices => params[:min_choices] || nil
}
@poll_question = @poll.exercise_bank_questions.new(poll_options)
if params[:insert_id].present? #插入问题时那么从插入的这个id以后的question_num都将要+1
insert_poll = @poll.exercise_bank_questions.find_by(id: params[:insert_id])
if insert_poll.present? #如果该问题存在的话,意思是如果是第一题,那么就不存在插入
ques_num = insert_poll.question_number.to_i
@poll_question.question_number = ques_num + 1 #更新了问题的位置
@poll.exercise_bank_questions.insert_question_ex(ques_num).update_all("question_number = question_number + 1")
end
end
if @poll_question.save!
if params[:question_type] != 3
p_answer = params[:question_answers]
p_other_answer = params[:question_other_answer]
# 新增选择题答案选择的选项
(1..p_answer.count).each do |i|
answer = p_answer[i-1] # 传入的答案的内容
question_option = {
:choice_position => i,
:choice_text => answer
}
poll_answers = @poll_question.exercise_bank_choices.new question_option
poll_answers.save
end
# 新增答案的其他选项
if p_other_answer
question_option = {
:choice_position => p_answer.count + 1,
:choice_text => ''
}
poll_answers = @poll_question.exercise_bank_choices.new question_option
poll_answers.save
end
end
end
normal_status("创建成功")
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def update
ActiveRecord::Base.transaction do
begin
if @poll_question.question_type < 3 #当为单选题或多选题时
p_answer = params[:question_answers]
p_other_answer = params[:question_other_answer]
p_answer_count = p_answer.count
@poll_current_answers = @poll_question.exercise_bank_choices.count
@poll_question.exercise_bank_choices.each do |an|
if (p_answer_count < @poll_current_answers) && (p_answer_count..@poll_current_answers).to_a.include?(an.choice_position)
an.destroy
end
end
(1..p_answer_count).each do |i|
answer = @poll_question.exercise_bank_choices.find_choice_custom("choice_position",i).first
if answer # 判断该位置的answer是否存在存在则更新.不存在则跳到下一步
answer.choice_text = p_answer[i-1]
answer.choice_position = i
answer.save
else
answer_options = {
:choice_position => i,
:choice_text => p_answer[i-1]
}
@poll_question.exercise_bank_choices.new answer_options
end
end
if p_other_answer #判断答案的其他选项是否存在
other_answer = @poll_question.exercise_bank_choices.find_choice_custom("choice_text","").first
if other_answer.blank?
question_option = {
:choice_position => p_answer_count + 1,
:choice_text => ''
}
@poll_question.exercise_bank_choices.new question_option
else
other_answer.choice_position = p_answer_count + 1
other_answer.save
end
end
end
@poll_question.update_attributes(poll_questions_params)
normal_status("问卷更新成功")
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
private
def bank_admin
tip_exception(403, "无权限") unless @poll.user_id == current_user.id || current_user.admin?
end
def get_poll
@poll = ExerciseBank.find_by!(id: params[:exercise_bank_id])
end
def get_poll_question
@poll_question = ExerciseBankQuestion.find_by!(id: params[:id])
@poll = @poll_question.exercise_bank
end
def poll_questions_params
params.permit(:question_title,:question_type,:is_necessary,:question_number,:max_choices,:min_choices)
end
def validates_params
tip_exception(-1, "问题标题不能为空!") if params[:question_title].blank?
tip_exception(-1, "是否要求必答的值不能为空!") if params[:is_necessary].blank?
tip_exception(-1, "问题类型不能为空!") if params[:question_type].blank?
if params[:min_choices].present? && params[:max_choices].present? && (params[:min_choices].to_i > params[:max_choices].to_i)
tip_exception(-1, "最小可选不能大于最大可选!")
elsif params[:question_answers].present? && (params[:max_choices].to_i > params[:question_answers].count)
tip_exception(-1, "选择题的最大可选项不能大于答案数!")
elsif [1,3].include?(params[:question_type]) && (params[:max_choices].to_i > 0 || params[:min_choices].to_i > 0)
tip_exception(-1, "单选题或主观题不能有最大或最小选择数!")
elsif params[:question_type] == 3 && (params[:question_answers] || params[:question_other_answer])
tip_exception(-1, "主观问题不需要可选答案!")
elsif params[:question_type] != 3
if params[:question_answers].present? && params[:question_answers].include?("")
tip_exception(-1, "选择题不能有空值!")
elsif params[:question_other_answer].present? && params[:question_other_answer].length > 0
tip_exception(-1, "其他选项不能有值!")
elsif params[:question_type] == 1 && params[:question_answers].count < 2
tip_exception(-1, "单选题选项不能小于2")
elsif params[:question_type] == 2 && params[:question_answers].count < 3
tip_exception(-1, "多选题选项不能小于3")
end
end
end
end

@ -901,9 +901,9 @@ class PollsController < ApplicationController
error_question = [] error_question = []
@poll_multi_questions.each do |q| @poll_multi_questions.each do |q|
poll_user_votes = current_user.poll_votes.where(poll_question_id:q.id)&.size poll_user_votes = current_user.poll_votes.where(poll_question_id:q.id)&.size
if q.max_choices.present? && (poll_user_votes > q.max_choices) if q.max_choices.present? && (q.max_choices > 0) && (poll_user_votes > q.max_choices)
error_messages = "#{q.question_number}题:超过最大选项限制" error_messages = "#{q.question_number}题:超过最大选项限制"
elsif q.min_choices.present? && (poll_user_votes < q.min_choices) elsif q.min_choices.present? && (q.min_choices > 0)&& (poll_user_votes < q.min_choices)
error_messages = "#{q.question_number}题:不得少于最小选项限制" error_messages = "#{q.question_number}题:不得少于最小选项限制"
else else
error_messages = nil error_messages = nil
@ -936,7 +936,7 @@ class PollsController < ApplicationController
def commit_result def commit_result
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@poll_users = @poll.all_poll_users(current_user.id) @poll_users = @poll.all_poll_users(current_user.id).where(commit_status:1) # 问卷已提交的用户
@poll_commit_ids = @poll_users.commit_by_status(1).pluck(:user_id) #问卷提交用户的id @poll_commit_ids = @poll_users.commit_by_status(1).pluck(:user_id) #问卷提交用户的id
@page = params[:page] || 1 @page = params[:page] || 1
@limit = params[:limit] || 10 @limit = params[:limit] || 10

@ -1,6 +1,7 @@
class QuestionBanksController < ApplicationController class QuestionBanksController < ApplicationController
before_action :require_login, :check_auth before_action :require_login, :check_auth
before_action :params_filter before_action :params_filter, except: [:my_courses]
# before_action :teacher_or_admin, except: [:bank_list]
# 题库选用列表 # 题库选用列表
# object_type: # normal 普通作业题库; group 分组作业题库; poll问卷题库 exercise试卷题库; gtask 毕设选题题库gtopic 毕设任务 # object_type: # normal 普通作业题库; group 分组作业题库; poll问卷题库 exercise试卷题库; gtask 毕设选题题库gtopic 毕设任务
@ -79,10 +80,39 @@ class QuestionBanksController < ApplicationController
end end
end end
def my_courses
@courses = current_user.manage_courses.where(is_delete: 0, is_end: 0)
unless params[:search].blank?
@courses = @courses.where("name like ?", "%#{params[:search].strip}%")
end
end
def send_to_course
banks = object_banks
course = current_user.manage_courses.find_by!(id: params[:course_id])
banks.each do |bank|
case @object_type
when 'HomeworkBank' # 作业
quote_homework_bank bank, course
when 'ExerciseBank'
if bank.container_type == 'Exercise' # 试卷
quote_exercise_bank bank, course
else # 问卷
quote_poll_bank bank, course
end
when 'GtaskBank'
quote_gtask_bank bank, course
when 'GtopicBank'
quote_gtopic_bank bank, course
end
end
normal_status("发送成功")
end
def destroy def destroy
bank = current_bank bank = current_bank
unless user.admin? || bank.user_id == user.id unless current_user.admin? || bank.user_id == current_user.id
render_forbidden render_forbidden
return return
end end
@ -97,11 +127,32 @@ class QuestionBanksController < ApplicationController
render_ok render_ok
end end
def multi_delete
@objects = object_banks
@objects.destroy_all
normal_status("删除成功")
end
def multi_public
@objects = object_banks
@objects.update_all(is_public: true)
normal_status("更新成功")
end
private private
def object_banks
banks ||= @object_type.classify.constantize.where(@object_filter).where(id: params[:object_id])
unless current_user.admin?
banks = banks.where(user_id: current_user.id)
end
banks
end
def current_bank def current_bank
@_current_bank ||= @object_type.classify.constantize.where(@object_filter).find(params[:id]) @_current_bank ||= @object_type.classify.constantize.where(@object_filter).find(params[:id])
end end
def params_filter def params_filter
type = ["normal", "group", "poll", "exercise", "gtask", "gtopic"] type = ["normal", "group", "poll", "exercise", "gtask", "gtopic"]
tip_exception("object_type类型不正确") unless type.include?(params[:object_type]) tip_exception("object_type类型不正确") unless type.include?(params[:object_type])
@ -128,6 +179,10 @@ class QuestionBanksController < ApplicationController
end end
end end
def teacher_or_admin
tip_exception(403, "无权限操作") unless current_user.is_certification_teacher || current_user.admin?
end
def quote_homework_bank homework, course def quote_homework_bank homework, course
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
# 复制作业的基本信息 # 复制作业的基本信息

@ -6,15 +6,18 @@ class ShixunsController < ApplicationController
:discusses, :collaborators, :fork_list, :propaedeutics] :discusses, :collaborators, :fork_list, :propaedeutics]
before_action :check_account, only: [:new, :create, :shixun_exec] before_action :check_account, only: [:new, :create, :shixun_exec]
before_action :find_shixun, except: [:index, :new, :create, :menus, :get_recommend_shixuns,
:propaedeutics, :departments, :apply_shixun_mirror,
:get_mirror_script, :download_file]
before_action :find_shixun, :shixun_access_allowed, except: [:index, :new, :create, :menus, :get_recommend_shixuns, before_action :shixun_access_allowed, except: [:index, :new, :create, :menus, :get_recommend_shixuns,
:propaedeutics, :departments, :apply_shixun_mirror, :propaedeutics, :departments, :apply_shixun_mirror,
:get_mirror_script, :download_file] :get_mirror_script, :download_file]
before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy] before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy, :add_file]
before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish, before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish,
:shixun_members_added, :change_manager, :collaborators_delete, :shixun_members_added, :change_manager, :collaborators_delete,
:cancel_publish, :add_collaborators] :cancel_publish, :add_collaborators, :add_file]
before_action :portion_allowed, only: [:copy] before_action :portion_allowed, only: [:copy]
before_action :special_allowed, only: [:send_to_course, :search_user_courses] before_action :special_allowed, only: [:send_to_course, :search_user_courses]
@ -348,7 +351,8 @@ class ShixunsController < ApplicationController
sub_type.each do |mirror| sub_type.each do |mirror|
ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
# 实训子镜像服务配置 # 实训子镜像服务配置
ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) name = MirrorRepository.find_by(id: mirror).try(:name) #查看镜像是否有名称,如果没有名称就不用服务配置
ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) if name.present?
end end
end end
@ -422,7 +426,12 @@ class ShixunsController < ApplicationController
# 超级管理员和运营人员才能保存 中间层服务器pod信息的配置 # 超级管理员和运营人员才能保存 中间层服务器pod信息的配置
if current_user.admin? || current_user.business? if current_user.admin? || current_user.business?
@shixun.shixun_service_configs.destroy_all @shixun.shixun_service_configs.destroy_all
@shixun.shixun_service_configs.create!(service_config_params[:shixun_service_configs]) service_config_params[:shixun_service_configs].each do |config|
logger.info("####{config[:mirror_repository_id]}")
name = MirrorRepository.find_by_id(config[:mirror_repository_id])&.name
# 不保存没有镜像的配置
@shixun.shixun_service_configs.create!(config) if name.present?
end
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)

@ -92,6 +92,7 @@ class StudentWorksController < ApplicationController
student_work.commit_time = Time.now student_work.commit_time = Time.now
student_work.update_time = Time.now student_work.update_time = Time.now
student_work.commit_user_id = current_user.id student_work.commit_user_id = current_user.id
student_work.update_user_id = current_user.id
student_work.group_id = @homework.homework_type == "group" ? @homework.max_group_id : 0 student_work.group_id = @homework.homework_type == "group" ? @homework.max_group_id : 0
#提交作品时,计算是否迟交 #提交作品时,计算是否迟交
@ -112,7 +113,7 @@ class StudentWorksController < ApplicationController
homework_common_id: @homework.id, project_id: student_work.project_id, homework_common_id: @homework.id, project_id: student_work.project_id,
late_penalty: student_work.late_penalty, work_status: student_work.work_status, late_penalty: student_work.late_penalty, work_status: student_work.work_status,
commit_time: Time.now, update_time: Time.now, group_id: student_work.group_id, commit_time: Time.now, update_time: Time.now, group_id: student_work.group_id,
commit_user_id: current_user.id) commit_user_id: current_user.id, update_user_id: current_user.id)
stu_work.save! stu_work.save!
student_work.attachments.each do |attachment| student_work.attachments.each do |attachment|
att = attachment.copy att = attachment.copy
@ -156,6 +157,7 @@ class StudentWorksController < ApplicationController
begin begin
@work.description = params[:description] @work.description = params[:description]
@work.update_time = Time.now @work.update_time = Time.now
@work.update_user_id = current_user.id
# @work.commit_user_id = current_user.id # @work.commit_user_id = current_user.id
if @work.save! if @work.save!
Attachment.associate_container(params[:attachment_ids], @work.id, @work.class) Attachment.associate_container(params[:attachment_ids], @work.id, @work.class)
@ -172,7 +174,7 @@ class StudentWorksController < ApplicationController
# 原成员更新描述、更新时间以及附件 # 原成员更新描述、更新时间以及附件
@homework.student_works.where(group_id: @work.group_id, user_id: (work_user_ids & params_user_ids)).each do |work| @homework.student_works.where(group_id: @work.group_id, user_id: (work_user_ids & params_user_ids)).each do |work|
# work.update_attributes(update_time: Time.now, description: @work.description, commit_user_id: current_user.id) # work.update_attributes(update_time: Time.now, description: @work.description, commit_user_id: current_user.id)
work.update_attributes(update_time: Time.now, description: @work.description) work.update_attributes(update_time: Time.now, description: @work.description, update_user_id: current_user.id)
work.attachments.destroy_all work.attachments.destroy_all
@work.attachments.each do |attachment| @work.attachments.each do |attachment|
att = attachment.copy att = attachment.copy
@ -192,7 +194,7 @@ class StudentWorksController < ApplicationController
@homework.student_works.where(group_id: @work.group_id, user_id: delete_user_ids). @homework.student_works.where(group_id: @work.group_id, user_id: delete_user_ids).
update_all(work_status: 0, description: nil, late_penalty: 0, commit_time: nil, update_time: nil, update_all(work_status: 0, description: nil, late_penalty: 0, commit_time: nil, update_time: nil,
final_score: nil, teacher_score: nil, student_score: nil, teaching_asistant_score: nil, final_score: nil, teacher_score: nil, student_score: nil, teaching_asistant_score: nil,
work_score: nil, project_id: 0, group_id: 0, commit_user_id: nil) work_score: nil, project_id: 0, group_id: 0, commit_user_id: nil, update_user_id: nil)
# 新增加的成员 # 新增加的成员
(params_user_ids - work_user_ids).each do |user_id| (params_user_ids - work_user_ids).each do |user_id|
@ -200,7 +202,7 @@ class StudentWorksController < ApplicationController
stu_work.update_attributes(user_id: user_id, description: @work.description, homework_common_id: @homework.id, stu_work.update_attributes(user_id: user_id, description: @work.description, homework_common_id: @homework.id,
project_id: @work.project_id, late_penalty: @work.late_penalty, project_id: @work.project_id, late_penalty: @work.late_penalty,
work_status: @work.work_status, commit_time: Time.now, update_time: Time.now, work_status: @work.work_status, commit_time: Time.now, update_time: Time.now,
group_id: @work.group_id, commit_user_id: @work.commit_user_id) group_id: @work.group_id, commit_user_id: @work.commit_user_id, update_user_id: current_user.id)
@work.attachments.each do |attachment| @work.attachments.each do |attachment|
att = attachment.copy att = attachment.copy
att.author_id = attachment.author_id att.author_id = attachment.author_id
@ -653,15 +655,15 @@ class StudentWorksController < ApplicationController
# 查重作品调分 # 查重作品调分
def adjust_review_score def adjust_review_score
tip_exception("缺少type参数") if params[:type].blank? || !["review", "report"].include?(params[:type]) tip_exception("缺少type参数") if params[:type].blank? || !["review", "report"].include?(params[:type])
if params[:type] == "review" && (params[:score].nil? || params[:challenge_id].nil? || params[:code_rate].nil? || params[:copy_user_id].nil?) if params[:type] == "review" && (params[:score].blank? || params[:challenge_id].blank? || params[:code_rate].blank? || params[:copy_user_id].blank?)
tip_exception("参数错误score和challenge_id和code_rate和copy_user_id不能为空") tip_exception("参数错误score和challenge_id和code_rate和copy_user_id不能为空")
elsif params[:type] == "report" && (params[:score].nil? || params[:challenge_id].nil?) elsif params[:type] == "report" && (params[:score].blank? || params[:challenge_id].blank?)
tip_exception("参数错误score和challenge_id") tip_exception("参数错误score和challenge_id不能为空")
end end
challenge_setting = @homework.homework_challenge_settings.find_by(challenge_id: params[:challenge_id]) challenge_setting = @homework.homework_challenge_settings.find_by(challenge_id: params[:challenge_id])
challenge = challenge_setting&.challenge challenge = challenge_setting&.challenge
tip_exception("不能小于零") if params[:score] < 0 tip_exception("不能小于零") if params[:score].to_i < 0
tip_exception("不能大于关卡分值:#{challenge_setting.score}") if challenge_setting.score < params[:score] tip_exception("不能大于关卡分值:#{challenge_setting.score}") if challenge_setting.score < params[:score].to_i
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin

@ -270,7 +270,7 @@ class SubjectsController < ApplicationController
page = params[:page] || 1 page = params[:page] || 1
member_ids = @subject.subject_members.map(&:user_id).join(',') member_ids = @subject.subject_members.map(&:user_id).join(',')
condition = "%#{params[:search].strip}%".gsub(" ","") condition = "%#{params[:search].strip}%".gsub(" ","")
@users = User.where("id not in (?) and status = 1 and LOWER(concat(lastname, firstname, login, mail)) LIKE ?", member_ids, "#{condition}") @users = User.where("id not in (?) and status = 1 and LOWER(concat(lastname, ifnull(firstname, ''), login)) LIKE ?", member_ids, "#{condition}")
@users = @users.page(page).per(10) @users = @users.page(page).per(10)
@users = @users.includes(:user_extension) @users = @users.includes(:user_extension)
@ -450,7 +450,7 @@ class SubjectsController < ApplicationController
@time = 0 @time = 0
@user_tags = [] @user_tags = []
else else
pass_challenge_ids = pass_games.map(&:challenge_id) pass_challenge_ids = pass_games.map(&:challenge_id).uniq # 按道理是不用去重的,但是历史数据与重复
subject_challenge_count = @subject.shixuns.sum(:challenges_count) subject_challenge_count = @subject.shixuns.sum(:challenges_count)
# 用户通关获得的标签 # 用户通关获得的标签
@user_tags = ChallengeTag.where(challenge_id: pass_challenge_ids).pluck(:name) @user_tags = ChallengeTag.where(challenge_id: pass_challenge_ids).pluck(:name)

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

@ -1,4 +1,5 @@
class Users::QuestionBanksController < Users::BaseController class Users::QuestionBanksController < Users::BaseController
before_action :require_login
before_action :check_query_params! before_action :check_query_params!
before_action :check_user_permission! before_action :check_user_permission!
@ -8,7 +9,7 @@ class Users::QuestionBanksController < Users::BaseController
@count = question_banks.count @count = question_banks.count
@course_lists = service.course_lists @course_lists = service.course_lists
@question_banks = paginate(question_banks.includes(:user, :course_list), special: true) @question_banks = paginate(question_banks.includes(:user, :course_list))
load_question_banks_solve_count # for solve n + 1 load_question_banks_solve_count # for solve n + 1
end end
@ -18,8 +19,8 @@ class Users::QuestionBanksController < Users::BaseController
def load_question_banks_solve_count def load_question_banks_solve_count
question_bank_ids = @question_banks.map(&:id) question_bank_ids = @question_banks.map(&:id)
@solve_count_map = @solve_count_map =
case params[:category] case params[:object_type]
when 'common', 'group' then when 'normal', 'group' then
StudentWork.where(is_delete: false, work_status: [1, 2, 3]).joins(:homework_common) StudentWork.where(is_delete: false, work_status: [1, 2, 3]).joins(:homework_common)
.where(homework_commons: { homework_bank_id: question_bank_ids }) .where(homework_commons: { homework_bank_id: question_bank_ids })
.group('homework_commons.homework_bank_id').count .group('homework_commons.homework_bank_id').count
@ -36,20 +37,20 @@ class Users::QuestionBanksController < Users::BaseController
.group('graduation_tasks.gtask_bank_id').count .group('graduation_tasks.gtask_bank_id').count
when 'gtopic' then when 'gtopic' then
StudentGraduationTopic.joins(:graduation_topic) StudentGraduationTopic.joins(:graduation_topic)
.where(gtopic_banks: { gtopic_bank_id: question_bank_ids }).where('status != 0') .where(graduation_topics: { gtopic_bank_id: question_bank_ids }).where('student_graduation_topics.status = 1')
.group('gtopic_banks.gtopic_bank_id').count .group('graduation_topics.gtopic_bank_id').count
end end
end end
def query_params def query_params
params.permit(:type, :category, :course_list_id, :sort_by, :sort_direction) params.permit(:type, :object_type, :course_list_id, :sort_by, :sort_direction)
end end
def check_query_params! def check_query_params!
params[:type] = 'personal' if params[:type].blank? || !%w(personal publicly).include?(params[:type]) params[:type] = 'personal' if params[:type].blank? || !%w(personal publicly).include?(params[:type])
if params[:category].blank? || !%w(common group exercise poll gtask gtopic).include?(params[:category]) if params[:object_type].blank? || !%w(normal group exercise poll gtask gtopic).include?(params[:object_type])
params[:category] = 'common' params[:object_type] = 'normal'
end end
if params[:sort_by].blank? || !%w(updated_at name contributor).include?(params[:sort_by]) if params[:sort_by].blank? || !%w(updated_at name contributor).include?(params[:sort_by])
@ -62,12 +63,10 @@ class Users::QuestionBanksController < Users::BaseController
end end
def check_user_permission! def check_user_permission!
return if User.current.admin? || (observed_logged_user? && read_question_bank_permission?) if params[:type] == 'publicly'
render_error("未通过职业认证") unless User.current.admin? || User.current.certification_teacher?
render_forbidden else
render_forbidden unless User.current.admin? || User.current.is_teacher?
end end
def read_question_bank_permission?
params[:type] == 'personal' ? User.current.is_teacher? : User.current.certification_teacher?
end end
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

@ -48,7 +48,7 @@ module HomeworkCommonsHelper
end end
when 2, 5, 6 when 2, 5, 6
status << "评阅中" status << "评阅中"
time = "评阅剩余时间:" + (course.end_date.present? ? how_much_time(course.end_date.end_of_day) : "") time = course.end_date.present? ? ("评阅剩余时间:" + how_much_time(course.end_date.end_of_day)) : ""
time_status = 5 time_status = 5
end end

@ -14,6 +14,19 @@ module ShixunsHelper
%W(未发布 已发布 已关闭)[status-1] %W(未发布 已发布 已关闭)[status-1]
end end
def shixun_authentication_status shixun
case shixun.try(:status)
when 0,nil
"编辑中"
when 1
"待审核"
when 2
"已发布"
when 3
"已关闭"
end
end
# 已完成实训所获得的经验值 # 已完成实训所获得的经验值
def myshixun_exp myshixun def myshixun_exp myshixun
score = 0 score = 0

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

@ -95,6 +95,14 @@ class Challenge < ApplicationRecord
end end
end end
def tags_show
if self.challenge_tags.nil?
"--"
else
self.try(:challenge_tags).map(&:name).join(";")
end
end
## 选择题答案 ## 选择题答案
def choose_answer def choose_answer
result = [] result = []

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

@ -2,6 +2,18 @@ class Department < ApplicationRecord
belongs_to :school belongs_to :school
has_many :department_members, dependent: :destroy has_many :department_members, dependent: :destroy
has_many :member_users, through: :department_members, source: :user
has_many :user_extensions, dependent: :nullify
has_many :apply_add_departments
scope :without_deleted, -> { where(is_delete: false) } scope :without_deleted, -> { where(is_delete: false) }
def member?(user)
department_members.exists?(user_id: user.id)
end
def soft_delete!
update!(is_delete: true)
end
end end

@ -18,4 +18,7 @@ class ExerciseBank < ApplicationRecord
scope :exercise_bank_search, lambda { |keywords| scope :exercise_bank_search, lambda { |keywords|
where("name LIKE ?", "%#{keywords}%") unless keywords.blank?} where("name LIKE ?", "%#{keywords}%") unless keywords.blank?}
validates :name, length: { maximum: 60, too_long: "60 characters is the maximum allowed" }
validates :description, length: { maximum: 100, too_long: "100 characters is the maximum allowed" }
end end

@ -1,4 +1,7 @@
class ExerciseBankChoice < ApplicationRecord class ExerciseBankChoice < ApplicationRecord
belongs_to :exercise_bank_question belongs_to :exercise_bank_question
has_many :exercise_bank_standard_answers 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 end

@ -1,17 +1,24 @@
class ExerciseBankQuestion < ApplicationRecord class ExerciseBankQuestion < ApplicationRecord
belongs_to :exercise_bank belongs_to :exercise_bank
belongs_to :shixun belongs_to :shixun, optional: true
has_many :exercise_bank_shixun_challenges,:dependent => :destroy has_many :exercise_bank_shixun_challenges,:dependent => :destroy
has_many :exercise_bank_choices, :dependent => :destroy has_many :exercise_bank_choices, :dependent => :destroy
has_many :exercise_bank_standard_answers, :dependent => :destroy has_many :exercise_bank_standard_answers, :dependent => :destroy
#attr_accessible :question_number, :question_score, :question_title, :question_type #attr_accessible :question_number, :question_score, :question_title, :question_type
scope :insert_question_ex, lambda {|k| where("question_number > ?",k)}
scope :find_by_custom, lambda {|k,v| where("#{k} = ?",v)} #根据传入的参数查找问题
scope :left_question_choose, lambda {|k,v| where("#{k} > ?",v)} #根据传入的参数查找问题
scope :find_objective_questions, -> {where("question_type != ?",4)} #查找全部客观题
def question_type_name def question_type_name
case self.question_type case self.question_type
when 1 when 0
"单选题" "单选题"
when 2 when 1
"多选题" "多选题"
when 2
"判断题"
when 3 when 3
"填空题" "填空题"
when 4 when 4
@ -20,4 +27,14 @@ class ExerciseBankQuestion < ApplicationRecord
"实训题" "实训题"
end end
end end
#获取问题的全部标准答案
def get_standard_answer_ids
exercise_bank_standard_answers.pluck(:exercise_bank_choice_id)
end
def get_standard_answer_text
exercise_bank_standard_answers.pluck(:answer_text)
end
end end

@ -2,4 +2,5 @@ class ExerciseBankStandardAnswer < ApplicationRecord
belongs_to :exercise_bank_question belongs_to :exercise_bank_question
belongs_to :exercise_bank_choice belongs_to :exercise_bank_choice
#attr_accessible :answer_text #attr_accessible :answer_text
scope :standard_by_ids, lambda { |s| where(exercise_bank_choice_id: s) }
end end

@ -3,7 +3,7 @@ class HomeworkCommon < ApplicationRecord
enum homework_type: { normal: 1, program: 2, group: 3, practice: 4 }, _suffix: true enum homework_type: { normal: 1, program: 2, group: 3, practice: 4 }, _suffix: true
has_many :homework_group_settings, dependent: :destroy has_many :homework_group_settings, dependent: :destroy
has_many :published_settings, -> { group_published }, class_name: "HomeworkGroupSetting" has_many :published_settings, -> { group_published }, class_name: "HomeworkGroupSetting"
has_many :student_works, -> { where("is_delete = 0") } has_many :student_works, -> { where(is_delete: 0) }
has_many :score_student_works, -> { where("is_delete = 0 and work_status != 0").order("work_score desc") }, class_name: "StudentWork" has_many :score_student_works, -> { where("is_delete = 0 and work_status != 0").order("work_score desc") }, class_name: "StudentWork"
has_one :homework_detail_manual, dependent: :destroy has_one :homework_detail_manual, dependent: :destroy

@ -16,4 +16,8 @@ class LibraryApply < ApplicationRecord
transitions from: :pending, to: :agreed transitions from: :pending, to: :agreed
end end
end end
def status_i18n
end
end end

@ -0,0 +1,7 @@
# status: 0 创建镜像; 1 修改镜像ID 2 修改镜像name 3 删除镜像 4.从主节点同步镜像到子节点(子节点发生异常), 5. 修改镜像别名, 6. 修改镜像的状态
# user_id: -1时证明是非人为因素造成中间层异常导致
class MirrorOperationRecord < ActiveRecord::Base
default_scope { order(created_at: :desc) }
belongs_to :mirror_repository
end

@ -8,4 +8,8 @@ class MirrorRepository < ApplicationRecord
scope :published_mirror, -> { where(status: 1) } scope :published_mirror, -> { where(status: 1) }
scope :published_main_mirror, -> { published_mirror.where(main_type: 1) } scope :published_main_mirror, -> { published_mirror.where(main_type: 1) }
scope :published_small_mirror, -> { published_mirror.where(main_type: 0) } scope :published_small_mirror, -> { published_mirror.where(main_type: 0) }
def deletable?
status != 1 && !shixun_mirror_repositories.exists?
end
end end

@ -7,6 +7,9 @@ class Myshixun < ApplicationRecord
belongs_to :user belongs_to :user
belongs_to :shixun, counter_cache: true belongs_to :shixun, counter_cache: true
has_one :last_executable_task, -> { where(status: [0, 1]).reorder(created_at: :asc) }, class_name: 'Game'
has_one :last_task, -> { all }, class_name: 'Game'
validates_uniqueness_of :shixun_id, :scope => :user_id, :message => "shixun_id and user_id unique error" validates_uniqueness_of :shixun_id, :scope => :user_id, :message => "shixun_id and user_id unique error"
scope :finished, lambda { where(status: 1) } scope :finished, lambda { where(status: 1) }
scope :search_myshixun_user, ->(user_id){where(user_id:user_id)} scope :search_myshixun_user, ->(user_id){where(user_id:user_id)}

@ -1,3 +1,5 @@
class Partner < ApplicationRecord class Partner < ApplicationRecord
belongs_to :school, optional: true
has_many :users has_many :users
end end

@ -0,0 +1,4 @@
class PartnerCustomer < ApplicationRecord
belongs_to :partner
belongs_to :customer
end

@ -13,6 +13,9 @@ class School < ApplicationRecord
has_many :school_daily_reports, dependent: :destroy has_many :school_daily_reports, dependent: :destroy
has_many :courses has_many :courses
has_many :customers, dependent: :destroy
has_many :partners, dependent: :destroy
# 学校管理员 # 学校管理员
def manager?(user) def manager?(user)
ec_school_users.exists?(user_id: user.id) ec_school_users.exists?(user_id: user.id)

@ -78,6 +78,29 @@ class Shixun < ApplicationRecord
shixun_info.try(:evaluate_script) shixun_info.try(:evaluate_script)
end end
def fork_identifier
self.fork_from.nil? ? "--" : Shixun.where(id: self.fork_from).first.try(:identifier)
end
def shixun_status
status = ""
case self.status
when 0
status = "编辑中"
when 1
status = "审核中"
when 2
status = "已发布"
when 3
status = "已关闭"
end
status
end
def is_tag_used?(id)
tag_repertoires.map(&:id).include?(id)
end
# 实训用户tag # 实训用户tag
def user_tags_name(user = User.current) def user_tags_name(user = User.current)
Shixun.joins(challenges: [:challenge_tags, :games]).where(games: {status: 2, user_id: user.id}, shixuns: {id:id}) Shixun.joins(challenges: [:challenge_tags, :games]).where(games: {status: 2, user_id: user.id}, shixuns: {id:id})
@ -133,6 +156,10 @@ class Shixun < ApplicationRecord
User.find(self.user_id) User.find(self.user_id)
end end
def shixun_main_name
self.mirror_repositories.published_main_mirror.first.try(:type_name)
end
def is_published? def is_published?
status > 1 status > 1
end end

@ -2,6 +2,7 @@ class StudentWork < ApplicationRecord
#学生提交作品表 #work_status :0 未提交 1 已提交 2 迟交 #学生提交作品表 #work_status :0 未提交 1 已提交 2 迟交
belongs_to :user belongs_to :user
belongs_to :commit_user, class_name: 'User', foreign_key: :commit_user_id, optional: true belongs_to :commit_user, class_name: 'User', foreign_key: :commit_user_id, optional: true
belongs_to :update_user, class_name: 'User', foreign_key: :update_user_id, optional: true
belongs_to :homework_common belongs_to :homework_common
belongs_to :myshixun, optional: true belongs_to :myshixun, optional: true
has_many :student_works_evaluation_distributions, dependent: :destroy has_many :student_works_evaluation_distributions, dependent: :destroy

@ -139,7 +139,7 @@ class User < ApplicationRecord
has_many :videos, dependent: :destroy has_many :videos, dependent: :destroy
# 客户管理 # 客户管理
belongs_to :partner belongs_to :partner, optional: true
# Groups and active users # Groups and active users
scope :active, lambda { where(status: STATUS_ACTIVE) } scope :active, lambda { where(status: STATUS_ACTIVE) }

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

@ -28,7 +28,13 @@ class Admins::UserQuery < ApplicationQuery
keyword = params[:keyword].to_s.strip.presence keyword = params[:keyword].to_s.strip.presence
if keyword if keyword
sql = 'CONCAT(lastname, firstname) LIKE :keyword OR login LIKE :keyword OR mail LIKE :keyword OR phone LIKE :keyword' sql = 'CONCAT(lastname, firstname) LIKE :keyword OR login LIKE :keyword OR mail LIKE :keyword OR phone LIKE :keyword'
users = users.where(sql, keyword: keyword) users = users.where(sql, keyword: "%#{keyword}%")
end
# 姓名
name = params[:name].to_s.strip.presence
if name.present?
users = users.where('CONCAT(lastname, firstname) LIKE :name', name: "%#{name}%")
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…
Cancel
Save