From 66297cd5511aeb878baa9ee1173f6f88b27ed56f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com>
Date: Tue, 3 Sep 2019 09:04:05 +0800
Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/assets/javascripts/admin.js | 1 +
.../javascripts/admins/message-modal.js | 14 +
app/assets/javascripts/admins/users/index.js | 68 +
app/assets/javascripts/application.js | 1 -
app/assets/javascripts/jquery.mloading.js | 202 +
app/assets/stylesheets/admin.scss | 1 +
app/assets/stylesheets/jquery.mloading.scss | 94 +
.../import_course_members_controller.rb | 10 +
.../admins/import_users_controller.rb | 10 +
app/controllers/courses_controller.rb | 7 +-
app/controllers/exercises_controller.rb | 1 +
.../graduation_tasks_controller.rb | 1 +
.../homework_commons_controller.rb | 2 +
app/controllers/polls_controller.rb | 1 +
app/controllers/student_works_controller.rb | 2 +-
.../admins/import_course_member_excel.rb | 20 +
app/imports/admins/import_user_excel.rb | 33 +
app/imports/application_import.rb | 6 +
app/imports/base_import_xlsx.rb | 23 +
app/models/student_works_score.rb | 5 +-
.../admins/import_course_member_service.rb | 63 +
app/services/admins/import_user_service.rb | 89 +
app/services/ecs/import_course_service.rb | 2 +-
app/services/ecs/import_student_service.rb | 2 +-
.../shared/modal/_message_modal.html.erb | 18 +
app/views/admins/users/index.html.erb | 7 +-
.../users/shared/_import_user_modal.html.erb | 30 +
.../comment_list.json.jbuilder | 2 +-
app/views/layouts/admin.html.erb | 3 +
.../student_works/comment_list.json.jbuilder | 2 +-
.../users/question_banks/index.json.jbuilder | 2 +-
config/routes.rb | 2 +
...49_migrate_excellent_course_course_list.rb | 12 +
dump.rdb | Bin 2197 -> 2385 bytes
...fest-fd1f19755cf79ae07a20ee9d2676d85e.json | 2 +-
...da5443521854cd6fe7eecf750cf443f1e699c9.css | 19193 ---
...443521854cd6fe7eecf750cf443f1e699c9.css.gz | Bin 52434 -> 0 bytes
...90a23ab2e86fdf39e89a1fc2c2642c16a0d7ef.css | 19313 +++
...23ab2e86fdf39e89a1fc2c2642c16a0d7ef.css.gz | Bin 0 -> 53258 bytes
...ec5f7d561b068730a3a8ead9b3e6acc63ca674.js} | 287 +
...5f7d561b068730a3a8ead9b3e6acc63ca674.js.gz | Bin 0 -> 900151 bytes
...a62d8b76f65baf7b06fdedc47323635bcdaf.js.gz | Bin 896729 -> 0 bytes
...5537a46deb578488e47bbb006d551b54f72895.css | 50125 ------
...7a46deb578488e47bbb006d551b54f72895.css.gz | Bin 132235 -> 0 bytes
...304541807c3ea985eb566bdabdbafee7f6c6735.js | 131164 ---------------
...541807c3ea985eb566bdabdbafee7f6c6735.js.gz | Bin 935077 -> 0 bytes
...209e1c2b2e60336f0f01e19f0581663918708fb.js | 18882 +++
...e1c2b2e60336f0f01e19f0581663918708fb.js.gz | Bin 0 -> 146867 bytes
...4bc61badb8dd37ea38b74d864ba5d14b201d71.css | 50365 ++++++
...61badb8dd37ea38b74d864ba5d14b201d71.css.gz | Bin 0 -> 134115 bytes
...7815c096c25e0ab74aba341ae916166cd287.js.gz | Bin 711176 -> 711176 bytes
...4c4a620f522278a4668cc218465ad8f539966f.css | 15969 --
...a620f522278a4668cc218465ad8f539966f.css.gz | Bin 42961 -> 0 bytes
...0bfed6093f1ad56a3cc3cef00be02faedb0176.css | 15969 ++
...ed6093f1ad56a3cc3cef00be02faedb0176.css.gz | Bin 0 -> 43235 bytes
public/react/src/modules/courses/Index.js | 138 +-
.../courses/busyWork/CommonWorkDetailIndex.js | 29 +-
.../courses/busyWork/CommonWorkQuestion.js | 10 +-
.../busyWork/common/TabRightComponents.js | 5 +-
.../busyWork/reply/CommonWorkAppraiseReply.js | 9 +-
.../courses/common/comments/CCommentItem.js | 15 +-
.../src/modules/courses/css/busyWork.css | 161 +-
.../GraduationTasksappraiseMainEditor.js | 6 +-
.../modules/courses/members/studentsList.js | 2 +-
.../src/modules/courses/new/CoursesNew.js | 30 +-
.../src/modules/courses/new/Goldsubject.js | 199 +-
.../src/modules/courses/ordering/Ordering.css | 109 +
.../src/modules/courses/ordering/Ordering.js | 296 +
.../src/modules/courses/poll/PollListItem.js | 2 +-
.../react/src/modules/courses/poll/PollNew.js | 36 +-
.../courses/shixunHomework/shixunHomework.js | 10 +-
.../react/src/modules/message/js/MessagSub.js | 2 +-
public/react/src/modules/tpm/TPMIndexHOC.js | 3 +
73 files changed, 106300 insertions(+), 216767 deletions(-)
create mode 100644 app/assets/javascripts/admins/message-modal.js
create mode 100644 app/assets/javascripts/jquery.mloading.js
create mode 100644 app/assets/stylesheets/jquery.mloading.scss
create mode 100644 app/controllers/admins/import_course_members_controller.rb
create mode 100644 app/controllers/admins/import_users_controller.rb
create mode 100644 app/imports/admins/import_course_member_excel.rb
create mode 100644 app/imports/admins/import_user_excel.rb
create mode 100644 app/imports/base_import_xlsx.rb
create mode 100644 app/services/admins/import_course_member_service.rb
create mode 100644 app/services/admins/import_user_service.rb
create mode 100644 app/views/admins/shared/modal/_message_modal.html.erb
create mode 100644 app/views/admins/users/shared/_import_user_modal.html.erb
create mode 100644 db/migrate/20190902062449_migrate_excellent_course_course_list.rb
delete mode 100644 public/assets/admin-07f89a76946f8ce796dafa51fbda5443521854cd6fe7eecf750cf443f1e699c9.css
delete mode 100644 public/assets/admin-07f89a76946f8ce796dafa51fbda5443521854cd6fe7eecf750cf443f1e699c9.css.gz
create mode 100644 public/assets/admin-521862c9da30ecc23745b70d7290a23ab2e86fdf39e89a1fc2c2642c16a0d7ef.css
create mode 100644 public/assets/admin-521862c9da30ecc23745b70d7290a23ab2e86fdf39e89a1fc2c2642c16a0d7ef.css.gz
rename public/assets/{admin-81f6ac4c1ad5e53b10117d319ac4a62d8b76f65baf7b06fdedc47323635bcdaf.js => admin-73c70ed3ded5da876bc29f9fb1ec5f7d561b068730a3a8ead9b3e6acc63ca674.js} (99%)
create mode 100644 public/assets/admin-73c70ed3ded5da876bc29f9fb1ec5f7d561b068730a3a8ead9b3e6acc63ca674.js.gz
delete mode 100644 public/assets/admin-81f6ac4c1ad5e53b10117d319ac4a62d8b76f65baf7b06fdedc47323635bcdaf.js.gz
delete mode 100644 public/assets/application-1bce1740cf43111049b991ad4d5537a46deb578488e47bbb006d551b54f72895.css
delete mode 100644 public/assets/application-1bce1740cf43111049b991ad4d5537a46deb578488e47bbb006d551b54f72895.css.gz
delete mode 100644 public/assets/application-830ab01de7cd41145be3bd392304541807c3ea985eb566bdabdbafee7f6c6735.js
delete mode 100644 public/assets/application-830ab01de7cd41145be3bd392304541807c3ea985eb566bdabdbafee7f6c6735.js.gz
create mode 100644 public/assets/application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js
create mode 100644 public/assets/application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js.gz
create mode 100644 public/assets/application-b12c6a987e49d1cda015d172244bc61badb8dd37ea38b74d864ba5d14b201d71.css
create mode 100644 public/assets/application-b12c6a987e49d1cda015d172244bc61badb8dd37ea38b74d864ba5d14b201d71.css.gz
delete mode 100644 public/assets/college-279b722d063f61aec89f1ad6f44c4a620f522278a4668cc218465ad8f539966f.css
delete mode 100644 public/assets/college-279b722d063f61aec89f1ad6f44c4a620f522278a4668cc218465ad8f539966f.css.gz
create mode 100644 public/assets/college-315d626b40fca41ae2670fb1700bfed6093f1ad56a3cc3cef00be02faedb0176.css
create mode 100644 public/assets/college-315d626b40fca41ae2670fb1700bfed6093f1ad56a3cc3cef00be02faedb0176.css.gz
create mode 100644 public/react/src/modules/courses/ordering/Ordering.css
create mode 100644 public/react/src/modules/courses/ordering/Ordering.js
diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js
index 12b89804b..3e9601bf8 100644
--- a/app/assets/javascripts/admin.js
+++ b/app/assets/javascripts/admin.js
@@ -12,6 +12,7 @@
//= require jquery.cxselect
//= require bootstrap-datepicker
//= require bootstrap.viewer
+//= require jquery.mloading
//= require echarts
//= require lib/codemirror
diff --git a/app/assets/javascripts/admins/message-modal.js b/app/assets/javascripts/admins/message-modal.js
new file mode 100644
index 000000000..227d75776
--- /dev/null
+++ b/app/assets/javascripts/admins/message-modal.js
@@ -0,0 +1,14 @@
+$(document).on('turbolinks:load', function() {
+ var $modal = $('.modal.admin-message-modal');
+ if ($modal.length > 0) {
+ $modal.on('hide.bs.modal', function(){
+ $modal.find('.modal-body').html('');
+ });
+ }
+});
+
+function showMessageModal(html) {
+ var $modal = $('.modal.admin-message-modal');
+ $modal.find('.modal-body').html(html);
+ $modal.modal('show');
+}
\ No newline at end of file
diff --git a/app/assets/javascripts/admins/users/index.js b/app/assets/javascripts/admins/users/index.js
index f0ddf1e0f..4d4f0f945 100644
--- a/app/assets/javascripts/admins/users/index.js
+++ b/app/assets/javascripts/admins/users/index.js
@@ -117,5 +117,73 @@ $(document).on('turbolinks:load', function(){
});
}
});
+
+
+ // 导入学生
+ var $importUserModal = $('.modal.admin-import-user-modal');
+ var $importUserForm = $importUserModal.find('form.admin-import-user-form')
+
+ $importUserModal.on('show.bs.modal', function(){
+ $importUserModal.find('.file-names').html('选择文件');
+ $importUserModal.find('.upload-file-input').trigger('click');
+ });
+ $importUserModal.find('.upload-file-input').on('change', function(e){
+ var file = $(this)[0].files[0];
+
+ $importUserModal.find('.file-names').html(file ? file.name : '请选择文件');
+ })
+
+ var importUserFormValid = function(){
+ if($importUserForm.find('input[name="file"]').val() == undefined || $importUserForm.find('input[name="file"]').val().length == 0){
+ $importUserForm.find('.error').html('请选择文件');
+ return false;
+ }
+
+ return true;
+ };
+
+ var buildResultMessage = function(data){
+ var messageHtml = "
导入结果:成功" + data.success + "条,失败"+ data.fail.length + "条
";
+
+ if(data.fail.length > 0){
+ messageHtml += '数据 失败原因 ';
+
+ data.fail.forEach(function(item){
+ messageHtml += '' + item.data + ' ' + item.message + ' ';
+ });
+
+ messageHtml += '
'
+ }
+
+ return messageHtml;
+ }
+
+ $importUserModal.on('click', '.submit-btn', function(){
+ $importUserForm.find('.error').html('');
+
+ if (importUserFormValid()) {
+ $('body').mLoading({ text: '正在导入...' });
+
+ $.ajax({
+ method: 'POST',
+ dataType: 'json',
+ url: '/admins/import_users',
+ data: new FormData($importUserForm[0]),
+ processData: false,
+ contentType: false,
+ success: function(data){
+ $('body').mLoading('destroy');
+ $importUserModal.modal('hide');
+
+ showMessageModal(buildResultMessage(data));
+ },
+ error: function(res){
+ $('body').mLoading('destroy');
+ var data = res.responseJSON;
+ $importUserForm.find('.error').html(data.message);
+ }
+ });
+ }
+ });
}
});
\ No newline at end of file
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 07a3c90d4..839fadb57 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -16,4 +16,3 @@
//= require jquery3
//= require popper
//= require bootstrap-sprockets
-//= require_tree .
diff --git a/app/assets/javascripts/jquery.mloading.js b/app/assets/javascripts/jquery.mloading.js
new file mode 100644
index 000000000..6230186ab
--- /dev/null
+++ b/app/assets/javascripts/jquery.mloading.js
@@ -0,0 +1,202 @@
+/* Author:mingyuhisoft@163.com
+ * Github:https://github.com/imingyu/jquery.mloading
+ * Npm:npm install jquery.mloading.js
+ * Date:2016-7-4
+ */
+
+;(function (root, factory) {
+ 'use strict';
+
+ if (typeof module === 'object' && typeof module.exports === 'object') {
+ factory(require('jquery'),root);
+ } if(typeof define ==="function"){
+ if(define.cmd){
+ define(function(require, exports, module){
+ var $ = require("jquery");
+ factory($,root);
+ });
+ }else{
+ define(["jquery"],function($){
+ factory($,root);
+ });
+ }
+ }else {
+ factory(root.jQuery,root);
+ }
+} (typeof window !=="undefined" ? window : this, function ($, root, undefined) {
+ 'use strict';
+ if(!$){
+ $ = root.jQuery || null;
+ }
+ if(!$){
+ throw new TypeError("必须引入jquery库方可正常使用!");
+ }
+
+ var arraySlice = Array.prototype.slice,
+ comparison=function (obj1,obj2) {
+ var result=true;
+ for(var pro in obj1){
+ if(obj1[pro] !== obj2[obj1]){
+ result=true;
+ break;
+ }
+ }
+ return result;
+ }
+
+ function MLoading(dom,options) {
+ options=options||{};
+ this.dom=dom;
+ this.options=$.extend(true,{},MLoading.defaultOptions,options);
+ this.curtain=null;
+ this.render().show();
+ }
+ MLoading.prototype={
+ constructor:MLoading,
+ initElement:function () {
+ var dom=this.dom,
+ ops=this.options;
+ var curtainElement=dom.children(".mloading"),
+ bodyElement = curtainElement.children('.mloading-body'),
+ barElement = bodyElement.children('.mloading-bar'),
+ iconElement = barElement.children('.mloading-icon'),
+ textElement = barElement.find(".mloading-text");
+ if (curtainElement.length == 0) {
+ curtainElement = $('
');
+ dom.append(curtainElement);
+ }
+ if (bodyElement.length == 0) {
+ bodyElement = $('
');
+ curtainElement.append(bodyElement);
+ }
+ if (barElement.length == 0) {
+ barElement = $('
');
+ bodyElement.append(barElement);
+ }
+ if (iconElement.length == 0) {
+ var _iconElement=document.createElement(ops.iconTag);
+ iconElement = $(_iconElement);
+ iconElement.addClass("mloading-icon");
+ barElement.append(iconElement);
+ }
+ if (textElement.length == 0) {
+ textElement = $(' ');
+ barElement.append(textElement);
+ }
+
+ this.curtainElement=curtainElement;
+ this.bodyElement = bodyElement;
+ this.barElement = barElement;
+ this.iconElement = iconElement;
+ this.textElement = textElement;
+ return this;
+ },
+ render:function () {
+ var dom=this.dom,
+ ops=this.options;
+ this.initElement();
+ if(dom.is("html") || dom.is("body")){
+ this.curtainElement.addClass("mloading-full");
+ }else{
+ this.curtainElement.removeClass("mloading-full");
+
+ if(!dom.hasClass("mloading-container")){
+ dom.addClass("mloading-container");
+ }
+ }
+ if(ops.mask){
+ this.curtainElement.addClass("mloading-mask");
+ }else{
+ this.curtainElement.removeClass("mloading-mask");
+ }
+ if(ops.content!="" && typeof ops.content!="undefined"){
+ if(ops.html){
+ this.bodyElement.html(ops.content);
+ }else{
+ this.bodyElement.text(ops.content);
+ }
+ }else{
+ this.iconElement.attr("src",ops.icon);
+ if(ops.html){
+ this.textElement.html(ops.text);
+ }else{
+ this.textElement.text(ops.text);
+ }
+ }
+
+ return this;
+ },
+ setOptions:function (options) {
+ options=options||{};
+ var oldOptions = this.options;
+ this.options = $.extend(true,{},this.options,options);
+ if(!comparison(oldOptions,this.options)) this.render();
+ },
+ show:function () {
+ var dom=this.dom,
+ ops=this.options,
+ barElement=this.barElement;
+ this.curtainElement.addClass("active");
+ barElement.css({
+ "marginTop":"-"+barElement.outerHeight()/2+"px",
+ "marginLeft":"-"+barElement.outerWidth()/2+"px"
+ });
+
+ return this;
+ },
+ hide:function () {
+ var dom=this.dom,
+ ops=this.options;
+ this.curtainElement.removeClass("active");
+ if(!dom.is("html") && !dom.is("body")){
+ dom.removeClass("mloading-container");
+ }
+ return this;
+ },
+ destroy:function () {
+ var dom=this.dom,
+ ops=this.options;
+ this.curtainElement.remove();
+ if(!dom.is("html") && !dom.is("body")){
+ dom.removeClass("mloading-container");
+ }
+ dom.removeData(MLoading.dataKey);
+ return this;
+ }
+ };
+ MLoading.dataKey="MLoading";
+ MLoading.defaultOptions = {
+ text:"加载中...",
+ iconTag:"img",
+ icon:"data:image/gif;base64,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",
+ html:false,
+ content:"",//设置content后,text和icon设置将无效
+ mask:true//是否显示遮罩(半透明背景)
+ };
+
+ $.fn.mLoading=function (options) {
+ var ops={},
+ funName="",
+ funArgs=[];
+ if(typeof options==="object"){
+ ops = options;
+ }else if(typeof options ==="string"){
+ funName=options;
+ funArgs = arraySlice.call(arguments).splice(0,1);
+ }
+ return this.each(function (i,element) {
+ var dom = $(element),
+ plsInc=dom.data(MLoading.dataKey);
+ if(!plsInc){
+ plsInc=new MLoading(dom,ops);
+ }
+
+ if(funName){
+ var fun = plsInc[funName];
+ if(typeof fun==="function"){
+ fun.apply(plsInc,funArgs);
+ }
+ }
+ });
+ }
+}));
\ No newline at end of file
diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss
index d3a298dcf..30fd635a6 100644
--- a/app/assets/stylesheets/admin.scss
+++ b/app/assets/stylesheets/admin.scss
@@ -5,6 +5,7 @@
@import "select2-bootstrap4.min";
@import "bootstrap-datepicker";
@import "bootstrap-datepicker.standalone";
+@import "jquery.mloading";
@import "lib/codemirror";
@import "common";
diff --git a/app/assets/stylesheets/jquery.mloading.scss b/app/assets/stylesheets/jquery.mloading.scss
new file mode 100644
index 000000000..a347b928c
--- /dev/null
+++ b/app/assets/stylesheets/jquery.mloading.scss
@@ -0,0 +1,94 @@
+/* Author:mingyuhisoft@163.com
+ * Github:https://github.com/imingyu/jquery.mloading
+ * Npm:npm install jquery.mloading.js
+ * Date:2016-7-4
+ */
+.mloading-container {
+ position: relative;
+ min-height: 70px;
+ -webkit-transition: height 0.6s ease-in-out;
+ -o-transition: height 0.6s ease-in-out;
+ transition: height 0.6s ease-in-out;
+}
+.mloading {
+ position: absolute;
+ background: #E9E9E8;
+ font: normal 12px/22px "Microsoft Yahei", "微软雅黑", "宋体";
+ display: none;
+ z-index: 1600;
+ background: rgba(233, 233, 232, 0);
+}
+.mloading.active {
+ display: block;
+}
+.mloading.mloading-mask {
+ background: rgba(233, 233, 232, 0.75);
+ filter: progid:DXImageTransform.Microsoft.Alpha(opacity=75);
+}
+.mloading-full {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+}
+.mloading-container > .mloading {
+ top: 0px;
+ left: 0px;
+ width: 100%;
+ height: 100%;
+}
+.mloading-body {
+ width: 100%;
+ height: 100%;
+ position: relative;
+}
+.mloading-bar {
+ width: 250px;
+ min-height: 22px;
+ text-align: center;
+ background: #fff;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.27);
+ border-radius: 7px;
+ padding: 20px 15px;
+ font-size: 14px;
+ color: #999;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-left: -140px;
+ margin-top: -30px;
+ word-break: break-all;
+}
+@media (max-width: 300px) {
+ .mloading-bar {
+ width: 62px;
+ height: 56px;
+ margin-left: -30px !important;
+ margin-top: -30px !important;
+ padding: 0;
+ line-height: 56px;
+ }
+ .mloading-bar > .mloading-text {
+ display: none;
+ }
+}
+.mloading-bar-sm {
+ width: 62px;
+ height: 56px;
+ margin-left: -30px !important;
+ margin-top: -30px !important;
+ padding: 0;
+ line-height: 56px;
+}
+.mloading-bar-sm > .mloading-text {
+ display: none;
+}
+.mloading-icon {
+ width: 16px;
+ height: 16px;
+ vertical-align: middle;
+}
+.mloading-text {
+ margin-left: 10px;
+}
\ No newline at end of file
diff --git a/app/controllers/admins/import_course_members_controller.rb b/app/controllers/admins/import_course_members_controller.rb
new file mode 100644
index 000000000..42022b710
--- /dev/null
+++ b/app/controllers/admins/import_course_members_controller.rb
@@ -0,0 +1,10 @@
+class Admins::ImportCourseMembersController < Admins::BaseController
+ def create
+ return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
+
+ result = Admins::ImportCourseMemberService.call(params[:file].to_io)
+ render_ok(result)
+ rescue Admins::ImportCourseMemberService::Error => ex
+ render_error(ex)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/import_users_controller.rb b/app/controllers/admins/import_users_controller.rb
new file mode 100644
index 000000000..5d8a60ce6
--- /dev/null
+++ b/app/controllers/admins/import_users_controller.rb
@@ -0,0 +1,10 @@
+class Admins::ImportUsersController < Admins::BaseController
+ def create
+ return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
+
+ result = Admins::ImportUserService.call(params[:file].to_io)
+ render_ok(result)
+ rescue Admins::ImportUserService::Error => ex
+ render_error(ex)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index c16f8a97b..b10147462 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -144,9 +144,12 @@ class CoursesController < ApplicationController
@course.course_list_id = new_course_list.id
end
else
+ subject = Subject.find_by!(id: params[:subject_id])
@course.start_date = params[:start_date]
- @course.subject_id = params[:subject_id]
+ @course.subject_id = subject.id
@course.excellent = true
+ course_list = CourseList.find_by(name: subject.name) || CourseList.create!(name: subject.name, user_id: current_user.id, is_admin: 0)
+ @course.course_list_id = course_list.id
end
@course.is_end = @course.end_date.present? && @course.end_date < Date.today
@@ -1238,7 +1241,7 @@ class CoursesController < ApplicationController
tip_exception("开始时间不能为空") if params[:start_date].blank?
tip_exception("结束时间不能为空") if params[:end_date].blank?
tip_exception("结束时间必须晚于开始时间") if strf_date(params[:end_date]) <= strf_date(params[:start_date])
- tip_exception("开始时间和结束时间不能与往期开课时间重叠") if @course.nil? && @subject.max_course_end_date && strf_date(params[:start_date]) <= strf_date(@subject.max_course_end_date)
+ tip_exception("开始时间和结束时间不能早于往期开课时间") if @course.nil? && @subject.max_course_end_date && strf_date(params[:start_date]) <= strf_date(@subject.max_course_end_date)
validate_start_end_date if @course.present?
tip_exception("开放课堂必须包含公告栏和在线学习模块") unless params[:course_module_types].include?("announcement") && params[:course_module_types].include?("online_learning")
end
diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb
index 5db704fce..3be35345e 100644
--- a/app/controllers/exercises_controller.rb
+++ b/app/controllers/exercises_controller.rb
@@ -354,6 +354,7 @@ class ExercisesController < ApplicationController
# question_bank = QuestionBank.new ques_params
# question_bank.save
# end
+ exercise.update_attributes!(exercise_bank_id: current_ex_bank.id)
end
# 试卷的问题的输入
exercise.exercise_questions.each do |q|
diff --git a/app/controllers/graduation_tasks_controller.rb b/app/controllers/graduation_tasks_controller.rb
index 727bdb77e..fe7511e29 100644
--- a/app/controllers/graduation_tasks_controller.rb
+++ b/app/controllers/graduation_tasks_controller.rb
@@ -301,6 +301,7 @@ class GraduationTasksController < ApplicationController
course_list_id: @course.course_list_id)
task_bank.save!
+ task.update_attributes!(gtask_bank_id: task_bank.id)
end
task.attachments.each do |attachment|
att = attachment.copy
diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb
index 081e2fdf1..8268382bd 100644
--- a/app/controllers/homework_commons_controller.rb
+++ b/app/controllers/homework_commons_controller.rb
@@ -1322,6 +1322,8 @@ class HomeworkCommonsController < ApplicationController
else
new_homework_bank = add_to_homework_bank_f homework
new_homework_bank.save!
+
+ homework.update_attributes!(homework_bank_id: new_homework_bank.id)
end
rescue Exception => e
diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index bc549cf1d..7cb7ee800 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -562,6 +562,7 @@ class PollsController < ApplicationController
question_bank = QuestionBank.new ques_params
question_bank.save
end
+ poll.update_attributes!(exercise_bank_id: current_ex_bank.id)
end
# 问卷的问题的输入
poll.poll_questions.each do |f|
diff --git a/app/controllers/student_works_controller.rb b/app/controllers/student_works_controller.rb
index 519bb7e7d..99a02106c 100644
--- a/app/controllers/student_works_controller.rb
+++ b/app/controllers/student_works_controller.rb
@@ -541,7 +541,7 @@ class StudentWorksController < ApplicationController
def destroy_score
score = @work.student_works_scores.find_by(id: params[:score_id])
tip_exception("该评阅记录不存在") unless score.present?
- tip_exception("该评阅记录不能删除") unless score.allow_delete(@current_user, @user_course_identity)
+ tip_exception("该评阅记录不能删除") unless score.allow_delete(current_user)
begin
score.destroy
normal_status(0,"删除成功")
diff --git a/app/imports/admins/import_course_member_excel.rb b/app/imports/admins/import_course_member_excel.rb
new file mode 100644
index 000000000..ddd3b01a1
--- /dev/null
+++ b/app/imports/admins/import_course_member_excel.rb
@@ -0,0 +1,20 @@
+class Admins::ImportCourseMemberExcel < BaseImportXlsx
+ Data = Struct.new(:student_id, :name, :course_id, :role, :course_group_name, :school_id)
+
+ def read_each(&block)
+ sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
+ data = row.map(&method(:cell_value))[0..5]
+ block.call Data.new(*data)
+ end
+ end
+
+ private
+
+ def check_sheet_valid!
+ raise_import_error('请按照模板格式导入') if sheet.row(1).size != 6
+ end
+
+ def cell_value(obj)
+ obj&.cell_value&.to_s&.strip
+ end
+end
diff --git a/app/imports/admins/import_user_excel.rb b/app/imports/admins/import_user_excel.rb
new file mode 100644
index 000000000..a1d13e356
--- /dev/null
+++ b/app/imports/admins/import_user_excel.rb
@@ -0,0 +1,33 @@
+class Admins::ImportUserExcel < BaseImportXlsx
+ UserData = Struct.new(:student_id, :name, :department_name, :identity, :technical_title, :phone)
+
+ def read_each(&block)
+ sheet.each_row_streaming(pad_cells: true, offset: 3) do |row|
+ data = row.map(&method(:cell_value))[0..5]
+ block.call UserData.new(*data)
+ end
+ end
+
+ def school
+ @school ||= begin
+ school_id = sheet.cell(1, 1).to_s.strip
+ school_name = sheet.cell(1, 2).to_s.strip
+
+ School.find_by(id: school_id, name: school_name)
+ end
+ end
+
+ def identifier
+ @_identifier ||= sheet.cell(2, 1).to_s.strip
+ end
+
+ private
+
+ def check_sheet_valid!
+ raise_import_error('请按照模板格式导入') if school.blank?
+ end
+
+ def cell_value(obj)
+ obj&.cell_value
+ end
+end
diff --git a/app/imports/application_import.rb b/app/imports/application_import.rb
index cd2e8734c..abb6b623f 100644
--- a/app/imports/application_import.rb
+++ b/app/imports/application_import.rb
@@ -1,5 +1,11 @@
class ApplicationImport
+ Error = Class.new(StandardError)
+
def logger(msg)
Rails.logger.error(msg)
end
+
+ def raise_import_error(message)
+ raise Error, message
+ end
end
\ No newline at end of file
diff --git a/app/imports/base_import_xlsx.rb b/app/imports/base_import_xlsx.rb
new file mode 100644
index 000000000..e96ef7efc
--- /dev/null
+++ b/app/imports/base_import_xlsx.rb
@@ -0,0 +1,23 @@
+class BaseImportXlsx < ApplicationImport
+
+ attr_reader :sheet
+
+ def initialize(path)
+ raise Error, '只支持xlsx格式' unless !path.is_a?(String) || path.end_with?('.xlsx')
+
+ begin
+ @sheet = Roo::Excelx.new(path)
+ rescue Exception => ex
+ Util.logger_error(ex)
+ raise Error, '打开文件失败'
+ end
+
+ check_sheet_valid!
+ end
+
+ def read_each(&block);end
+
+ private
+
+ def check_sheet_valid!;end
+end
\ No newline at end of file
diff --git a/app/models/student_works_score.rb b/app/models/student_works_score.rb
index f6c7b3e33..19043f7f8 100644
--- a/app/models/student_works_score.rb
+++ b/app/models/student_works_score.rb
@@ -13,9 +13,8 @@ belongs_to :student_work
identity < Course::STUDENT || self.user == user || self.reviewer_role != 3
end
- def allow_delete current_user, identity
- self.is_invalid && (current_user == self.user || identity < Course::STUDENT) ||
- (self.score.nil? && current_user == self.user)
+ def allow_delete current_user
+ (self.is_invalid || self.score.nil?) && (current_user == self.user || current_user.admin?)
end
# 匿评分
diff --git a/app/services/admins/import_course_member_service.rb b/app/services/admins/import_course_member_service.rb
new file mode 100644
index 000000000..8f162902f
--- /dev/null
+++ b/app/services/admins/import_course_member_service.rb
@@ -0,0 +1,63 @@
+class Admins::ImportCourseMemberService < ApplicationService
+ Error = Class.new(StandardError)
+
+ attr_reader :file, :result
+
+ def initialize(file)
+ @file = file
+ @result = { success: 0, fail: [] }
+ end
+
+ def call
+ raise Error, '文件不存在' if file.blank?
+
+ excel = Admins::ImportCourseMemberExcel.new(file)
+ excel.read_each(&method(:create_course_member))
+
+ result
+ rescue ApplicationImport::Error => ex
+ raise Error, ex.message
+ end
+
+ private
+
+ def create_course_member(data)
+ raise '课堂角色必须为 2、3、4' unless [2, 3, 4].include?(data.role.to_i)
+
+ user = User.joins(:user_extension).where(user_extensions: { student_id: data.student_id, school_id: data.school_id }).first
+ raise '该学号的用户不存在' if user.blank?
+ course = Course.find_by(id: data.course_id)
+ raise '该课堂不存在' if course.blank?
+
+ course_group = nil
+ if data.course_group_name.present?
+ course_group = course.course_groups.find_or_create_by!(name: data.course_group_name)
+ end
+
+ member = course.course_members.find_by(user_id: user.id, role: data.role.to_i)
+ # 如果已是课堂成员且是学生身份and不在指定的分班则移动到该分班
+ if member.present? && member.role == :STUDENT && course_group && member.course_group_id != course_group&.id
+ member.update!(course_group_id: course_group&.id)
+ elsif member.blank?
+ course.course_members.create!(user_id: user.id, role: data.role.to_i, course_group_id: course_group&.id)
+ extra =
+ case data.role.to_i
+ when 2 then 9
+ when 3 then 7
+ else 10
+ end
+
+ Tiding.create!(user_id: user.id, trigger_user_id: course.tea_id, container_id: course.id,
+ container_type: 'TeacherJoinCourse', belong_container_id: course.id,
+ belong_container_type: 'Course', tiding_type: 'System', extra: extra)
+ end
+
+ result[:success] += 1
+ rescue Exception => ex
+ fail_data = data.as_json
+ fail_data[:data] = fail_data.values.join(',')
+ fail_data[:message] = ex.message
+
+ result[:fail] << fail_data
+ end
+end
\ No newline at end of file
diff --git a/app/services/admins/import_user_service.rb b/app/services/admins/import_user_service.rb
new file mode 100644
index 000000000..e5e7abfe6
--- /dev/null
+++ b/app/services/admins/import_user_service.rb
@@ -0,0 +1,89 @@
+class Admins::ImportUserService < ApplicationService
+ Error = Class.new(StandardError)
+
+ attr_reader :file, :school, :prefix, :result
+
+ def initialize(file)
+ @file = file
+ @result = { success: 0, fail: [] }
+ end
+
+ def call
+ raise Error, '文件不存在' if file.blank?
+
+ excel = Admins::ImportUserExcel.new(file)
+ @school = excel.school
+ @prefix = excel.identifier
+
+ excel.read_each(&method(:save_user))
+
+ result
+ rescue ApplicationImport::Error => ex
+ raise Error, ex.message
+ end
+
+ private
+
+ def save_user(data)
+ user = find_user(data)
+
+ if user.blank?
+ create_user(data)
+ else
+ user.update_column(:certification, 1)
+ end
+
+ result[:success] += 1
+ rescue Exception => ex
+ fail_data = data.as_json
+ fail_data[:data] = fail_data.values.join(',')
+ fail_data[:message] = ex.message
+
+ result[:fail] << fail_data
+ end
+
+ def create_user(data)
+ department = school.departments.find_by(name: data.department_name)
+
+ attr = {
+ status: User::STATUS_ACTIVE,
+ login: "#{prefix}#{data.student_id}",
+ firstname: '',
+ lastname: data.name,
+ nickname: data.name,
+ professional_certification: 1,
+ certification: 1,
+ password: '12345678',
+ phone: data.phone
+ }
+ ActiveRecord::Base.transaction do
+ user = User.create!(attr)
+
+ extension_attr = {
+ school_id: school.id, location: school.province, location_city: school.city,
+ gender: 0, identity: data.identity.to_i, department_id: department&.id, student_id: data.student_id
+ }
+
+ extension_attr[:technical_title] =
+ case data.identity.to_i
+ when 0 then %w(教授 副教授 讲师 助教).include?(data.technical_title) || '讲师'
+ when 2 then %w(企业管理者 部门管理者 高级工程师 工程师 助理工程师).include?(data.technical_title) || '助理工程师'
+ else nil
+ end
+
+ user.create_user_extension!(extension_attr)
+ end
+ end
+
+ def find_user(data)
+ users = User.joins(:user_extension).where(user_extensions: { identity: data.identity, school_id: school.id })
+
+ if data.identity.to_i == 1
+ users = users.where(user_extensions: { student_id: data.student_id })
+ else
+ users = users.where(user_extensions: { technical_title: data.technical_title }).where('CONCAT(users.lastname,users.firstname) = ?', data.name)
+ end
+
+ users.first
+ end
+end
\ No newline at end of file
diff --git a/app/services/ecs/import_course_service.rb b/app/services/ecs/import_course_service.rb
index 016336940..93adfc532 100644
--- a/app/services/ecs/import_course_service.rb
+++ b/app/services/ecs/import_course_service.rb
@@ -9,7 +9,7 @@ class Ecs::ImportCourseService < ApplicationService
end
def call
- raise_import_error('文件不存在') if attachment.blank?
+ raise Error, '文件不存在' if attachment.blank?
path = attachment.diskfile
excel = Ecs::ImportCourseExcel.new(path)
diff --git a/app/services/ecs/import_student_service.rb b/app/services/ecs/import_student_service.rb
index daa384d58..9014e221c 100644
--- a/app/services/ecs/import_student_service.rb
+++ b/app/services/ecs/import_student_service.rb
@@ -9,7 +9,7 @@ class Ecs::ImportStudentService < ApplicationService
end
def call
- raise_import_error('文件不存在') if attachment.blank?
+ raise Error, '文件不存在' if attachment.blank?
path = attachment.diskfile
excel = Ecs::ImportStudentExcel.new(path)
diff --git a/app/views/admins/shared/modal/_message_modal.html.erb b/app/views/admins/shared/modal/_message_modal.html.erb
new file mode 100644
index 000000000..94454ca2d
--- /dev/null
+++ b/app/views/admins/shared/modal/_message_modal.html.erb
@@ -0,0 +1,18 @@
+
\ No newline at end of file
diff --git a/app/views/admins/users/index.html.erb b/app/views/admins/users/index.html.erb
index b145edd24..fa6d67a64 100644
--- a/app/views/admins/users/index.html.erb
+++ b/app/views/admins/users/index.html.erb
@@ -3,7 +3,7 @@
<% end %>
- <%= form_tag(admins_users_path, method: :get, class: 'form-inline search-form', remote: true) do %>
+ <%= form_tag(admins_users_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
状态:
<% status_options = [['全部', ''], ['正常', User::STATUS_ACTIVE], ['未激活', User::STATUS_REGISTERED], ['已锁定', User::STATUS_LOCKED]] %>
@@ -26,10 +26,13 @@
<%= text_field_tag(:school_name, params[:school_name], class: 'form-control col-sm-2', placeholder: '学校/单位检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %>
+
+ <%= javascript_void_link '导入用户', class: 'btn btn-secondary btn-sm', data: { toggle: 'modal', target: '.admin-import-user-modal'} %>
<%= render partial: 'admins/users/shared/user_list', locals: { users: @users } %>
-<%= render partial: 'admins/users/shared/reward_grade_modal' %>
\ No newline at end of file
+<%= render partial: 'admins/users/shared/reward_grade_modal' %>
+<%= render partial: 'admins/users/shared/import_user_modal' %>
\ No newline at end of file
diff --git a/app/views/admins/users/shared/_import_user_modal.html.erb b/app/views/admins/users/shared/_import_user_modal.html.erb
new file mode 100644
index 000000000..ff3c725b9
--- /dev/null
+++ b/app/views/admins/users/shared/_import_user_modal.html.erb
@@ -0,0 +1,30 @@
+
\ No newline at end of file
diff --git a/app/views/graduation_works/comment_list.json.jbuilder b/app/views/graduation_works/comment_list.json.jbuilder
index 51595c55b..77898c91d 100644
--- a/app/views/graduation_works/comment_list.json.jbuilder
+++ b/app/views/graduation_works/comment_list.json.jbuilder
@@ -15,7 +15,7 @@ json.comment_scores @comment_scores do |score|
json.score score.score
json.content score.comment
json.is_invalid score.is_invalid
- json.delete @current_user == score.user && (score.is_invalid || score.score.nil?)
+ json.delete (@current_user == score.user || @current_user.admin?) && (score.is_invalid || score.score.nil?)
json.attachments score.attachments do |atta|
json.partial! "attachments/attachment_simple", locals: {attachment: atta, delete: false}
end
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb
index fc16c0beb..330ca8fc0 100644
--- a/app/views/layouts/admin.html.erb
+++ b/app/views/layouts/admin.html.erb
@@ -35,5 +35,8 @@
+
+
+ <%= render 'admins/shared/modal/message_modal' %>