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 @@
部门名称 | +单位名称 | +用户数 | +已职业认证 | +部门管理员 | +统计链接 | +云主机数 | +<%= sort_tag('创建时间', name: 'created_at', path: admins_departments_path) %> | +操作 | +
---|---|---|---|---|---|---|---|---|
头像 | +姓名 | +教学案例 | +案例描述 | +时间 | + <% if is_processed %> +拒绝原因 | +状态 | + <% else %> +操作 | + <% end %> +
---|---|---|---|---|---|---|---|
+ <%= link_to "/users/#{user.login}", class: 'professional-authentication-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %>
+ |
+ <%= 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') %> | + + <% if is_processed %> +<%= overflow_hidden_span apply.reason %> | +<%= t("library_apply.status.#{apply.status}") %> | + <% else %> ++ <%= 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}") + }) %> + | + <% end %> +
序号 | +ID | +实训名称 | +技术平台 | +权限 | +技术体系 | +上传图片 | +创建者 | +关闭 | +复制 | +代码执行时间 | +
+ 操作
+
+ ssh/隐藏/首页/跳关/隐藏目录
+
+ |
+
+
+ <% shixun_settings.each_with_index do |shixun,index| %>
+
---|
序号 | +ID | +实训名称 | +技术平台 | +Fork源 | +实践 | +选择 | +状态 | +创建者 | +<%= sort_tag('创建于', name: 'created_at', path: admins_shixuns_path) %> | +单测 | +操作 | + + + <% shixuns.each_with_index do |shixun,index| %> +
---|---|---|---|---|---|---|---|---|---|---|---|
<%= (@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 %> + | +
"+(escaped?code:escape(code,true))+"\n
"}return''+(escaped?code:escape(code,true))+"\n
\n"};Renderer.prototype.blockquote=function(quote){return"\n"+quote+"\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"
"+text+"
\n"};Renderer.prototype.table=function(header,body){return""+text+"
"};Renderer.prototype.br=function(){return this.options.xhtml?""+escape(e.message+"",true)+""}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else{if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); \ No newline at end of file +/** + * marked - a markdown parser + * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + 2019 08 29 + + case"html":return this.renderer.html((this.token.text)); + --> + case"html":return this.renderer.paragraph(this.inline.output(this.token.text)); + + add: && !(e instanceof String) + */ +!function(e){"use strict";var x={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:/^ {0,3}(`{3,}|~{3,})([^`~\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,nptable:g,table:g,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/,text:/^[^\n]+/};function a(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||k.defaults,this.rules=x.normal,this.options.pedantic?this.rules=x.pedantic:this.options.gfm&&(this.rules=x.gfm)}x._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,x._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,x.def=i(x.def).replace("label",x._label).replace("title",x._title).getRegex(),x.bullet=/(?:[*+-]|\d{1,9}\.)/,x.item=/^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/,x.item=i(x.item,"gm").replace(/bull/g,x.bullet).getRegex(),x.list=i(x.list).replace(/bull/g,x.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+x.def.source+")").getRegex(),x._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",x._comment=//,x.html=i(x.html,"i").replace("comment",x._comment).replace("tag",x._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),x.paragraph=i(x._paragraph).replace("hr",x.hr).replace("heading"," {0,3}#{1,6} +").replace("|lheading","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}|~{3,})[^`\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)").replace("tag",x._tag).getRegex(),x.blockquote=i(x.blockquote).replace("paragraph",x.paragraph).getRegex(),x.normal=f({},x),x.gfm=f({},x.normal,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/}),x.pedantic=f({},x.normal,{html:i("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?\\1> *(?:\\n{2,}|\\s*$)|
'+(n?e:_(e,!0))+"
\n":""+(n?e:_(e,!0))+"
"},r.prototype.blockquote=function(e){return"\n"+e+"\n"},r.prototype.html=function(e){return e},r.prototype.heading=function(e,t,n,r){return this.options.headerIds?"
"+e+"
\n"},r.prototype.table=function(e,t){return t&&(t=""+t+""),""+e+"
"},r.prototype.br=function(){return this.options.xhtml?""+_(e.message+"",!0)+"";throw e}}g.exec=g,k.options=k.setOptions=function(e){return f(k.defaults,e),k},k.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new r,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,xhtml:!1}},k.defaults=k.getDefaults(),k.Parser=h,k.parser=h.parse,k.Renderer=r,k.TextRenderer=s,k.Lexer=a,k.lexer=a.lex,k.InlineLexer=p,k.inlineLexer=p.output,k.Slugger=t,k.parse=k,"undefined"!=typeof module&&"object"==typeof exports?module.exports=k:"function"==typeof define&&define.amd?define(function(){return k}):e.marked=k}(this||("undefined"!=typeof window?window:global)); \ No newline at end of file diff --git a/public/katex/katex.min.css b/public/katex/katex.min.css index d6fb8374d..7ef1dec98 100644 --- a/public/katex/katex.min.css +++ b/public/katex/katex.min.css @@ -1 +1,2 @@ -@font-face{font-family:KaTeX_AMS;src:url(fonts/KaTeX_AMS-Regular.eot);src:url(fonts/KaTeX_AMS-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_AMS-Regular.woff2) format('woff2'),url(fonts/KaTeX_AMS-Regular.woff) format('woff'),url(fonts/KaTeX_AMS-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Bold.eot);src:url(fonts/KaTeX_Caligraphic-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Caligraphic-Bold.woff2) format('woff2'),url(fonts/KaTeX_Caligraphic-Bold.woff) format('woff'),url(fonts/KaTeX_Caligraphic-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Regular.eot);src:url(fonts/KaTeX_Caligraphic-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Caligraphic-Regular.woff2) format('woff2'),url(fonts/KaTeX_Caligraphic-Regular.woff) format('woff'),url(fonts/KaTeX_Caligraphic-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Bold.eot);src:url(fonts/KaTeX_Fraktur-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Fraktur-Bold.woff2) format('woff2'),url(fonts/KaTeX_Fraktur-Bold.woff) format('woff'),url(fonts/KaTeX_Fraktur-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Regular.eot);src:url(fonts/KaTeX_Fraktur-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Fraktur-Regular.woff2) format('woff2'),url(fonts/KaTeX_Fraktur-Regular.woff) format('woff'),url(fonts/KaTeX_Fraktur-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Bold.eot);src:url(fonts/KaTeX_Main-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Bold.woff2) format('woff2'),url(fonts/KaTeX_Main-Bold.woff) format('woff'),url(fonts/KaTeX_Main-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Italic.eot);src:url(fonts/KaTeX_Main-Italic.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Italic.woff2) format('woff2'),url(fonts/KaTeX_Main-Italic.woff) format('woff'),url(fonts/KaTeX_Main-Italic.ttf) format('truetype');font-weight:400;font-style:italic}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Regular.eot);src:url(fonts/KaTeX_Main-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Regular.woff2) format('woff2'),url(fonts/KaTeX_Main-Regular.woff) format('woff'),url(fonts/KaTeX_Main-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Math;src:url(fonts/KaTeX_Math-Italic.eot);src:url(fonts/KaTeX_Math-Italic.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Math-Italic.woff2) format('woff2'),url(fonts/KaTeX_Math-Italic.woff) format('woff'),url(fonts/KaTeX_Math-Italic.ttf) format('truetype');font-weight:400;font-style:italic}@font-face{font-family:KaTeX_SansSerif;src:url(fonts/KaTeX_SansSerif-Regular.eot);src:url(fonts/KaTeX_SansSerif-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_SansSerif-Regular.woff2) format('woff2'),url(fonts/KaTeX_SansSerif-Regular.woff) format('woff'),url(fonts/KaTeX_SansSerif-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Script;src:url(fonts/KaTeX_Script-Regular.eot);src:url(fonts/KaTeX_Script-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Script-Regular.woff2) format('woff2'),url(fonts/KaTeX_Script-Regular.woff) format('woff'),url(fonts/KaTeX_Script-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size1;src:url(fonts/KaTeX_Size1-Regular.eot);src:url(fonts/KaTeX_Size1-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size1-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size1-Regular.woff) format('woff'),url(fonts/KaTeX_Size1-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size2;src:url(fonts/KaTeX_Size2-Regular.eot);src:url(fonts/KaTeX_Size2-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size2-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size2-Regular.woff) format('woff'),url(fonts/KaTeX_Size2-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size3;src:url(fonts/KaTeX_Size3-Regular.eot);src:url(fonts/KaTeX_Size3-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size3-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size3-Regular.woff) format('woff'),url(fonts/KaTeX_Size3-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size4;src:url(fonts/KaTeX_Size4-Regular.eot);src:url(fonts/KaTeX_Size4-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size4-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size4-Regular.woff) format('woff'),url(fonts/KaTeX_Size4-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Typewriter;src:url(fonts/KaTeX_Typewriter-Regular.eot);src:url(fonts/KaTeX_Typewriter-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Typewriter-Regular.woff2) format('woff2'),url(fonts/KaTeX_Typewriter-Regular.woff) format('woff'),url(fonts/KaTeX_Typewriter-Regular.ttf) format('truetype');font-weight:400;font-style:normal}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:inline-block;text-align:initial}.katex{font:400 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;white-space:nowrap;text-indent:0}.katex .katex-html{display:inline-block}.katex .katex-mathml{position:absolute;clip:rect(1px,1px,1px,1px);padding:0;border:0;height:1px;width:1px;overflow:hidden}.katex .base,.katex .strut{display:inline-block}.katex .mathrm{font-style:normal}.katex .textit{font-style:italic}.katex .mathit{font-family:KaTeX_Math;font-style:italic}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .amsrm,.katex .mathbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr{font-family:KaTeX_Script}.katex .mathsf{font-family:KaTeX_SansSerif}.katex .mainit{font-family:KaTeX_Main;font-style:italic}.katex .mord+.mop{margin-left:.16667em}.katex .mord+.mbin{margin-left:.22222em}.katex .mord+.mrel{margin-left:.27778em}.katex .mop+.mop,.katex .mop+.mord,.katex .mord+.minner{margin-left:.16667em}.katex .mop+.mrel{margin-left:.27778em}.katex .mop+.minner{margin-left:.16667em}.katex .mbin+.minner,.katex .mbin+.mop,.katex .mbin+.mopen,.katex .mbin+.mord{margin-left:.22222em}.katex .mrel+.minner,.katex .mrel+.mop,.katex .mrel+.mopen,.katex .mrel+.mord{margin-left:.27778em}.katex .mclose+.mop{margin-left:.16667em}.katex .mclose+.mbin{margin-left:.22222em}.katex .mclose+.mrel{margin-left:.27778em}.katex .mclose+.minner,.katex .minner+.mop,.katex .minner+.mord,.katex .mpunct+.mclose,.katex .mpunct+.minner,.katex .mpunct+.mop,.katex .mpunct+.mopen,.katex .mpunct+.mord,.katex .mpunct+.mpunct,.katex .mpunct+.mrel{margin-left:.16667em}.katex .minner+.mbin{margin-left:.22222em}.katex .minner+.mrel{margin-left:.27778em}.katex .minner+.minner,.katex .minner+.mopen,.katex .minner+.mpunct{margin-left:.16667em}.katex .mbin.mtight,.katex .mclose.mtight,.katex .minner.mtight,.katex .mop.mtight,.katex .mopen.mtight,.katex .mord.mtight,.katex .mpunct.mtight,.katex .mrel.mtight{margin-left:0}.katex .mclose+.mop.mtight,.katex .minner+.mop.mtight,.katex .mop+.mop.mtight,.katex .mop+.mord.mtight,.katex .mord+.mop.mtight{margin-left:.16667em}.katex .reset-textstyle.textstyle{font-size:1em}.katex .reset-textstyle.scriptstyle{font-size:.7em}.katex .reset-textstyle.scriptscriptstyle{font-size:.5em}.katex .reset-scriptstyle.textstyle{font-size:1.42857em}.katex .reset-scriptstyle.scriptstyle{font-size:1em}.katex .reset-scriptstyle.scriptscriptstyle{font-size:.71429em}.katex .reset-scriptscriptstyle.textstyle{font-size:2em}.katex .reset-scriptscriptstyle.scriptstyle{font-size:1.4em}.katex .reset-scriptscriptstyle.scriptscriptstyle{font-size:1em}.katex .style-wrap{position:relative}.katex .vlist{display:inline-block}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist .baseline-fix{display:inline-table;table-layout:fixed}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{width:100%}.katex .mfrac .frac-line:before{border-bottom-style:solid;border-bottom-width:1px;content:"";display:block}.katex .mfrac .frac-line:after{border-bottom-style:solid;border-bottom-width:.04em;content:"";display:block;margin-top:-1px}.katex .mspace{display:inline-block}.katex .mspace.negativethinspace{margin-left:-.16667em}.katex .mspace.thinspace{width:.16667em}.katex .mspace.negativemediumspace{margin-left:-.22222em}.katex .mspace.mediumspace{width:.22222em}.katex .mspace.thickspace{width:.27778em}.katex .mspace.sixmuspace{width:.333333em}.katex .mspace.eightmuspace{width:.444444em}.katex .mspace.enspace{width:.5em}.katex .mspace.twelvemuspace{width:.666667em}.katex .mspace.quad{width:1em}.katex .mspace.qquad{width:2em}.katex .llap,.katex .rlap{width:0;position:relative}.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .rlap>.inner{left:0}.katex .katex-logo .a{font-size:.75em;margin-left:-.32em;position:relative;top:-.2em}.katex .katex-logo .t{margin-left:-.23em}.katex .katex-logo .e{margin-left:-.1667em;position:relative;top:.2155em}.katex .katex-logo .x{margin-left:-.125em}.katex .rule{display:inline-block;border:0 solid;position:relative}.katex .overline .overline-line,.katex .underline .underline-line{width:100%}.katex .overline .overline-line:before,.katex .underline .underline-line:before{border-bottom-style:solid;border-bottom-width:1px;content:"";display:block}.katex .overline .overline-line:after,.katex .underline .underline-line:after{border-bottom-style:solid;border-bottom-width:.04em;content:"";display:block;margin-top:-1px}.katex .sqrt>.sqrt-sign{position:relative}.katex .sqrt .sqrt-line{width:100%}.katex .sqrt .sqrt-line:before{border-bottom-style:solid;border-bottom-width:1px;content:"";display:block}.katex .sqrt .sqrt-line:after{border-bottom-style:solid;border-bottom-width:.04em;content:"";display:block;margin-top:-1px}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer,.katex .sizing{display:inline-block}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:2em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:3.46em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:4.14em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.98em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.47142857em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.95714286em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.55714286em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.875em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.125em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.25em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.5em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.8em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.1625em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.5875em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:3.1125em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.77777778em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.88888889em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.6em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.92222222em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.3em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.76666667em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.7em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.8em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.9em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.2em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.44em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.73em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:2.07em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.49em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.58333333em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.66666667em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.75em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.83333333em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44166667em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.725em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.075em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.48611111em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.55555556em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.625em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.69444444em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.20138889em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.4375em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72916667em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.28901734em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.40462428em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.46242775em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.52023121em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.57803468em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69364162em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83236994em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.19653179em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.43930636em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.24154589em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.33816425em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.38647343em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.43478261em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.48309179em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.57971014em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69565217em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83574879em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20289855em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.20080321em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.2811245em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.32128514em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.36144578em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.40160643em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48192771em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57831325em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69477912em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.8313253em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist>span,.katex .op-limits>.vlist>span{text-align:center}.katex .accent .accent-body>span{width:0}.katex .accent .accent-body.accent-vec>span{position:relative;left:.326em}.katex .mtable .vertical-separator{display:inline-block;margin:0 -.025em;border-right:.05em solid #000}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist{text-align:center}.katex .mtable .col-align-l>.vlist{text-align:left}.katex .mtable .col-align-r>.vlist{text-align:right} \ No newline at end of file +/* https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/katex.min.css */ +@font-face{font-family:KaTeX_AMS;src:url(fonts/KaTeX_AMS-Regular.woff2) format("woff2"),url(fonts/KaTeX_AMS-Regular.woff) format("woff"),url(fonts/KaTeX_AMS-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Bold.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Regular.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Bold.woff) format("woff"),url(fonts/KaTeX_Fraktur-Bold.ttf) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Regular.woff) format("woff"),url(fonts/KaTeX_Fraktur-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Bold.woff2) format("woff2"),url(fonts/KaTeX_Main-Bold.woff) format("woff"),url(fonts/KaTeX_Main-Bold.ttf) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Main-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Main-BoldItalic.ttf) format("truetype");font-weight:700;font-style:italic}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Italic.woff2) format("woff2"),url(fonts/KaTeX_Main-Italic.woff) format("woff"),url(fonts/KaTeX_Main-Italic.ttf) format("truetype");font-weight:400;font-style:italic}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Regular.woff2) format("woff2"),url(fonts/KaTeX_Main-Regular.woff) format("woff"),url(fonts/KaTeX_Main-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Math;src:url(fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Math-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Math-BoldItalic.ttf) format("truetype");font-weight:700;font-style:italic}@font-face{font-family:KaTeX_Math;src:url(fonts/KaTeX_Math-Italic.woff2) format("woff2"),url(fonts/KaTeX_Math-Italic.woff) format("woff"),url(fonts/KaTeX_Math-Italic.ttf) format("truetype");font-weight:400;font-style:italic}@font-face{font-family:"KaTeX_SansSerif";src:url(fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Bold.woff) format("woff"),url(fonts/KaTeX_SansSerif-Bold.ttf) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:"KaTeX_SansSerif";src:url(fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Italic.woff) format("woff"),url(fonts/KaTeX_SansSerif-Italic.ttf) format("truetype");font-weight:400;font-style:italic}@font-face{font-family:"KaTeX_SansSerif";src:url(fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Regular.woff) format("woff"),url(fonts/KaTeX_SansSerif-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Script;src:url(fonts/KaTeX_Script-Regular.woff2) format("woff2"),url(fonts/KaTeX_Script-Regular.woff) format("woff"),url(fonts/KaTeX_Script-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size1;src:url(fonts/KaTeX_Size1-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size1-Regular.woff) format("woff"),url(fonts/KaTeX_Size1-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size2;src:url(fonts/KaTeX_Size2-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size2-Regular.woff) format("woff"),url(fonts/KaTeX_Size2-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size3;src:url(fonts/KaTeX_Size3-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size3-Regular.woff) format("woff"),url(fonts/KaTeX_Size3-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size4;src:url(fonts/KaTeX_Size4-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size4-Regular.woff) format("woff"),url(fonts/KaTeX_Size4-Regular.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Typewriter;src:url(fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(fonts/KaTeX_Typewriter-Regular.woff) format("woff"),url(fonts/KaTeX_Typewriter-Regular.ttf) format("truetype");font-weight:400;font-style:normal}.katex{font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0;text-rendering:auto}.katex *{-ms-high-contrast-adjust:none!important}.katex .katex-version:after{content:"0.11.0"}.katex .katex-mathml{position:absolute;clip:rect(1px,1px,1px,1px);padding:0;border:0;height:1px;width:1px;overflow:hidden}.katex .katex-html>.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathdefault{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-weight:700;font-style:italic}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;vertical-align:bottom;position:relative}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;vertical-align:bottom;font-size:1px;width:2px;min-width:2px}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{display:inline-block;width:100%;border-bottom-style:solid}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{width:0;position:relative}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{display:inline-block;border:0 solid;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{display:inline-block;width:100%;border-bottom-style:solid}.katex .hdashline{display:inline-block;width:100%;border-bottom-style:dashed}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .op-limits>.vlist-t{text-align:center}.katex .accent>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{display:block;position:absolute;width:100%;height:inherit;fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1}.katex svg path{stroke:none}.katex img{border-style:none;min-width:0;min-height:0;max-width:none;max-height:none}.katex .stretchy{width:100%;display:block;position:relative;overflow:hidden}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{width:100%;position:relative;overflow:hidden}.katex .halfarrow-left{position:absolute;left:0;width:50.2%;overflow:hidden}.katex .halfarrow-right{position:absolute;right:0;width:50.2%;overflow:hidden}.katex .brace-left{position:absolute;left:0;width:25.1%;overflow:hidden}.katex .brace-center{position:absolute;left:25%;width:50%;overflow:hidden}.katex .brace-right{position:absolute;right:0;width:25.1%;overflow:hidden}.katex .x-arrow-pad{padding:0 .5em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{box-sizing:border-box;border:.04em solid}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{text-align:left} \ No newline at end of file diff --git a/public/katex/katex.min.js b/public/katex/katex.min.js index b8df4cc0c..9219684be 100644 --- a/public/katex/katex.min.js +++ b/public/katex/katex.min.js @@ -1,4 +1,2 @@ -(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.katex=e()}})(function(){var e,t,r;return function a(e,t,r){function i(s,l){if(!t[s]){if(!e[s]){var o=typeof require=="function"&&require;if(!l&&o)return o(s,!0);if(n)return n(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var p=t[s]={exports:{}};e[s][0].call(p.exports,function(t){var r=e[s][1][t];return i(r?r:t)},p,p.exports,a,e,t,r)}return t[s].exports}var n=typeof require=="function"&&require;for(var s=0;s
0&&(e="."===(e=t)?null:e),e};Jt({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,greediness:6,argTypes:["math","math","size","text","math","math"]},handler:function(t,e){var r=t.parser,a=e[4],n=e[5],i=Ft(e[0],"atom");i&&(i=Vt(e[0],"open"));var o=i?Er(i.text):null,s=Ft(e[1],"atom");s&&(s=Vt(e[1],"close"));var h,l=s?Er(s.text):null,m=Dt(e[2],"size"),c=null;h=!!m.isBlank||(c=m.value).number>0;var u="auto",p=Ft(e[3],"ordgroup");if(p){if(p.body.length>0){var d=Dt(p.body[0],"textord");u=Or[Number(d.text)]}}else p=Dt(e[3],"textord"),u=Or[Number(p.text)];return{type:"genfrac",mode:r.mode,numer:a,denom:n,continued:!1,hasBarLine:h,barSize:c,leftDelim:o,rightDelim:l,size:u}},htmlBuilder:Ir,mathmlBuilder:Rr}),Jt({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:function(t,e){var r=t.parser,a=(t.funcName,t.token);return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:Dt(e[0],"size").value,token:a}}}),Jt({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:function(t,e){var r=t.parser,a=(t.funcName,e[0]),n=function(t){if(!t)throw new Error("Expected non-null, but got "+String(t));return t}(Dt(e[1],"infix").size),i=e[2],o=n.number>0;return{type:"genfrac",mode:r.mode,numer:a,denom:i,continued:!1,hasBarLine:o,barSize:n,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:Ir,mathmlBuilder:Rr});var Lr=function(t,e){var r,a,n=e.style,i=Ft(t,"supsub");i?(r=i.sup?ce(i.sup,e.havingStyle(n.sup()),e):ce(i.sub,e.havingStyle(n.sub()),e),a=Dt(i.base,"horizBrace")):a=Dt(t,"horizBrace");var o,s=ce(a.base,e.havingBaseStyle(w.DISPLAY)),h=Re(a,e);if(a.isOver?(o=Pt.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:h}]},e)).children[0].children[0].children[1].classes.push("svg-align"):(o=Pt.makeVList({positionType:"bottom",positionData:s.depth+.1+h.height,children:[{type:"elem",elem:h},{type:"kern",size:.1},{type:"elem",elem:s}]},e)).children[0].children[0].children[0].classes.push("svg-align"),r){var l=Pt.makeSpan(["mord",a.isOver?"mover":"munder"],[o],e);o=a.isOver?Pt.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:l},{type:"kern",size:.2},{type:"elem",elem:r}]},e):Pt.makeVList({positionType:"bottom",positionData:l.depth+.2+r.height+r.depth,children:[{type:"elem",elem:r},{type:"kern",size:.2},{type:"elem",elem:l}]},e)}return Pt.makeSpan(["mord",a.isOver?"mover":"munder"],[o],e)};Jt({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:function(t,e){var r=t.parser,a=t.funcName;return{type:"horizBrace",mode:r.mode,label:a,isOver:/^\\over/.test(a),base:e[0]}},htmlBuilder:Lr,mathmlBuilder:function(t,e){var r=Ie(t.label);return new xe.MathNode(t.isOver?"mover":"munder",[Se(t.base,e),r])}}),Jt({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:function(t,e){var r=t.parser,a=e[1],n=Dt(e[0],"url").url;return r.settings.isTrusted({command:"\\href",url:n})?{type:"href",mode:r.mode,href:n,body:te(a)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:function(t,e){var r=oe(t.body,e,!1);return Pt.makeAnchor(t.href,[],r,e)},mathmlBuilder:function(t,e){var r=ke(t.body,e);return r instanceof fe||(r=new fe("mrow",[r])),r.setAttribute("href",t.href),r}}),Jt({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:function(t,e){var r=t.parser,a=Dt(e[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:a}))return r.formatUnsupportedCmd("\\url");for(var n=[],i=0;i0&&(u+=M,p-=M)}var z=[{type:"elem",elem:n,shift:p,marginRight:b,marginLeft:y},{type:"elem",elem:a,shift:-u,marginRight:b}];x=Pt.makeVList({positionType:"individualShift",children:z},e)}else if(n){p=Math.max(p,m.sub1,n.height-.8*m.xHeight);var T=[{type:"elem",elem:n,marginLeft:y,marginRight:b}];x=Pt.makeVList({positionType:"shift",positionData:p,children:T},e)}else{if(!a)throw new Error("supsub must have either sup or sub.");u=Math.max(u,i,a.depth+.25*m.xHeight),x=Pt.makeVList({positionType:"shift",positionData:-u,children:[{type:"elem",elem:a,marginRight:b}]},e)}var A=le(l,"right")||"mord";return Pt.makeSpan([A],[l,Pt.makeSpan(["msupsub"],[x])],e)},mathmlBuilder:function(t,e){var r,a=!1,n=Ft(t.base,"horizBrace");n&&!!t.sup===n.isOver&&(a=!0,r=n.isOver),!t.base||"op"!==t.base.type&&"operatorname"!==t.base.type||(t.base.parentIsSupSub=!0);var i,o=[Se(t.base,e)];if(t.sub&&o.push(Se(t.sub,e)),t.sup&&o.push(Se(t.sup,e)),a)i=r?"mover":"munder";else if(t.sub)if(t.sup){var s=t.base;i=s&&"op"===s.type&&s.limits&&e.style===w.DISPLAY?"munderover":s&&"operatorname"===s.type&&s.alwaysHandleSupSub&&(e.style===w.DISPLAY||s.limits)?"munderover":"msubsup"}else{var h=t.base;i=h&&"op"===h.type&&h.limits&&(e.style===w.DISPLAY||h.alwaysHandleSupSub)?"munder":h&&"operatorname"===h.type&&h.alwaysHandleSupSub&&(h.limits||e.style===w.DISPLAY)?"munder":"msub"}else{var l=t.base;i=l&&"op"===l.type&&l.limits&&(e.style===w.DISPLAY||l.alwaysHandleSupSub)?"mover":l&&"operatorname"===l.type&&l.alwaysHandleSupSub&&(l.limits||e.style===w.DISPLAY)?"mover":"msup"}return new xe.MathNode(i,o)}}),Qt({type:"atom",htmlBuilder:function(t,e){return Pt.mathsym(t.text,t.mode,e,["m"+t.family])},mathmlBuilder:function(t,e){var r=new xe.MathNode("mo",[ve(t.text,t.mode)]);if("bin"===t.family){var a=ye(t,e);"bold-italic"===a&&r.setAttribute("mathvariant",a)}else"punct"===t.family?r.setAttribute("separator","true"):"open"!==t.family&&"close"!==t.family||r.setAttribute("stretchy","false");return r}});var $r={mi:"italic",mn:"normal",mtext:"normal"};Qt({type:"mathord",htmlBuilder:function(t,e){return Pt.makeOrd(t,e,"mathord")},mathmlBuilder:function(t,e){var r=new xe.MathNode("mi",[ve(t.text,t.mode,e)]),a=ye(t,e)||"italic";return a!==$r[r.type]&&r.setAttribute("mathvariant",a),r}}),Qt({type:"textord",htmlBuilder:function(t,e){return Pt.makeOrd(t,e,"textord")},mathmlBuilder:function(t,e){var r,a=ve(t.text,t.mode,e),n=ye(t,e)||"normal";return r="text"===t.mode?new xe.MathNode("mtext",[a]):/[0-9]/.test(t.text)?new xe.MathNode("mn",[a]):"\\prime"===t.text?new xe.MathNode("mo",[a]):new xe.MathNode("mi",[a]),n!==$r[r.type]&&r.setAttribute("mathvariant",n),r}});var Zr={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},Kr={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};Qt({type:"spacing",htmlBuilder:function(t,e){if(Kr.hasOwnProperty(t.text)){var r=Kr[t.text].className||"";if("text"===t.mode){var a=Pt.makeOrd(t,e,"textord");return a.classes.push(r),a}return Pt.makeSpan(["mspace",r],[Pt.mathsym(t.text,t.mode,e)],e)}if(Zr.hasOwnProperty(t.text))return Pt.makeSpan(["mspace",Zr[t.text]],[],e);throw new o('Unknown type of space "'+t.text+'"')},mathmlBuilder:function(t,e){if(!Kr.hasOwnProperty(t.text)){if(Zr.hasOwnProperty(t.text))return new xe.MathNode("mspace");throw new o('Unknown type of space "'+t.text+'"')}return new xe.MathNode("mtext",[new xe.TextNode("\xa0")])}});var Jr=function(){var t=new xe.MathNode("mtd",[]);return t.setAttribute("width","50%"),t};Qt({type:"tag",mathmlBuilder:function(t,e){var r=new xe.MathNode("mtable",[new xe.MathNode("mtr",[Jr(),new xe.MathNode("mtd",[ke(t.body,e)]),Jr(),new xe.MathNode("mtd",[ke(t.tag,e)])])]);return r.setAttribute("width","100%"),r}});var Qr={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},ta={"\\textbf":"textbf","\\textmd":"textmd"},ea={"\\textit":"textit","\\textup":"textup"},ra=function(t,e){var r=t.font;return r?Qr[r]?e.withTextFontFamily(Qr[r]):ta[r]?e.withTextFontWeight(ta[r]):e.withTextFontShape(ea[r]):e};Jt({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],greediness:2,allowedInText:!0,consumeMode:"text"},handler:function(t,e){var r=t.parser,a=t.funcName,n=e[0];return{type:"text",mode:r.mode,body:te(n),font:a}},htmlBuilder:function(t,e){var r=ra(t,e),a=oe(t.body,r,!0);return Pt.makeSpan(["mord","text"],Pt.tryCombineChars(a),r)},mathmlBuilder:function(t,e){var r=ra(t,e);return ke(t.body,r)}}),Jt({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:function(t,e){return{type:"underline",mode:t.parser.mode,body:e[0]}},htmlBuilder:function(t,e){var r=ce(t.body,e),a=Pt.makeLineSpan("underline-line",e),n=e.fontMetrics().defaultRuleThickness,i=Pt.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:n},{type:"elem",elem:a},{type:"kern",size:3*n},{type:"elem",elem:r}]},e);return Pt.makeSpan(["mord","underline"],[i],e)},mathmlBuilder:function(t,e){var r=new xe.MathNode("mo",[new xe.TextNode("\u203e")]);r.setAttribute("stretchy","true");var a=new xe.MathNode("munder",[Se(t.body,e),r]);return a.setAttribute("accentunder","true"),a}}),Jt({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler:function(t,e,r){throw new o("\\verb ended by end of line instead of matching delimiter")},htmlBuilder:function(t,e){for(var r=aa(t),a=[],n=e.havingStyle(e.style.text()),i=0;i' + text + '';
+ }
+ };
markedRenderer.paragraph = function(text) {
var isTeXInline = /\$\$(.*)\$\$/g.test(text);
diff --git a/public/react/public/js/js_min_all.js b/public/react/public/js/js_min_all.js
index 0d56d86ba..6d0838c59 100755
--- a/public/react/public/js/js_min_all.js
+++ b/public/react/public/js/js_min_all.js
@@ -71,6 +71,7 @@ function AssertException(message){this.message=message}function assert(exp,messa
/*! jQuery.flowchart.js v1.1.0 | jquery.flowchart.min.js | jQuery plugin for flowchart.js. | MIT License | By: Pandao | https://github.com/pandao/jquery.flowchart.js | 2015-03-09 */
(function(factory){if(typeof require==="function"&&typeof exports==="object"&&typeof module==="object"){module.exports=factory}else{if(typeof define==="function"){factory(jQuery,flowchart)}else{factory($,flowchart)}}}(function(jQuery,flowchart){(function($){$.fn.flowChart=function(options){options=options||{};var defaults={"x":0,"y":0,"line-width":2,"line-length":50,"text-margin":10,"font-size":14,"font-color":"black","line-color":"black","element-color":"black","fill":"white","yes-text":"yes","no-text":"no","arrow-end":"block","symbols":{"start":{"font-color":"black","element-color":"black","fill":"white"},"end":{"class":"end-element"}},"flowstate":{"past":{"fill":"#CCCCCC","font-size":12},"current":{"fill":"black","font-color":"white","font-weight":"bold"},"future":{"fill":"white"},"request":{"fill":"blue"},"invalid":{"fill":"#444444"},"approved":{"fill":"#58C4A3","font-size":12,"yes-text":"APPROVED","no-text":"n/a"},"rejected":{"fill":"#C45879","font-size":12,"yes-text":"n/a","no-text":"REJECTED"}}};return this.each(function(){var $this=$(this);var diagram=flowchart.parse($this.text());var settings=$.extend(true,defaults,options);$this.html("");diagram.drawSVG(this,settings)})}})(jQuery)}));
+
/*
* Editor.md
*
@@ -82,7 +83,8 @@ function AssertException(message){this.message=message}function assert(exp,messa
* {@link https://github.com/pandao/editor.md}
* @updateTime 2015-06-09
*/
-function initEditormdPasteUpload(e,i,o){e.cm.getInputField().addEventListener("paste",function(o){_whenPasterDoUpload(o,i,function(i){i.id&&e.cm.replaceSelection("")})})}!function(e){"use strict";"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?module.exports=e:"function"==typeof define?define.amd||define(["../../../../editormd/examples/js/jquery.min"],e):window.editormd=e()}(function(){"use strict";var e="undefined"!=typeof jQuery?jQuery:Zepto;if(void 0!==e){var t,i,o,r=function(e,t){return new r.fn.init(e,t)};r.title=r.$name="Editor.md",r.version="1.5.0",r.homePage="https://pandao.github.io/editor.md/",r.classPrefix="editormd-",r.toolbarModes={full:["undo","redo","|","bold","del","italic","quote","ucwords","uppercase","lowercase","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","link","reference-link","image","code","preformatted-text","code-block","table","datetime","emoji","html-entities","pagebreak","|","goto-line","watch","preview","fullscreen","clear","search","|","help","info"],simple:["undo","redo","|","bold","del","italic","quote","uppercase","lowercase","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","watch","preview","fullscreen","|","help","info"],mini:["undo","redo","|","watch","preview","|","help","info"]},r.defaults={mode:"gfm",name:"",value:"",theme:"",editorTheme:"default",previewTheme:"",markdown:"",appendMarkdown:"",width:"100%",height:"100%",path:"./lib/",pluginPath:"",delay:300,autoLoadModules:!0,watch:!0,placeholder:"Enjoy Markdown! coding now...",gotoLine:!0,codeFold:!1,autoHeight:!1,autoFocus:!0,autoCloseTags:!0,searchReplace:!0,syncScrolling:!0,readOnly:!1,tabSize:4,indentUnit:4,lineNumbers:!0,lineWrapping:!0,autoCloseBrackets:!0,showTrailingSpace:!0,matchBrackets:!0,indentWithTabs:!0,styleSelectedText:!0,matchWordHighlight:!0,styleActiveLine:!0,dialogLockScreen:!0,dialogShowMask:!0,dialogDraggable:!0,dialogMaskBgColor:"#fff",dialogMaskOpacity:.1,fontSize:"13px",saveHTMLToTextarea:!1,disabledKeyMaps:[],onload:function(){},onresize:function(){},onchange:function(){},onwatch:null,onunwatch:null,onpreviewing:function(){},onpreviewed:function(){},onfullscreen:function(){},onfullscreenExit:function(){},onscroll:function(){},onpreviewscroll:function(){},imageUpload:!1,imageFormats:["jpg","jpeg","gif","png","bmp","webp"],imageUploadURL:"",crossDomainUpload:!1,uploadCallbackURL:"",toc:!0,tocm:!1,tocTitle:"",tocDropdown:!1,tocContainer:"",tocStartLevel:1,htmlDecode:"style,iframe|on*",pageBreak:!0,atLink:!0,emailLink:!0,taskList:!1,emoji:!1,tex:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0,toolbar:!0,toolbarAutoFixed:!0,toolbarIcons:"full",toolbarTitles:{},toolbarHandlers:{ucwords:function(){return r.toolbarHandlers.ucwords},lowercase:function(){return r.toolbarHandlers.lowercase}},toolbarCustomIcons:{lowercase:'a',ucwords:'Aa'},toolbarIconsClass:{undo:"fa-undo",redo:"fa-repeat",bold:"fa-bold",del:"fa-strikethrough",italic:"fa-italic",quote:"fa-quote-left",uppercase:"fa-font",h1:r.classPrefix+"bold",h2:r.classPrefix+"bold",h3:r.classPrefix+"bold",h4:r.classPrefix+"bold",h5:r.classPrefix+"bold",h6:r.classPrefix+"bold","list-ul":"fa-list-ul","list-ol":"fa-list-ol",hr:"fa-minus",link:"fa-link","reference-link":"fa-anchor",image:"fa-picture-o",code:"fa-code","preformatted-text":"fa-file-code-o","code-block":"fa-file-code-o",table:"fa-table",datetime:"fa-clock-o",emoji:"fa-smile-o","html-entities":"fa-copyright",pagebreak:"fa-newspaper-o","goto-line":"fa-terminal",watch:"fa-eye-slash",unwatch:"fa-eye",preview:"fa-desktop",search:"fa-search",fullscreen:"fa-arrows-alt",clear:"fa-eraser",help:"fa-question-circle",info:"fa-info-circle"},toolbarIconTexts:{},lang:{name:"zh-cn",description:"开源在线Markdown编辑器
Open source online Markdown editor.",tocTitle:"目录",toolbar:{undo:"撤销(Ctrl+Z)",redo:"重做(Ctrl+Y)",bold:"粗体",del:"删除线",italic:"斜体",quote:"引用",ucwords:"将每个单词首字母转成大写",uppercase:"将所选转换成大写",lowercase:"将所选转换成小写",h1:"标题1",h2:"标题2",h3:"标题3",h4:"标题4",h5:"标题5",h6:"标题6","list-ul":"无序列表","list-ol":"有序列表",hr:"横线",link:"链接","reference-link":"引用链接",image:"添加图片",code:"行内代码","preformatted-text":"预格式文本 / 代码块(缩进风格)","code-block":"代码块(多语言风格)",table:"添加表格",datetime:"日期时间",emoji:"Emoji表情","html-entities":"HTML实体字符",pagebreak:"插入分页符","goto-line":"跳转到行",watch:"关闭实时预览",unwatch:"开启实时预览",preview:"全窗口预览HTML(按 Shift + ESC还原)",fullscreen:"全屏(按ESC还原)",clear:"清空",search:"搜索",help:"使用帮助",info:"关于"+r.title},buttons:{enter:"确定",cancel:"取消",close:"关闭"},dialog:{link:{title:"添加链接",url:"链接地址",urlTitle:"链接标题",urlEmpty:"错误:请填写链接地址。"},referenceLink:{title:"添加引用链接",name:"引用名称",url:"链接地址",urlId:"链接ID",urlTitle:"链接标题",nameEmpty:"错误:引用链接的名称不能为空。",idEmpty:"错误:请填写引用链接的ID。",urlEmpty:"错误:请填写引用链接的URL地址。"},image:{title:"添加图片",url:"图片地址",link:"图片链接",alt:"图片描述",uploadButton:"本地上传",imageURLEmpty:"错误:图片地址不能为空。",uploadFileEmpty:"错误:上传的图片不能为空。",formatNotAllowed:"错误:只允许上传图片文件,允许上传的图片文件格式有:"},preformattedText:{title:"添加预格式文本或代码块",emptyAlert:"错误:请填写预格式文本或代码的内容。"},codeBlock:{title:"添加代码块",selectLabel:"代码语言:",selectDefaultText:"请选择代码语言",otherLanguage:"其他语言",unselectedLanguageAlert:"错误:请选择代码所属的语言类型。",codeEmptyAlert:"错误:请填写代码内容。"},htmlEntities:{title:"HTML 实体字符"},help:{title:"使用帮助"}}}},r.classNames={tex:r.classPrefix+"tex"},r.dialogZindex=99999,r.$katex=null,r.$marked=null,r.$CodeMirror=null,r.$prettyPrint=null,r.prototype=r.fn={state:{watching:!1,loaded:!1,preview:!1,fullscreen:!1},init:function(t,i){i=i||{},"object"==typeof t&&(i=t);var a=this.classPrefix=r.classPrefix,n=o=e.extend(!0,r.defaults,i);this.settings=n,t="object"==typeof t?n.id:t;var s=this.editor=e("#"+t);this.id=t,this.lang=n.lang;var l=this.classNames={textarea:{html:a+"html-textarea",markdown:a+"markdown-textarea"}};n.pluginPath=""===n.pluginPath?n.path+"../plugins/":n.pluginPath,this.state.watching=!!n.watch,s.hasClass("editormd")||s.addClass("editormd"),s.css({width:"number"==typeof n.width?n.width+"px":n.width,height:"number"==typeof n.height?n.height+"px":n.height}),n.autoHeight&&s.css("height","auto");var c=this.markdownTextarea=s.children("textarea");c.length<1&&(s.append(""),c=this.markdownTextarea=s.children("textarea")),c.addClass(l.textarea.markdown).attr("placeholder",n.placeholder),void 0!==c.attr("name")&&""!==c.attr("name")||c.attr("name",""!==n.name?n.name:t+"-markdown-doc");var h=[n.readOnly?"":'',n.saveHTMLToTextarea?'':"",'
"+this.atLink(this.emoji(e))+"
\n"},s.code=function(e,t,i){return"seq"===t||"sequence"===t?''+e+"
":n.Renderer.prototype.code.apply(this,arguments)},s.tablecell=function(e,t){var i=t.header?"th":"td";return(t.align?"<"+i+' style="text-align:'+t.align+'">':"<"+i+">")+this.atLink(this.emoji(e))+""+i+">\n"},s.listitem=function(e){return o.taskList&&/^\s*\[[x\s]\]\s*/.test(e)?(e=e.replace(/^\s*\[\s\]\s*/,' ').replace(/^\s*\[x\]\s*/,' '),'"+this.atLink(this.emoji(e))+"
\n"},s.code=function(e,t,i){return"seq"===t||"sequence"===t?''+e+"
":n.Renderer.prototype.code.apply(this,arguments)},s.tablecell=function(e,t){var i=t.header?"th":"td";return(t.align?"<"+i+' style="text-align:'+t.align+'">':"<"+i+">")+this.atLink(this.emoji(e))+""+i+">\n"},s.listitem=function(e){return o.taskList&&/^\s*\[[x\s]\]\s*/.test(e)?(e=e.replace(/^\s*\[\s\]\s*/,' ').replace(/^\s*\[x\]\s*/,' '),'0&&(e="."===(e=t)?null:e),e};Jt({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,greediness:6,argTypes:["math","math","size","text","math","math"]},handler:function(t,e){var r=t.parser,a=e[4],n=e[5],i=Ft(e[0],"atom");i&&(i=Vt(e[0],"open"));var o=i?Er(i.text):null,s=Ft(e[1],"atom");s&&(s=Vt(e[1],"close"));var h,l=s?Er(s.text):null,m=Dt(e[2],"size"),c=null;h=!!m.isBlank||(c=m.value).number>0;var u="auto",p=Ft(e[3],"ordgroup");if(p){if(p.body.length>0){var d=Dt(p.body[0],"textord");u=Or[Number(d.text)]}}else p=Dt(e[3],"textord"),u=Or[Number(p.text)];return{type:"genfrac",mode:r.mode,numer:a,denom:n,continued:!1,hasBarLine:h,barSize:c,leftDelim:o,rightDelim:l,size:u}},htmlBuilder:Ir,mathmlBuilder:Rr}),Jt({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:function(t,e){var r=t.parser,a=(t.funcName,t.token);return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:Dt(e[0],"size").value,token:a}}}),Jt({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:function(t,e){var r=t.parser,a=(t.funcName,e[0]),n=function(t){if(!t)throw new Error("Expected non-null, but got "+String(t));return t}(Dt(e[1],"infix").size),i=e[2],o=n.number>0;return{type:"genfrac",mode:r.mode,numer:a,denom:i,continued:!1,hasBarLine:o,barSize:n,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:Ir,mathmlBuilder:Rr});var Lr=function(t,e){var r,a,n=e.style,i=Ft(t,"supsub");i?(r=i.sup?ce(i.sup,e.havingStyle(n.sup()),e):ce(i.sub,e.havingStyle(n.sub()),e),a=Dt(i.base,"horizBrace")):a=Dt(t,"horizBrace");var o,s=ce(a.base,e.havingBaseStyle(w.DISPLAY)),h=Re(a,e);if(a.isOver?(o=Pt.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:h}]},e)).children[0].children[0].children[1].classes.push("svg-align"):(o=Pt.makeVList({positionType:"bottom",positionData:s.depth+.1+h.height,children:[{type:"elem",elem:h},{type:"kern",size:.1},{type:"elem",elem:s}]},e)).children[0].children[0].children[0].classes.push("svg-align"),r){var l=Pt.makeSpan(["mord",a.isOver?"mover":"munder"],[o],e);o=a.isOver?Pt.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:l},{type:"kern",size:.2},{type:"elem",elem:r}]},e):Pt.makeVList({positionType:"bottom",positionData:l.depth+.2+r.height+r.depth,children:[{type:"elem",elem:r},{type:"kern",size:.2},{type:"elem",elem:l}]},e)}return Pt.makeSpan(["mord",a.isOver?"mover":"munder"],[o],e)};Jt({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:function(t,e){var r=t.parser,a=t.funcName;return{type:"horizBrace",mode:r.mode,label:a,isOver:/^\\over/.test(a),base:e[0]}},htmlBuilder:Lr,mathmlBuilder:function(t,e){var r=Ie(t.label);return new xe.MathNode(t.isOver?"mover":"munder",[Se(t.base,e),r])}}),Jt({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:function(t,e){var r=t.parser,a=e[1],n=Dt(e[0],"url").url;return r.settings.isTrusted({command:"\\href",url:n})?{type:"href",mode:r.mode,href:n,body:te(a)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:function(t,e){var r=oe(t.body,e,!1);return Pt.makeAnchor(t.href,[],r,e)},mathmlBuilder:function(t,e){var r=ke(t.body,e);return r instanceof fe||(r=new fe("mrow",[r])),r.setAttribute("href",t.href),r}}),Jt({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:function(t,e){var r=t.parser,a=Dt(e[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:a}))return r.formatUnsupportedCmd("\\url");for(var n=[],i=0;i0&&(u+=M,p-=M)}var z=[{type:"elem",elem:n,shift:p,marginRight:b,marginLeft:y},{type:"elem",elem:a,shift:-u,marginRight:b}];x=Pt.makeVList({positionType:"individualShift",children:z},e)}else if(n){p=Math.max(p,m.sub1,n.height-.8*m.xHeight);var T=[{type:"elem",elem:n,marginLeft:y,marginRight:b}];x=Pt.makeVList({positionType:"shift",positionData:p,children:T},e)}else{if(!a)throw new Error("supsub must have either sup or sub.");u=Math.max(u,i,a.depth+.25*m.xHeight),x=Pt.makeVList({positionType:"shift",positionData:-u,children:[{type:"elem",elem:a,marginRight:b}]},e)}var A=le(l,"right")||"mord";return Pt.makeSpan([A],[l,Pt.makeSpan(["msupsub"],[x])],e)},mathmlBuilder:function(t,e){var r,a=!1,n=Ft(t.base,"horizBrace");n&&!!t.sup===n.isOver&&(a=!0,r=n.isOver),!t.base||"op"!==t.base.type&&"operatorname"!==t.base.type||(t.base.parentIsSupSub=!0);var i,o=[Se(t.base,e)];if(t.sub&&o.push(Se(t.sub,e)),t.sup&&o.push(Se(t.sup,e)),a)i=r?"mover":"munder";else if(t.sub)if(t.sup){var s=t.base;i=s&&"op"===s.type&&s.limits&&e.style===w.DISPLAY?"munderover":s&&"operatorname"===s.type&&s.alwaysHandleSupSub&&(e.style===w.DISPLAY||s.limits)?"munderover":"msubsup"}else{var h=t.base;i=h&&"op"===h.type&&h.limits&&(e.style===w.DISPLAY||h.alwaysHandleSupSub)?"munder":h&&"operatorname"===h.type&&h.alwaysHandleSupSub&&(h.limits||e.style===w.DISPLAY)?"munder":"msub"}else{var l=t.base;i=l&&"op"===l.type&&l.limits&&(e.style===w.DISPLAY||l.alwaysHandleSupSub)?"mover":l&&"operatorname"===l.type&&l.alwaysHandleSupSub&&(l.limits||e.style===w.DISPLAY)?"mover":"msup"}return new xe.MathNode(i,o)}}),Qt({type:"atom",htmlBuilder:function(t,e){return Pt.mathsym(t.text,t.mode,e,["m"+t.family])},mathmlBuilder:function(t,e){var r=new xe.MathNode("mo",[ve(t.text,t.mode)]);if("bin"===t.family){var a=ye(t,e);"bold-italic"===a&&r.setAttribute("mathvariant",a)}else"punct"===t.family?r.setAttribute("separator","true"):"open"!==t.family&&"close"!==t.family||r.setAttribute("stretchy","false");return r}});var $r={mi:"italic",mn:"normal",mtext:"normal"};Qt({type:"mathord",htmlBuilder:function(t,e){return Pt.makeOrd(t,e,"mathord")},mathmlBuilder:function(t,e){var r=new xe.MathNode("mi",[ve(t.text,t.mode,e)]),a=ye(t,e)||"italic";return a!==$r[r.type]&&r.setAttribute("mathvariant",a),r}}),Qt({type:"textord",htmlBuilder:function(t,e){return Pt.makeOrd(t,e,"textord")},mathmlBuilder:function(t,e){var r,a=ve(t.text,t.mode,e),n=ye(t,e)||"normal";return r="text"===t.mode?new xe.MathNode("mtext",[a]):/[0-9]/.test(t.text)?new xe.MathNode("mn",[a]):"\\prime"===t.text?new xe.MathNode("mo",[a]):new xe.MathNode("mi",[a]),n!==$r[r.type]&&r.setAttribute("mathvariant",n),r}});var Zr={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},Kr={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};Qt({type:"spacing",htmlBuilder:function(t,e){if(Kr.hasOwnProperty(t.text)){var r=Kr[t.text].className||"";if("text"===t.mode){var a=Pt.makeOrd(t,e,"textord");return a.classes.push(r),a}return Pt.makeSpan(["mspace",r],[Pt.mathsym(t.text,t.mode,e)],e)}if(Zr.hasOwnProperty(t.text))return Pt.makeSpan(["mspace",Zr[t.text]],[],e);throw new o('Unknown type of space "'+t.text+'"')},mathmlBuilder:function(t,e){if(!Kr.hasOwnProperty(t.text)){if(Zr.hasOwnProperty(t.text))return new xe.MathNode("mspace");throw new o('Unknown type of space "'+t.text+'"')}return new xe.MathNode("mtext",[new xe.TextNode("\xa0")])}});var Jr=function(){var t=new xe.MathNode("mtd",[]);return t.setAttribute("width","50%"),t};Qt({type:"tag",mathmlBuilder:function(t,e){var r=new xe.MathNode("mtable",[new xe.MathNode("mtr",[Jr(),new xe.MathNode("mtd",[ke(t.body,e)]),Jr(),new xe.MathNode("mtd",[ke(t.tag,e)])])]);return r.setAttribute("width","100%"),r}});var Qr={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},ta={"\\textbf":"textbf","\\textmd":"textmd"},ea={"\\textit":"textit","\\textup":"textup"},ra=function(t,e){var r=t.font;return r?Qr[r]?e.withTextFontFamily(Qr[r]):ta[r]?e.withTextFontWeight(ta[r]):e.withTextFontShape(ea[r]):e};Jt({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],greediness:2,allowedInText:!0,consumeMode:"text"},handler:function(t,e){var r=t.parser,a=t.funcName,n=e[0];return{type:"text",mode:r.mode,body:te(n),font:a}},htmlBuilder:function(t,e){var r=ra(t,e),a=oe(t.body,r,!0);return Pt.makeSpan(["mord","text"],Pt.tryCombineChars(a),r)},mathmlBuilder:function(t,e){var r=ra(t,e);return ke(t.body,r)}}),Jt({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:function(t,e){return{type:"underline",mode:t.parser.mode,body:e[0]}},htmlBuilder:function(t,e){var r=ce(t.body,e),a=Pt.makeLineSpan("underline-line",e),n=e.fontMetrics().defaultRuleThickness,i=Pt.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:n},{type:"elem",elem:a},{type:"kern",size:3*n},{type:"elem",elem:r}]},e);return Pt.makeSpan(["mord","underline"],[i],e)},mathmlBuilder:function(t,e){var r=new xe.MathNode("mo",[new xe.TextNode("\u203e")]);r.setAttribute("stretchy","true");var a=new xe.MathNode("munder",[Se(t.body,e),r]);return a.setAttribute("accentunder","true"),a}}),Jt({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler:function(t,e,r){throw new o("\\verb ended by end of line instead of matching delimiter")},htmlBuilder:function(t,e){for(var r=aa(t),a=[],n=e.havingStyle(e.style.text()),i=0;i
-
- {
- item.is_pdf && item.is_pdf == true ?
-
+ { item.author && {item.author} } {item.commit_count===undefined?"":{item.commit_count} 已交} {item.uncommit_count===undefined?"":{item.uncommit_count} 未交} { diff --git a/public/react/src/modules/courses/completetaskdetails/Completetaskdetails.js b/public/react/src/modules/courses/completetaskdetails/Completetaskdetails.js new file mode 100644 index 000000000..850ed2b89 --- /dev/null +++ b/public/react/src/modules/courses/completetaskdetails/Completetaskdetails.js @@ -0,0 +1,84 @@ +import React, {Component} from "react"; +import { WordsBtn,on, off, trigger,markdownToHTML,getImageUrl} from 'educoder'; +import { + Button, + Checkbox, + message, + InputNumber, + DatePicker, + Radio, + Tooltip, + notification, +} from "antd"; +import './completetaskdetails.css'; +import GroupPackage from "../groupjobbank/GroupPackage"; +import GroupPackage2 from "../groupjobbank/GroupPackage2"; + + +class Groupjobbandetails extends Component { + + constructor(props) { + super(props); + + this.state = { + + } + } + + componentDidMount() { + console.log("Groupjobbandetails"); + console.log("componentDidMount"); + // let query = this.props.location.pathname; + // const type = query.split('/'); + // this.setState({ + // shixuntypes:type[3] + // }) + // this.props.triggerRef(this); + + + + + } + // 获取数据地方 + getTrainingjobsetting = () => { + var homeworkid = this.props.match.params.homeworkid; + } + + //跳转道描点的地方 + scrollToAnchor = (anchorName) => { + if (anchorName) { + // 找到锚点 + let anchorElement = document.getElementById(anchorName); + // 如果对应id的锚点存在,就跳转到锚点 + if(anchorElement) { anchorElement.scrollIntoView(); } + } + }; + + + + render() { + + return ( +
+ 课题类型: + 设计 +
++ 课题来源: + 生产/社会实践 +
++ 课题性质1: + 设计 +
++ 课题性质2: + 设计 +
++ 课题重复情况: + 新需求 +
++ 调研或实习地点: + 长沙 +
++ 课题单位来源: + 湖南省据C++创始人Stroustrup有限公司 +
++ { item.author && {item.author} } {item.exercise_status===1?"":{item.exercise_answer} 已答} {item.exercise_status===1?"":{item.exercise_unanswer} 未答} {item.unreview_count===null||item.exercise_status===1?"":{item.unreview_count} 未评数 } diff --git a/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js b/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js index f38ad7435..1fc1905d1 100644 --- a/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js +++ b/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js @@ -553,6 +553,9 @@ class ExerciseReviewAndAnswer extends Component{ height:16px; margin-top:2px; } + .standardAnswer.editormd-html-preview,.answerStyle.editormd-html-preview{ + width:100%!important + } `} {/*
*/}+ 分组要求: + 2~ 5(学生提交作品时需要关联同组成员,组内成员作品共享) +
++ 基于项目实施 + (学生必须在本平台创建项目,项目管理员可以提交作品) +
++ MySQL数据库编程开发实训(基础篇) +
+- 学生列表 - 邀请码:CKPYL -