diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js index 7d1908547..ee85468c0 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -25,6 +25,12 @@ $.fn.select2.defaults.set('language', 'zh-CN'); Turbolinks.setProgressBarDelay(200); +$.notifyDefaults({ + type: 'success', + z_index: 9999, + delay: 2000 +}); + $(document).on('turbolinks:load', function(){ $('[data-toggle="tooltip"]').tooltip(); $('[data-toggle="popover"]').popover(); diff --git a/app/assets/javascripts/admins/departments/index.js b/app/assets/javascripts/admins/departments/index.js new file mode 100644 index 000000000..eb0fc3a6a --- /dev/null +++ b/app/assets/javascripts/admins/departments/index.js @@ -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'); + } + }); + } +}); \ No newline at end of file diff --git a/app/assets/javascripts/admins/library_applies/index.js b/app/assets/javascripts/admins/library_applies/index.js new file mode 100644 index 000000000..ce890d4fb --- /dev/null +++ b/app/assets/javascripts/admins/library_applies/index.js @@ -0,0 +1,21 @@ +$(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'); + } + }); + + } +}) \ No newline at end of file diff --git a/app/assets/javascripts/admins/modals/admin-edit-department-modal.js b/app/assets/javascripts/admins/modals/admin-edit-department-modal.js new file mode 100644 index 000000000..a1df01ba5 --- /dev/null +++ b/app/assets/javascripts/admins/modals/admin-edit-department-modal.js @@ -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() + }); + } + }); + }) +}); \ No newline at end of file diff --git a/app/assets/javascripts/admins/modals/admin-merge-department-modal.js b/app/assets/javascripts/admins/modals/admin-merge-department-modal.js new file mode 100644 index 000000000..aead3f485 --- /dev/null +++ b/app/assets/javascripts/admins/modals/admin-merge-department-modal.js @@ -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); + } + }); + } + }); + } +}); \ No newline at end of file diff --git a/app/assets/javascripts/admins/shixun_settings/shixun_settings.js b/app/assets/javascripts/admins/shixun_settings/shixun_settings.js new file mode 100644 index 000000000..150d2cc8b --- /dev/null +++ b/app/assets/javascripts/admins/shixun_settings/shixun_settings.js @@ -0,0 +1,33 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-shixun-settings-index-page').length > 0) { + $(".shixun-settings-select").on("change", function () { + var s_value = $(this).val(); + var s_name = $(this).attr("name"); + var json = {}; + json[s_name] = s_value; + $.ajax({ + url: "/admins/shixun_settings", + type: "GET", + dataType:'script', + data: json + }) + }); + + $(".shixun-setting-form").on("change",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 + }) + }) + } +}); + diff --git a/app/assets/javascripts/admins/shixuns/index.js b/app/assets/javascripts/admins/shixuns/index.js new file mode 100644 index 000000000..cf926c3c9 --- /dev/null +++ b/app/assets/javascripts/admins/shixuns/index.js @@ -0,0 +1,6 @@ +$(document).on('turbolinks:load', function() { + $('select#tag-choosed').select2({ + placeholder: "请选择分类", + allowClear: true + }); +}); \ No newline at end of file diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 7710423ea..ec9c0fbc7 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -46,11 +46,24 @@ label.error { } } +input.form-control { + font-size: 14px; +} + .flex-1 { flex: 1; } +.btn-default{ + color: #666; + background: #e1e1e1!important; +} +.export-absolute{ + right:20px; + position: absolute; +} +.position-r{position:relative;} .font-12 { font-size: 12px !important; } .font-14 { font-size: 14px !important; } .font-16 { font-size: 16px !important; } -.font-18 { font-size: 18px !important; } \ No newline at end of file +.font-18 { font-size: 18px !important; } diff --git a/app/assets/stylesheets/admins/departments.scss b/app/assets/stylesheets/admins/departments.scss new file mode 100644 index 000000000..7d9d078e5 --- /dev/null +++ b/app/assets/stylesheets/admins/departments.scss @@ -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; + } + } + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/admins/library_applies.scss b/app/assets/stylesheets/admins/library_applies.scss new file mode 100644 index 000000000..23b7ce30a --- /dev/null +++ b/app/assets/stylesheets/admins/library_applies.scss @@ -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; } + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/admins/shixun.scss b/app/assets/stylesheets/admins/shixun.scss new file mode 100644 index 000000000..75f8a54b5 --- /dev/null +++ b/app/assets/stylesheets/admins/shixun.scss @@ -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; } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/admins/shixun_settings.scss b/app/assets/stylesheets/admins/shixun_settings.scss new file mode 100644 index 000000000..c38fc0c6d --- /dev/null +++ b/app/assets/stylesheets/admins/shixun_settings.scss @@ -0,0 +1,14 @@ +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; +} \ No newline at end of file diff --git a/app/assets/stylesheets/select2-bootstrap4.min.scss b/app/assets/stylesheets/select2-bootstrap4.min.scss index f84b4090a..c39ca0195 100644 --- a/app/assets/stylesheets/select2-bootstrap4.min.scss +++ b/app/assets/stylesheets/select2-bootstrap4.min.scss @@ -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} \ No newline at end of file +.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} \ No newline at end of file diff --git a/app/controllers/admins/department_members_controller.rb b/app/controllers/admins/department_members_controller.rb new file mode 100644 index 000000000..ba483acef --- /dev/null +++ b/app/controllers/admins/department_members_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/admins/departments_controller.rb b/app/controllers/admins/departments_controller.rb new file mode 100644 index 000000000..ed7c3d3db --- /dev/null +++ b/app/controllers/admins/departments_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/admins/library_applies_controller.rb b/app/controllers/admins/library_applies_controller.rb new file mode 100644 index 000000000..678dc31ad --- /dev/null +++ b/app/controllers/admins/library_applies_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/admins/shixun_settings_controller.rb b/app/controllers/admins/shixun_settings_controller.rb new file mode 100644 index 000000000..55b0381f1 --- /dev/null +++ b/app/controllers/admins/shixun_settings_controller.rb @@ -0,0 +1,86 @@ +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 + @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 diff --git a/app/controllers/admins/shixuns_controller.rb b/app/controllers/admins/shixuns_controller.rb new file mode 100644 index 000000000..a4aa8a044 --- /dev/null +++ b/app/controllers/admins/shixuns_controller.rb @@ -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 diff --git a/app/controllers/concerns/admins/render_helper.rb b/app/controllers/concerns/admins/render_helper.rb index 94b7c29cb..0f136b62d 100644 --- a/app/controllers/concerns/admins/render_helper.rb +++ b/app/controllers/concerns/admins/render_helper.rb @@ -17,9 +17,9 @@ module Admins::RenderHelper json: -> { render status: 404, json: { message: '资源未找到' } }) end - def render_unprocessable_entity(message) + def render_unprocessable_entity(message, type: :alert) render_by_format(html: -> { render 'admins/shared/422' }, - js: -> { render_js_error(message) }, + js: -> { render_js_error(message, type: type) }, json: -> { render status: 422, json: { message: message } }) end alias_method :render_error, :render_unprocessable_entity @@ -40,7 +40,11 @@ module Admins::RenderHelper end alias_method :render_success_js, :render_delete_success - def render_js_error(message) - render_js_template 'admins/shared/error', locals: { message: 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 } + end end end \ No newline at end of file diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 59b0d7e41..fb68f23bf 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -890,7 +890,7 @@ class CoursesController < ApplicationController name = worksheet.cell(row, 1).to_s 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 end end diff --git a/app/controllers/exercise_bank_questions_controller.rb b/app/controllers/exercise_bank_questions_controller.rb index 416358af6..b64e71b59 100644 --- a/app/controllers/exercise_bank_questions_controller.rb +++ b/app/controllers/exercise_bank_questions_controller.rb @@ -124,6 +124,7 @@ class ExerciseBankQuestionsController < ApplicationController @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("试卷问题创建失败!") @@ -185,7 +186,6 @@ class ExerciseBankQuestionsController < ApplicationController 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 #表示答案有更改的 - standard_answer_change = true 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 # 传入的标准答案差集共同的,剩余的表示需要新建 @@ -216,7 +216,6 @@ class ExerciseBankQuestionsController < ApplicationController 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 #全部的答案数组序号 - standard_answer_change = true #删除多余的选项 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 @@ -300,7 +299,7 @@ class ExerciseBankQuestionsController < ApplicationController elsif @exercise_question.question_type == Exercise::PRACTICAL question_score = 0 shixun_name = params[:shixun_name] || @exercise_question.shixun_name - @exercise_question.exercise_shixun_challenges.each_with_index do |challenge, index| + @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) @@ -309,32 +308,63 @@ class ExerciseBankQuestionsController < ApplicationController @exercise_question.shixun_name = shixun_name @exercise_question.save end + normal_status(0,"试卷更新成功") + rescue Exception => e + uid_logger_error(e.message) + tip_exception("页面调用失败!") + raise ActiveRecord::Rollback + end + end + end - #当试卷已发布时(试卷的总状态),当标准答案修改时,如有已提交的学生,需重新计算分数. - - if standard_answer_change && @exercise.exercise_status >= Exercise::PUBLISHED - # ex_users_committed = @exercise.exercise_users.exercise_user_committed - # if ex_users_committed.size > 0 - # ex_users_committed.each do |ex_user| - # update_objective_score = update_single_score(@exercise_question,ex_user.user_id,standard_answer) - # if update_objective_score != 0 - # objective_score = ex_user.objective_score - # new_objective_score = objective_score + update_objective_score - # total_score = ex_user.score + update_objective_score - # total_score = total_score < 0.0 ? 0.0 : total_score - # ex_user.update_attributes(objective_score:new_objective_score,score:total_score) - # end - # end - # end - normal_status(3,"修改了标准答案\n是否重新计算学生答题的成绩?") + 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(0,"试卷更新成功!") + normal_status(-1, "移动失败,请输入参数") end + rescue Exception => e + uid_logger_error(e.message) + tip_exception("问题移动失败!") + 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("页面调用失败!") - raise ActiveRecord::Rollback + tip_exception("删除失败") end end end diff --git a/app/controllers/exercise_banks_controller.rb b/app/controllers/exercise_banks_controller.rb index 29af3c42b..cc7a1003e 100644 --- a/app/controllers/exercise_banks_controller.rb +++ b/app/controllers/exercise_banks_controller.rb @@ -1,8 +1,9 @@ #encoding: UTF-8 class ExerciseBanksController < ApplicationController before_action :require_login - before_action :find_bank + 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, @@ -47,6 +48,38 @@ class ExerciseBanksController < ApplicationController normal_status(0,"试卷更新成功!") end + def choose_shixun + search = params[:search] + if !current_user.admin? #当不为管理员的时候 + user_school_id = current_user.school_id #当前用户的学校id + if user_school_id.present? + none_shixun_ids = ShixunSchool.where("school_id != #{user_school_id}").pluck(:shixun_id) + @publish_shixuns = Shixun.where.not(id: none_shixun_ids).unhidden + end + else + @publish_shixuns = Shixun.unhidden + end + if search.present? + @publish_shixuns = @publish_shixuns.search_by_name(search) + end + + @shixuns = @publish_shixuns.joins(:challenges).where("challenges.st != 0").distinct + # 全部页面,需返回 + @shixuns_count = @shixuns.count + + # 分页 + @page = params[:page] || 1 + @limit = params[:limit] || 8 + + @shixuns = @shixuns.page(@page).per(@limit) + end + + #确认实训的选择 + def commit_shixun + @shixun_challenges = @shixun.challenges + @shixun_challenges_count = @shixun_challenges.size + end + private def find_bank @@ -57,4 +90,17 @@ class ExerciseBanksController < ApplicationController def bank_admin tip_exception(403, "无权限") unless (current_user.certification_teacher? && @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 + end diff --git a/app/controllers/question_banks_controller.rb b/app/controllers/question_banks_controller.rb index 96fcbeace..00fea5f3e 100644 --- a/app/controllers/question_banks_controller.rb +++ b/app/controllers/question_banks_controller.rb @@ -1,6 +1,7 @@ class QuestionBanksController < ApplicationController before_action :require_login, :check_auth before_action :params_filter, except: [:my_courses] + before_action :teacher_or_admin, except: [:bank_list] # 题库选用列表 # object_type: # normal 普通作业题库; group 分组作业题库; poll问卷题库; exercise试卷题库; gtask 毕设选题题库;gtopic 毕设任务 @@ -81,24 +82,29 @@ class QuestionBanksController < ApplicationController 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 - bank = current_bank - course = current_user.manage_courses.find_by(id: params[:course_id]) - 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 + 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 - when 'GtaskBank' - quote_gtask_bank bank, course - when 'GtopicBank' - quote_gtopic_bank bank, course end normal_status("发送成功") end @@ -106,7 +112,7 @@ class QuestionBanksController < ApplicationController def destroy bank = current_bank - unless user.admin? || bank.user_id == user.id + unless current_user.admin? || bank.user_id == current_user.id render_forbidden return end @@ -121,11 +127,32 @@ class QuestionBanksController < ApplicationController render_ok 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 + 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 @_current_bank ||= @object_type.classify.constantize.where(@object_filter).find(params[:id]) end + def params_filter type = ["normal", "group", "poll", "exercise", "gtask", "gtopic"] tip_exception("object_type类型不正确") unless type.include?(params[:object_type]) @@ -152,6 +179,10 @@ class QuestionBanksController < ApplicationController 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 ActiveRecord::Base.transaction do # 复制作业的基本信息 diff --git a/app/controllers/users/question_banks_controller.rb b/app/controllers/users/question_banks_controller.rb index d0a331291..e966b67e9 100644 --- a/app/controllers/users/question_banks_controller.rb +++ b/app/controllers/users/question_banks_controller.rb @@ -8,7 +8,7 @@ class Users::QuestionBanksController < Users::BaseController @count = question_banks.count @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 end diff --git a/app/helpers/shixuns_helper.rb b/app/helpers/shixuns_helper.rb index d849053ca..b41750bed 100644 --- a/app/helpers/shixuns_helper.rb +++ b/app/helpers/shixuns_helper.rb @@ -14,6 +14,19 @@ module ShixunsHelper %W(未发布 已发布 已关闭)[status-1] 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 score = 0 diff --git a/app/jobs/delete_department_notify_job.rb b/app/jobs/delete_department_notify_job.rb new file mode 100644 index 000000000..1da5e2e85 --- /dev/null +++ b/app/jobs/delete_department_notify_job.rb @@ -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 diff --git a/app/models/challenge.rb b/app/models/challenge.rb index 8087fd6ab..455fd1b6a 100644 --- a/app/models/challenge.rb +++ b/app/models/challenge.rb @@ -95,6 +95,14 @@ class Challenge < ApplicationRecord end end + def tags_show + if self.challenge_tags.nil? + "--" + else + self.try(:challenge_tags).map(&:name).join(";") + end + end + ## 选择题答案 def choose_answer result = [] diff --git a/app/models/department.rb b/app/models/department.rb index 9c4a0908b..1923cfb33 100644 --- a/app/models/department.rb +++ b/app/models/department.rb @@ -2,6 +2,14 @@ class Department < ApplicationRecord belongs_to :school 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) } + + def soft_delete! + update!(is_delete: true) + end end diff --git a/app/models/library_apply.rb b/app/models/library_apply.rb index 0a7ec8aec..85944169b 100644 --- a/app/models/library_apply.rb +++ b/app/models/library_apply.rb @@ -16,4 +16,8 @@ class LibraryApply < ApplicationRecord transitions from: :pending, to: :agreed end end + + def status_i18n + + end end \ No newline at end of file diff --git a/app/models/shixun.rb b/app/models/shixun.rb index d61ba45b9..db6bca43e 100644 --- a/app/models/shixun.rb +++ b/app/models/shixun.rb @@ -78,6 +78,29 @@ class Shixun < ApplicationRecord shixun_info.try(:evaluate_script) 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 def user_tags_name(user = User.current) 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) end + def shixun_main_name + self.mirror_repositories.published_main_mirror.first.try(:type_name) + end + def is_published? status > 1 end diff --git a/app/queries/admins/department_query.rb b/app/queries/admins/department_query.rb new file mode 100644 index 000000000..b0b5d0118 --- /dev/null +++ b/app/queries/admins/department_query.rb @@ -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 \ No newline at end of file diff --git a/app/queries/admins/library_apply_query.rb b/app/queries/admins/library_apply_query.rb new file mode 100644 index 000000000..9fdc2d067 --- /dev/null +++ b/app/queries/admins/library_apply_query.rb @@ -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 \ No newline at end of file diff --git a/app/queries/admins/shixun_query.rb b/app/queries/admins/shixun_query.rb new file mode 100644 index 000000000..0d726f267 --- /dev/null +++ b/app/queries/admins/shixun_query.rb @@ -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 \ No newline at end of file diff --git a/app/queries/admins/shixun_settings_query.rb b/app/queries/admins/shixun_settings_query.rb new file mode 100644 index 000000000..32cfdb8bf --- /dev/null +++ b/app/queries/admins/shixun_settings_query.rb @@ -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 \ No newline at end of file diff --git a/app/queries/admins/user_query.rb b/app/queries/admins/user_query.rb index 5a633f059..75e50fc1b 100644 --- a/app/queries/admins/user_query.rb +++ b/app/queries/admins/user_query.rb @@ -28,7 +28,13 @@ class Admins::UserQuery < ApplicationQuery keyword = params[:keyword].to_s.strip.presence if 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 # 学校名称 diff --git a/app/services/admins/add_department_member_service.rb b/app/services/admins/add_department_member_service.rb new file mode 100644 index 000000000..f8331cf4a --- /dev/null +++ b/app/services/admins/add_department_member_service.rb @@ -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 \ No newline at end of file diff --git a/app/views/admins/daily_school_statistics/index.html.erb b/app/views/admins/daily_school_statistics/index.html.erb index 054e06fc6..39dcba633 100644 --- a/app/views/admins/daily_school_statistics/index.html.erb +++ b/app/views/admins/daily_school_statistics/index.html.erb @@ -5,7 +5,7 @@
<%= form_tag(admins_daily_school_statistics_path, method: :get, class: 'form-inline search-form', remote: true) do %> <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: 'ID/单位名称搜索') %> - <%= submit_tag('搜索', class: 'btn btn-primary ml-3') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <% end %> <%#= link_to '导出Excel', export_admins_daily_school_statistics_path(format: :xlsx), class: 'btn btn-outline-primary export-action' %> diff --git a/app/views/admins/department_members/create.js.erb b/app/views/admins/department_members/create.js.erb new file mode 100644 index 000000000..4355c7432 --- /dev/null +++ b/app/views/admins/department_members/create.js.erb @@ -0,0 +1,4 @@ +$('.modal.admin-add-department-member-modal').modal('hide'); +$.notify({ message: '操作成功' }); + +$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: { department: current_department }) %>") \ No newline at end of file diff --git a/app/views/admins/department_members/destroy.js.erb b/app/views/admins/department_members/destroy.js.erb new file mode 100644 index 000000000..d3eb3755b --- /dev/null +++ b/app/views/admins/department_members/destroy.js.erb @@ -0,0 +1,2 @@ +$.notify({ message: '操作成功' }); +$('.department-list-container .department-item-<%= current_department.id %> .member-user-item-<%= @member.user_id %>').remove(); \ No newline at end of file diff --git a/app/views/admins/departments/edit.js.erb b/app/views/admins/departments/edit.js.erb new file mode 100644 index 000000000..dc86d3ae0 --- /dev/null +++ b/app/views/admins/departments/edit.js.erb @@ -0,0 +1,2 @@ +$('.admin-modal-container').html("<%= j( render partial: 'admins/departments/shared/edit_department_modal', locals: { department: current_department } ) %>"); +$('.modal.admin-edit-department-modal').modal('show'); \ No newline at end of file diff --git a/app/views/admins/departments/index.html.erb b/app/views/admins/departments/index.html.erb new file mode 100644 index 000000000..54ca47252 --- /dev/null +++ b/app/views/admins/departments/index.html.erb @@ -0,0 +1,33 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('部门列表') %> +<% end %> + +
+ <%= form_tag(admins_departments_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> +
+ <%= hidden_field_tag(:with_member, false) %> + <%= check_box_tag(:with_member, true, params[:with_member].to_s == 'true', class: 'form-check-input') %> + +
+ +
+ <%= hidden_field_tag(:with_identifier, false) %> + <%= check_box_tag(:with_identifier, true, params[:with_identifier].to_s == 'true', class: 'form-check-input') %> + +
+ + <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '部门/单位名称检索') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> + <% end %> + + <%= javascript_void_link '新建部门', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-create-department-modal' } %> +
+ +
+ <%= render partial: 'admins/departments/shared/list', + locals: { departments: @departments, users_count: @users_count, professional_auth_count: @professional_auth_count } %> +
+ +<%= render 'admins/departments/shared/create_department_modal' %> +<%= render 'admins/departments/shared/add_department_member_modal' %> +<%= render 'admins/departments/shared/merge_department_modal' %> \ No newline at end of file diff --git a/app/views/admins/departments/index.js.erb b/app/views/admins/departments/index.js.erb new file mode 100644 index 000000000..bd2e4b25d --- /dev/null +++ b/app/views/admins/departments/index.js.erb @@ -0,0 +1 @@ +$('.department-list-container').html("<%= j(render partial: 'admins/departments/shared/list', locals: { departments: @departments, users_count: @users_count, professional_auth_count: @professional_auth_count }) %>"); \ No newline at end of file diff --git a/app/views/admins/departments/shared/_add_department_member_modal.html.erb b/app/views/admins/departments/shared/_add_department_member_modal.html.erb new file mode 100644 index 000000000..5d2707222 --- /dev/null +++ b/app/views/admins/departments/shared/_add_department_member_modal.html.erb @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/app/views/admins/departments/shared/_create_department_modal.html.erb b/app/views/admins/departments/shared/_create_department_modal.html.erb new file mode 100644 index 000000000..ae6605eb8 --- /dev/null +++ b/app/views/admins/departments/shared/_create_department_modal.html.erb @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/app/views/admins/departments/shared/_department_item.html.erb b/app/views/admins/departments/shared/_department_item.html.erb new file mode 100644 index 000000000..2f39d6248 --- /dev/null +++ b/app/views/admins/departments/shared/_department_item.html.erb @@ -0,0 +1,28 @@ +<% not_list = defined?(:users_count) %> + +<%= overflow_hidden_span department.name, width: 150 %> +<%= overflow_hidden_span department.school.name, width: 150 %> + +<% if not_list %> + <%= department.user_extensions.count %> + <%= department.user_extensions.joins(:user).where(users: { professional_certification: true }).count %> +<% else %> + <%= users_count.fetch(department.id, 0) %> + <%= professional_auth_count.fetch(department.id, 0) %> +<% end %> + + + <%= render partial: 'admins/departments/shared/member_users', locals: { department: department } %> + +<%= link_to department.identifier.to_s, '#', target: '_blank' %> +<%= department.host_count %> +<%= department.created_at&.strftime('%Y-%m-%d %H:%M') %> + + <%= link_to '编辑', edit_admins_department_path(department), remote: true, class: 'action' %> + + <%= javascript_void_link '添加管理员', class: 'action', data: { department_id: department.id, toggle: 'modal', target: '.admin-add-department-member-modal' } %> + + <%= javascript_void_link '更改', class: 'action', data: { school_id: department.school_id, department_id: department.id, toggle: 'modal', target: '.admin-merge-department-modal' } %> + + <%= delete_link '删除', admins_department_path(department, element: ".department-item-#{department.id}"), class: 'delete-department-action' %> + \ No newline at end of file diff --git a/app/views/admins/departments/shared/_edit_department_modal.html.erb b/app/views/admins/departments/shared/_edit_department_modal.html.erb new file mode 100644 index 000000000..38b43bbce --- /dev/null +++ b/app/views/admins/departments/shared/_edit_department_modal.html.erb @@ -0,0 +1,25 @@ + \ No newline at end of file diff --git a/app/views/admins/departments/shared/_list.html.erb b/app/views/admins/departments/shared/_list.html.erb new file mode 100644 index 000000000..6af63d6f4 --- /dev/null +++ b/app/views/admins/departments/shared/_list.html.erb @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + <% if departments.present? %> + <% departments.each do |department| %> + + <%= render 'admins/departments/shared/department_item', department: department %> + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
部门名称单位名称用户数已职业认证部门管理员统计链接云主机数<%= sort_tag('创建时间', name: 'created_at', path: admins_departments_path) %>操作
+ +<%= render partial: 'admins/shared/paginate', locals: { objects: departments } %> \ No newline at end of file diff --git a/app/views/admins/departments/shared/_member_users.html.erb b/app/views/admins/departments/shared/_member_users.html.erb new file mode 100644 index 000000000..8d4d466db --- /dev/null +++ b/app/views/admins/departments/shared/_member_users.html.erb @@ -0,0 +1,12 @@ +
+ <% department.member_users.each do |user| %> + + <%= link_to user.real_name, "/users/#{user.login}", target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } %> + <%= link_to(admins_department_department_member_path(department, user_id: user.id), + method: :delete, remote: true, class: 'ml-1 delete-member-action', + data: { confirm: '确认删除吗?' }) do %> + + <% end %> + + <% end %> +
\ No newline at end of file diff --git a/app/views/admins/departments/shared/_merge_department_modal.html.erb b/app/views/admins/departments/shared/_merge_department_modal.html.erb new file mode 100644 index 000000000..200e75ccd --- /dev/null +++ b/app/views/admins/departments/shared/_merge_department_modal.html.erb @@ -0,0 +1,31 @@ + \ No newline at end of file diff --git a/app/views/admins/departments/update.js.erb b/app/views/admins/departments/update.js.erb new file mode 100644 index 000000000..359bac59c --- /dev/null +++ b/app/views/admins/departments/update.js.erb @@ -0,0 +1,4 @@ +$('.modal.admin-edit-department-modal').modal('hide'); +$.notify({ message: '操作成功' }); + +$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: { department: current_department }) %>") \ No newline at end of file diff --git a/app/views/admins/identity_authentications/index.html.erb b/app/views/admins/identity_authentications/index.html.erb index 170a8fc4a..38b7dfd63 100644 --- a/app/views/admins/identity_authentications/index.html.erb +++ b/app/views/admins/identity_authentications/index.html.erb @@ -21,7 +21,7 @@ <%= select_tag(:status, options_for_select(status_options), class: 'form-control') %>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '姓名/学校/单位检索') %> - <%= submit_tag('搜索', class: 'btn btn-primary ml-3') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <% end %> diff --git a/app/views/admins/library_applies/index.html.erb b/app/views/admins/library_applies/index.html.erb new file mode 100644 index 000000000..55a7e9e09 --- /dev/null +++ b/app/views/admins/library_applies/index.html.erb @@ -0,0 +1,32 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('教学案例发布') %> +<% end %> + +
+ + + <%= form_tag(admins_library_applies_path(unsafe_params), method: :get, class: 'form-inline search-form justify-content-end mt-3', remote: true) do %> +
+ + <% status_options = [['全部', 'processed'], ['已同意', 'agreed'], ['已拒绝', 'refused']] %> + <%= select_tag(:status, options_for_select(status_options) ,class: 'form-control') %> +
+ <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '编号/名称检索') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3') %> + <% end %> +
+ +
+ <%= render(partial: 'admins/library_applies/shared/list', locals: { applies: @library_applies }) %> +
+ +<%= render(partial: 'admins/shared/admin_common_refuse_modal') %> \ No newline at end of file diff --git a/app/views/admins/library_applies/index.js.erb b/app/views/admins/library_applies/index.js.erb new file mode 100644 index 000000000..6f4c3e712 --- /dev/null +++ b/app/views/admins/library_applies/index.js.erb @@ -0,0 +1 @@ +$('.library-applies-list-container').html("<%= j( render partial: 'admins/library_applies/shared/list', locals: { applies: @library_applies } ) %>"); \ No newline at end of file diff --git a/app/views/admins/library_applies/shared/_list.html.erb b/app/views/admins/library_applies/shared/_list.html.erb new file mode 100644 index 000000000..4aa853ca6 --- /dev/null +++ b/app/views/admins/library_applies/shared/_list.html.erb @@ -0,0 +1,56 @@ +<% is_processed = params[:status].to_s != 'pending' %> + + + + + + + + + + <% if is_processed %> + + + <% else %> + + <% end %> + + + + <% if applies.present? %> + <% applies.each do |apply| %> + <% user = apply.library.user %> + <% library = apply.library %> + + + + + + + + <% if is_processed %> + + + <% else %> + + <% end %> + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
头像姓名教学案例案例描述时间拒绝原因状态操作
+ <%= link_to "/users/#{user.login}", class: 'professional-authentication-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %> + + <% end %> + <%= user.real_name %><%= link_to library.title, library_path(library), :target => "_blank" %><%= overflow_hidden_span library.content[0..50] + "..."%><%= apply.updated_at.strftime('%Y-%m-%d %H:%M') %><%= overflow_hidden_span apply.reason %><%= t("library_apply.status.#{apply.status}") %> + <%= agree_link '同意', agree_admins_library_apply_path(apply, element: ".library_applies-#{apply.id}"), 'data-confirm': '确认审核通过?' %> + <%= javascript_void_link('拒绝', class: 'action refuse-action', + data: { + toggle: 'modal', target: '.admin-common-refuse-modal', id: apply.id, + url: refuse_admins_library_apply_path(apply, element: ".library_applies-#{apply.id}") + }) %> +
+ +<%= render partial: 'admins/shared/paginate', locals: { objects: applies } %> \ No newline at end of file diff --git a/app/views/admins/professional_authentications/index.html.erb b/app/views/admins/professional_authentications/index.html.erb index e10d2bd80..32eaa47bd 100644 --- a/app/views/admins/professional_authentications/index.html.erb +++ b/app/views/admins/professional_authentications/index.html.erb @@ -21,7 +21,7 @@ <%= select_tag(:status, options_for_select(status_options), class: 'form-control') %> <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '姓名/学校/单位检索') %> - <%= submit_tag('搜索', class: 'btn btn-primary ml-3') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <% end %> diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb index 8c995ec45..499b14d23 100644 --- a/app/views/admins/shared/_sidebar.html.erb +++ b/app/views/admins/shared/_sidebar.html.erb @@ -22,10 +22,18 @@
  • <%= sidebar_item_group('#shixun-submenu', '实训管理', icon: 'window-restore') do %> +
  • <%= sidebar_item(admins_shixuns_path, '实训列表', icon: 'jsfiddle', controller: 'admins-shixuns') %>
  • +
  • <%= sidebar_item(admins_shixun_settings_path, '实训配置', icon: 'cog', controller: 'admins-shixun_settings') %>
  • <%= sidebar_item(admins_mirror_repositories_path, '镜像管理', icon: 'cubes', controller: 'admins-mirror_repositories') %>
  • <% end %> +
  • + <%= sidebar_item_group('#schools-submenu', '单位管理', icon: 'building') do %> +
  • <%= sidebar_item(admins_departments_path, '部门列表', icon: 'sitemap', controller: 'admins-departments') %>
  • + <% end %> + + <%#= sidebar_item_group('#course-submenu', '课堂+', icon: 'mortar-board') do %> @@ -48,7 +56,8 @@
  • <%= sidebar_item(admins_identity_authentications_path, '实名认证', icon: 'id-card-o', controller: 'admins-identity_authentications') %>
  • <%= sidebar_item(admins_professional_authentications_path, '职业认证', icon: 'drivers-license', controller: 'admins-professional_authentications') %>
  • <%= sidebar_item(admins_shixun_authorizations_path, '实训发布', icon: 'object-ungroup', controller: 'admins-shixun_authorizations') %>
  • -
  • <%= sidebar_item(admins_subject_authorizations_path, '实践课程发布', icon: 'object-group', controller: 'admins-subject_authorizations') %>
  • +
  • <%= sidebar_item(admins_subject_authorizations_path, '实践课程发布', icon: 'object-group', controller: 'admins-subject_authorizations') %>
  • +
  • <%= sidebar_item(admins_library_applies_path, '教学案例发布', icon: 'language', controller: 'admins-library_applies') %>
  • <% end %> diff --git a/app/views/admins/shixun_authorizations/index.html.erb b/app/views/admins/shixun_authorizations/index.html.erb index 743f2e1b2..3aaa1ce89 100644 --- a/app/views/admins/shixun_authorizations/index.html.erb +++ b/app/views/admins/shixun_authorizations/index.html.erb @@ -21,7 +21,7 @@ <%= select_tag(:status, options_for_select(status_options), class: 'form-control') %> <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '实训名称检索') %> - <%= submit_tag('搜索', class: 'btn btn-primary ml-3') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <% end %> diff --git a/app/views/admins/shixun_settings/index.html.erb b/app/views/admins/shixun_settings/index.html.erb new file mode 100644 index 000000000..939ed7d72 --- /dev/null +++ b/app/views/admins/shixun_settings/index.html.erb @@ -0,0 +1,76 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('实训配置', admins_shixun_settings_path) %> +<% end %> + +
    + <%= form_tag(admins_shixun_settings_path, method: :get, class: 'form-inline search-form', remote: true) do %> +
    +
    +
    + + <% status_options = [['全部', ''], ["编辑中(#{@editing_shixuns})", "editing"], ["待审核(#{@pending_shixuns})", 'pending'], ["已发布(#{@processed_shixuns})", 'processed'],["已关闭(#{@closed_shixuns})",'closed']] %> + <%= select_tag(:status, options_for_select(status_options), class: 'form-control') %> +
    +
    + + <%= select_tag(:tag, options_for_select(@shixuns_type_check.unshift(["",nil])), class: 'form-control',id:"tag-choosed") %> +
    +
    + + <% auto_trial_options = [['创建者姓名', 0], ['实训名称', 1], ['学校名称', 2]] %> + <%= select_tag(:search_type, options_for_select(auto_trial_options), class: 'form-control') %> +
    + <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '输入关键字搜索') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3') %> + <%= link_to "清除",admins_shixun_settings_path(status:nil,tag:nil,search_type:nil,keyword:nil),class: "btn btn-default" %> + +
    + " class="btn btn-primary export-absolute" id="shixun_xls">导出 +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + <% end %> +
    + +
    + <%= render partial: 'admins/shixun_settings/shared/list', locals: { shixun_settings: @shixun_settings } %> +
    + diff --git a/app/views/admins/shixun_settings/index.js.erb b/app/views/admins/shixun_settings/index.js.erb new file mode 100644 index 000000000..af07e062a --- /dev/null +++ b/app/views/admins/shixun_settings/index.js.erb @@ -0,0 +1 @@ +$(".shixun-settings-list-container").html("<%= j render partial: "admins/shixun_settings/shared/list",locals: {shixun_settings:@shixun_settings} %>") \ No newline at end of file diff --git a/app/views/admins/shixun_settings/shared/_list.html.erb b/app/views/admins/shixun_settings/shared/_list.html.erb new file mode 100644 index 000000000..14a97d002 --- /dev/null +++ b/app/views/admins/shixun_settings/shared/_list.html.erb @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + <% shixun_settings.each_with_index do |shixun,index| %> + + <% page_no = (@params_page.to_i - 1) * 20 + index + 1 %> + <%= render partial: "admins/shixun_settings/shared/td",locals: {shixun: shixun,page_no:page_no} %> + + <% end %> + +
    序号ID实训名称技术平台权限技术体系上传图片创建者关闭复制代码执行时间 + 操作 +
    + ssh/隐藏/首页/跳关/隐藏目录 +
    +
    + +<%= render partial: 'admins/shared/paginate', locals: { objects: shixun_settings } %> \ No newline at end of file diff --git a/app/views/admins/shixun_settings/shared/_td.html.erb b/app/views/admins/shixun_settings/shared/_td.html.erb new file mode 100644 index 000000000..931ad11ac --- /dev/null +++ b/app/views/admins/shixun_settings/shared/_td.html.erb @@ -0,0 +1,59 @@ +<%= page_no %> +<%= shixun.identifier %> + + + <%= link_to overflow_hidden_span(shixun.name,width:160), "/shixuns/#{shixun.identifier}", :target => "_blank", :title => shixun.name %> + + + + <%= display_text shixun.shixun_main_name %> + + + <% status_options = [['超级管理员', '0'], ["合作团队", "1"]] %> + <%= select_tag(:use_scope, options_for_select(status_options,shixun.use_scope),class:"form-control shixun-setting-form",data:{id:shixun.id}) %> + + + <%= select_tag(:tag_repertoires, options_for_select(@shixun_tags,shixun.tag_repertoires.pluck(:id)),multiple:true,class:"form-control shixun-setting-form",data:{id:shixun.id},id:"tags-chosen-#{shixun.id}") %> + + + + -- + + + <%#= File.exist?(disk_filename("Shixun",shixun.id)) ? "重新上传" : "上传图片" %> + + <%# if File.exist?(disk_filename("Shixun",shixun.id)) %> + <%#= image_tag(url_to_avatar(shixun), :class => "w80 h80 fl ml5 shixun_image_show", :id => "shixun_image_show_#{shixun.id}") %> + <%# else %> + + <%# end %> + + +<%= link_to shixun.owner.try(:show_real_name),"/users/#{shixun.owner.login}",target:'_blank' %> + + <% if shixun.status.to_i < 3 %> + <%= link_to "关闭", admins_shixun_setting_path(shixun,status:3,page_no:page_no),method: :put, :class => "", :remote => true %> + <% else %> + 已关闭 + <% end %> + + + <%= check_box_tag :can_copy,!shixun.can_copy,shixun.can_copy,remote:true,data:{id:shixun.id},class:"shixun-setting-form" %> + + + + + + <%= check_box_tag :webssh,(shixun.webssh == 1 ? 0 : 1),(shixun.webssh == 1 ? true : false),remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form",title:"ssh" %> + <%= check_box_tag :hidden,!shixun.hidden,shixun.hidden,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"隐藏"%> + <%= check_box_tag :homepage_show,!shixun.homepage_show,shixun.homepage_show,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form",title:"首页" %> + <%= check_box_tag :task_pass,!shixun.task_pass,shixun.task_pass,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"跳关"%> + <%= check_box_tag :code_hidden,!shixun.code_hidden,shixun.code_hidden,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"隐藏目录"%> + + + \ No newline at end of file diff --git a/app/views/admins/shixun_settings/update.js.erb b/app/views/admins/shixun_settings/update.js.erb new file mode 100644 index 000000000..bd98a01af --- /dev/null +++ b/app/views/admins/shixun_settings/update.js.erb @@ -0,0 +1 @@ +$("#setting-item-<%= @shixun.id %>").html("<%= j render partial: "admins/shixun_settings/shared/td",locals: {shixun: @shixun,page_no:@page_no} %>") \ No newline at end of file diff --git a/app/views/admins/shixuns/index.html.erb b/app/views/admins/shixuns/index.html.erb new file mode 100644 index 000000000..5dea7fda5 --- /dev/null +++ b/app/views/admins/shixuns/index.html.erb @@ -0,0 +1,33 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('实训列表', admins_shixuns_path) %> +<% end %> + +
    + <%= form_tag(admins_shixuns_path, method: :get, class: 'form-inline search-form', remote: true) do %> +
    + + <% status_options = [['全部', ''], ["编辑中(#{@editing_shixuns})", "editing"], ["待审核(#{@pending_shixuns})", 'pending'], ["已发布(#{@processed_shixuns})", 'processed'],["已关闭(#{@closed_shixuns})",'closed']] %> + <%= select_tag(:status, options_for_select(status_options), class: 'form-control') %> +
    + +
    + + <%= select_tag(:tag, options_for_select(@shixuns_type_check.unshift(["",nil])), class: 'form-control',id:"tag-choosed") %> +
    + +
    + + <% auto_trial_options = [['创建者姓名', 0], ['实训名称', 1], ['学校名称', 2]] %> + <%= select_tag(:search_type, options_for_select(auto_trial_options), class: 'form-control') %> +
    + <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '输入关键字搜索') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3') %> + <%= link_to "清除",admins_shixuns_path(status:nil,tag:nil,search_type:nil,keyword:nil),class: "btn btn-default" %> + <% end %> + " class="btn btn-primary" id="shixun_xls">导出 + +
    + +
    + <%= render partial: 'admins/shixuns/shared/list', locals: { shixuns: @shixuns } %> +
    diff --git a/app/views/admins/shixuns/index.js.erb b/app/views/admins/shixuns/index.js.erb new file mode 100644 index 000000000..a53098853 --- /dev/null +++ b/app/views/admins/shixuns/index.js.erb @@ -0,0 +1 @@ +$(".shixuns-list-container").html("<%= j render partial: "admins/shixuns/shared/list",locals: {shixuns:@shixuns} %>") \ No newline at end of file diff --git a/app/views/admins/shixuns/shared/_list.html.erb b/app/views/admins/shixuns/shared/_list.html.erb new file mode 100644 index 000000000..9d0c34b5f --- /dev/null +++ b/app/views/admins/shixuns/shared/_list.html.erb @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + <% shixuns.each_with_index do |shixun,index| %> + + + + + + + + + + + + + + + <% end %> + +
    序号ID实训名称技术平台Fork源实践选择状态创建者<%= sort_tag('创建于', name: 'created_at', path: admins_shixuns_path) %>单测操作
    <%= (@params_page.to_i - 1) * 20 + index + 1%><%= shixun.identifier %><%= link_to overflow_hidden_span(shixun.name), "/shixuns/#{shixun.identifier}", :target => "_blank", :title => shixun.name %> + <%= shixun.shixun_main_name.nil? ? "--" : shixun.shixun_main_name %> + + <% if shixun.try(:fork_from).nil? %> + -- + <% else%> + <%= link_to shixun.try(:identifier), shixun_path(shixun.try(:identifier)), target: '_blank'%> + <% end%> + <%= shixun.challenges.where(:st => 0).size %><%= shixun.challenges.where(:st => 1).size %><%= shixun_authentication_status shixun %><%= link_to shixun.owner.try(:show_real_name),"/users/#{shixun.owner.try(:login)}",target:'_blank' %><%= format_time shixun.created_at %> + class="ml-3 mr5 magic-checkbox" id="join_teacher_homepage_<%= shixun.id %>"> + + + <% if shixun.status == 0 %> + <%= link_to(l(:button_delete), admins_shixun_path(shixun), :method => :delete, :data => { confirm: "您确定要删除吗?" } ) %> + <% end %> +
    + +<%= render partial: 'admins/shared/paginate', locals: { objects: shixuns } %> \ No newline at end of file diff --git a/app/views/admins/subject_authorizations/index.html.erb b/app/views/admins/subject_authorizations/index.html.erb index 3d5539663..522278a3d 100644 --- a/app/views/admins/subject_authorizations/index.html.erb +++ b/app/views/admins/subject_authorizations/index.html.erb @@ -21,7 +21,7 @@ <%= select_tag(:status, options_for_select(status_options), class: 'form-control') %> <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '实训课程名称检索') %> - <%= submit_tag('搜索', class: 'btn btn-primary ml-3') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <% end %> diff --git a/app/views/admins/users/index.html.erb b/app/views/admins/users/index.html.erb index 5d2af36c3..b145edd24 100644 --- a/app/views/admins/users/index.html.erb +++ b/app/views/admins/users/index.html.erb @@ -24,7 +24,7 @@ <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: 'ID/姓名/邮箱/手机号检索') %> <%= text_field_tag(:school_name, params[:school_name], class: 'form-control col-sm-2', placeholder: '学校/单位检索') %> - <%= submit_tag('搜索', class: 'btn btn-primary ml-3') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <% end %> diff --git a/app/views/admins/users/index.json.jbuilder b/app/views/admins/users/index.json.jbuilder new file mode 100644 index 000000000..5591474a4 --- /dev/null +++ b/app/views/admins/users/index.json.jbuilder @@ -0,0 +1,6 @@ +json.count @users.total_count +json.users do + json.array! @users.each do |user| + json.extract! user, :id, :login, :real_name, :identity, :school_name + end +end \ No newline at end of file diff --git a/app/views/admins/users/shared/_reward_grade_modal.html.erb b/app/views/admins/users/shared/_reward_grade_modal.html.erb index 87c74c499..2cf741906 100644 --- a/app/views/admins/users/shared/_reward_grade_modal.html.erb +++ b/app/views/admins/users/shared/_reward_grade_modal.html.erb @@ -2,7 +2,7 @@