diff --git a/app/controllers/student_works_controller.rb b/app/controllers/student_works_controller.rb index b4677f4e3..f6872e533 100644 --- a/app/controllers/student_works_controller.rb +++ b/app/controllers/student_works_controller.rb @@ -92,6 +92,7 @@ class StudentWorksController < ApplicationController student_work.commit_time = Time.now student_work.update_time = Time.now student_work.commit_user_id = current_user.id + student_work.update_user_id = current_user.id student_work.group_id = @homework.homework_type == "group" ? @homework.max_group_id : 0 #提交作品时,计算是否迟交 @@ -112,7 +113,7 @@ class StudentWorksController < ApplicationController homework_common_id: @homework.id, project_id: student_work.project_id, late_penalty: student_work.late_penalty, work_status: student_work.work_status, commit_time: Time.now, update_time: Time.now, group_id: student_work.group_id, - commit_user_id: current_user.id) + commit_user_id: current_user.id, update_user_id: current_user.id) stu_work.save! student_work.attachments.each do |attachment| att = attachment.copy @@ -156,6 +157,7 @@ class StudentWorksController < ApplicationController begin @work.description = params[:description] @work.update_time = Time.now + @work.update_user_id = current_user.id # @work.commit_user_id = current_user.id if @work.save! Attachment.associate_container(params[:attachment_ids], @work.id, @work.class) @@ -172,7 +174,7 @@ class StudentWorksController < ApplicationController # 原成员更新描述、更新时间以及附件 @homework.student_works.where(group_id: @work.group_id, user_id: (work_user_ids & params_user_ids)).each do |work| # work.update_attributes(update_time: Time.now, description: @work.description, commit_user_id: current_user.id) - work.update_attributes(update_time: Time.now, description: @work.description) + work.update_attributes(update_time: Time.now, description: @work.description, update_user_id: current_user.id) work.attachments.destroy_all @work.attachments.each do |attachment| att = attachment.copy @@ -192,7 +194,7 @@ class StudentWorksController < ApplicationController @homework.student_works.where(group_id: @work.group_id, user_id: delete_user_ids). update_all(work_status: 0, description: nil, late_penalty: 0, commit_time: nil, update_time: nil, final_score: nil, teacher_score: nil, student_score: nil, teaching_asistant_score: nil, - work_score: nil, project_id: 0, group_id: 0, commit_user_id: nil) + work_score: nil, project_id: 0, group_id: 0, commit_user_id: nil, update_user_id: nil) # 新增加的成员 (params_user_ids - work_user_ids).each do |user_id| @@ -200,7 +202,7 @@ class StudentWorksController < ApplicationController stu_work.update_attributes(user_id: user_id, description: @work.description, homework_common_id: @homework.id, project_id: @work.project_id, late_penalty: @work.late_penalty, work_status: @work.work_status, commit_time: Time.now, update_time: Time.now, - group_id: @work.group_id, commit_user_id: @work.commit_user_id) + group_id: @work.group_id, commit_user_id: @work.commit_user_id, update_user_id: current_user.id) @work.attachments.each do |attachment| att = attachment.copy att.author_id = attachment.author_id diff --git a/app/models/student_work.rb b/app/models/student_work.rb index 074068273..168cfeb68 100644 --- a/app/models/student_work.rb +++ b/app/models/student_work.rb @@ -2,6 +2,7 @@ class StudentWork < ApplicationRecord #学生提交作品表 #work_status :0 未提交 1 已提交 2 迟交 belongs_to :user belongs_to :commit_user, class_name: 'User', foreign_key: :commit_user_id, optional: true + belongs_to :update_user, class_name: 'User', foreign_key: :update_user_id, optional: true belongs_to :homework_common belongs_to :myshixun, optional: true has_many :student_works_evaluation_distributions, dependent: :destroy diff --git a/app/views/student_works/show.json.jbuilder b/app/views/student_works/show.json.jbuilder index 5756ac9cb..192e4d8ec 100644 --- a/app/views/student_works/show.json.jbuilder +++ b/app/views/student_works/show.json.jbuilder @@ -5,7 +5,8 @@ json.is_evaluation @is_evaluation json.author_name @is_evaluation ? "匿名" : @work.user.real_name json.is_leader_work @work.user_id == @work.commit_user_id if @homework.homework_type == "group" json.is_author @is_author -json.update_user_name @is_evaluation ? "匿名" : @work.commit_user.try(:real_name) +json.commit_user_name @is_evaluation ? "匿名" : @work.commit_user.try(:real_name) +json.update_user_name @is_evaluation ? "匿名" : @work.update_user.try(:real_name) json.update_atta @homework.late_duration && @is_author diff --git a/db/migrate/20190828011222_add_update_user_id_to_student_works.rb b/db/migrate/20190828011222_add_update_user_id_to_student_works.rb new file mode 100644 index 000000000..c8e007998 --- /dev/null +++ b/db/migrate/20190828011222_add_update_user_id_to_student_works.rb @@ -0,0 +1,6 @@ +class AddUpdateUserIdToStudentWorks < ActiveRecord::Migration[5.2] + def change + add_column :student_works, :update_user_id, :integer + StudentWork.update_all("update_user_id = commit_user_id") + end +end diff --git a/public/assets/.sprockets-manifest-1c370772f16743f825981ab0e5c94237.json b/public/assets/.sprockets-manifest-1c370772f16743f825981ab0e5c94237.json index 5f5a55fd7..da6cf8633 100644 --- a/public/assets/.sprockets-manifest-1c370772f16743f825981ab0e5c94237.json +++ b/public/assets/.sprockets-manifest-1c370772f16743f825981ab0e5c94237.json @@ -1 +1 @@ -{"files":{"admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js":{"logical_path":"admin.js","mtime":"2019-08-26T15:21:11+08:00","size":907839,"digest":"6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d","integrity":"sha256-ZXXxOZlT+xk1wDenuL0oxK/we3C+2bQfr2iZqJr0tX0="},"admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css":{"logical_path":"admin.css","mtime":"2019-08-26T15:21:47+08:00","size":655571,"digest":"8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5","integrity":"sha256-iisDy4oFXcY/RUQ7MEyudzgjMb66VbFXCz08iqQkQtU="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-08-21T15:10:12+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js":{"logical_path":"application.js","mtime":"2019-08-26T15:21:11+08:00","size":1042232,"digest":"a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533","integrity":"sha256-o6TzVJ1oZwVyuwdwDIWprBHlNu3HP+9udIlyO/U15TM="},"application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css":{"logical_path":"application.css","mtime":"2019-08-26T15:21:47+08:00","size":1182859,"digest":"a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46","integrity":"sha256-p1CLiOtqaaWzAWAr3cFHRc7AmFPqfZHG+uhWuW54j0Y="}},"assets":{"admin.js":"admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js","admin.css":"admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js","application.css":"application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css"}} \ No newline at end of file +{"files":{"admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js":{"logical_path":"admin.js","mtime":"2019-08-26T15:21:11+08:00","size":907839,"digest":"6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d","integrity":"sha256-ZXXxOZlT+xk1wDenuL0oxK/we3C+2bQfr2iZqJr0tX0="},"admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css":{"logical_path":"admin.css","mtime":"2019-08-26T15:21:47+08:00","size":655571,"digest":"8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5","integrity":"sha256-iisDy4oFXcY/RUQ7MEyudzgjMb66VbFXCz08iqQkQtU="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-08-21T15:10:12+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js":{"logical_path":"application.js","mtime":"2019-08-26T15:21:11+08:00","size":1042232,"digest":"a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533","integrity":"sha256-o6TzVJ1oZwVyuwdwDIWprBHlNu3HP+9udIlyO/U15TM="},"application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css":{"logical_path":"application.css","mtime":"2019-08-26T15:21:47+08:00","size":1182859,"digest":"a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46","integrity":"sha256-p1CLiOtqaaWzAWAr3cFHRc7AmFPqfZHG+uhWuW54j0Y="},"admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js":{"logical_path":"admin.js","mtime":"2019-08-27T16:36:09+08:00","size":912415,"digest":"7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5","integrity":"sha256-eFnzThB+w1iAwgOmxx+9C2ud/dAHubh0HbPF+vsi16U="},"admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css":{"logical_path":"admin.css","mtime":"2019-08-27T10:22:33+08:00","size":655943,"digest":"e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909","integrity":"sha256-6TUrQDRuLDbB1N6PboBAUQJkdDDawfgeatjvmTVQWQk="},"application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js":{"logical_path":"application.js","mtime":"2019-08-27T16:36:09+08:00","size":1046808,"digest":"a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687","integrity":"sha256-pNbFFV2lod+7cpH68J9VXVV+5C7Z6ywMCU0QiY41xoc="},"application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css":{"logical_path":"application.css","mtime":"2019-08-27T10:22:33+08:00","size":1183231,"digest":"3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17","integrity":"sha256-PQdAVU9xCLuhDXnTTwzEfcoadPoKHEI//9Xe+Zw4bhc="}},"assets":{"admin.js":"admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js","admin.css":"admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js","application.css":"application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css"}} \ No newline at end of file diff --git a/public/assets/admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js b/public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js similarity index 99% rename from public/assets/admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js rename to public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js index 2ff813ff4..e96beedb5 100644 --- a/public/assets/admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js +++ b/public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js @@ -27721,6 +27721,7 @@ $(document).on('turbolinks:load', function(){ $(document).on('turbolinks:load', function() { if ($('body.admins-identity-authentications-index-page').length > 0) { var $searchFrom = $('.identity-authentication-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -27732,14 +27733,160 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } }) ; +$(document).on('turbolinks:load', function() { + if ($('body.admins-mirror-repositories-edit-page, body.admins-mirror-repositories-update-page').length > 0) { + var $form = $('form.edit-mirror'); + + $form.validate({ + errorElement: 'span', + errorClass: 'danger text-danger', + rules: { + "mirror_repository[type_name]": { + required: true + } + } + }); + + $form.submit(function(e){ + if(!$form.valid()){ e.preventDefault(); } + }); + } +}); +$(document).on('turbolinks:load', function() { + if ($('body.admins-mirror-repositories-index-page').length > 0) { + } +}); +$(document).on('turbolinks:load', function() { + $('.admin-modal-container').on('show.bs.modal', '.modal.admin-choose-mirror-modal', function(){ + var $modal = $('.modal.admin-choose-mirror-modal'); + var $form = $modal.find('form.admin-choose-mirror-form'); + + var validateForm = function(){ + var checkedValue = $form.find('input[name="mirror_number"]:checked').val(); + + if(checkedValue == undefined){ + $modal.find('.error').html('必须选择一种镜像保存!'); + return false; + } + return true; + } + + $modal.on('click', '.submit-btn', function(){ + $form.find('.error').html(''); + var url = $form.attr('action'); + + if (validateForm()) { + $.ajax({ + method: 'POST', + dataType: 'script', + url: url, + data: $form.serialize(), + }).done(function(){ + $modal.modal('hide'); + }); + } + }); + }) +}); +$(document).on('turbolinks:load', function() { + var $modal = $('.modal.admin-replace-mirror-modal'); + if ($modal.length > 0) { + var $form = $modal.find('form.admin-replace-mirror-form'); + var $mirrorIdInput = $modal.find('.modal-body input[name="mirror_id"]'); + var $mirrorSelect = $modal.find('.new-mirror-select'); + + var setMirror = function(id, name){ + $mirrorIdInput.val(id); + $form.find('.mirror-id-container').html(id); + $form.find('.mirror-name-container').html(name); + } + + $form.validate({ + errorElement: 'span', + errorClass: 'danger text-danger', + rules: { + new_mirror_id: { + required: true + }, + }, + messages: { + new_mirror_id: { + required: '请选择新镜像' + } + } + }); + + // modal ready fire + $modal.on('show.bs.modal', function (event) { + var $link = $(event.relatedTarget); + + var mirrorId = $link.data('id'); + var mirrorName = $link.data('name'); + + setMirror(mirrorId, mirrorName); + $mirrorSelect.select2('val', ' '); + }); + $modal.on('hide.bs.modal', function () { + setMirror('', ''); + $mirrorSelect.select2('val', ' '); + $('#new_mirror_id-error').remove(); + }); + + $mirrorSelect.select2({ + theme: 'bootstrap4', + placeholder: '输入要合并的镜像名', + minimumInputLength: 1, + ajax: { + url: '/admins/mirror_repositories/for_select', + dataType: 'json', + data: function(params){ + return { keyword: params.term }; + }, + processResults: function(data){ + return { results: data.mirrors } + } + }, + templateResult: function (item) { + if(!item.id || item.id === '') return item.text; + return item.name; + }, + templateSelection: function(item){ + if (item.id) { + $('#new_mirror_id-error').remove(); + $('#new_mirror_id').val(item.id); + } + return item.name || item.text; + } + }); + + $modal.on('click', '.submit-btn', function(){ + $form.find('.error').html(''); + + if ($form.valid()) { + var url = $form.data('url'); + + $.ajax({ + method: 'POST', + dataType: 'script', + url: url, + data: $form.serialize(), + }).done(function(){ + $modal.modal('hide'); + }); + } + }); + } +}); $(document).on('turbolinks:load', function() { if ($('body.admins-professional-authentications-index-page').length > 0) { var $searchFrom = $('.professional-authentication-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -27751,6 +27898,7 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } @@ -27905,6 +28053,7 @@ $(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function() { if ($('body.admins-shixun-authorizations-index-page').length > 0) { var $searchFrom = $('.shixun-authorization-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -27916,6 +28065,7 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } @@ -27940,6 +28090,7 @@ $(document).on('turbolinks:load', function(){ $(document).on('turbolinks:load', function() { if ($('body.admins-subject-authorizations-index-page').length > 0) { var $searchFrom = $('.subject-authorization-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -27951,6 +28102,7 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } @@ -28267,8 +28419,11 @@ $(document).on('turbolinks:load', function(){ // flash alert提示框自动关闭 if($('.admin-alert-container .alert').length > 0){ setTimeout(function(){ - $('.admin-alert-container .alert').alert('close'); + $('.admin-alert-container .alert:not(.alert-danger)').alert('close'); }, 2000); + setTimeout(function(){ + $('.admin-alert-container .alert.alert-danger').alert('close'); + }, 5000); } }); diff --git a/public/assets/admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js.gz b/public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js.gz similarity index 93% rename from public/assets/admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js.gz rename to public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js.gz index dc9ae6dba..1f8df17c9 100644 Binary files a/public/assets/admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js.gz and b/public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js.gz differ diff --git a/public/assets/admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css b/public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css similarity index 99% rename from public/assets/admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css rename to public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css index cfd303453..25449185a 100644 --- a/public/assets/admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css +++ b/public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css @@ -18403,3 +18403,23 @@ label.error { -webkit-box-flex: 1; flex: 1; } + +/* line 52, app/assets/stylesheets/admin.scss */ +.font-12 { + font-size: 12px !important; +} + +/* line 53, app/assets/stylesheets/admin.scss */ +.font-14 { + font-size: 14px !important; +} + +/* line 54, app/assets/stylesheets/admin.scss */ +.font-16 { + font-size: 16px !important; +} + +/* line 55, app/assets/stylesheets/admin.scss */ +.font-18 { + font-size: 18px !important; +} diff --git a/public/assets/admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css.gz b/public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css.gz similarity index 60% rename from public/assets/admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css.gz rename to public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css.gz index 682386081..d54280d98 100644 Binary files a/public/assets/admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css.gz and b/public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css.gz differ diff --git a/public/assets/application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css b/public/assets/application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css similarity index 99% rename from public/assets/application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css rename to public/assets/application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css index 0a6d821b6..71cce1a19 100644 --- a/public/assets/application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css +++ b/public/assets/application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css @@ -18403,6 +18403,26 @@ label.error { -webkit-box-flex: 1; flex: 1; } + +/* line 52, app/assets/stylesheets/admin.scss */ +.font-12 { + font-size: 12px !important; +} + +/* line 53, app/assets/stylesheets/admin.scss */ +.font-14 { + font-size: 14px !important; +} + +/* line 54, app/assets/stylesheets/admin.scss */ +.font-16 { + font-size: 16px !important; +} + +/* line 55, app/assets/stylesheets/admin.scss */ +.font-18 { + font-size: 18px !important; +} @charset "UTF-8"; /* line 1, app/assets/stylesheets/admins/common.scss */ .admin-body-container { diff --git a/public/assets/application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css.gz b/public/assets/application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css.gz new file mode 100644 index 000000000..f6679e254 Binary files /dev/null and b/public/assets/application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css.gz differ diff --git a/public/assets/application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js b/public/assets/application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js similarity index 99% rename from public/assets/application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js rename to public/assets/application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js index 268928474..cde5193e8 100644 --- a/public/assets/application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js +++ b/public/assets/application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js @@ -27721,6 +27721,7 @@ $(document).on('turbolinks:load', function(){ $(document).on('turbolinks:load', function() { if ($('body.admins-identity-authentications-index-page').length > 0) { var $searchFrom = $('.identity-authentication-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -27732,14 +27733,160 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } }) ; +$(document).on('turbolinks:load', function() { + if ($('body.admins-mirror-repositories-edit-page, body.admins-mirror-repositories-update-page').length > 0) { + var $form = $('form.edit-mirror'); + + $form.validate({ + errorElement: 'span', + errorClass: 'danger text-danger', + rules: { + "mirror_repository[type_name]": { + required: true + } + } + }); + + $form.submit(function(e){ + if(!$form.valid()){ e.preventDefault(); } + }); + } +}); +$(document).on('turbolinks:load', function() { + if ($('body.admins-mirror-repositories-index-page').length > 0) { + } +}); +$(document).on('turbolinks:load', function() { + $('.admin-modal-container').on('show.bs.modal', '.modal.admin-choose-mirror-modal', function(){ + var $modal = $('.modal.admin-choose-mirror-modal'); + var $form = $modal.find('form.admin-choose-mirror-form'); + + var validateForm = function(){ + var checkedValue = $form.find('input[name="mirror_number"]:checked').val(); + + if(checkedValue == undefined){ + $modal.find('.error').html('必须选择一种镜像保存!'); + return false; + } + return true; + } + + $modal.on('click', '.submit-btn', function(){ + $form.find('.error').html(''); + var url = $form.attr('action'); + + if (validateForm()) { + $.ajax({ + method: 'POST', + dataType: 'script', + url: url, + data: $form.serialize(), + }).done(function(){ + $modal.modal('hide'); + }); + } + }); + }) +}); +$(document).on('turbolinks:load', function() { + var $modal = $('.modal.admin-replace-mirror-modal'); + if ($modal.length > 0) { + var $form = $modal.find('form.admin-replace-mirror-form'); + var $mirrorIdInput = $modal.find('.modal-body input[name="mirror_id"]'); + var $mirrorSelect = $modal.find('.new-mirror-select'); + + var setMirror = function(id, name){ + $mirrorIdInput.val(id); + $form.find('.mirror-id-container').html(id); + $form.find('.mirror-name-container').html(name); + } + + $form.validate({ + errorElement: 'span', + errorClass: 'danger text-danger', + rules: { + new_mirror_id: { + required: true + }, + }, + messages: { + new_mirror_id: { + required: '请选择新镜像' + } + } + }); + + // modal ready fire + $modal.on('show.bs.modal', function (event) { + var $link = $(event.relatedTarget); + + var mirrorId = $link.data('id'); + var mirrorName = $link.data('name'); + + setMirror(mirrorId, mirrorName); + $mirrorSelect.select2('val', ' '); + }); + $modal.on('hide.bs.modal', function () { + setMirror('', ''); + $mirrorSelect.select2('val', ' '); + $('#new_mirror_id-error').remove(); + }); + + $mirrorSelect.select2({ + theme: 'bootstrap4', + placeholder: '输入要合并的镜像名', + minimumInputLength: 1, + ajax: { + url: '/admins/mirror_repositories/for_select', + dataType: 'json', + data: function(params){ + return { keyword: params.term }; + }, + processResults: function(data){ + return { results: data.mirrors } + } + }, + templateResult: function (item) { + if(!item.id || item.id === '') return item.text; + return item.name; + }, + templateSelection: function(item){ + if (item.id) { + $('#new_mirror_id-error').remove(); + $('#new_mirror_id').val(item.id); + } + return item.name || item.text; + } + }); + + $modal.on('click', '.submit-btn', function(){ + $form.find('.error').html(''); + + if ($form.valid()) { + var url = $form.data('url'); + + $.ajax({ + method: 'POST', + dataType: 'script', + url: url, + data: $form.serialize(), + }).done(function(){ + $modal.modal('hide'); + }); + } + }); + } +}); $(document).on('turbolinks:load', function() { if ($('body.admins-professional-authentications-index-page').length > 0) { var $searchFrom = $('.professional-authentication-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -27751,6 +27898,7 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } @@ -27905,6 +28053,7 @@ $(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function() { if ($('body.admins-shixun-authorizations-index-page').length > 0) { var $searchFrom = $('.shixun-authorization-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -27916,6 +28065,7 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } @@ -27940,6 +28090,7 @@ $(document).on('turbolinks:load', function(){ $(document).on('turbolinks:load', function() { if ($('body.admins-subject-authorizations-index-page').length > 0) { var $searchFrom = $('.subject-authorization-list-form'); + $searchFrom.find('select[name="status"]').val('pending'); $searchFrom.on('click', '.search-form-tab', function(){ var $link = $(this); @@ -27951,6 +28102,7 @@ $(document).on('turbolinks:load', function() { $searchFrom.find('.status-filter').show(); } else { $searchFrom.find('.status-filter').hide(); + $searchFrom.find('select[name="status"]').val('pending'); } }); } @@ -28267,8 +28419,11 @@ $(document).on('turbolinks:load', function(){ // flash alert提示框自动关闭 if($('.admin-alert-container .alert').length > 0){ setTimeout(function(){ - $('.admin-alert-container .alert').alert('close'); + $('.admin-alert-container .alert:not(.alert-danger)').alert('close'); }, 2000); + setTimeout(function(){ + $('.admin-alert-container .alert.alert-danger').alert('close'); + }, 5000); } }); diff --git a/public/assets/application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js.gz b/public/assets/application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js.gz similarity index 80% rename from public/assets/application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js.gz rename to public/assets/application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js.gz index 120f1b4fd..32521705d 100644 Binary files a/public/assets/application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js.gz and b/public/assets/application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js.gz differ diff --git a/public/assets/application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css.gz b/public/assets/application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css.gz deleted file mode 100644 index d437dd106..000000000 Binary files a/public/assets/application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css.gz and /dev/null differ diff --git a/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js b/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js index a0129ec67..f29204563 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js @@ -280,10 +280,10 @@ class CommonWorkAppraise extends Component{ })} -
+ {isAdmin &&
温馨提示: 点击其他组员的姓名,可以快速评阅TA的作品 -
+
} diff --git a/public/react/src/modules/courses/busyWork/CommonWorkList.js b/public/react/src/modules/courses/busyWork/CommonWorkList.js index ca550a965..d6c3d8946 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkList.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkList.js @@ -563,7 +563,7 @@ class CommonWorkList extends Component{ late_penalty, absence_penalty, appeal_penalty ,end_immediately ,publish_immediately - , homework_id, visible, work_group, project_info + , homework_id, visible, work_group, project_info, is_leader } =this.state; @@ -610,7 +610,7 @@ class CommonWorkList extends Component{ }else{ StudentData=isStudent ? [{ id, user_name, user_login, student_id, group_name, work_status, update_time, teacher_score, teaching_asistant_score, student_score, ultimate_score, work_score, student_comment_count, appeal_all_count, appeal_deal_count, - late_penalty, absence_penalty, appeal_penalty, project_info, + late_penalty, absence_penalty, appeal_penalty, project_info, is_leader, work_group, isMine: true }] : [] } const columns = buildColumns(this, student_works, StudentData) @@ -695,8 +695,8 @@ class CommonWorkList extends Component{ - {options_course_group.length > 1 && } {isGroup && } + {options_course_group.length > 1 && } {/* value={search} */} diff --git a/public/react/src/modules/courses/busyWork/CommonWorkPost.js b/public/react/src/modules/courses/busyWork/CommonWorkPost.js index d2c1ca01e..1859d6b70 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkPost.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkPost.js @@ -4,7 +4,7 @@ import {Link} from 'react-router-dom'; import axios from 'axios'; import _ from 'lodash' -import { WordsBtn, getUploadActionUrl, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll } from 'educoder'; +import { WordsBtn, getUploadActionUrl, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, ConditionToolTip } from 'educoder'; import Modals from '../../modals/Modals'; import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; import LeaderIcon from './common/LeaderIcon' @@ -724,13 +724,13 @@ render(){
-
{members.map((item,key)=>{ return(
9 ? item.group_name : ''} >{item.group_name}
-
12 ? item.student_id : ''} >{item.student_id}
{item.commit_status===true?已提交 :""}
@@ -761,26 +761,30 @@ render(){ } .members .leaderIcon { } + .workPost.members { + width: 452px; + } `} -
+
{selectmemberslist&&selectmemberslist.map((item,key)=>{ + const _is_leader = (item.is_leader || !this.isEdit && key==0) return(
- -
- {item.user_name}{ (item.is_leader || !this.isEdit && key==0) && } + 5}> +
5 && _is_leader ? '#4CACFF' : 'inherit'}`}}> + {item.user_name}{ item.user_name.length <= 5 && _is_leader && }
- +
-
9 ? item.group_name : ''} >{item.group_name}
-
12 ? item.student_id : ''} >{item.student_id}
{item.user_id != this.props.current_user.user_id ? diff --git a/public/react/src/modules/courses/busyWork/common/LeaderIcon.js b/public/react/src/modules/courses/busyWork/common/LeaderIcon.js index 8599b8bd0..7d56d1b24 100644 --- a/public/react/src/modules/courses/busyWork/common/LeaderIcon.js +++ b/public/react/src/modules/courses/busyWork/common/LeaderIcon.js @@ -8,8 +8,9 @@ export default function LeaderIcon(props = {}) { icon =
组长
diff --git a/public/react/src/modules/courses/graduation/tasks/GraduationTaskssettinglist.js b/public/react/src/modules/courses/graduation/tasks/GraduationTaskssettinglist.js index 4e2c58bb8..1b25a5717 100644 --- a/public/react/src/modules/courses/graduation/tasks/GraduationTaskssettinglist.js +++ b/public/react/src/modules/courses/graduation/tasks/GraduationTaskssettinglist.js @@ -711,8 +711,12 @@ class GraduationTaskssettinglist extends Component{ title: '姓名', dataIndex: 'name', key: 'name', - - className:'edu-txt-center' + className:'edu-txt-center', + render: (text, record) => ( + +
{record.name}
+
+ ), }, { title: '学号', dataIndex: 'stduynumber', @@ -720,7 +724,7 @@ class GraduationTaskssettinglist extends Component{ className:'edu-txt-center', render: (text, record) => ( - {record.stduynumber} +
{record.stduynumber}
), }, { @@ -935,6 +939,7 @@ class GraduationTaskssettinglist extends Component{ if(taskslistdata&&taskslistdata.have_grouping===false){ + columns.some((item,key)=> { if (item.title === "分组") { columns.splice(key, 1) @@ -964,10 +969,35 @@ class GraduationTaskssettinglist extends Component{ .ant-table-tbody>tr>td, .ant-table-thead>tr>th{ padding: 16px 10px } + ` } + {taskslistdata&&taskslistdata.have_grouping===true|| + taskslistdata&&taskslistdata.have_project===true|| + taskslistdata&&taskslistdata.cross_comment===true?:""} {/*提示*/} 分班情况: + +
+ this.groupgroup(e,taskslistdata.search_assistants&&taskslistdata.search_assistants.course_group_info.length)} style={{width: '1000px', paddingTop: '4px'}}> + + + {taskslistdata.search_assistants&&taskslistdata.search_assistants.course_group_info.map((item,key)=>{ + return( + + {item.group_group_name} + ({item.count}) + + + ) + })} + +
- this.groupgroup(e,taskslistdata.search_assistants&&taskslistdata.search_assistants.course_group_info.length)} style={{width: '1000px', paddingTop: '4px'}}> - - this.groupgroup([])}>不限 - - - {taskslistdata.search_assistants&&taskslistdata.search_assistants.course_group_info.map((item,key)=>{ - return( - - {item.group_group_name} - ({item.count}) - - - ) - })} - :""} diff --git a/public/react/src/modules/forums/MemoNew.js b/public/react/src/modules/forums/MemoNew.js index 11a3d0ca2..00a39b184 100644 --- a/public/react/src/modules/forums/MemoNew.js +++ b/public/react/src/modules/forums/MemoNew.js @@ -1,835 +1,838 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames' - -import { Select,Icon, Upload, Button } from 'antd'; - -// demo http://react-component.github.io/upload/examples/simple.html -// import Upload from 'rc-upload'; - -import axios from 'axios' - -import 'antd/lib/select/style/index.css' -import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor' - -import { getUrl, getUploadActionUrl, appendFileSizeToUploadFileAll, appendFileSizeToUploadFile } from 'educoder' -const Option = Select.Option; -const $ = window.$; - -let origin = getUrl(); -let path = getUrl("/editormd/lib/") - -// load -if (!window.postUpMsg) { - $.getScript( - `${origin}/javascripts/attachments.js`, - (data, textStatus, jqxhr) => { - - }); -} - -// editorMD to create -/** - * - * @param id 渲染DOM的id - * @param width 宽度 - * @param high 高度 - * @param placeholder - * @param imageUrl 上传图片的url - * @returns {*} 返回一个editorMD实例 - */ -function create_editorMD(id, width, high, placeholder, imageUrl, callback){ - var editorName = window.editormd(id, { - width : width, - height : high, - syncScrolling : "single", - //你的lib目录的路径,我这边用JSP做测试的 - path : path , // "/editormd/lib/" - tex : true, - tocm : true, - emoji : true, - taskList : true, - codeFold : true, - searchReplace : true, - htmlDecode : "style,script,iframe", - sequenceDiagram : true, - autoFocus: false, - toolbarIcons : function() { - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table" - // , '|', "underlineIcon" - , "|", "watch", "clear" ] - }, - toolbarCustomIcons : { - testIcon : "
", - testIcon1 : "
", - - // underlineIcon例子 - // underlineIcon : "
" - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea : true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity : 0.6, - placeholder: placeholder, - imageUpload : true, - imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL : imageUrl,//url - onload: function(){ - - // underlineIcon例子 - // $('#'+ id + " .underline").bind('click', function() { - // var __Cursor = editorName.cm.getDoc().getCursor(); - // editorName.appendMarkdown('__') - // editorName.cm.setCursor(__Cursor.line, __Cursor.ch + 2); - // }); - - // this.previewing(); - $("#"+ id +" [type=\"latex\"]").bind("click", function(){ - editorName.cm.replaceSelection("```latex"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("```"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line-1, 0); - }); - - $("#"+ id +" [type=\"inline\"]").bind("click", function(){ - editorName.cm.replaceSelection("$$$$"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line, __Cursor.ch-2); - editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - window.md_elocalStorage(editorName, `memoNew_${id}`, "memoNew"); - - callback && callback() - } - }); - return editorName; -} - -const typeNameMap = { - '技术分享': 5, - '操作指南': 3, -} -export const typeNameMap2 = { - 5: '技术分享', - 3: '操作指南', -} -const defaultType = '技术分享' - -const languageSeparator = '/' -class MemoNew extends Component { - constructor(props) { - super(props) - this.mdRef = React.createRef(); - - // https://testbdweb.trustie.net/uploads.js?attachment_id=1&filename=jqui.js - // https://ant.design/components/upload-cn/ - this.uploaderProps = { - action: '/uploads.js', - data: { attachment_id: 1 }, // , filename: 2 - headers: { - Authorization: 'authorization-text', - }, - multiple: true, - beforeUpload(file) { - // console.log('beforeUpload', file.name); - }, - onStart: (file) => { - console.log('onStart', file.name); - // this.refs.inner.abort(file); - }, - onSuccess(file) { - console.log('onSuccess', file); - }, - onProgress(step, file) { - console.log('onProgress', Math.round(step.percent), file.name); - }, - onError(err) { - console.log('onError', err); - }, - }; - - this.state = { - memoSubject: '', - memoContent: '', - memoType: typeNameMap[defaultType], - memoRepertoire: '', - memoLanguage: [], - - repertoires: [], - currentSelectRepertoiresIndex: -1, - repertoiresTagMap: {}, - - fileList: [] - } - } - onCommit() { - const { memoSubject, memoRepertoire, memoLanguage, currentMemoId, memoType } = this.state; - const { showNotification } = this.props; - if (!memoSubject) { - showNotification('请先输入话题名称') - return - } - let mdVal; - try { - mdVal = this.mdRef.current.getValue() - - } catch (e) { - showNotification('编辑器还未加载完毕,请稍后') - return - } - - if (!mdVal) { - showNotification('请先输入话题内容') - return - } - // !memoRepertoire || - if (memoType === 5 && ( !memoLanguage || memoLanguage.length === 0 )) { - showNotification('请先选择技术标签') - return - } - /* - - - - http://localhost:3000/attachments/download/185790/Git-2.17.1.2-32-bit.exe - https://www.educoder.net/attachments/205112.js?attachment_id=1 - */ - // collect attachments - const $ = window.$; - const attachmentsMap = {}; - const attachmentIds = this.state.fileList.map(item => { - return item.response ? item.response.id : item.id - }) - // $('#attachments_fields .attachment').each(( index, item ) => { - // const filename = $(item).find('.upload_filename').val(); - // // $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val() - // const token = $(item).find('input:nth-child(7)').val() - // const attachment_id = parseInt($(item).children().last().val()) - // attachmentsMap[index] = { - // filename, - // token, - // attachment_id - // } - // attachmentIds.push(attachment_id) - // }) - - - if (currentMemoId) { - this.updateMemo(attachmentIds) - } else { - this.newMemo(attachmentIds) - } - } - onCancel() { - const { currentMemoId, memoType } = this.state; - if (currentMemoId) { // 编辑 - this.props.history.push(`/forums/${currentMemoId}`) - } else { // 新建 - this.props.history.push(`/forums`) - } - // debugger;this.props.history.goBack() - } - updateMemo(attachmentsMap) { - const { memoSubject, memoRepertoire, memoLanguage, memoType, currentMemoId, content } = this.state; - const mdVal = this.mdRef.current.getValue() - console.log('isContentEdit: ', mdVal === content); - const newMemoUrl = `/memos/${currentMemoId}.json` - axios.put(newMemoUrl, { - content_changed: this.contentChanged, - tags: memoLanguage, - // memo:{ - subject: memoSubject , - content: mdVal, - forum_id: memoType, - repertoire_name: memoRepertoire, - // language: memoLanguage.join(languageSeparator), - // - // }, - attachment_ids: attachmentsMap - }, { - // withCredentials: true, - }) - .then((response) => { - const { status, message, memo_id } = response.data; - if (status === 0) { - window.$("html,body").animate({"scrollTop":0}) - this.props.history.push(`/forums/${currentMemoId}`) - } else { - this.props.showNotification(message) - } - }).catch((error) => { - console.log(error) - }) - } - newMemo(attachmentsMap) { - const { memoSubject, memoRepertoire, memoLanguage, memoType } = this.state; - const mdVal = this.mdRef.current.getValue() - - const newMemoUrl = `/memos.json` - axios.post(newMemoUrl, { - tags: memoLanguage, - // memo:{ - subject: memoSubject , - content: mdVal, - forum_id: memoType, - // repertoire_name: memoRepertoire, - - // }, - attachment_ids: attachmentsMap - }, { - // withCredentials: true, - }) - .then((response) => { - const { status, message, memo_id } = response.data; - if (status === 0) { - window.$("html,body").animate({"scrollTop":0}) - this.props.history.push(`/forums/${memo_id}`) - } else { - this.props.showNotification(message) - } - }).catch((error) => { - console.log(error) - }) - } - componentDidMount() { - const newMemoUrl = `/memos/new.json` - axios.get(newMemoUrl,{ - // withCredentials: true, - }) - .then((response) => { - const data = response.data; - const repertoires = []; - const repertoiresTagMap = {} - if ( data.tag_list ) { - // data.tag_list.forEach((item, index)=>{ - // const tagArray = []; - // item.tag.forEach( (tag, index) => { - // tagArray.push(tag.name) - // }) - // repertoires.push(item.rep.repertoire.name) - // repertoiresTagMap[item.rep.repertoire.name] = tagArray - // }) - this.setState({ - tag_list: data.tag_list - // repertoires, - // repertoiresTagMap - }) - - // const user = response.data.current_user; - // user.tidding_count = response.data.tidding_count; - // this.props.initCommonState(user) - - // 初始化 csrf meta - const $ = window.$ - $('head').append( $('') ) - $('head').append( $(``) ) - } - }).catch((error) => { - console.log(error) - }) - - // 如果是编辑 - const { match } = this.props - const memoId = match.params.memoId; - if (memoId) { - const memoUrl = `/memos/${match.params.memoId}/edit.json`; - axios.get(memoUrl,{ - // withCredentials: true, - }) - .then((response) => { - const tag_list = response.data.tag_list - if (tag_list) { - // this.setState({...response.data}) - const { content, forum_id, id, repertoire_name, subject, - current_user, tag_list, attachments_url, memo_tags, attachments } = response.data; - this.initMD(content); - // this.onRepertoiresChange(repertoire_name) - // tag -> memo_tags - const tag = memo_tags; - let memoLanguage = [] - if (tag) { - memoLanguage = tag.map((item, index) => { - return item.id + "" - }) - } - const fileList = attachments.map(item => { - return { - id: item.id, - uid: item.id, - name: appendFileSizeToUploadFile(item), - url: item.url, - filesize: item.filesize, - status: 'done' - } - }) - this.setState({ - fileList, - currentMemoId: memoId, - memoSubject: subject, - memoType: forum_id, - memoRepertoire: repertoire_name, - memoLanguage, - attachments_url, - content - - // repertoires: [], - // currentSelectRepertoiresIndex: -1, - }, ()=> { - // 解决有时候编辑时内容不显示的问题 - setTimeout(() => { - this.mdRef.current && this.mdRef.current.setValue(content || '') - }, 2000) - - $('.upload_filename').each((index, item) => { - var width = window._textWidth($(item), '14px'); - console.log(width) - $(item).css('width', width + 20) - }) - - }) - // 加载完后滚动条滚动 - window.$("html,body").animate({"scrollTop":0}) - - this.props.initForumState({ - // current_user, - tag_list - }) - } - - }).catch((error) => { - console.log(error) - }) - } else { - this.initMD(); - } - - - - - } - initMD(initValue) { - return; - - this.contentChanged = false; - const placeholder = ""; - // amp; - // 编辑时要传memoId - // const imageUrl = `/upload_with_markdown?container_id=&container_type=Memo`; - const imageUrl = `/api/attachments.json`; - - // 创建editorMd - - const taskpass_editormd = create_editorMD("memoMD", '100%', 400, placeholder, imageUrl, () => { - setTimeout(()=>{ - taskpass_editormd.resize() - taskpass_editormd.cm && taskpass_editormd.cm.refresh() - }, 500) - - if (initValue) { - taskpass_editormd.setValue(initValue) - } - taskpass_editormd.cm.on("change", (_cm, changeObj) =>{ - console.log('....contentChanged') - this.contentChanged = true; - }) - }); - this.taskpass_editormd = taskpass_editormd; - window.taskpass_editormd = taskpass_editormd; - - } - - renderOptions(array) { - const elementArray = []; - array.forEach(( item, index ) => { - elementArray.push( - - ) - }) - return elementArray - } - onRepertoiresChange(value) { - - const index = this.state.repertoires.indexOf(value) - - this.setState({ - currentSelectRepertoiresIndex: index, - memoRepertoire: value, - memoLanguage: '' - }); - }; - - renderTag() { - const { tag_list } = this.state; - if (!tag_list || tag_list.length === 0) { - return '' - } - const result = [] - - tag_list.forEach((item, index) => { - result.push() - }) - - return result; - } - - onTagChange(value) { - if (value && value.length > 3) { - this.props.showNotification(`最多选择3个技术标签`) - - return; - } - this.setState({ - memoLanguage: value - }) - } - - onTypeChange(value) { - - this.setState({ - memoType: typeNameMap[value] - }) - } - onMemoNameChange(e) { - this.setState({ - memoSubject: e.target.value - }) - } - renderAttachment() { - const { attachments_url } = this.state; - const attachments = [] - attachments_url.forEach((item, index) => { - const ar = item.url.split('/') - const fileName = ar[ar.length - 1] - /* -

- - {fileName} - -

- */ - // ?attachment_id=2 - /* - - - - */ - attachments.push( - - - - - - {window.conver_size(item.id)} - - - -
- {/**/} - -
-
-
- - ) - }) - return attachments; - } - handleChange = (info) => { - if (info.file.status === 'uploading' || info.file.status === 'done') { - let fileList = info.fileList; - this.setState({ - fileList: appendFileSizeToUploadFileAll(fileList) - }); - } - } - onAttachmentRemove = (file) => { - this.props.confirm({ - // title: '确定要删除这个附件吗?', - content: '是否确认删除?', - - okText: '确定', - cancelText: '取消', - // content: 'Some descriptions', - onOk: () => { - this.deleteAttachment(file) - }, - onCancel() { - console.log('Cancel'); - }, - }); - return false; - } - deleteAttachment = (file) => { - // 初次上传不能直接取uid - const url = `/attachments/${file.response ? file.response.id : file.uid}.json` - axios.delete(url, { - }) - .then((response) => { - if (response.data) { - const { status } = response.data; - if (status == 0) { - console.log('--- success') - - this.setState((state) => { - const index = state.fileList.indexOf(file); - const newFileList = state.fileList.slice(); - newFileList.splice(index, 1); - return { - fileList: newFileList, - }; - }); - } - } - }) - .catch(function (error) { - console.log(error); - }); - } - render() { - const { match, history } = this.props - const { - // repertoires, repertoiresTagMap, currentSelectRepertoiresIndex, memoRepertoire, - tag_list, - memoSubject, memoType, - memoLanguage, attachments_url, fileList } = this.state; - const memoId = match.params.memoId; - - const uploadProps = { - width: 600, - fileList, - multiple: true, - // https://github.com/ant-design/ant-design/issues/15505 - // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // showUploadList: false, - action: `${getUploadActionUrl()}`, - onChange: this.handleChange, - onRemove: this.onAttachmentRemove, - beforeUpload: (file) => { - console.log('beforeUpload', file.name); - const isLt150M = file.size / 1024 / 1024 < 150; - if (!isLt150M) { - this.props.showNotification('文件大小必须小于150MB!'); - } - return isLt150M; - }, - }; - return ( -
-
- { memoId ? '编辑话题' : '发布话题'} - {/* - */} -
- -
-
-

话题名称

-
- * -
- this.onMemoNameChange(val)} placeholder=""> - -
-
- - 必填项 - -
-
-
-
- -
-
-

内容

-
- * -
- - - {/*
- -
*/} -

-

-
-
- - 必填项 - -
-
- - - - {/*
- - { attachments_url && !!attachments_url.length && - this.renderAttachment() - } - - - {debugger;window.addInputFiles( window.$('.file_selector')[0] ) }} - style={{'display':'none'}} type="file"> - - -
*/} - - - {/*开始上传*/} - - - (单个文件150M以内) - - - {/* 请求status 422 */} - - {/* */} - {/* */} -
-
- {/* TODOTODO 这里重复的html代码太多,如果有其他页面有类似需求,需要封装*/} - -
-
-

话题类型

-
- * -
- -
-
- - 必填项 - -
-
-
-
- - {/* memoType === typeNameMap['技术分享'] && -
-
-

技术标签

-
- * -
- -
-
- -
- -
- - 必填项 - -
-
-
-
*/} - - { memoType === typeNameMap['技术分享'] && -
-
-

技术标签

-
- * - -
- -
- -
- - 必填项 - -
-
-
-
} - - - -
- ); - } -} - -export default MemoNew; +import React, { Component } from 'react'; +import { Redirect } from 'react-router'; + +import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; + +import PropTypes from 'prop-types'; + +import classNames from 'classnames' + +import { Select,Icon, Upload, Button } from 'antd'; + +// demo http://react-component.github.io/upload/examples/simple.html +// import Upload from 'rc-upload'; + +import axios from 'axios' + +import 'antd/lib/select/style/index.css' +import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor' + +import { getUrl, getUploadActionUrl, appendFileSizeToUploadFileAll, appendFileSizeToUploadFile } from 'educoder' +const Option = Select.Option; +const $ = window.$; + +let origin = getUrl(); +let path = getUrl("/editormd/lib/") + +// load +if (!window.postUpMsg) { + $.getScript( + `${origin}/javascripts/attachments.js`, + (data, textStatus, jqxhr) => { + + }); +} + +// editorMD to create +/** + * + * @param id 渲染DOM的id + * @param width 宽度 + * @param high 高度 + * @param placeholder + * @param imageUrl 上传图片的url + * @returns {*} 返回一个editorMD实例 + */ +function create_editorMD(id, width, high, placeholder, imageUrl, callback){ + var editorName = window.editormd(id, { + width : width, + height : high, + syncScrolling : "single", + //你的lib目录的路径,我这边用JSP做测试的 + path : path , // "/editormd/lib/" + tex : true, + tocm : true, + emoji : true, + taskList : true, + codeFold : true, + searchReplace : true, + htmlDecode : "style,script,iframe", + sequenceDiagram : true, + autoFocus: false, + toolbarIcons : function() { + // Or return editormd.toolbarModes[name]; // full, simple, mini + // Using "||" set icons align right. + return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table" + // , '|', "underlineIcon" + , "|", "watch", "clear" ] + }, + toolbarCustomIcons : { + testIcon : "
", + testIcon1 : "
", + + // underlineIcon例子 + // underlineIcon : "
" + }, + //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 + saveHTMLToTextarea : true, + // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 + dialogMaskOpacity : 0.6, + placeholder: placeholder, + imageUpload : true, + imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], + imageUploadURL : imageUrl,//url + onload: function(){ + + // underlineIcon例子 + // $('#'+ id + " .underline").bind('click', function() { + // var __Cursor = editorName.cm.getDoc().getCursor(); + // editorName.appendMarkdown('__') + // editorName.cm.setCursor(__Cursor.line, __Cursor.ch + 2); + // }); + + // this.previewing(); + $("#"+ id +" [type=\"latex\"]").bind("click", function(){ + editorName.cm.replaceSelection("```latex"); + editorName.cm.replaceSelection("\n"); + editorName.cm.replaceSelection("\n"); + editorName.cm.replaceSelection("```"); + var __Cursor = editorName.cm.getDoc().getCursor(); + editorName.cm.setCursor(__Cursor.line-1, 0); + }); + + $("#"+ id +" [type=\"inline\"]").bind("click", function(){ + editorName.cm.replaceSelection("$$$$"); + var __Cursor = editorName.cm.getDoc().getCursor(); + editorName.cm.setCursor(__Cursor.line, __Cursor.ch-2); + editorName.cm.focus(); + }); + $("[type=\"inline\"]").attr("title", "行内公式"); + $("[type=\"latex\"]").attr("title", "多行公式"); + + window.md_elocalStorage(editorName, `memoNew_${id}`, "memoNew"); + + callback && callback() + } + }); + return editorName; +} + +const typeNameMap = { + '技术分享': 5, + '操作指南': 3, +} +export const typeNameMap2 = { + 5: '技术分享', + 3: '操作指南', +} +const defaultType = '技术分享' + +const languageSeparator = '/' +class MemoNew extends Component { + constructor(props) { + super(props) + this.mdRef = React.createRef(); + + // https://testbdweb.trustie.net/uploads.js?attachment_id=1&filename=jqui.js + // https://ant.design/components/upload-cn/ + this.uploaderProps = { + action: '/uploads.js', + data: { attachment_id: 1 }, // , filename: 2 + headers: { + Authorization: 'authorization-text', + }, + multiple: true, + beforeUpload(file) { + // console.log('beforeUpload', file.name); + }, + onStart: (file) => { + console.log('onStart', file.name); + // this.refs.inner.abort(file); + }, + onSuccess(file) { + console.log('onSuccess', file); + }, + onProgress(step, file) { + console.log('onProgress', Math.round(step.percent), file.name); + }, + onError(err) { + console.log('onError', err); + }, + }; + + this.state = { + memoSubject: '', + memoContent: '', + memoType: typeNameMap[defaultType], + memoRepertoire: '', + memoLanguage: [], + + repertoires: [], + currentSelectRepertoiresIndex: -1, + repertoiresTagMap: {}, + + fileList: [] + } + } + onCommit() { + const { memoSubject, memoRepertoire, memoLanguage, currentMemoId, memoType } = this.state; + const { showNotification } = this.props; + if (!memoSubject) { + showNotification('请先输入话题名称') + return + } + let mdVal; + try { + mdVal = this.mdRef.current.getValue() + + } catch (e) { + showNotification('编辑器还未加载完毕,请稍后') + return + } + + if (!mdVal) { + showNotification('请先输入话题内容') + return + } + // !memoRepertoire || + if (memoType === 5 && ( !memoLanguage || memoLanguage.length === 0 )) { + showNotification('请先选择技术标签') + return + } + /* + + + + http://localhost:3000/attachments/download/185790/Git-2.17.1.2-32-bit.exe + https://www.educoder.net/attachments/205112.js?attachment_id=1 + */ + // collect attachments + const $ = window.$; + const attachmentsMap = {}; + const attachmentIds = this.state.fileList.map(item => { + return item.response ? item.response.id : item.id + }) + // $('#attachments_fields .attachment').each(( index, item ) => { + // const filename = $(item).find('.upload_filename').val(); + // // $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val() + // const token = $(item).find('input:nth-child(7)').val() + // const attachment_id = parseInt($(item).children().last().val()) + // attachmentsMap[index] = { + // filename, + // token, + // attachment_id + // } + // attachmentIds.push(attachment_id) + // }) + + + if (currentMemoId) { + this.updateMemo(attachmentIds) + } else { + this.newMemo(attachmentIds) + } + } + onCancel() { + const { currentMemoId, memoType } = this.state; + if (currentMemoId) { // 编辑 + this.props.history.push(`/forums/${currentMemoId}`) + } else { // 新建 + this.props.history.push(`/forums`) + } + // debugger;this.props.history.goBack() + } + updateMemo(attachmentsMap) { + const { memoSubject, memoRepertoire, memoLanguage, memoType, currentMemoId, content } = this.state; + const mdVal = this.mdRef.current.getValue() + console.log('isContentEdit: ', mdVal === content); + const newMemoUrl = `/memos/${currentMemoId}.json` + axios.put(newMemoUrl, { + content_changed: this.contentChanged, + tags: memoLanguage, + // memo:{ + subject: memoSubject , + content: mdVal, + forum_id: memoType, + repertoire_name: memoRepertoire, + // language: memoLanguage.join(languageSeparator), + // + // }, + attachment_ids: attachmentsMap + }, { + // withCredentials: true, + }) + .then((response) => { + const { status, message, memo_id } = response.data; + if (status === 0) { + window.$("html,body").animate({"scrollTop":0}) + this.props.history.push(`/forums/${currentMemoId}`) + } else { + this.props.showNotification(message) + } + }).catch((error) => { + console.log(error) + }) + } + newMemo(attachmentsMap) { + const { memoSubject, memoRepertoire, memoLanguage, memoType } = this.state; + const mdVal = this.mdRef.current.getValue() + + const newMemoUrl = `/memos.json` + axios.post(newMemoUrl, { + tags: memoLanguage, + // memo:{ + subject: memoSubject , + content: mdVal, + forum_id: memoType, + // repertoire_name: memoRepertoire, + + // }, + attachment_ids: attachmentsMap + }, { + // withCredentials: true, + }) + .then((response) => { + const { status, message, memo_id } = response.data; + if (status === 0) { + window.$("html,body").animate({"scrollTop":0}) + this.props.history.push(`/forums/${memo_id}`) + } else { + this.props.showNotification(message) + } + }).catch((error) => { + console.log(error) + }) + } + componentDidMount() { + const newMemoUrl = `/memos/new.json` + axios.get(newMemoUrl,{ + // withCredentials: true, + }) + .then((response) => { + const data = response.data; + const repertoires = []; + const repertoiresTagMap = {} + if ( data.tag_list ) { + // data.tag_list.forEach((item, index)=>{ + // const tagArray = []; + // item.tag.forEach( (tag, index) => { + // tagArray.push(tag.name) + // }) + // repertoires.push(item.rep.repertoire.name) + // repertoiresTagMap[item.rep.repertoire.name] = tagArray + // }) + this.setState({ + tag_list: data.tag_list + // repertoires, + // repertoiresTagMap + }) + + // const user = response.data.current_user; + // user.tidding_count = response.data.tidding_count; + // this.props.initCommonState(user) + + // 初始化 csrf meta + const $ = window.$ + $('head').append( $('') ) + $('head').append( $(``) ) + } + }).catch((error) => { + console.log(error) + }) + + // 如果是编辑 + const { match } = this.props + const memoId = match.params.memoId; + if (memoId) { + const memoUrl = `/memos/${match.params.memoId}/edit.json`; + axios.get(memoUrl,{ + // withCredentials: true, + }) + .then((response) => { + const tag_list = response.data.tag_list + if (tag_list) { + // this.setState({...response.data}) + const { content, forum_id, id, repertoire_name, subject, + current_user, tag_list, attachments_url, memo_tags, attachments } = response.data; + this.initMD(content); + // this.onRepertoiresChange(repertoire_name) + // tag -> memo_tags + const tag = memo_tags; + let memoLanguage = [] + if (tag) { + memoLanguage = tag.map((item, index) => { + return item.id + "" + }) + } + const fileList = attachments.map(item => { + return { + id: item.id, + uid: item.id, + name: appendFileSizeToUploadFile(item), + url: item.url, + filesize: item.filesize, + status: 'done' + } + }) + this.setState({ + fileList, + currentMemoId: memoId, + memoSubject: subject, + memoType: forum_id, + memoRepertoire: repertoire_name, + memoLanguage, + attachments_url, + content + + // repertoires: [], + // currentSelectRepertoiresIndex: -1, + }, ()=> { + // 解决有时候编辑时内容不显示的问题 + setTimeout(() => { + this.mdRef.current && this.mdRef.current.setValue(content || '') + }, 2000) + + $('.upload_filename').each((index, item) => { + var width = window._textWidth($(item), '14px'); + console.log(width) + $(item).css('width', width + 20) + }) + + }) + // 加载完后滚动条滚动 + window.$("html,body").animate({"scrollTop":0}) + + this.props.initForumState({ + // current_user, + tag_list + }) + } + + }).catch((error) => { + console.log(error) + }) + } else { + this.initMD(); + } + + + + + } + initMD(initValue) { + return; + + this.contentChanged = false; + const placeholder = ""; + // amp; + // 编辑时要传memoId + // const imageUrl = `/upload_with_markdown?container_id=&container_type=Memo`; + const imageUrl = `/api/attachments.json`; + + // 创建editorMd + + const taskpass_editormd = create_editorMD("memoMD", '100%', 400, placeholder, imageUrl, () => { + setTimeout(()=>{ + taskpass_editormd.resize() + taskpass_editormd.cm && taskpass_editormd.cm.refresh() + }, 500) + + if (initValue) { + taskpass_editormd.setValue(initValue) + } + taskpass_editormd.cm.on("change", (_cm, changeObj) =>{ + console.log('....contentChanged') + this.contentChanged = true; + }) + }); + this.taskpass_editormd = taskpass_editormd; + window.taskpass_editormd = taskpass_editormd; + + } + + renderOptions(array) { + const elementArray = []; + array.forEach(( item, index ) => { + elementArray.push( + + ) + }) + return elementArray + } + onRepertoiresChange(value) { + + const index = this.state.repertoires.indexOf(value) + + this.setState({ + currentSelectRepertoiresIndex: index, + memoRepertoire: value, + memoLanguage: '' + }); + }; + + renderTag() { + const { tag_list } = this.state; + if (!tag_list || tag_list.length === 0) { + return '' + } + const result = [] + + tag_list.forEach((item, index) => { + result.push() + }) + + return result; + } + + onTagChange(value) { + if (value && value.length > 3) { + this.props.showNotification(`最多选择3个技术标签`) + + return; + } + this.setState({ + memoLanguage: value + }) + } + + onTypeChange(value) { + + this.setState({ + memoType: typeNameMap[value] + }) + } + onMemoNameChange(e) { + this.setState({ + memoSubject: e.target.value + }) + } + renderAttachment() { + const { attachments_url } = this.state; + const attachments = [] + attachments_url.forEach((item, index) => { + const ar = item.url.split('/') + const fileName = ar[ar.length - 1] + /* +

+ + {fileName} + +

+ */ + // ?attachment_id=2 + /* + + + + */ + attachments.push( + + + + + + {window.conver_size(item.id)} + + + +
+ {/**/} + +
+
+
+ + ) + }) + return attachments; + } + handleChange = (info) => { + if (info.file.status === 'uploading' || info.file.status === 'done') { + let fileList = info.fileList; + this.setState({ + fileList: appendFileSizeToUploadFileAll(fileList) + }); + } + } + onAttachmentRemove = (file) => { + this.props.confirm({ + // title: '确定要删除这个附件吗?', + content: '是否确认删除?', + + okText: '确定', + cancelText: '取消', + // content: 'Some descriptions', + onOk: () => { + this.deleteAttachment(file) + }, + onCancel() { + console.log('Cancel'); + }, + }); + return false; + } + deleteAttachment = (file) => { + // 初次上传不能直接取uid + const url = `/attachments/${file.response ? file.response.id : file.uid}.json` + axios.delete(url, { + }) + .then((response) => { + if (response.data) { + const { status } = response.data; + if (status == 0) { + console.log('--- success') + + this.setState((state) => { + const index = state.fileList.indexOf(file); + const newFileList = state.fileList.slice(); + newFileList.splice(index, 1); + return { + fileList: newFileList, + }; + }); + } + } + }) + .catch(function (error) { + console.log(error); + }); + } + render() { + const { match, history } = this.props + const { + // repertoires, repertoiresTagMap, currentSelectRepertoiresIndex, memoRepertoire, + tag_list, + memoSubject, memoType, + memoLanguage, attachments_url, fileList } = this.state; + const memoId = match.params.memoId; + + const uploadProps = { + width: 600, + fileList, + multiple: true, + // https://github.com/ant-design/ant-design/issues/15505 + // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 + // showUploadList: false, + action: `${getUploadActionUrl()}`, + onChange: this.handleChange, + onRemove: this.onAttachmentRemove, + beforeUpload: (file) => { + console.log('beforeUpload', file.name); + const isLt150M = file.size / 1024 / 1024 < 150; + if (!isLt150M) { + this.props.showNotification('文件大小必须小于150MB!'); + } + return isLt150M; + }, + }; + return ( +
+

交流问答 / 详情

+
+ { memoId ? '编辑话题' : '发布话题'} + {/* + */} +
+ +
+
+

话题名称

+
+ * +
+ this.onMemoNameChange(val)} placeholder=""> + +
+
+ + 必填项 + +
+
+
+
+ +
+
+

内容

+
+ * +
+ + + {/*
+ +
*/} +

+

+
+
+ + 必填项 + +
+
+ + + + {/*
+ + { attachments_url && !!attachments_url.length && + this.renderAttachment() + } + + + {debugger;window.addInputFiles( window.$('.file_selector')[0] ) }} + style={{'display':'none'}} type="file"> + + +
*/} + + + {/*开始上传*/} + + + (单个文件150M以内) + + + {/* 请求status 422 */} + + {/* */} + {/* */} +
+
+ {/* TODOTODO 这里重复的html代码太多,如果有其他页面有类似需求,需要封装*/} + +
+
+

话题类型

+
+ * +
+ +
+
+ + 必填项 + +
+
+
+
+ + {/* memoType === typeNameMap['技术分享'] && +
+
+

技术标签

+
+ * +
+ +
+
+ +
+ +
+ + 必填项 + +
+
+
+
*/} + + { memoType === typeNameMap['技术分享'] && +
+
+

技术标签

+
+ * + +
+ +
+ +
+ + 必填项 + +
+
+
+
} + + + +
+ ); + } +} + +export default MemoNew; diff --git a/public/react/src/modules/tpm/challengesnew/TPMquestion.js b/public/react/src/modules/tpm/challengesnew/TPMquestion.js index 82d94f787..8fc2b1133 100644 --- a/public/react/src/modules/tpm/challengesnew/TPMquestion.js +++ b/public/react/src/modules/tpm/challengesnew/TPMquestion.js @@ -411,9 +411,7 @@ export default class TPMquestion extends Component { window.location.href = '/shixuns/'+this.props.match.params.shixunId+'/challenges/'+this.props.match.params.checkpointId+'/editquestion'; } questionadd=()=>{ - $('html').animate({ - scrollTop: 10 - }, 200); + let{questionaddarray}=this.state; let questionaddsums=questionaddarray.length; @@ -431,15 +429,13 @@ export default class TPMquestion extends Component { } }) - - questionaddarrays.push({type:0,choose_id:0}); this.setState({ activetype:0, questionaddarray:questionaddarrays, questionaddtype:true, + editquestionaddtype:false, newquestionaddtype:true, - editquestionaddtype:false, questionlists:[{str:"A",val:"",type:false},{str:"B",val:"",type:false},{str:"C",val:"",type:false},{str:"D",val:"",type:false}], answeshixunsGroup: 1, answeoptions:[10,20], @@ -447,17 +443,17 @@ export default class TPMquestion extends Component { shixunssanswerkillvalue:"", shixunsskillanswerlist:[], contentMdRefval:"", - newquestioMDMdContval:"" + newquestioMDMdContval:"", }) - // setTimeout(() => { - // this.newquestioMDMdCont.current.setValue('') - // this.newquestioMDMdRef.current.setValue('') - // - // }, 2000) - - this.shixunsautoHeight() + setTimeout(() => { + this.newquestioMDMdRef.current.setValue('') + }, 1000) + setTimeout(() => { + this.newquestioMDMdCont.current.setValue('') + }, 1500) + // this.shixunsautoHeight() } editquestionlists=(newquestionlists)=>{ @@ -592,6 +588,10 @@ export default class TPMquestion extends Component { } answer_subit=(sumtype,challenge_choose_id)=>{ + $('html').animate({ + scrollTop:10 + }, 500); + let {challenge_id,questionlists,shixunsskillanswerlist,answeonshixunsmark,answeshixunsGroup,questionaddarray} =this.state; if(challenge_id===undefined){ message.error("关卡id为空"); @@ -679,6 +679,7 @@ export default class TPMquestion extends Component { let id = this.props.match.params.shixunId; + let checkpointId=this.props.match.params.checkpointId let url; if(sumtype==="edit"){ let newquestioMDvalue = this.neweditanswerRef.current.getValue().trim(); @@ -781,7 +782,9 @@ export default class TPMquestion extends Component { description: '新建成功,请点击右侧加号继续添加', }); - // this.getanswer_subitlist() + window.location.href=`/shixuns/${id}/challenges/${checkpointId}/editquestion/${response.data.challenge_choose_id}`; + + // this.getanswer_subitlist() // this.gochooseid("/shixuns/"+this.props.match.params.shixunId+"/challenges/"+this.props.match.params.checkpointId+"/editquestion"+"/"+response.data.challenge_choose_id) }).catch((error) => { console.log(error) @@ -817,7 +820,8 @@ export default class TPMquestion extends Component { neweditanswerRefval:'', editanswersRefval:'' }) - + this.newquestioMDMdRef.current.setValue('') + this.newquestioMDMdCont.current.setValue('') }else{ let id = this.props.match.params.shixunId; let url ='/shixuns/'+id+'/challenges/'+challenge_id+'/edit_choose_question.json?choose_id='+challenge_choose_id; @@ -920,6 +924,7 @@ export default class TPMquestion extends Component { ) }) + return (
diff --git a/public/react/src/modules/tpm/challengesnew/TpmQuestionEdit.js b/public/react/src/modules/tpm/challengesnew/TpmQuestionEdit.js index 32b56aae1..d0e6f98bd 100644 --- a/public/react/src/modules/tpm/challengesnew/TpmQuestionEdit.js +++ b/public/react/src/modules/tpm/challengesnew/TpmQuestionEdit.js @@ -4,6 +4,8 @@ import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal,Tooltip} from import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; +import axios from 'axios'; + import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; const Option = Select.Option; @@ -21,7 +23,17 @@ export default class TpmQuestionEdit extends Component { componentDidMount() { } - + delecbtns=()=>{ + let url=`/shixuns/${this.props.match.params.shixunId}/challenges/${this.props.match.params.checkpointId}/destroy_challenge_choose.json`; + axios.delete((url), { data: { + choose_id:this.props.match.params.choose_id + }}) + .then((result)=>{ + if(result.data.status===1){ + window.location.href=`/shixuns/${this.props.match.params.shixunId}/challenges/${this.props.match.params.checkpointId}/editquestion`; + } + }) + } render() { @@ -202,6 +214,9 @@ export default class TpmQuestionEdit extends Component { onClick={()=>this.props.answer_subit()}>提交 取消 + + this.delecbtns()} + className="delectshixuncdbtn fr">删除
diff --git a/public/react/src/modules/tpm/challengesnew/TpmQuestionNew.js b/public/react/src/modules/tpm/challengesnew/TpmQuestionNew.js index 855f6ce53..861c4f879 100644 --- a/public/react/src/modules/tpm/challengesnew/TpmQuestionNew.js +++ b/public/react/src/modules/tpm/challengesnew/TpmQuestionNew.js @@ -35,7 +35,7 @@ export default class TpmQuestionNew extends Component { *
+ needRecreate={true} watch={true} className="courseMessageMD" initValue={this.props.contentMdRefval}>
@@ -108,7 +108,7 @@ export default class TpmQuestionNew extends Component {
+ needRecreate={true} watch={true} className="courseMessageMD" initValue={this.props.newquestioMDMdContval}>
必填项 diff --git a/public/react/src/modules/user/usersInfo/InfosBanner.js b/public/react/src/modules/user/usersInfo/InfosBanner.js index f163f5ed5..3aa329ec9 100644 --- a/public/react/src/modules/user/usersInfo/InfosBanner.js +++ b/public/react/src/modules/user/usersInfo/InfosBanner.js @@ -1,132 +1,124 @@ -import React, { Component } from 'react'; - -import {Link} from 'react-router-dom'; -import {Tooltip,Menu} from 'antd'; -import {getImageUrl} from 'educoder'; - -import "./usersInfo.css" -import "../../courses/css/members.css" -import "../../courses/css/Courses.css" - -import { LinkAfterLogin } from 'educoder' - -class InfosBanner extends Component{ - constructor(props){ - super(props); - } - render(){ - let { - data , - id, - login, - moduleName, - current_user, - }=this.props; - let is_current=this.props.is_current; - let {username}= this.props.match.params; - let {pathname}=this.props.location; - moduleName=pathname.split("/")[3]; - - console.log(is_current) - return( -
-
-
-

头像

-
-

- {data && data.name} - { - data && is_current == false && data.identity =="学生" ? "" : - - } -

-

- - - - - - -

-
-
-
- {is_current ? "我":"TA"}的经验值 - {data && data.experience} -
-
- {is_current ? "我":"TA"}的金币 - {data && data.grade} -
- { - is_current ? - - { - data && data.attendance_signed ? - 已签到 - : - 签到 - } - - : - - - 私信 - - - } -
-
-
-
  • - this.setState({moduleName: 'courses'})} - to={`/users/${username}/courses`}>翻转课堂 -
  • -
  • - this.setState({moduleName: 'shixuns'})} - to={`/users/${username}/shixuns`}>开发社区 -
  • -
  • - this.setState({moduleName: 'paths'})} - to={`/users/${username}/paths`}>实践课程 -
  • -
  • - this.setState({moduleName: 'projects'})} - to={`/users/${username}/projects`}>项目 -
  • -
  • - this.setState({moduleName: 'package'})} - to={`/users/${username}/package`}>众包 -
  • - {((is_current && current_user && current_user.is_teacher ) || current_user && current_user.admin) - &&
  • - this.setState({moduleName: 'videos'})} - to={`/users/${username}/videos`}>视频 -
  • } - - {((is_current && current_user && current_user.is_teacher ) || current_user && current_user.admin) - &&
  • - this.setState({moduleName: 'videos'})} - to={`/users/${username}/videos`}>题库 -
  • } - -
    -
    -
    - ) - } -} +import React, { Component } from 'react'; + +import {Link} from 'react-router-dom'; +import {Tooltip,Menu} from 'antd'; +import {getImageUrl} from 'educoder'; + +import "./usersInfo.css" +import "../../courses/css/members.css" +import "../../courses/css/Courses.css" + +import { LinkAfterLogin } from 'educoder' + +class InfosBanner extends Component{ + constructor(props){ + super(props); + } + render(){ + let { + data , + id, + login, + moduleName, + current_user, + }=this.props; + let is_current=this.props.is_current; + let {username}= this.props.match.params; + let {pathname}=this.props.location; + moduleName=pathname.split("/")[3]; + + return( +
    +
    +
    +

    头像

    +
    +

    + {data && data.name} + { + data && is_current == false && data.identity =="学生" ? "" : + + } +

    +

    + + + + + + +

    +
    +
    +
    + {is_current ? "我":"TA"}的经验值 + {data && data.experience} +
    +
    + {is_current ? "我":"TA"}的金币 + {data && data.grade} +
    + { + is_current ? + + { + data && data.attendance_signed ? + 已签到 + : + 签到 + } + + : + + + 私信 + + + } +
    +
    +
    +
  • + this.setState({moduleName: 'courses'})} + to={`/users/${username}/courses`}>翻转课堂 +
  • +
  • + this.setState({moduleName: 'shixuns'})} + to={`/users/${username}/shixuns`}>实训项目 +
  • +
  • + this.setState({moduleName: 'paths'})} + to={`/users/${username}/paths`}>实践课程 +
  • +
  • + this.setState({moduleName: 'projects'})} + to={`/users/${username}/projects`}>开发项目 +
  • +
  • + this.setState({moduleName: 'package'})} + to={`/users/${username}/package`}>众包 +
  • + {((is_current && current_user && current_user.is_teacher ) || current_user && current_user.admin) + &&
  • + this.setState({moduleName: 'videos'})} + to={`/users/${username}/videos`}>视频 +
  • } + +
    +
    +
    + ) + } +} export default InfosBanner; \ No newline at end of file diff --git a/public/stylesheets/educoder/edu-main.css b/public/stylesheets/educoder/edu-main.css index f59827f45..c66453b4c 100644 --- a/public/stylesheets/educoder/edu-main.css +++ b/public/stylesheets/educoder/edu-main.css @@ -538,6 +538,27 @@ a.edu-greyline-btn:hover,a.edu-greyshallowline-btn:hover{border:1px solid #B2B2B font-weight: 400; color: rgba(255,255,255,1); } + +/*删除按钮*/ +.delectshixuncdbtn{ + display: block; + border: 1px solid #CDCDCD; + background-color: #fafafa; + color: #999!important; + width: 120px; + text-align: center; + height: 30px; + line-height: 30px; + border-radius: 2px; + width: 130px; + height: 40px; + background: rgba(77,124,254,0); + border-radius: 4px; + line-height: 40px; + font-size: 16px; + font-family: MicrosoftYaHei; + font-weight: 400; +} .defalutSubmitbtn:hover{background-color: #459BE6;border: 1px solid #459BE6;} /*-------------------------------------------公用按钮:以white-btn(或者edu-default-btn无padding)为基础,宽度和高度可以用padding填充,颜色用edu-color-btn,end-----------------------------------------*/