From 97a432fa6a82c6da66391c0bc36ac1d414ceecb7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com>
Date: Fri, 20 Dec 2019 09:11:39 +0800
Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/colleges_controller.rb | 12 +-
app/controllers/hacks_controller.rb | 4 +-
.../homework_commons_controller.rb | 14 +-
app/controllers/myshixuns_controller.rb | 2 +-
app/models/curriculum.rb | 4 -
app/models/curriculum_direction.rb | 4 -
app/models/hack_user_lastest_code.rb | 2 +-
app/models/item_bank.rb | 2 -
app/models/knowledge_point.rb | 5 -
app/models/knowledge_point_container.rb | 3 -
.../colleges/student_shixun.json.jbuilder | 2 +-
app/views/colleges/teachers.json.jbuilder | 2 +-
...1218070922_create_curriculum_directions.rb | 9 -
.../20191218071017_create_curriculums.rb | 10 -
.../20191218071111_create_knowledge_points.rb | 11 -
...71343_create_knowledge_point_containers.rb | 12 -
...1219120819_modify_description_for_hacks.rb | 10 +
public/react/package.json | 1 +
public/react/public/js/jupyter.js | 32 +-
public/react/src/App.js | 13 +-
public/react/src/college/College.js | 1259 +++++++++++++++++
.../college/colleagechart/Colleagechart.js | 84 ++
.../college/colleagechart/Colleagechartzu.js | 149 ++
.../src/college/colleagecss/colleage.css | 213 +++
.../common/components/comment/CommentForm.js | 116 ++
.../common/components/comment/CommentIcon.js | 32 +
.../common/components/comment/CommentItem.js | 165 +++
.../common/components/comment/CommentList.js | 20 +
.../src/common/components/comment/index.js | 22 +
.../src/common/components/comment/index.scss | 111 ++
.../src/common/quillForEditor/ImageBlot.js | 54 +
.../src/common/quillForEditor/deepEqual.js | 47 +
.../react/src/common/quillForEditor/index.js | 166 +++
.../react/src/common/reactQuill/ImageBlot.js | 54 +
.../react/src/common/reactQuill/ReactQuill.js | 45 +
.../react/src/common/reactQuill/deepEqual.js | 47 +
public/react/src/common/reactQuill/flatten.js | 26 +
public/react/src/common/reactQuill/index.js | 108 ++
public/react/src/common/reactQuill/index.scss | 32 +
public/react/src/common/reactQuill/lib.js | 13 +
.../src/common/reactQuill/useDeepEqualMemo.js | 27 +
.../src/common/reactQuill/useMountQuill.js | 148 ++
.../react/src/common/reactQuill/useQuill.js | 60 +
.../src/common/reactQuill/useQuillOnChange.js | 33 +
.../common/reactQuill/useQuillPlaceholder.js | 22 +
.../common/reactQuill/useQuillValueSync.js | 31 +
.../src/modules/developer/DeveloperHome.js | 21 +-
.../components/controlSetting/index.js | 24 +-
.../components/controlSetting/index.scss | 7 +-
.../developer/components/execResult/index.js | 14 +-
.../developer/components/initTabCtx/index.js | 7 +-
.../components/initTabCtx/index.scss | 3 +-
.../components/monacoSetting/index.js | 3 +-
.../components/myMonacoEditor/index.js | 59 +-
.../components/myMonacoEditor/index.scss | 33 +-
.../modules/developer/newOrEditTask/index.js | 102 +-
.../developer/newOrEditTask/index.scss | 16 +-
.../leftpane/editorTab/AddTestDemo.js | 24 +-
.../newOrEditTask/leftpane/editorTab/index.js | 53 +-
.../leftpane/editorTab/index.scss | 5 +
.../developer/newOrEditTask/leftpane/index.js | 22 -
.../newOrEditTask/leftpane/prevTab/index.js | 77 +-
.../newOrEditTask/rightpane/index.scss | 5 +-
.../modules/developer/split_pane_resizer.scss | 6 +-
.../modules/developer/studentStudy/index.js | 63 +-
.../modules/developer/studentStudy/index.scss | 2 +-
.../studentStudy/leftpane/comment/index.js | 13 +-
.../studentStudy/leftpane/comment/index.scss | 8 +
.../developer/studentStudy/leftpane/index.js | 63 +-
.../studentStudy/leftpane/index.scss | 7 +
.../leftpane/taskDescription/index.js | 18 +-
.../developer/studentStudy/rightpane/index.js | 32 +-
public/react/src/modules/tpm/TPMBanner.js | 71 +-
public/react/src/modules/tpm/TPMIndex.js | 11 +-
.../tpm/TPMsettings/LearningSettings.js | 6 +-
.../tpm/TPMsettings/Shixuninformation.js | 13 +
.../modules/tpm/challengesnew/TPManswer.js | 4 +-
.../modules/tpm/challengesnew/TPManswer2.js | 4 +-
.../tpm/challengesnew/TPMchallengesnew.js | 4 +-
.../tpm/challengesnew/TPMevaluation.js | 4 +-
.../modules/tpm/challengesnew/TPMquestion.js | 4 +-
.../modules/tpm/component/TPMRightSection.js | 6 +-
.../src/modules/tpm/component/TPMright.css | 5 +
.../tpm/shixunchild/Challenges/Challenges.js | 42 +-
.../Challenges/Challengesjupyter.js | 45 +-
.../Collaborators/Collaborators.css | 9 +
.../Collaborators/Collaborators.js | 11 +-
.../src/modules/tpm/shixuns/ShixunCardList.js | 2 +-
public/react/src/redux/actions/actionTypes.js | 5 +-
public/react/src/redux/actions/common.js | 4 +-
public/react/src/redux/actions/index.js | 4 +-
public/react/src/redux/actions/ojForUser.js | 45 +-
public/react/src/redux/actions/ojForm.js | 20 +-
.../src/redux/reducers/ojForUserReducer.js | 29 +-
.../react/src/redux/reducers/ojFormReducer.js | 4 +-
public/react/src/services/ojService.js | 15 +-
spec/models/curriculum_direction_spec.rb | 5 -
spec/models/curriculum_spec.rb | 5 -
spec/models/knowledge_point_container_spec.rb | 5 -
spec/models/knowledge_point_spec.rb | 5 -
100 files changed, 3821 insertions(+), 491 deletions(-)
delete mode 100644 app/models/curriculum.rb
delete mode 100644 app/models/curriculum_direction.rb
delete mode 100644 app/models/knowledge_point.rb
delete mode 100644 app/models/knowledge_point_container.rb
delete mode 100644 db/migrate/20191218070922_create_curriculum_directions.rb
delete mode 100644 db/migrate/20191218071017_create_curriculums.rb
delete mode 100644 db/migrate/20191218071111_create_knowledge_points.rb
delete mode 100644 db/migrate/20191218071343_create_knowledge_point_containers.rb
create mode 100644 db/migrate/20191219120819_modify_description_for_hacks.rb
create mode 100644 public/react/src/college/College.js
create mode 100644 public/react/src/college/colleagechart/Colleagechart.js
create mode 100644 public/react/src/college/colleagechart/Colleagechartzu.js
create mode 100644 public/react/src/college/colleagecss/colleage.css
create mode 100644 public/react/src/common/components/comment/CommentForm.js
create mode 100644 public/react/src/common/components/comment/CommentIcon.js
create mode 100644 public/react/src/common/components/comment/CommentItem.js
create mode 100644 public/react/src/common/components/comment/CommentList.js
create mode 100644 public/react/src/common/components/comment/index.js
create mode 100644 public/react/src/common/components/comment/index.scss
create mode 100644 public/react/src/common/quillForEditor/ImageBlot.js
create mode 100644 public/react/src/common/quillForEditor/deepEqual.js
create mode 100644 public/react/src/common/quillForEditor/index.js
create mode 100644 public/react/src/common/reactQuill/ImageBlot.js
create mode 100644 public/react/src/common/reactQuill/ReactQuill.js
create mode 100644 public/react/src/common/reactQuill/deepEqual.js
create mode 100644 public/react/src/common/reactQuill/flatten.js
create mode 100644 public/react/src/common/reactQuill/index.js
create mode 100644 public/react/src/common/reactQuill/index.scss
create mode 100644 public/react/src/common/reactQuill/lib.js
create mode 100644 public/react/src/common/reactQuill/useDeepEqualMemo.js
create mode 100644 public/react/src/common/reactQuill/useMountQuill.js
create mode 100644 public/react/src/common/reactQuill/useQuill.js
create mode 100644 public/react/src/common/reactQuill/useQuillOnChange.js
create mode 100644 public/react/src/common/reactQuill/useQuillPlaceholder.js
create mode 100644 public/react/src/common/reactQuill/useQuillValueSync.js
create mode 100644 public/react/src/modules/developer/studentStudy/leftpane/comment/index.scss
delete mode 100644 spec/models/curriculum_direction_spec.rb
delete mode 100644 spec/models/curriculum_spec.rb
delete mode 100644 spec/models/knowledge_point_container_spec.rb
delete mode 100644 spec/models/knowledge_point_spec.rb
diff --git a/app/controllers/colleges_controller.rb b/app/controllers/colleges_controller.rb
index 71009d2dd..707255866 100644
--- a/app/controllers/colleges_controller.rb
+++ b/app/controllers/colleges_controller.rb
@@ -21,7 +21,7 @@ class CollegesController < ApplicationController
# 实训总数
@shixuns_count = Shixun.visible.joins('left join user_extensions on user_extensions.user_id = shixuns.user_id')
.where(user_extensions: { school_id: current_school.id }).count
- render json: { teachers_count: @teachers_count, students_count: @students_count, courses_count: @courses_count, shixuns_count: @shixuns_count }
+ render json: { teachers_count: @teachers_count, students_count: @students_count, courses_count: @courses_count, shixuns_count: @shixuns_count, school: current_school.name }
end
def shixun_time
@@ -44,8 +44,8 @@ class CollegesController < ApplicationController
(SELECT count(c.id) FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.user_id=users.id AND m.role in (1,2,3) and c.school_id = #{current_school.id} AND c.is_delete = 0) as course_count
FROM `users`, user_extensions ue where ue.school_id=#{current_school.id} and users.id=ue.user_id and ue.identity=0 ORDER BY publish_shixun_count desc, course_count desc, id desc LIMIT 10")
# ).order("publish_shixun_count desc, experience desc").limit(10)
- @teacher_count = UserExtension.where(school_id: current_school.id)
- .select('SUM(IF(identity=0, 1, 0)) AS teachers_count').first.teachers_count
+ # @teacher_count = UserExtension.where(school_id: current_school.id)
+ # .select('SUM(IF(identity=0, 1, 0)) AS teachers_count').first.teachers_count
@teachers =
@teachers.map do |teacher|
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.role in (1,2,3) AND m.user_id=#{teacher.id} AND c.is_delete = 0 and c.school_id = #{current_school.id}")
@@ -99,7 +99,7 @@ class CollegesController < ApplicationController
@course_count = courses.size
courses = courses.left_joins(practice_homeworks: { student_works: { myshixun: :games } })
- .select('courses.id, courses.name, courses.is_end, sum(games.evaluate_count) evaluating_count')
+ .select('courses.id, courses.name, courses.is_end, IFNULL(sum(games.evaluate_count), 0) evaluating_count')
.group('courses.id').order('is_end asc, evaluating_count desc')
@courses = paginate courses
@@ -117,7 +117,7 @@ class CollegesController < ApplicationController
# 学生实训
def student_shixun
- @student_count = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).count
+ # @student_count = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).count
@students = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).includes(:user_extension).order('experience desc').limit(10)
student_ids = @students.map(&:id)
@@ -158,7 +158,7 @@ class CollegesController < ApplicationController
return true if current_user.admin_or_business? # 超级管理员|运营
return true if current_college.is_a?(Department) && current_college.member?(current_user) # 部门管理员
return true if current_user.is_teacher? && current_user.school_id == current_school.id # 学校老师
- return true if current_school.customers.exists? && current_user.partner&.partner_customers&.exists?(customer_id: current_school.customer_id)
+ # return true if current_school.customers.exists? && current_user.partner&.partner_customers&.exists?(customer_id: current_school.customer_id)
false
end
diff --git a/app/controllers/hacks_controller.rb b/app/controllers/hacks_controller.rb
index cab952a04..b7f6a30a2 100644
--- a/app/controllers/hacks_controller.rb
+++ b/app/controllers/hacks_controller.rb
@@ -9,9 +9,11 @@ class HacksController < ApplicationController
def start
# 未发布的编程题,只能作者、或管理员访问
start_hack_auth
- user_hack = @hack.hack_user_lastest_codes.mine(current_user.id)
+ user_hack = @hack.hack_user_lastest_codes.where(user_id: current_user.id).first
+ logger.info("#user_hack: #{user_hack}")
identifier =
if user_hack.present?
+ logger.info("#####user_hack_id:#{user_hack.id}")
user_hack.identifier
else
user_identifier = generate_identifier HackUserLastestCode, 12
diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb
index 8a1c07ddf..3a60dcde5 100644
--- a/app/controllers/homework_commons_controller.rb
+++ b/app/controllers/homework_commons_controller.rb
@@ -167,7 +167,11 @@ class HomeworkCommonsController < ApplicationController
if params[:work_status].present?
params_work_status = params[:work_status]
work_status = params_work_status.map{|status| status.to_i}
- @student_works = @student_works.where(compelete_status: work_status)
+ if @homework.homework_type == "practice"
+ @student_works = @student_works.where(compelete_status: work_status)
+ else
+ @student_works = @student_works.where(work_status: work_status)
+ end
end
# 分班情况
@@ -1497,8 +1501,12 @@ class HomeworkCommonsController < ApplicationController
@user = @student_work.user
tip_exception("当前用户无作品可以显示") if @student_work.nil?
# 查询最新一次的查重标识query_id
- group_id = @course.course_members.where(user_id: params[:user_id]).pluck(:course_group_id).first
- query_id = @homework.homework_group_reviews.where(:course_group_id => group_id).last.try(:query_id)
+ group_id = @course.students.where(user_id: params[:user_id]).pluck(:course_group_id).first
+ homework_group_review = @homework.homework_group_reviews.where(:course_group_id => group_id).last || @homework.homework_group_reviews.last
+ query_id = homework_group_review.try(:query_id)
+ Rails.logger.info("##################------query_id: #{query_id}")
+ tip_exception(-1, "query_id有误") unless query_id.present?
+
results = ReviewService.query_result({user_id: params[:user_id], query_id: query_id})
@shixun = @homework.shixuns.take
if results.status == 0
diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb
index 987f4873a..0e9ba477a 100644
--- a/app/controllers/myshixuns_controller.rb
+++ b/app/controllers/myshixuns_controller.rb
@@ -247,7 +247,7 @@ class MyshixunsController < ApplicationController
def update_file
begin
@hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first
- tip_exception("技术平台为空!") if @myshixun.mirror_name.blank?
+ tip_exception("实验环境不能为空,请查看实训模板的环境配置项是否正确!") if (@myshixun.mirror_name.blank? || @myshixun.mirror_name.first.to_s == "-1")
path = params[:path].strip unless params[:path].blank?
game_id = params[:game_id]
game = Game.find(game_id)
diff --git a/app/models/curriculum.rb b/app/models/curriculum.rb
deleted file mode 100644
index 0b78814bc..000000000
--- a/app/models/curriculum.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-class Curriculum < ApplicationRecord
- belongs_to :curriculum_direction
- has_many :knowledge_points, dependent: :destroy
-end
diff --git a/app/models/curriculum_direction.rb b/app/models/curriculum_direction.rb
deleted file mode 100644
index 1c9211559..000000000
--- a/app/models/curriculum_direction.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-class CurriculumDirection < ApplicationRecord
- has_many :curriculums
- has_many :knowledge_points
-end
diff --git a/app/models/hack_user_lastest_code.rb b/app/models/hack_user_lastest_code.rb
index b4a707603..830f16dde 100644
--- a/app/models/hack_user_lastest_code.rb
+++ b/app/models/hack_user_lastest_code.rb
@@ -8,7 +8,7 @@ class HackUserLastestCode < ApplicationRecord
belongs_to :user
has_many :hack_user_codes, dependent: :destroy
has_one :hack_user_debug
- scope :mine, ->(author_id){ find_by(user_id: author_id) }
+ scope :mine, ->(author_id){ where(user_id: author_id).first }
scope :mine_hack, ->(author_id){ where(user_id: author_id) }
scope :passed, -> {where(status: 1)}
diff --git a/app/models/item_bank.rb b/app/models/item_bank.rb
index 32c349e34..8078a55e0 100644
--- a/app/models/item_bank.rb
+++ b/app/models/item_bank.rb
@@ -3,8 +3,6 @@ class ItemBank < ApplicationRecord
# item_type: 0 单选 1 多选 2 判断 3 填空 4 简答 5 实训 6 编程
enum item_type: { SINGLE: 0, MULTIPLE: 1, JUDGMENT: 2, COMPLETION: 3, SUBJECTIVE: 4, PRACTICAL: 5, PROGRAM: 6 }
- belongs_to :curriculum
- belongs_to :curriculum_direction
belongs_to :user
has_one :item_analysis, dependent: :destroy
diff --git a/app/models/knowledge_point.rb b/app/models/knowledge_point.rb
deleted file mode 100644
index 3d75b66a1..000000000
--- a/app/models/knowledge_point.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class KnowledgePoint < ApplicationRecord
- belongs_to :curriculum_direction
- belongs_to :curriculum
- has_many :knowledge_point_containers, dependent: :destroy
-end
diff --git a/app/models/knowledge_point_container.rb b/app/models/knowledge_point_container.rb
deleted file mode 100644
index ea73d00e7..000000000
--- a/app/models/knowledge_point_container.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class KnowledgePointContainer < ApplicationRecord
- belongs_to :knowledge_point
-end
diff --git a/app/views/colleges/student_shixun.json.jbuilder b/app/views/colleges/student_shixun.json.jbuilder
index 431603afa..97e418148 100644
--- a/app/views/colleges/student_shixun.json.jbuilder
+++ b/app/views/colleges/student_shixun.json.jbuilder
@@ -7,4 +7,4 @@ json.teachers @students do |student|
json.grade student.grade
json.experience student.experience
end
-json.student_count @student_count
\ No newline at end of file
+# json.student_count @student_count
\ No newline at end of file
diff --git a/app/views/colleges/teachers.json.jbuilder b/app/views/colleges/teachers.json.jbuilder
index 29b383fa4..1308f0cf4 100644
--- a/app/views/colleges/teachers.json.jbuilder
+++ b/app/views/colleges/teachers.json.jbuilder
@@ -8,4 +8,4 @@ json.teachers @teachers do |teacher|
json.complete_rate teacher['complete_rate']
json.publish_shixun_count teacher['publish_shixun_count']
end
-json.teacher_count @teacher_count
\ No newline at end of file
+# json.teacher_count @teacher_count
\ No newline at end of file
diff --git a/db/migrate/20191218070922_create_curriculum_directions.rb b/db/migrate/20191218070922_create_curriculum_directions.rb
deleted file mode 100644
index 9203aa435..000000000
--- a/db/migrate/20191218070922_create_curriculum_directions.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class CreateCurriculumDirections < ActiveRecord::Migration[5.2]
- def change
- create_table :curriculum_directions do |t|
- t.string :name
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20191218071017_create_curriculums.rb b/db/migrate/20191218071017_create_curriculums.rb
deleted file mode 100644
index 885f2a676..000000000
--- a/db/migrate/20191218071017_create_curriculums.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class CreateCurriculums < ActiveRecord::Migration[5.2]
- def change
- create_table :curriculums do |t|
- t.string :name
- t.references :curriculum_direction, index: true
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20191218071111_create_knowledge_points.rb b/db/migrate/20191218071111_create_knowledge_points.rb
deleted file mode 100644
index 2f748d266..000000000
--- a/db/migrate/20191218071111_create_knowledge_points.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class CreateKnowledgePoints < ActiveRecord::Migration[5.2]
- def change
- create_table :knowledge_points do |t|
- t.string :name
- t.references :curriculum_direction, index: true
- t.references :curriculum, index: true
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20191218071343_create_knowledge_point_containers.rb b/db/migrate/20191218071343_create_knowledge_point_containers.rb
deleted file mode 100644
index 0b6944ea7..000000000
--- a/db/migrate/20191218071343_create_knowledge_point_containers.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class CreateKnowledgePointContainers < ActiveRecord::Migration[5.2]
- def change
- create_table :knowledge_point_containers do |t|
- t.references :knowledge_point
- t.integer :container_id
- t.string :container_type
-
- t.timestamps
- end
- add_index :knowledge_point_containers, [:knowledge_point_id, :container_id, :container_type], name: "container_index", unique: true
- end
-end
diff --git a/db/migrate/20191219120819_modify_description_for_hacks.rb b/db/migrate/20191219120819_modify_description_for_hacks.rb
new file mode 100644
index 000000000..3cc45fd5d
--- /dev/null
+++ b/db/migrate/20191219120819_modify_description_for_hacks.rb
@@ -0,0 +1,10 @@
+class ModifyDescriptionForHacks < ActiveRecord::Migration[5.2]
+ def change
+ change_column :hacks, :description, :longtext
+ change_column :hack_codes, :code, :longtext
+ change_column :hack_user_lastest_codes, :code, :longtext
+ change_column :hack_user_codes, :code, :longtext
+ change_column :hack_user_debugs, :code, :longtext
+
+ end
+end
diff --git a/public/react/package.json b/public/react/package.json
index 66db5e6f8..144292feb 100644
--- a/public/react/package.json
+++ b/public/react/package.json
@@ -61,6 +61,7 @@
"prop-types": "^15.6.1",
"qs": "^6.6.0",
"quill": "^1.3.7",
+ "quill-delta-to-html": "^0.11.0",
"raf": "3.4.0",
"rc-form": "^2.1.7",
"rc-pagination": "^1.16.2",
diff --git a/public/react/public/js/jupyter.js b/public/react/public/js/jupyter.js
index 8d76a9a7f..6e52088c3 100644
--- a/public/react/public/js/jupyter.js
+++ b/public/react/public/js/jupyter.js
@@ -1,11 +1,29 @@
-//用于嵌入到jupyter pod中的js
-//guange 2019.12.18
-
-window.onload=function(){
- require(["base/js/namespace"],function(Jupyter) {
- Jupyter.notebook.save_checkpoint();
- });
+ window.onload=function(){
+ // require(["base/js/namespace"],function(Jupyter) {
+ // Jupyter.notebook.save_checkpoint();
+ // });
+ $('.navbar-nav').children().eq(7).css({'display':'none'})
+ console.log($('.navbar-nav').children().eq(7))
}
+
+// //子目标父窗口接收子窗口发送的消息
+// let message = {type: 'open', link:'需要发送的消息'};
+// //子窗口向父窗口发送消息,消息中包含我们想跳转的链接
+// window.parent.postMessage(message,'需要发送的消息');
+
+
+
+ // //目标父窗口接收子窗口发送的消息
+ // window.addEventListener('message', (e)=>{
+ // let origin = event.origin || event.originalEvent.origin;
+ // if (origin !== '需要发送的消息') {
+ // return;
+ // }else {
+ // //更换iframe的src,实现iframe页面跳转
+ // 执行方法
+ // }
+ // },false);
+
\ No newline at end of file
diff --git a/public/react/src/App.js b/public/react/src/App.js
index 93b293e36..07fd13e49 100644
--- a/public/react/src/App.js
+++ b/public/react/src/App.js
@@ -72,6 +72,7 @@ const Otherlogin=Loadable({
loading: Loading,
})
+
const Otherloginstart=Loadable({
loader: () => import('./modules/login/Otherloginstart'),
loading: Loading,
@@ -300,6 +301,11 @@ const Developer = Loadable({
loader: () => import('./modules/developer'),
loading: Loading
})
+// 学院统计
+const College = Loadable({
+ loader: () => import('./college/College'),
+ loading: Loading
+})
// 开发者编辑模块
const NewOrEditTask = Loadable({
@@ -614,7 +620,10 @@ class App extends Component {
{/*/>*/}
-
+ ()
+ }/>
{/* jupyter */}
+
()
} />
+
()
diff --git a/public/react/src/college/College.js b/public/react/src/college/College.js
new file mode 100644
index 000000000..bc43252b7
--- /dev/null
+++ b/public/react/src/college/College.js
@@ -0,0 +1,1259 @@
+import React, {Component} from "react";
+import {Link, NavLink} from 'react-router-dom';
+import {WordsBtn, ActionBtn,SnackbarHOC,getImageUrl} from 'educoder';
+import axios from 'axios';
+import {
+ notification,
+ Spin,
+ Table,
+ Pagination,
+} from "antd";
+import Colleagechart from './colleagechart/Colleagechart'
+import Colleagechartzu from './colleagechart/Colleagechartzu'
+import {TPMIndexHOC} from "../modules/tpm/TPMIndexHOC";
+import NoneData from './../modules/courses/coursesPublic/NoneData';
+
+import './colleagecss/colleage.css';
+import Shixunechart from "../modules/courses/shixunHomework/shixunreport/Shixunechart";
+class College extends Component {
+ constructor(props) {
+ super(props);
+ // this.answerMdRef = React.createRef();
+ this.state = {
+ coursesloading:false,
+ columns: [
+ {
+ title: '名称',
+ dataIndex: 'name',
+ key: 'name',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth247",
+ render: (text, record) => (
+ {
+ record.name
+ }
+ )
+ },
+ {
+ title: '管理教师',
+ dataIndex: 'teachers',
+ key: 'teachers',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth340",
+ render: (text, record) => (
+
+ {
+ record.teachers
+ }
+
+ )
+ },
+ {
+ title: '评测次数',
+ dataIndex: 'times',
+ key: 'times',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth175",
+ render: (text, record) => (
+
+ {
+ record.evaluating_count
+ }
+
+ ),
+ },
+ {
+ title: '学生',
+ key: 'student',
+ dataIndex: 'student',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth255",
+ render: (text, record) => (
+
+ {
+ record.student_count
+ }
+
+ )
+ },
+ {
+ title: '实训作业',
+ dataIndex: 'training',
+ key: 'training',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.shixun_work_count
+ }
+
+ )
+
+ },
+ {
+ title: '资源',
+ dataIndex: 'resources',
+ key: 'resources',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.attachment_count
+ }
+
+ ),
+ },
+ {
+ title: '帖子',
+ dataIndex: 'posts',
+ key: 'posts',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+ {
+ record.message_count
+ }
+ )
+ },
+ {
+ title: '其它任务',
+ dataIndex: 'othertasks',
+ key: 'othertasks',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.other_work_count
+ }
+
+ )
+ },
+ {
+ title: '状态',
+ dataIndex: 'states',
+ key: 'states',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.is_end?
+ "已结束"
+ :
+ "正在进行"
+ }
+
+ )
+ },
+ {
+ title: '时间',
+ dataIndex: 'timemy',
+ key: 'timemy',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.activity_time
+ }
+
+ )
+ },
+ ],
+ page:1,
+ limit:10,
+ total_users:50,
+ teachersloading:false,
+ teacherranking:[
+ {
+ title: '排名',
+ dataIndex: 'ranking',
+ key: 'ranking',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.id
+ }
+
+ )
+ },
+ {
+ title: '姓名',
+ dataIndex: 'name',
+ key: 'name',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth105",
+ render: (text, record) => (
+ {
+ record.name
+ }
+
+ )
+ },
+ {
+ title: '管理课堂',
+ dataIndex: 'classroom',
+ key: 'classroom',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth175",
+ render: (text, record) => (
+
+ {
+ record.course_count
+ }
+
+ ),
+ },
+ {
+ title: '已发布实训作业',
+ key: 'assignment',
+ dataIndex: 'assignment',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth255",
+ render: (text, record) => (
+
+ {
+ record.shixun_work_count
+ }
+
+ )
+ },
+ {
+ title: '未发布实训作业',
+ dataIndex: 'released',
+ key: 'released',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.un_shixun_work_count
+ }
+
+ )
+
+ },
+ {
+ title: '学生数',
+ dataIndex: 'studentnumber',
+ key: 'studentnumber',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.student_count
+ }
+
+ ),
+ },
+ {
+ title: '完成率',
+ dataIndex: 'completionrate',
+ key: 'completionrate',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.complete_rate+"%"
+ }
+
+ )
+ },
+ {
+ title: '发布实训',
+ dataIndex: 'releasetraining',
+ key: 'releasetraining',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.publish_shixun_count
+ }
+
+ )
+ }
+ ],
+ studentranking:[
+ {
+ title: '排名',
+ dataIndex: 'ranking',
+ key: 'ranking',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ width:'100px',
+ render: (text, record) => (
+
+ {
+ record.id===1?
+ :record.id===2?
+
+ :record.id===3?
+
+ :record.id
+ }
+
+ )
+ },
+ {
+ title: '姓名',
+ dataIndex: 'name',
+ key: 'name',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth105",
+ width:'100px',
+ render: (text, record) => (
+ {
+ record.name
+ }
+
+ )
+ },
+ {
+ title: '学号',
+ dataIndex: 'studentid',
+ key: 'studentid',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth175",
+ render: (text, record) => (
+
+ {
+ record.student_id
+ }
+
+ ),
+ },
+ {
+ title: '完成实训',
+ key: 'training',
+ dataIndex: 'training',
+ align: 'center',
+ className: "edu-txt-center font-14 maxnamewidth255",
+ render: (text, record) => (
+
+ {
+ record.shixun_count
+ }
+
+ )
+ },
+ {
+ title: '在学实训',
+ dataIndex: 'learning',
+ key: 'learning',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.study_shixun_count
+ }
+
+ )
+
+ },
+ {
+ title: '金币',
+ dataIndex: 'goldcoin',
+ key: 'goldcoin',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.grade
+ }
+
+ ),
+ },
+ {
+ title: '经验值',
+ dataIndex: 'empirical',
+ key: 'empirical',
+ align: 'center',
+ className: "edu-txt-center font-14",
+ render: (text, record) => (
+
+ {
+ record.experience
+ }
+
+ )
+ },
+ ],
+ school:"",
+ teachers_count:null,
+ students_count:null,
+ courses_count:null,
+ shixuns_count:null,
+ shixun_report_count:null,
+ shixun_time:null,
+ courses:null,
+ course_count:0,
+ pages:1,
+ limits:10,
+ teachers:null,
+ teacher_count:0,
+ students:null,
+ student_count:0,
+ shixun_chart_data:null,
+ shixun_chart_datanames:null,
+ studentionsnames:null,
+ studentionsvalues:null
+ }
+
+ }
+
+
+ componentDidMount(){
+ console.log("College");
+ console.log(this.props.match.params.id);
+ this.gettop();
+ this.Numberofinternshipreports();
+ this.Actualcombattimeoftrainees();
+ this.Classnumber(1,10);
+ this.Teacherranking(1,10);
+ this.Studentranking(1,10);
+ this.Onlinetraining();
+ this.Hottest();
+ }
+ //头部
+ gettop=()=>{
+ const id =this.props.match.params.id;
+ const url=`/colleges/${id}/statistics.json`;
+ axios.get(url).then((response) => {
+ if(response===null||response===undefined){
+ this.setState({
+ teachers_count:0,
+ students_count:0,
+ courses_count:0,
+ shixuns_count:0,
+ school:"",
+ })
+ return
+ }
+ if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
+ this.setState({
+ teachers_count:0,
+ students_count:0,
+ courses_count:0,
+ shixuns_count:0,
+ school:"",
+ })
+ }else{
+ this.setState({
+ teachers_count:response.data.teachers_count,
+ students_count:response.data.students_count,
+ courses_count:response.data.courses_count,
+ shixuns_count:response.data.shixuns_count,
+ school:response.data.school,
+ })
+ }
+ }).catch((error) => {
+ console.log(error)
+ this.setState({
+ teachers_count:0,
+ students_count:0,
+ courses_count:0,
+ shixuns_count:0,
+ school:"",
+ })
+ });
+ }
+
+ //获取实训报告数
+ Numberofinternshipreports=()=>{
+ const id =this.props.match.params.id;
+ const url=`/colleges/${id}/shixun_report_count.json`;
+ axios.get(url).then((response) => {
+ if(response===null||response===undefined){
+ this.setState({
+ shixun_report_count:0,
+ })
+ return
+ }
+ if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
+ this.setState({
+ shixun_report_count:0,
+ })
+ }else{
+ if (response.data.status === -1){
+ this.setState({
+ shixun_report_count:0,
+ })
+ return
+ }
+ this.setState({
+ shixun_report_count:response.data.shixun_report_count,
+ })
+ }
+ }).catch((error) => {
+ console.log(error)
+ this.setState({
+ shixun_report_count:0,
+ })
+ });
+ }
+
+ //学员实战时间
+ Actualcombattimeoftrainees=()=>{
+ const id =this.props.match.params.id;
+ const url=`/colleges/${id}/shixun_time.json`;
+ axios.get(url).then((response) => {
+ if(response===null||response===undefined){
+ this.setState({
+ shixun_time:0,
+ })
+ return
+ }
+ if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
+ this.setState({
+ shixun_time:0,
+ })
+ }else{
+ if (response.data.status === -1){
+ this.setState({
+ shixun_time:0,
+ })
+ return
+ }
+ this.setState({
+ shixun_time:response.data.shixun_time,
+ })
+ }
+ }).catch((error) => {
+ console.log(error)
+ this.setState({
+ shixun_time:0,
+ })
+ });
+ }
+
+ //课堂信息
+ Classnumber=(page,per_page)=>{
+ const id =this.props.match.params.id;
+ const url=`/colleges/${id}/course_statistics.json`;
+ this.setState({
+ coursesloading:true
+ })
+ axios.get(url,{params:{
+ page:page,
+ per_page:per_page,
+ }
+ }).then((response) => {
+ if(response===null||response===undefined){
+ this.setState({
+ courses:[],
+ course_count:0
+ })
+ return
+ }
+ if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
+ this.setState({
+ courses:[],
+ course_count:0
+ })
+ }else{
+ if (response.data.status === -1){
+ this.setState({
+ courses:[],
+ course_count:0
+ })
+ return
+ }
+ this.setState({
+ courses:response.data.courses,
+ course_count:response.data.course_count,
+ page:page,
+ limit:per_page
+ })
+ }
+ this.setState({
+ coursesloading:false
+ })
+ }).catch((error) => {
+ this.setState({
+ courses:[],
+ course_count:0,
+ coursesloading:false
+ })
+ });
+ }
+
+ //教师排名
+ Teacherranking=(page,per_page)=>{
+ const id =this.props.match.params.id;
+ const url=`/colleges/${id}/teachers.json`;
+ this.setState({
+ teachersloading:true
+ })
+ axios.get(url,{params:{
+ page:page,
+ per_page:per_page,
+ }
+ }).then((response) => {
+ if(response===null||response===undefined){
+ this.setState({
+ teachers:[],
+ teacher_count:0
+ })
+ return
+ }
+ if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
+ this.setState({
+ teachers:[],
+ teacher_count:0
+ })
+ }else{
+ if (response.data.status === -1){
+ this.setState({
+ teachers:[],
+ teacher_count:0
+ })
+ return
+ }
+ let teachers=[];
+ if(response.data.teachers){
+ for(let i=0;i {
+ this.setState({
+ teachers:[],
+ teacher_count:0,
+ teachersloading:false
+ })
+ });
+ }
+ //学生排名
+
+ Studentranking=(page,per_page)=>{
+ const id =this.props.match.params.id;
+ const url=`/colleges/${id}/student_shixun.json`;
+ this.setState({
+ studentsloading:true
+ })
+ axios.get(url,{params:{
+ page:page,
+ per_page:per_page,
+ }
+ }).then((response) => {
+ if(response===null||response===undefined){
+ this.setState({
+ students:[],
+ student_count:0,
+ })
+ return
+ }
+ if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
+ this.setState({
+ students:[],
+ student_count:0,
+ })
+ }else{
+ if (response.data.status === -1){
+ this.setState({
+ students:[],
+ student_count:0,
+ })
+ return
+ }
+ let students=[];
+ if(response.data.teachers){
+ for(let i=0;i {
+ this.setState({
+ students:[],
+ student_count:0,
+ studentsloading:false
+ })
+ });
+ }
+
+ //在线实训情况
+ Onlinetraining=()=>{
+ const id =this.props.match.params.id;
+ const url=`/colleges/${id}/shixun_chart_data.json`;
+ axios.get(url).then((response) => {
+ if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
+ this.setState({
+ shixun_chart_data:[],
+ shixun_chart_datanames:[]
+ })
+ }else{
+ if (response.data.status === -1){
+ this.setState({
+ shixun_chart_data:[],
+ shixun_chart_datanames:[]
+ })
+ return
+ }
+
+ this.setState({
+ shixun_chart_data:response.data.data,
+ shixun_chart_datanames:response.data.names
+ })
+ }
+ }).catch((error) => {
+ this.setState({
+ shixun_chart_data:[],
+ shixun_chart_datanames:[]
+ })
+ });
+ }
+ //最热测评
+ Hottest=()=>{
+ const id =this.props.match.params.id;
+ const url=`/colleges/${id}/student_hot_evaluations.json`;
+ axios.get(url).then((response) => {
+ if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
+ this.setState({
+ studentionsnames: [],
+ studentionsvalues: []
+ })
+ }else {
+ if (response.data.status === -1) {
+ this.setState({
+ studentionsnames: [],
+ studentionsvalues: []
+ })
+ return
+ }
+ this.setState({
+ studentionsnames: response.data.names,
+ studentionsvalues: response.data.values
+ })
+ }
+ }).catch((error) => {
+ this.setState({
+ studentionsnames: [],
+ studentionsvalues: []
+ })
+ });
+ }
+
+ table1handleChange(){
+
+ }
+
+ //塞选
+ paginationonChange=(pageNumber)=>{
+ this.Classnumber(pageNumber,10);
+ }
+
+ paginationonChanges=(pageNumber)=>{
+ this.Teacherranking(pageNumber,10);
+ }
+ paginationonChangess=(pageNumber)=>{
+ this.Studentranking(pageNumber,10);
+ }
+ render() {
+ let {columns,page,limit,total_users,teacherranking,studentranking,
+ teachers_count,students_count, courses_count, shixuns_count,shixun_report_count,shixun_time,courses,course_count,school,teachers,
+ pages,limits, teacher_count,teachersloading,coursesloading,pagess,limitss,studentsloading,students,student_count,shixun_chart_data,
+ shixun_chart_datanames, studentionsnames,studentionsvalues
+ } = this.state;
+
+ return (
+
+
+
+
{school}
+
+
+ {/*//教师1*/}
+
+ 教师
+
+
+ {teachers_count?teachers_count:0}
+
+
+
+
+
+ 学生
+
+
+ {students_count?students_count:0}
+
+
+
+
+
+ 课堂
+
+
+ {courses_count?courses_count:0}
+
+
+
+
+
+ 共建实训
+
+
+ {shixuns_count?shixuns_count:0}
+
+
+ {/*//教师2*/}
+
+
+
+
+
+
+
+
+
+ 基本使用情况
+
+ {/*基本使用情况1*/}
+
+
+ 教师
+
+
+ 学生
+
+
+ 课堂
+
+
+ 共建实训
+
+
+ 实习报告
+
+
+ 学员实战时间
+
+
+
+
+ {/*基本使用情况2*/}
+
+
+ {
+ teachers_count?
+
{teachers_count}人
+ :
+
+ }
+
+
+ {
+ students_count?
+
{students_count}人
+ :
+
+ }
+
+
+ {
+ courses_count?
+
{courses_count}个
+ :
+
+ }
+
+
+ {
+ shixuns_count?
+
{shixuns_count}个
+ :
+
+ }
+
+
+ {
+ shixun_report_count?
+
{shixun_report_count}个
+ :
+
+ }
+
+
+ {
+ shixun_time?
+
{shixun_time}天
+ :
+
+ }
+
+
+ {/*基本使用情况3结束*/}
+
+
+
+
+
+ 课堂
+
+ {
+ courses===null?
+
+
+
+
+ :
+ JSON.stringify(courses) === "[]" ?
+
+
+
+ :
+
+
+
+
+ {courses === undefined ? "" :
}
+
+
+ {
+ course_count>=11?
+
+ :""
+ }
+
+
+ }
+
+
+
+
+
+
+
+
+ 教师排名
+
+ {
+ teachers===null?
+
+
+
+
+ :
+ JSON.stringify(teachers) === "[]" ?
+
+
+
+ :
+
+
+
+ {teachers === undefined ? "" :
}
+
+
+ }
+
+
+
+ {/*
*/}
+
+
+
+
+ 在线实训情况
+
+ {
+ shixun_chart_data===null?
+
+
+
+
+ :
+ JSON.stringify(shixun_chart_data) === "[]" ?
+
+
+
+ :
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+ 学生排名
+
+ {
+ students === null ?
+
+
+
+
+ :
+ JSON.stringify(students) === "[]" ?
+
+
+
+ :
+
+
+
+ {students === undefined ? "" :
}
+
+
+ }
+ {/*
*/}
+
+
+
+
+
+
+
+
+ 最热评测
+
+ {
+ studentionsnames===null?
+
+
+
+
+ :
+ JSON.stringify(studentionsnames) === "[]" ?
+
+
+
+ :
+
+
+
+ }
+
+
+
+
+
+
+ )
+ }
+}
+export default SnackbarHOC() (TPMIndexHOC ( College ));
+
+
diff --git a/public/react/src/college/colleagechart/Colleagechart.js b/public/react/src/college/colleagechart/Colleagechart.js
new file mode 100644
index 000000000..fca01280a
--- /dev/null
+++ b/public/react/src/college/colleagechart/Colleagechart.js
@@ -0,0 +1,84 @@
+import React, {Component} from "react";
+import {WordsBtn} from 'educoder';
+import {Table} from "antd";
+import {Link,Switch,Route,Redirect} from 'react-router-dom';
+const echarts = require('echarts');
+
+
+
+function startechart(data,datanane){
+ var effChart = echarts.init(document.getElementById('shixun_skill_chart'));
+
+ var option = {
+
+ tooltip : {
+ trigger: 'item',
+ formatter: "{d}%
"
+ },
+ legend: {
+ // orient: 'vertical',
+ // top: 'middle',
+ bottom: 50,
+ left: 'center',
+ data: datanane
+ },
+ series : [
+ {
+ type: 'pie',
+ radius : '65%',
+ center: ['50%', '35%'],
+ selectedMode: 'single',
+ data:data,
+ itemStyle: {
+ emphasis: {
+ shadowBlur: 10,
+ shadowOffsetX: 0,
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
+ }
+ }
+ }
+ ]
+ };
+ effChart.setOption(option);
+}
+class Colleagechart extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ }
+ }
+
+ componentDidMount() {
+ startechart(this.props.data,this.props.datanane)
+ }
+
+
+ componentDidUpdate = (prevProps) => {
+ if (prevProps.data!= this.props.data) {
+ startechart(this.props.data,this.props.datanane)
+ }
+ }
+
+
+ render() {
+ let {data}=this.props;
+
+ return (
+
+
+ )
+ }
+}
+
+export default Colleagechart;
diff --git a/public/react/src/college/colleagechart/Colleagechartzu.js b/public/react/src/college/colleagechart/Colleagechartzu.js
new file mode 100644
index 000000000..5c0269700
--- /dev/null
+++ b/public/react/src/college/colleagechart/Colleagechartzu.js
@@ -0,0 +1,149 @@
+import React, {Component} from "react";
+import {WordsBtn} from 'educoder';
+import {Table} from "antd";
+import {Link,Switch,Route,Redirect} from 'react-router-dom';
+const echarts = require('echarts');
+
+
+
+function startechart(names, values){
+ var effChart = echarts.init(document.getElementById('shixun_skill_charts'));
+
+ var Color = ['#962e66', '#623363', '#CCCCCC', '#9A9A9A', '#FF8080', '#FF80C2', '#B980FF', '#80B9FF', '#6FE9FF', '#4DE8B4', '#F8EF63', '#FFB967'];
+
+ var option = {
+ backgroundColor: '#fff',
+ grid: {
+ left: '3%',
+ right: '8%',
+ bottom: '15%',
+ containLabel: true
+ },
+
+ tooltip: {
+ show: "true",
+ trigger: 'item',
+ formatter: '{c0}',
+ backgroundColor: 'rgba(0,0,0,0.7)', // 背景
+ padding: [8, 10], //内边距
+ extraCssText: 'box-shadow: 0 0 3px rgba(255, 255, 255, 0.4);', //添加阴影
+ axisPointer: { // 坐标轴指示器,坐标轴触发有效
+ type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
+ }
+ },
+ xAxis: {
+ type: 'value',
+ axisTick: {
+ show: false
+ },
+ axisLine: {
+ show: true,
+ lineStyle: {
+ color: '#CCCCCC'
+ }
+ },
+ splitLine: {
+ show: false,
+ lineStyle: {
+ color: '#CCCCCC'
+ }
+ },
+ axisLabel: {
+ textStyle: {
+ color: '#656565',
+ fontWeight: 'normal',
+ fontSize: '12'
+ },
+ formatter: '{value}'
+ }
+ },
+ yAxis: {
+ type: 'category',
+ axisLine: {
+ lineStyle: {
+ color: '#cccccc'
+ }
+ },
+ splitLine: {
+ show: false
+ },
+ axisTick: {
+ show: false
+ },
+ splitArea: {
+ show: false
+ },
+ axisLabel: {
+ inside: false,
+ textStyle: {
+ color: '#656565',
+ fontWeight: 'normal',
+ fontSize: '12'
+ }
+ },
+ data: names
+ },
+ series: [{
+ name: '',
+ type: 'bar',
+ itemStyle: {
+ normal: {
+ show: true,
+ color: function(params) {
+ return Color[params.dataIndex]
+ },
+ barBorderRadius: 50,
+ borderWidth: 0,
+ borderColor: '#333'
+ }
+ },
+ barGap: '0%',
+ barCategoryGap: '50%',
+ data: values
+ }
+
+ ]
+ };
+ effChart.setOption(option);
+}
+class Colleagechartzu extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ }
+ }
+
+ componentDidMount() {
+ startechart(this.props.data,this.props.datavule)
+ }
+
+
+ componentDidUpdate = (prevProps) => {
+ if (prevProps.data!= this.props.data) {
+ startechart(this.props.data,this.props.datavule)
+ }
+ }
+
+
+ render() {
+ let {data}=this.props;
+
+ return (
+
+
+ )
+ }
+}
+
+export default Colleagechartzu;
diff --git a/public/react/src/college/colleagecss/colleage.css b/public/react/src/college/colleagecss/colleage.css
new file mode 100644
index 000000000..801b86603
--- /dev/null
+++ b/public/react/src/college/colleagecss/colleage.css
@@ -0,0 +1,213 @@
+.yslstatistic-header {
+ width: 100%;
+ height: 240px;
+ background-image: url('/images/educoder/statistics.jpg');
+ background-size: 100% 100%;
+}
+.yslborder{
+ border: 1px solid;
+}
+.yslstatistic-header-title{
+ flex: 1;
+ display: flex;
+ align-items: center;
+ color: #4CACFF;
+ font-size: 32px;
+}
+.yslstatistic-header-content{
+ width: 100%;
+ display: flex;
+ justify-content: space-around;
+}
+.yslstatistic-header-item{
+ margin-bottom: 22px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ color: #fff;
+}
+.yslstatistic-header-item-label{
+ color: #989898;
+}
+
+.yslstatistic-base-item-label{
+ width: 217px;
+ text-align: center;
+ font-size: 16px;
+ height: 48px;
+ line-height: 48px;
+ color: #686868;
+ background: #F5F5F5;
+ border-top: 1px solid #EBEBEB;
+}
+.yslstatistic-base-item-labels{
+ width: 217px;
+ text-align: center;
+ height: 100px;
+ line-height: 100px;
+ background: #ffffff;
+ border-top: 1px solid #EBEBEB;
+ border-bottom: 1px solid #EBEBEB;
+}
+.yslstatistic-base-item-labelsp{
+ color: #000000;
+ font-size: 24px;
+}
+.yslstatistic-base-item-labelsspan{
+ color: #000000;
+ margin-left: 5px;
+ font-size: 16px;
+}
+.jibenshiyong100{
+ width: 100%;
+}
+
+.yslstatistic-header-item-content{
+ font-size: 24px;
+}
+/* 中间居中 */
+.intermediatecenter{
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+}
+/* 简单居中 */
+.intermediatecenterysls{
+ display: flex;
+ align-items: center;
+}
+.spacearound{
+ display: flex;
+ justify-content: space-around;
+
+}
+.spacebetween{
+ display: flex;
+ justify-content: space-between;
+}
+/* 头顶部居中 */
+.topcenter{
+ display: -webkit-flex;
+ flex-direction: column;
+ align-items: center;
+
+}
+
+
+/* x轴正方向排序 */
+/* 一 二 三 四 五 六 七 八 */
+.sortinxdirection{
+ display: flex;
+ flex-direction:row;
+}
+/* x轴反方向排序 */
+/* 八 七 六 五 四 三 二 一 */
+.xaxisreverseorder{
+ display: flex;
+ flex-direction:row-reverse;
+}
+/* 垂直布局 正方向*/
+/* 一
+ 二
+ 三
+ 四
+ 五
+ 六
+ 七
+ 八 */
+.verticallayout{
+ display: flex;
+ flex-direction:column;
+}
+/* 垂直布局 反方向*/
+.reversedirection{
+ display: flex;
+ flex-direction:column-reverse;
+}
+
+.h4{
+ font-size: 1.5rem;
+ font-weight: 500 !important;
+}
+.ysllinjibenshiyong{
+ font-weight: 500;
+ line-height: 1.2;
+ padding: 2rem 1.25rem;
+ border-bottom: unset;
+ background:#fff;
+}
+.linjibenshiyong{
+ font-weight: 500;
+ line-height: 1.2;
+ padding: 2rem 1.25rem;
+ border-bottom: unset;
+ background:#fff;
+ box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1);
+ border-radius:2px;
+}
+.yslslinjibenshiyong{
+ font-weight: 500;
+ line-height: 1.2;
+ border-bottom: unset;
+ box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1);
+ border-radius:2px;
+}
+.yinyin{
+ background: #fff;
+ box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1);
+ border-radius:2px;
+}
+.edu-back-eeee{
+ background:#EEEEEE !important;
+}
+.mt-4{
+ margin-top: 1.5rem !important;
+}
+
+.statistic-label{
+ padding: 2rem 1.25rem;
+ font-size: 1.5rem;
+ font-weight: 400 !important;
+}
+.mb50{
+ padding-bottom: 50px !important;
+}
+.mt40{
+ margin-top: 40px;
+}
+.mb80{
+ margin-bottom: 80px;
+}
+.task-hide{overflow:hidden; white-space: nowrap; text-overflow:ellipsis;}
+a:hover{
+ color:#0056b3;
+}
+.color-blue{
+ color: #4CACFF;
+}
+
+.color-huang{
+ color:#ffc107 !important
+}
+.maxnamewidth105{
+ max-width: 105px;
+ overflow:hidden;
+ text-overflow:ellipsis;
+ white-space:nowrap;
+ cursor: default;
+}
+.maxnamewidth247{
+ max-width: 247px;
+ overflow:hidden;
+ text-overflow:ellipsis;
+ white-space:nowrap;
+ cursor: default;
+}
+.maxnamewidth340{
+ max-width: 340px;
+ overflow:hidden;
+ text-overflow:ellipsis;
+ white-space:nowrap;
+ cursor: default;
+}
diff --git a/public/react/src/common/components/comment/CommentForm.js b/public/react/src/common/components/comment/CommentForm.js
new file mode 100644
index 000000000..73e36cff9
--- /dev/null
+++ b/public/react/src/common/components/comment/CommentForm.js
@@ -0,0 +1,116 @@
+/*
+ * @Description: 评论表单
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-17 17:32:55
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-18 17:51:44
+ */
+import React, { useState } from 'react';
+import { Form, Button, Input } from 'antd';
+import QuillForEditor from '../../quillForEditor';
+import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html'
+const FormItem = Form.Item;
+
+function CommentForm (props) {
+
+ const {
+ commentCtxChagne,
+ onCancel,
+ onSubmit,
+ form
+ } = props;
+
+ const { getFieldDecorator } = form;
+ const [ctx, setCtx] = useState('');
+
+ const options = [
+ ['bold', 'italic', 'underline'],
+ [{header: [1,2,3,false]}],
+ ['blockquote', 'code-block'],
+ ['link', 'image'],
+ ['formula']
+ ];
+ // const { form: { getFieldDecorator } } = props;
+ const [showQuill, setShowQuill] = useState(false);
+ // 点击输入框
+ const handleInputClick = () => {
+ setShowQuill(true);
+ }
+ // 取消
+ const handleCancle = () => {
+ setShowQuill(false);
+ onCancel && onCancel();
+ }
+
+ // 编辑器内容变化时
+ const handleContentChange = (content) => {
+ setCtx(content);
+ try {
+ const _html = new QuillDeltaToHtmlConverter(content.ops, {}).convert();
+ // props.form.setFieldsValue({'comment': _html.replace(/<\/?[^>]*>/g, '')});
+ props.form.setFieldsValue({'comment': _html});
+ } catch (error) {
+ console.log(error);
+ }
+ }
+ // 发送
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ props.form.validateFields((err, values) => {
+ if (!err) {
+ setShowQuill(false);
+ const content = ctx;
+ props.form.setFieldsValue({'comment': ''});
+ setCtx('');
+ console.log(content);
+ onSubmit && onSubmit(content);
+ }
+ });
+ }
+ return (
+
+ );
+}
+
+export default Form.create()(CommentForm);
diff --git a/public/react/src/common/components/comment/CommentIcon.js b/public/react/src/common/components/comment/CommentIcon.js
new file mode 100644
index 000000000..5440e2579
--- /dev/null
+++ b/public/react/src/common/components/comment/CommentIcon.js
@@ -0,0 +1,32 @@
+/*
+ * @Description:
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-18 10:49:46
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-18 11:39:23
+ */
+import './index.scss';
+import React from 'react';
+import { Icon } from 'antd';
+function CommentIcon ({
+ type, // 图标类型
+ count, // 评论数
+ iconClick,
+ ...props
+}) {
+
+ // 点击图标
+ const handleSpanClick = () => {
+ iconClick && iconClick();
+ }
+
+ return (
+
+
+ { count }
+
+ )
+}
+
+export default CommentIcon;
diff --git a/public/react/src/common/components/comment/CommentItem.js b/public/react/src/common/components/comment/CommentItem.js
new file mode 100644
index 000000000..19da645f5
--- /dev/null
+++ b/public/react/src/common/components/comment/CommentItem.js
@@ -0,0 +1,165 @@
+/*
+ * @Description: 评论单列
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-17 17:35:17
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-19 18:02:28
+ */
+import './index.scss';
+import React, { useState } from 'react';
+import CommentIcon from './CommentIcon';
+import { getImageUrl, CNotificationHOC } from 'educoder'
+import { Icon } from 'antd';
+import moment from 'moment';
+// import QuillForEditor from '../../quillForEditor';
+import CommentForm from './CommentForm';
+
+// import {ModalConfirm} from '../ModalConfirm';
+function CommentItem ({
+ options,
+ confirm
+}) {
+ // 显示评论输入框
+ const [showQuill, setShowQuill] = useState(false);
+ // 加载更多评论内容
+ const [showMore, setShowMore] = useState(false);
+ // 箭头方向
+ const [arrow, setArrow] = useState(false);
+ // 删除评论
+ const deleteComment = () => {
+ console.log('删除评论...');
+ confirm({
+ title: '提示',
+ content: (确定要删除该条回复吗?
),
+ onOk () {
+ console.log('点击了删除');
+ }
+ });
+ // ModalConfirm('提示', (确定要删除该条回复吗?
), () => {
+ // console.log('点击了删除');
+ // });
+ }
+
+ // 评论头像
+ const commentAvatar = (url) => (
+
+ );
+
+ // 评论信息
+ const commentInfo = () => (
+
+ 用户名
+ {moment(new Date(), 'YYYYMMDD HHmmss').fromNow()}
+
+
+ );
+
+ // 评论内容
+ const commentCtx = (ctx) => (
+
+ 这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容
+
+ );
+
+ // 加载更多
+ const handleOnLoadMore = () => {
+ if (!arrow) {
+ // 展开所有
+ } else {
+ // 收起
+ }
+ setArrow(!arrow);
+ };
+
+ // 评论追加内容
+ const commentAppend = () => {
+
+ return (
+
+ -
+ {commentAvatar()}
+
+ {commentInfo()}
+ {commentCtx()}
+
+
+ -
+ {commentAvatar()}
+
+ {commentInfo()}
+ {commentCtx()}
+
+
+ -
+ {commentAvatar()}
+
+ {commentInfo()}
+ {commentCtx()}
+
+
+
+ -
+
展开其余23条评论
+
+
+
+
+
+ );
+ };
+ // 点击图标
+ const handleIconClick = () => {}
+
+ // 点击评论icon
+ const handleClickMessage = () => {
+ setShowQuill(true);
+ }
+
+ // 点击取消
+ const handleClickCancel = () => {
+ setShowQuill(false);
+ }
+
+ // 点击保存
+ const handleClickSubmit = (content) => {
+ // 保存并关闭
+ setShowQuill(false);
+ console.log('获取保存内容', content);
+ }
+
+ return (
+
+ {commentAvatar()}
+
+ {commentInfo()}
+ {commentCtx()}
+
+ {commentAppend()}
+
+
+
+ {/* 回复 */}
+
+ {/* 点赞 */}
+
+
+
+
+
+
+
+
+ );
+}
+
+export default CNotificationHOC() (CommentItem);
diff --git a/public/react/src/common/components/comment/CommentList.js b/public/react/src/common/components/comment/CommentList.js
new file mode 100644
index 000000000..9d8cde87b
--- /dev/null
+++ b/public/react/src/common/components/comment/CommentList.js
@@ -0,0 +1,20 @@
+/*
+ * @Description: 评论列表页
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-17 17:34:00
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-18 11:48:09
+ */
+import './index.scss';
+import React from 'react';
+import CommentItem from './CommentItem';
+function CommentList ({}) {
+ return (
+
+ );
+}
+
+export default CommentList;
diff --git a/public/react/src/common/components/comment/index.js b/public/react/src/common/components/comment/index.js
new file mode 100644
index 000000000..f0ecf3309
--- /dev/null
+++ b/public/react/src/common/components/comment/index.js
@@ -0,0 +1,22 @@
+/*
+ * @Description: 评论组件
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-17 17:31:33
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-18 11:47:39
+ */
+import React from 'react';
+import CommentForm from './CommentForm';
+import CommentList from './CommentList';
+function Comment (props) {
+
+ return (
+
+
+
+
+ );
+}
+
+export default Comment;
diff --git a/public/react/src/common/components/comment/index.scss b/public/react/src/common/components/comment/index.scss
new file mode 100644
index 000000000..816e6da6c
--- /dev/null
+++ b/public/react/src/common/components/comment/index.scss
@@ -0,0 +1,111 @@
+$bdColor: rgba(244,244,244,1);
+$bgColor: rgba(250,250,250,1);
+$lh14: 14px;
+$lh22: 22px;
+$fz14: 14px;
+$fz12: 12px;
+$ml: 20px;
+
+.comment_list_wrapper{
+ box-sizing: border-box;
+ border-top: 1px solid $bdColor;
+
+ .comment_item_area{
+ display: flex;
+ padding: 20px 0;
+ box-sizing: border-box;
+ border-bottom: 1px solid $bdColor;
+ .flex-image{
+ width: 48px;
+ height: 48px;
+ border-radius: 50%;
+ }
+ .item-desc{
+ flex: 1;
+ margin-left: $ml;
+ }
+ .item-header{
+ font-size: $fz14;
+ line-height: $lh14;
+ color: #333;
+ .item-time{
+ font-size: $fz12;
+ line-height: $lh14;
+ margin-left: $ml;
+ }
+ .item-close{
+ float: right;
+ cursor: pointer;
+ }
+ }
+ .item-ctx{
+ line-height: $lh22;
+ font-size: $fz12;
+ color: #333;
+ margin-top: 10px;
+ }
+ .comment_icon_area{
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 10px;
+
+ .comment-icon-margin{
+ margin-left: 30px;
+ }
+ }
+
+ .comment_item_quill{
+ margin-top: 20px;
+ }
+ }
+ .comment_icon_count{
+ cursor: pointer;
+ font-size: 12px;
+ line-height: 1.5;
+
+ .comment_icon{
+ color: #333;
+ }
+ .comment_count{
+ color: #999999;
+ margin-left: 10px;
+ transition: color .3s;
+ }
+
+ &:hover{
+ .comment_icon,
+ .comment_count{
+ color: #5091FF;
+ }
+ }
+ }
+ .comment_item_append_list{
+ position: relative;
+ background-color: $bgColor;
+ border-radius: 5px;
+ padding: 0 15px 10px;
+ margin: 15px 0;
+ &::before {
+ position: absolute;
+ left: 15px;
+ bottom: 100%;
+ height: 0;
+ width: 0;
+ content: '';
+ // border: 5px solid transparent;
+ border: 10px solid transparent;
+ border-bottom-color: $bgColor;
+ }
+
+ .comment_item_loadmore{
+ padding-top: 10px;
+ cursor: pointer;
+ .loadmore-txt,
+ .loadmore-icon{
+ color: #999;
+ text-align: center;
+ font-size: $fz12;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/react/src/common/quillForEditor/ImageBlot.js b/public/react/src/common/quillForEditor/ImageBlot.js
new file mode 100644
index 000000000..091bd2c1f
--- /dev/null
+++ b/public/react/src/common/quillForEditor/ImageBlot.js
@@ -0,0 +1,54 @@
+/*
+ * @Description: 重写图片
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-16 15:50:45
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-17 16:44:48
+ */
+import Quill from "quill";
+
+const BlockEmbed = Quill.import('blots/block/embed');
+
+export default class ImageBlot extends BlockEmbed {
+
+ static create(value) {
+
+ const node = super.create();
+
+ node.setAttribute('alt', value.alt);
+ node.setAttribute('src', value.url);
+
+ if (value.width) {
+ node.setAttribute('width', value.width);
+ }
+ if (value.height) {
+ node.setAttribute('height', value.height);
+ }
+ // 宽度和高度都不存在时,
+ if (!value.width && !value.height) {
+ node.setAttribute('display', 'block');
+ node.setAttribute('width', '100%');
+ }
+ // 给图片添加点击事件
+ node.onclick = () => {
+ value.onClick && value.onClick(value.url);
+ }
+ return node;
+ }
+
+ static value (node) {
+
+ return {
+ alt: node.getAttribute('alt'),
+ url: node.getAttribute('src'),
+ onclick: node.onclick,
+ // width: node.width,
+ // height: node.height,
+ display: node.getAttribute('display')
+ };
+ }
+}
+
+ImageBlot.blotName = 'image';
+ImageBlot.tagName = 'img';
\ No newline at end of file
diff --git a/public/react/src/common/quillForEditor/deepEqual.js b/public/react/src/common/quillForEditor/deepEqual.js
new file mode 100644
index 000000000..6f2b276bf
--- /dev/null
+++ b/public/react/src/common/quillForEditor/deepEqual.js
@@ -0,0 +1,47 @@
+function deepEqual (prev, current) {
+ if (prev === current) { // 基本类型比较,值,类型都相同 或者同为 null or undefined
+ return true;
+ }
+
+ if ((!prev && current)
+ || (prev && !current)
+ || (!prev && !current)
+ ) {
+ return false;
+ }
+
+ if (Array.isArray(prev)) {
+ if (!Array.isArray(current)) return false;
+ if (prev.length !== current.length) return false;
+
+ for (let i = 0; i < prev.length; i++) {
+ if (!deepEqual(current[i], prev[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if (typeof current === 'object') {
+ if (typeof prev !== 'object') return false;
+ const prevKeys = Object.keys(prev);
+ const curKeys = Object.keys(current);
+
+ if (prevKeys.length !== curKeys.length) return false;
+
+ prevKeys.sort();
+ curKeys.sort();
+
+ for (let i = 0; i < prevKeys.length; i++) {
+ if (prevKeys[i] !== curKeys[i]) return false;
+ const key = prevKeys[i];
+ if (!deepEqual(prev[key], current[key])) return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+export default deepEqual;
diff --git a/public/react/src/common/quillForEditor/index.js b/public/react/src/common/quillForEditor/index.js
new file mode 100644
index 000000000..6e6c01886
--- /dev/null
+++ b/public/react/src/common/quillForEditor/index.js
@@ -0,0 +1,166 @@
+/*
+ * @Description: quill 编辑器
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-18 08:49:30
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-19 16:58:50
+ */
+import 'quill/dist/quill.core.css'; // 核心样式
+import 'quill/dist/quill.snow.css'; // 有工具栏
+import 'quill/dist/quill.bubble.css'; // 无工具栏
+import 'katex/dist/katex.min.css'; // katex 表达式样式
+import React, { useState, useRef, useEffect } from 'react';
+import Quill from 'quill';
+import katex from 'katex';
+import deepEqual from './deepEqual.js'
+import { fetchUploadImage } from '../../services/ojService.js';
+import { getImageUrl } from 'educoder'
+import ImageBlot from './ImageBlot';
+
+window.Quill = Quill;
+window.katex = katex;
+Quill.register(ImageBlot);
+
+function QuillForEditor ({
+ placeholder,
+ readOnly,
+ options,
+ value,
+ imgAttrs = {}, // 指定图片的宽高
+ style = {},
+ wrapStyle = {},
+ showUploadImage,
+ onContentChange
+}) {
+ // toolbar 默认值
+ const defaultConfig = [
+ ['bold', 'italic', 'underline'],
+ [{align: []}, {list: 'ordered'}, {list: 'bullet'}], // 列表
+ [{script: 'sub'}, {script: 'super'}],
+ [{ 'color': [] }, { 'background': [] }],
+ [{header: [1,2,3,4,5,false]}],
+ ['blockquote', 'code-block'],
+ ['link', 'image', 'video'],
+ ['formula'],
+ ['clean']
+ ];
+
+ const editorRef = useRef(null);
+ // quill 实例
+ const [quill, setQuill] = useState(null);
+ const [selection, setSelection] = useState(null);
+
+ // 文本内容变化时
+ const handleOnChange = content => {
+ // console.log('编辑器内容====》》》》', content);
+ onContentChange && onContentChange(content);
+ };
+
+ const renderOptions = options || defaultConfig;
+ // quill 配置信息
+ const quillOption = {
+ modules: {
+ toolbar: renderOptions
+ },
+ readOnly,
+ placeholder,
+ theme: readOnly ? 'bubble' : 'snow'
+ };
+
+
+ useEffect(() => {
+ const _quill = new Quill(editorRef.current, quillOption);
+ setQuill(_quill);
+
+ // 处理图片上传功能
+ _quill.getModule('toolbar').addHandler('image', (e) => {
+ const input = document.createElement('input');
+ input.setAttribute('type', 'file');
+ input.setAttribute('accept', 'image/*');
+ input.click();
+
+ input.onchange = async (e) => {
+ const file = input.files[0]; // 获取文件信息
+ const formData = new FormData();
+ formData.append('file', file);
+
+ const range = _quill.getSelection(true);
+ let fileUrl = ''; // 保存上传成功后图片的url
+ // 上传文件
+ const result = await fetchUploadImage(formData);
+ // 获取上传图片的url
+ if (result.data && result.data.id) {
+ fileUrl = getImageUrl(`api/attachments/${result.data.id}`);
+ }
+ // 根据id获取文件路径
+ const { width, height } = imgAttrs;
+ // console.log('上传图片的url:', fileUrl);
+ if (fileUrl) {
+ _quill.insertEmbed(range.index, 'image', {
+ url: fileUrl,
+ alt: '图片信息',
+ onClick: showUploadImage,
+ width,
+ height
+ });
+ }
+ }
+ });
+ }, []);
+
+ // 设置值
+ useEffect(() => {
+ if (!quill) return
+ const previous = quill.getContents()
+ const current = value
+
+ if (!deepEqual(previous, current)) {
+ setSelection(quill.getSelection())
+ if (typeof value === 'string') {
+ quill.clipboard.dangerouslyPasteHTML(value, 'api')
+ } else {
+ quill.setContents(value)
+ }
+ }
+ }, [quill, value, setQuill]);
+
+ // 清除选择区域
+ useEffect(() => {
+ if (quill && selection) {
+ quill.setSelection(selection)
+ setSelection(null)
+ }
+ }, [quill, selection, setSelection]);
+
+ // 设置placeholder值
+ useEffect(() => {
+ if (!quill || !quill.root) return;
+ quill.root.dataset.placeholder = placeholder;
+ }, [quill, placeholder]);
+
+ // 处理内容变化
+ useEffect(() => {
+ if (!quill) return;
+ if (typeof handleOnChange !== 'function') return;
+ let handler;
+ quill.on(
+ 'text-change',
+ (handler = () => {
+ handleOnChange(quill.getContents()); // getContents: 检索编辑器内容
+ })
+ );
+ return () => {
+ quill.off('text-change', handler);
+ }
+ }, [quill, handleOnChange]);
+
+ // 返回结果
+ return (
+
+ );
+}
+
+export default QuillForEditor;
diff --git a/public/react/src/common/reactQuill/ImageBlot.js b/public/react/src/common/reactQuill/ImageBlot.js
new file mode 100644
index 000000000..091bd2c1f
--- /dev/null
+++ b/public/react/src/common/reactQuill/ImageBlot.js
@@ -0,0 +1,54 @@
+/*
+ * @Description: 重写图片
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-16 15:50:45
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-17 16:44:48
+ */
+import Quill from "quill";
+
+const BlockEmbed = Quill.import('blots/block/embed');
+
+export default class ImageBlot extends BlockEmbed {
+
+ static create(value) {
+
+ const node = super.create();
+
+ node.setAttribute('alt', value.alt);
+ node.setAttribute('src', value.url);
+
+ if (value.width) {
+ node.setAttribute('width', value.width);
+ }
+ if (value.height) {
+ node.setAttribute('height', value.height);
+ }
+ // 宽度和高度都不存在时,
+ if (!value.width && !value.height) {
+ node.setAttribute('display', 'block');
+ node.setAttribute('width', '100%');
+ }
+ // 给图片添加点击事件
+ node.onclick = () => {
+ value.onClick && value.onClick(value.url);
+ }
+ return node;
+ }
+
+ static value (node) {
+
+ return {
+ alt: node.getAttribute('alt'),
+ url: node.getAttribute('src'),
+ onclick: node.onclick,
+ // width: node.width,
+ // height: node.height,
+ display: node.getAttribute('display')
+ };
+ }
+}
+
+ImageBlot.blotName = 'image';
+ImageBlot.tagName = 'img';
\ No newline at end of file
diff --git a/public/react/src/common/reactQuill/ReactQuill.js b/public/react/src/common/reactQuill/ReactQuill.js
new file mode 100644
index 000000000..1b4209409
--- /dev/null
+++ b/public/react/src/common/reactQuill/ReactQuill.js
@@ -0,0 +1,45 @@
+/*
+ * @Description:
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-09 09:09:42
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-18 08:46:20
+ */
+import 'quill/dist/quill.core.css'; // 核心样式
+import 'quill/dist/quill.snow.css'; // 有工具栏
+import 'quill/dist/quill.bubble.css'; // 无工具栏
+import 'katex/dist/katex.min.css'; // katex 表达式样式
+import React, { useState, useReducer, useEffect } from 'react';
+import useQuill from './useQuill';
+
+function ReactQuill ({
+ disallowColors, // 不可见时颜色
+ placeholder, // 提示信息
+ uploadImage, // 图片上传
+ onChange, // 内容变化时
+ options, // 配置信息
+ value, // 显示的内容
+ style,
+ showUploadImage // 显示上传图片
+}) {
+
+ const [element, setElement] = useState(); // quill 渲染节点
+
+ useQuill({
+ disallowColors,
+ placeholder,
+ uploadImage,
+ onChange,
+ options,
+ value,
+ showUploadImage,
+ element
+ });
+
+ return (
+
+ );
+}
+
+export default ReactQuill;
diff --git a/public/react/src/common/reactQuill/deepEqual.js b/public/react/src/common/reactQuill/deepEqual.js
new file mode 100644
index 000000000..6f2b276bf
--- /dev/null
+++ b/public/react/src/common/reactQuill/deepEqual.js
@@ -0,0 +1,47 @@
+function deepEqual (prev, current) {
+ if (prev === current) { // 基本类型比较,值,类型都相同 或者同为 null or undefined
+ return true;
+ }
+
+ if ((!prev && current)
+ || (prev && !current)
+ || (!prev && !current)
+ ) {
+ return false;
+ }
+
+ if (Array.isArray(prev)) {
+ if (!Array.isArray(current)) return false;
+ if (prev.length !== current.length) return false;
+
+ for (let i = 0; i < prev.length; i++) {
+ if (!deepEqual(current[i], prev[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if (typeof current === 'object') {
+ if (typeof prev !== 'object') return false;
+ const prevKeys = Object.keys(prev);
+ const curKeys = Object.keys(current);
+
+ if (prevKeys.length !== curKeys.length) return false;
+
+ prevKeys.sort();
+ curKeys.sort();
+
+ for (let i = 0; i < prevKeys.length; i++) {
+ if (prevKeys[i] !== curKeys[i]) return false;
+ const key = prevKeys[i];
+ if (!deepEqual(prev[key], current[key])) return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+export default deepEqual;
diff --git a/public/react/src/common/reactQuill/flatten.js b/public/react/src/common/reactQuill/flatten.js
new file mode 100644
index 000000000..237cb543f
--- /dev/null
+++ b/public/react/src/common/reactQuill/flatten.js
@@ -0,0 +1,26 @@
+/*
+ * @Description: 将多维数组转变成一维数组
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-09 09:35:01
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-16 11:36:22
+ */
+function flatten (array) {
+ return flatten.rec(array, []);
+}
+
+flatten.rec = function flatten (array, result) {
+
+ for (let item of array) {
+ if (Array.isArray(item)) {
+ flatten(item, result);
+ } else {
+ result.push(item);
+ }
+ }
+
+ return result;
+}
+
+export default flatten;
diff --git a/public/react/src/common/reactQuill/index.js b/public/react/src/common/reactQuill/index.js
new file mode 100644
index 000000000..56a1a8d1f
--- /dev/null
+++ b/public/react/src/common/reactQuill/index.js
@@ -0,0 +1,108 @@
+/*
+ * @Description: 入口文件
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-17 10:41:48
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-17 20:34:40
+ */
+import React, { useState, useCallback, useEffect } from 'react';
+import ReactQuill from './lib';
+
+function Wrapper (props) {
+ // 默认工具栏配置项
+ const toolbarConfig = [
+ ['bold', 'italic', 'underline'],
+ [{align: []}, {list: 'ordered'}, {list: 'bullet'}], // 列表
+ [{script: 'sub'}, {script: 'super'}],
+ [{header: [1,2,3,4,5,false]}],
+ ['blockquote', 'code-block'],
+ ['link', 'image', 'video'],
+ ['formula'],
+ ['clean']
+ ];
+
+ const [placeholder] = useState(props.placeholder || 'placeholder');
+ const [disableBold] = useState(false);
+ const [value, setValue] = useState(props.value || '');
+ const [toolbar, setToolbar] = useState(toolbarConfig);
+ const [theme, setTheme] = useState(props.theme || 'snow');
+ const [readOnly] = useState(props.readOnly || false);
+
+ const {
+ onContentChagne, // 当编辑器内容变化时调用该函数
+ showUploadImage, // 显示上传图片, 返回url,主要用于点击图片放大
+ } = props;
+
+ // 配置信息
+ const options = {
+ modules: {
+ toolbar: toolbar,
+ clipboard: {
+ matchVisual: false
+ }
+ },
+ readOnly: readOnly,
+ theme: theme
+ }
+ // 配置信息
+ useEffect (() => {
+ if (props.options) {
+ setToolbar(props.options);
+ }
+ setTheme(props.theme || 'snow');
+ setValue(props.value);
+ }, [props]);
+
+ // 当内容变化时
+ const handleOnChange = useCallback(
+ contents => {
+ if (disableBold) {
+ setValue({
+ ops: contents.ops.map(x => {
+ x = {...x};
+ if (x && x.attributes && x.attributes.bold) {
+ x.attributes = { ...x.attributes };
+ delete x.attributes.bold;
+ if (!Object.keys(x.attributes).length) {
+ delete x.attributes;
+ }
+ }
+ return x;
+ })
+ });
+ } else {
+ setValue(contents);
+ }
+ onContentChagne && onContentChagne(contents);
+ }, [disableBold]
+ );
+
+ // 图片上传
+ const handleUploadImage = (files) => {
+ console.log('选择的图片信息', files);
+ }
+
+ // 显示图片
+ const handleShowUploadImage = (url) => {
+ // console.log('上传的图片url:', url);
+ showUploadImage && showUploadImage(url);
+ }
+
+ return (
+
+ handleShowUploadImage(url)}
+ />
+
+ );
+}
+
+export default Wrapper;
+// ReactDOM.render(
, document.querySelector('#root'));
diff --git a/public/react/src/common/reactQuill/index.scss b/public/react/src/common/reactQuill/index.scss
new file mode 100644
index 000000000..b6da52bf5
--- /dev/null
+++ b/public/react/src/common/reactQuill/index.scss
@@ -0,0 +1,32 @@
+#quill-toolbar{
+ .quill-btn{
+ vertical-align: middle;
+ }
+ .quill_image{
+ display: inline-block;
+ position: relative;
+ vertical-align: middle;
+ width: 28px;
+ height: 24px;
+ overflow: hidden;
+ .image_input{
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ opacity: 0;
+ }
+ .ql-image{
+ position: relative;
+ left: 0;
+ top: 0;
+ }
+ }
+}
+
+.react_quill_area{
+ .ql-toolbar:not(:last-child) {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/public/react/src/common/reactQuill/lib.js b/public/react/src/common/reactQuill/lib.js
new file mode 100644
index 000000000..430a95bb7
--- /dev/null
+++ b/public/react/src/common/reactQuill/lib.js
@@ -0,0 +1,13 @@
+/*
+ * @Description: 导出 ReactQuill
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-09 09:08:24
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-16 11:37:13
+ */
+import ReactQuill from './ReactQuill';
+import useQuill from './useQuill';
+
+export default ReactQuill;
+export { useQuill };
diff --git a/public/react/src/common/reactQuill/useDeepEqualMemo.js b/public/react/src/common/reactQuill/useDeepEqualMemo.js
new file mode 100644
index 000000000..948e21781
--- /dev/null
+++ b/public/react/src/common/reactQuill/useDeepEqualMemo.js
@@ -0,0 +1,27 @@
+/*
+ * @Description:
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-12 19:48:55
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-16 11:38:16
+ */
+import { useState, useEffect } from 'react';
+import deepEqual from './deepEqual';
+
+function useDeepEqual (input) {
+
+ const [value, setValue] = useState(input);
+
+ useEffect(() => {
+
+ if (!deepEqual(input, value)) {
+ setValue(input)
+ }
+
+ }, [input, value]);
+
+ return value;
+}
+
+export default useDeepEqual;
diff --git a/public/react/src/common/reactQuill/useMountQuill.js b/public/react/src/common/reactQuill/useMountQuill.js
new file mode 100644
index 000000000..c2313c480
--- /dev/null
+++ b/public/react/src/common/reactQuill/useMountQuill.js
@@ -0,0 +1,148 @@
+/*
+ * @Description: 创建 reactQuill实例
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-09 09:31:42
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-17 20:42:05
+ */
+import Quill from 'quill'; // 导入quill
+import { useState, useEffect, useMemo } from 'react';
+import flatten from './flatten.js';
+import useDeepEqualMemo from './useDeepEqualMemo';
+import Katex from 'katex';
+import ImageBlot from './ImageBlot';
+import { fetchUploadImage } from '../../services/ojService.js';
+import { getImageUrl } from 'educoder'
+window.katex = Katex;
+
+Quill.register(ImageBlot);
+
+function useMountQuill ({
+ element,
+ options: passedOptions,
+ uploadImage,
+ showUploadImage,
+ imgAttrs = {} // 指定图片的宽高属性
+}) {
+
+ // 是否引入 katex
+ const [katexLoaded, setKatexLoaded] = useState(Boolean(window.katex))
+ const [quill, setQuill] = useState(null);
+
+ const options = useDeepEqualMemo(passedOptions);
+ console.log('use mount quill: ', passedOptions);
+
+ // 判断options中是否包含公式
+ const requireKatex = useMemo(() => {
+ return flatten(options.modules.toolbar).includes('formula');
+ }, [options]);
+
+ // 加载katex
+ useEffect(() => {
+ if (!requireKatex) return;
+ if (katexLoaded) return;
+
+ const interval = setInterval(() => {
+ if (window.katex) {
+ setKatexLoaded(true);
+ clearInterval(interval);
+ }
+ });
+
+ return () => { // 定义回调清除定时器
+ clearInterval(interval);
+ }
+
+ }, [
+ setKatexLoaded,
+ katexLoaded,
+ requireKatex
+ ]);
+
+ // 加载 quill
+ useEffect(() => {
+ if (!element) return;
+ if (requireKatex && !katexLoaded) {
+ element.innerHTML = `
+
+ Loading Katex...
+
+ `
+ }
+ // 清空内容
+ element.innerHTML = '';
+ console.log(element);
+ // 创建 quill 节点
+ const quillNode = document.createElement('div');
+ element.appendChild(quillNode); // 将quill节点追回到 element 元素中
+
+ const quill = new Quill(element, options);
+ setQuill(quill);
+ // 加载上传图片功能
+ if (typeof uploadImage === 'function') {
+ quill.getModule('toolbar').addHandler('image', (e) => {
+ // 创建type类型输入框加载本地图片
+ const input = document.createElement('input');
+ input.setAttribute('type', 'file');
+ input.setAttribute('accept', 'image/*');
+ input.click();
+
+ input.onchange = async (e) => {
+ const file = input.files[0]; // 获取文件信息
+ const formData = new FormData();
+ formData.append('file', file);
+
+ // const reader = new FileReader();
+ // reader.readAsDataURL(file);
+ // console.log('文件信息===>>', reader);
+ // reader.onload = function (e) {
+ // debugger;
+ // console.log('文件信息===>>', e.target.result);
+ // const image = new Image();
+ // image.src = e.target.result;
+
+ // image.onload = function () {
+ // // file.width =
+ // console.log(image.width, image.height);
+ // }
+ // }
+
+ const range = quill.getSelection(true);
+ let fileUrl = ''; // 保存上传成功后图片的url
+ // 上传文件
+ const result = await fetchUploadImage(formData);
+ // 获取上传图片的url
+ if (result.data && result.data.id) {
+ fileUrl = getImageUrl(`api/attachments/${result.data.id}`);
+ }
+ // 根据id获取文件路径
+ const { width, height } = imgAttrs;
+ // console.log('上传图片的url:', fileUrl);
+ if (fileUrl) {
+ quill.insertEmbed(range.index, 'image', {
+ url: fileUrl,
+ alt: '',
+ onClick: showUploadImage,
+ width,
+ height
+ });
+ }
+ }
+ });
+ }
+
+ return () => {
+ element.innerHTML = '';
+ }
+ }, [
+ element,
+ options,
+ requireKatex,
+ katexLoaded,
+ ]);
+
+ return quill;
+}
+
+export default useMountQuill;
diff --git a/public/react/src/common/reactQuill/useQuill.js b/public/react/src/common/reactQuill/useQuill.js
new file mode 100644
index 000000000..b959dbc52
--- /dev/null
+++ b/public/react/src/common/reactQuill/useQuill.js
@@ -0,0 +1,60 @@
+/*
+ * @Description:
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-09 09:09:50
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-17 15:46:50
+ */
+import useQuillPlaceholder from './useQuillPlaceholder';
+import useQuillValueSync from './useQuillValueSync';
+import useQuillOnChange from './useQuillOnChange';
+import useMountQuill from './useMountQuill';
+import { useEffect } from 'react';
+
+function useQuill ({
+ disallowColors,
+ placeholder,
+ uploadImage,
+ onChange,
+ options,
+ value,
+ element,
+ showUploadImage
+}) {
+
+ // 获取 quill 实例
+ const quill = useMountQuill({
+ element,
+ options,
+ uploadImage,
+ showUploadImage
+ });
+
+ useEffect(() => {
+ if (disallowColors && quill) {
+ quill.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => {
+ delta.ops = delta.ops.map(op => {
+ if (op.attributes && op.attributes.color) {
+ const { color, ...attributes } = op.attributes;
+ return {
+ ...op,
+ attributes
+ }
+ }
+ return op;
+ });
+ return delta;
+ });
+ }
+ }, [
+ disallowColors,
+ quill
+ ]);
+
+ useQuillPlaceholder(quill, placeholder);
+ useQuillValueSync(quill, value);
+ useQuillOnChange(quill, onChange);
+}
+
+export default useQuill;
diff --git a/public/react/src/common/reactQuill/useQuillOnChange.js b/public/react/src/common/reactQuill/useQuillOnChange.js
new file mode 100644
index 000000000..45333a4e1
--- /dev/null
+++ b/public/react/src/common/reactQuill/useQuillOnChange.js
@@ -0,0 +1,33 @@
+/*
+ * @Description:
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-12 19:49:11
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-16 11:39:27
+ */
+import { useEffect } from 'react';
+
+function useQuillOnChange (quill, onChange) {
+
+ useEffect(() => {
+
+ if (!quill) return;
+ if (typeof onChange !== 'function') return;
+
+ let handler;
+
+ quill.on(
+ 'text-change',
+ (handler = () => {
+ onChange(quill.getContents()); // getContents: 检索编辑器内容
+ })
+ );
+
+ return () => {
+ quill.off('text-change', handler);
+ }
+ }, [quill, onChange]);
+}
+
+export default useQuillOnChange;
diff --git a/public/react/src/common/reactQuill/useQuillPlaceholder.js b/public/react/src/common/reactQuill/useQuillPlaceholder.js
new file mode 100644
index 000000000..ccc341568
--- /dev/null
+++ b/public/react/src/common/reactQuill/useQuillPlaceholder.js
@@ -0,0 +1,22 @@
+/*
+ * @Description:
+ * @Author: tangjiang
+ * @Github:
+ * @Date: 2019-12-09 09:28:34
+ * @LastEditors: tangjiang
+ * @LastEditTime: 2019-12-16 11:39:48
+ */
+import { useEffect } from 'react'
+
+function useQuillPlaceholder (
+ quill,
+ placeholder
+) {
+
+ useEffect(() => {
+ if (!quill || !quill.root) return;
+ quill.root.dataset.placeholder = placeholder;
+ }, [quill, placeholder]);
+}
+
+export default useQuillPlaceholder;
diff --git a/public/react/src/common/reactQuill/useQuillValueSync.js b/public/react/src/common/reactQuill/useQuillValueSync.js
new file mode 100644
index 000000000..696d88949
--- /dev/null
+++ b/public/react/src/common/reactQuill/useQuillValueSync.js
@@ -0,0 +1,31 @@
+import { useEffect, useState } from 'react'
+import deepEqual from './deepEqual.js'
+
+function useQuillValueSync(quill, value) {
+ const [selection, setSelection] = useState(null)
+
+ useEffect(() => {
+ if (!quill) return
+
+ const previous = quill.getContents()
+ const current = value
+
+ if (!deepEqual(previous, current)) {
+ setSelection(quill.getSelection())
+ if (typeof value === 'string') {
+ quill.clipboard.dangerouslyPasteHTML(value, 'api')
+ } else {
+ quill.setContents(value)
+ }
+ }
+ }, [quill, value, setSelection])
+
+ useEffect(() => {
+ if (quill && selection) {
+ quill.setSelection(selection)
+ setSelection(null)
+ }
+ }, [quill, selection, setSelection])
+}
+
+export default useQuillValueSync
diff --git a/public/react/src/modules/developer/DeveloperHome.js b/public/react/src/modules/developer/DeveloperHome.js
index 5f787659e..73a5c37a1 100644
--- a/public/react/src/modules/developer/DeveloperHome.js
+++ b/public/react/src/modules/developer/DeveloperHome.js
@@ -16,7 +16,7 @@ import MultipTags from './components/multiptags';
// import { Link } from 'react-router-dom';
import CONST from '../../constants';
import { withRouter } from 'react-router';
-import { toStore } from 'educoder';
+import { toStore, CNotificationHOC } from 'educoder';
// import MyIcon from '../../common/components/MyIcon';
const {tagBackground, diffText} = CONST;
@@ -249,17 +249,26 @@ class DeveloperHome extends React.PureComponent {
// 删除
handleClickDelete = (record) => {
const { deleteItem } = this.props;
- Modal.confirm({
- title: '删除',
+ this.props.confirm({
+ title: '提示',
content: `确定要删除${record.name}吗?`,
- okText: '确定',
- cancelText: '取消',
onOk () {
// 调用删除接口
console.log(record.identifier);
deleteItem(record.identifier);
}
});
+ // Modal.confirm({
+ // title: '删除',
+ // content: `确定要删除${record.name}吗?`,
+ // okText: '确定',
+ // cancelText: '取消',
+ // onOk () {
+ // // 调用删除接口
+ // console.log(record.identifier);
+ // deleteItem(record.identifier);
+ // }
+ // });
}
// table条件变化时
handleTableChange = (pagination, filters, sorter) => {
@@ -562,5 +571,5 @@ const mapDispatchToProps = (dispatch) => ({
export default withRouter(connect(
mapStateToProps,
mapDispatchToProps
-)(DeveloperHome));
+)(CNotificationHOC() (DeveloperHome)));
// export default DeveloperHome;
diff --git a/public/react/src/modules/developer/components/controlSetting/index.js b/public/react/src/modules/developer/components/controlSetting/index.js
index 587e1bee9..1d4d7834c 100644
--- a/public/react/src/modules/developer/components/controlSetting/index.js
+++ b/public/react/src/modules/developer/components/controlSetting/index.js
@@ -4,10 +4,10 @@
* @Github:
* @Date: 2019-11-27 16:02:36
* @LastEditors: tangjiang
- * @LastEditTime: 2019-12-13 17:32:33
+ * @LastEditTime: 2019-12-19 19:47:32
*/
import './index.scss';
-import React, { useState, useRef } from 'react';
+import React, { useState, useRef, useEffect } from 'react';
import { Tabs, Button, Icon } from 'antd';
import { connect } from 'react-redux';
import InitTabCtx from '../initTabCtx';
@@ -23,14 +23,15 @@ const ControlSetting = (props) => {
submitLoading,
identifier,
excuteState,
+ showOrHideControl,
commitRecordDetail,
changeLoadingState,
changeSubmitLoadingStatus,
- showOrHideControl,
+ changeShowOrHideControl,
// debuggerCode,
// startDebuggerCode, // 外部存入
onDebuggerCode,
- updateCode,
+ // updateCode,
onSubmitForm
} = props;
const [defaultActiveKey, setDefaultActiveKey] = useState('1'); // 当前选中的tab
@@ -44,10 +45,14 @@ const ControlSetting = (props) => {
setDefaultActiveKey(key);
}
+ useEffect(() => {
+ setShowTextResult(props.showOrHideControl);
+ }, [props]);
+
// 显示/隐藏tab
const handleShowControl = () => {
setShowTextResult(!showTextResult);
- showOrHideControl(!showTextResult);
+ changeShowOrHideControl(!showTextResult);
}
// 调试代码
@@ -55,7 +60,7 @@ const ControlSetting = (props) => {
// console.log(formRef.current.handleTestCodeFormSubmit);
// 调出控制台界面
setShowTextResult(true);
- showOrHideControl(true);
+ changeShowOrHideControl(true);
formRef.current.handleTestCodeFormSubmit(() => {
setDefaultActiveKey('2');
});
@@ -84,7 +89,7 @@ const ControlSetting = (props) => {
@@ -131,19 +136,20 @@ const ControlSetting = (props) => {
const mapStateToProps = (state) => {
const {commonReducer, ojForUserReducer} = state;
- const {loading, excuteState, submitLoading } = commonReducer;
+ const {loading, excuteState, submitLoading, showOrHideControl } = commonReducer;
const { commitRecordDetail } = ojForUserReducer;
return {
loading,
submitLoading,
excuteState,
+ showOrHideControl,
// identifier: user_program_identifier,
commitRecordDetail // 提交详情
};
};
// changeSubmitLoadingStatus
const mapDispatchToProps = (dispatch) => ({
- showOrHideControl: (flag) => dispatch(actions.showOrHideControl(flag)),
+ changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag)),
changeLoadingState: (flag) => dispatch(actions.changeLoadingState(flag)),
changeSubmitLoadingStatus: (flag) => dispatch(actions.changeSubmitLoadingStatus(flag)),
debuggerCode: (identifier, values) => dispatch(actions.debuggerCode(identifier, values)),
diff --git a/public/react/src/modules/developer/components/controlSetting/index.scss b/public/react/src/modules/developer/components/controlSetting/index.scss
index 97838ce5c..31beda8a5 100644
--- a/public/react/src/modules/developer/components/controlSetting/index.scss
+++ b/public/react/src/modules/developer/components/controlSetting/index.scss
@@ -2,7 +2,8 @@
position: absolute;
bottom: 0;
width: 100%;
- background:rgba(30,30,30,1);
+ // background: red;
+ // background:rgba(30,30,30,1);
// height: 56px;
.control_tab{
position: absolute;
@@ -52,8 +53,8 @@
height: 56px;
padding-right: 30px;
padding-left: 10px;
- // background: #000;
- background:rgba(48,48,48,1);
+ background: rgba(18,28,36,1);
+ // background:rgba(48,48,48,1);
}
.setting_drawer{
diff --git a/public/react/src/modules/developer/components/execResult/index.js b/public/react/src/modules/developer/components/execResult/index.js
index 32bbbee91..6f9341b9a 100644
--- a/public/react/src/modules/developer/components/execResult/index.js
+++ b/public/react/src/modules/developer/components/execResult/index.js
@@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-28 08:44:54
* @LastEditors: tangjiang
- * @LastEditTime: 2019-12-10 09:24:02
+ * @LastEditTime: 2019-12-19 10:44:16
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
@@ -38,6 +38,15 @@ function ExecResult (props) {
);
+
+ const renderError = () => (
+
+
+ 未知异常
+
+
+ )
+
const renderFinish = () => {
const {
error_line,
@@ -60,6 +69,7 @@ function ExecResult (props) {
)
}
+ // console.log('执行结果====》》》》', status);
const excuteCtx = (state) => {
if (state === 0) {
return (
@@ -118,6 +128,8 @@ function ExecResult (props) {
setRenderCtx(() => (readerLoaded));
} else if ('finish' === excuteState) {
setRenderCtx(() => (renderFinish));
+ } else if ('error' === excuteState) {
+ setRenderCtx(() => (renderError))
}
}, [excuteState]);
diff --git a/public/react/src/modules/developer/components/initTabCtx/index.js b/public/react/src/modules/developer/components/initTabCtx/index.js
index 3834a3e11..3e707daa1 100644
--- a/public/react/src/modules/developer/components/initTabCtx/index.js
+++ b/public/react/src/modules/developer/components/initTabCtx/index.js
@@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 19:46:14
* @LastEditors: tangjiang
- * @LastEditTime: 2019-12-13 17:38:42
+ * @LastEditTime: 2019-12-19 10:47:05
*/
import './index.scss';
import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react';
@@ -26,6 +26,7 @@ function InitTabCtx (props, ref) {
const { inputValue, onDebuggerCode } = props;
+ console.log('default value', inputValue);
useImperativeHandle(ref, () => ({
handleTestCodeFormSubmit: (cb) => {
// console.log('父组件调用我啦~~~~~~~~~');
@@ -33,6 +34,10 @@ function InitTabCtx (props, ref) {
}
}));
+ useEffect(() => {
+ console.log('初始值: ========', props);
+ }, [props]);
+
// 渲染文本提示信息
const renderText = () => (请在这里添加测试用例,点击“调试代码”时将从这里读取输入来测试你的代码...);
// 渲染表单信息
diff --git a/public/react/src/modules/developer/components/initTabCtx/index.scss b/public/react/src/modules/developer/components/initTabCtx/index.scss
index 449db1d2a..5427aa374 100644
--- a/public/react/src/modules/developer/components/initTabCtx/index.scss
+++ b/public/react/src/modules/developer/components/initTabCtx/index.scss
@@ -49,7 +49,8 @@
}
.input_textarea_style{
- background:rgba(30,30,30,1) !important;
+ // background:rgba(30,30,30,1) !important;
+ background:rgba(7,15,25,1) !important;
color: #fff;
border-color: transparent;
outline: none;
diff --git a/public/react/src/modules/developer/components/monacoSetting/index.js b/public/react/src/modules/developer/components/monacoSetting/index.js
index a101819e0..669439577 100644
--- a/public/react/src/modules/developer/components/monacoSetting/index.js
+++ b/public/react/src/modules/developer/components/monacoSetting/index.js
@@ -4,10 +4,11 @@
* @Github:
* @Date: 2019-11-25 17:50:33
* @LastEditors: tangjiang
- * @LastEditTime: 2019-12-06 16:51:48
+ * @LastEditTime: 2019-12-19 19:32:08
*/
import React, { useState } from 'react';
import { fromStore, toStore } from 'educoder';
+// import { Icon } from 'antd';
// import { Select } from 'antd';
// const { Option } = Select;
const SettingDrawer = (props) => {
diff --git a/public/react/src/modules/developer/components/myMonacoEditor/index.js b/public/react/src/modules/developer/components/myMonacoEditor/index.js
index 60f54ee0a..948d5a4f5 100644
--- a/public/react/src/modules/developer/components/myMonacoEditor/index.js
+++ b/public/react/src/modules/developer/components/myMonacoEditor/index.js
@@ -4,12 +4,12 @@
* @Github:
* @Date: 2019-11-27 15:02:52
* @LastEditors: tangjiang
- * @LastEditTime: 2019-12-13 16:16:56
+ * @LastEditTime: 2019-12-19 19:36:24
*/
import './index.scss';
import React, { useState, useRef, useEffect } from 'react';
-import { Drawer, Modal } from 'antd';
-import { fromStore } from 'educoder';
+import { Drawer, Modal, Icon, Badge } from 'antd';
+import { fromStore, CNotificationHOC } from 'educoder';
import { connect } from 'react-redux';
import MonacoEditor from '@monaco-editor/react';
import SettingDrawer from '../../components/monacoSetting';
@@ -19,16 +19,25 @@ import MyIcon from '../../../../common/components/MyIcon';
// import actions from '../../../../redux/actions';
const { fontSetting, opacitySetting } = CONST;
+const maps = {
+ 'c': 'main.c',
+ 'c++': 'main.cc',
+ 'java': 'main.java',
+ 'pythone': 'main.py'
+};
function MyMonacoEditor (props, ref) {
const {
+ notice,
language,
identifier,
+ hadCodeUpdate,
showOrHideControl,
// saveUserInputCode,
onCodeChange,
- onRestoreInitialCode
+ onRestoreInitialCode,
+ onUpdateNotice
} = props;
const [showDrawer, setShowDrawer] = useState(false); // 控制配置滑框
@@ -50,7 +59,7 @@ function MyMonacoEditor (props, ref) {
}, [props]);
useEffect(() => {
- setHeight(showOrHideControl ? 'calc(100% - 382px)' : 'calc(100% - 56px)');
+ setHeight(showOrHideControl ? 'calc(100% - 378px)' : 'calc(100% - 56px)');
}, [showOrHideControl]);
// 控制侧边栏设置的显示
@@ -93,28 +102,51 @@ function MyMonacoEditor (props, ref) {
// 恢复初始代码
const handleRestoreCode = () => {
- Modal.confirm({
+ props.confirm({
+ title: '提示',
content: '确定要恢复代码吗?',
- okText: '确定',
- cancelText: '取消',
onOk () {
onRestoreInitialCode && onRestoreInitialCode();
}
})
+ // Modal.confirm({
+ // content: '确定要恢复代码吗?',
+ // okText: '确定',
+ // cancelText: '取消',
+ // onOk () {
+ // onRestoreInitialCode && onRestoreInitialCode();
+ // }
+ // })
+ }
+
+ const handleUpdateNotice = () => {
+ if (props.notice) {
+ onUpdateNotice && onUpdateNotice();
+ }
}
const renderRestore = identifier ? (
) : '';
+
+ // lex_has_save ${hadCodeUpdate} ? : ''
+ const _classnames = hadCodeUpdate ? `flex_strict flex_has_save` : 'flex_strict';
return (
{/* 未保存时 ? '学员初始代码文件' : main.x */}
- {identifier ? '' : '学员初始代码文件'}
- {identifier ? '已保存' : ''}
- {renderRestore}
- {/* */}
+ {identifier ? language ? maps[language.toLowerCase()] : '' : '学员初始代码文件'}
+ {identifier ? '已保存' : ''}
+
+
+
+ {renderRestore}
@@ -161,4 +192,4 @@ const mapDispatchToProps = (dispatch) => ({
export default connect(
mapStateToProps,
mapDispatchToProps
-)(MyMonacoEditor);
+)(CNotificationHOC() (MyMonacoEditor));
diff --git a/public/react/src/modules/developer/components/myMonacoEditor/index.scss b/public/react/src/modules/developer/components/myMonacoEditor/index.scss
index 7a7c4f030..61689b51e 100644
--- a/public/react/src/modules/developer/components/myMonacoEditor/index.scss
+++ b/public/react/src/modules/developer/components/myMonacoEditor/index.scss
@@ -1,19 +1,17 @@
.monaco_editor_area{
height: 100%;
- background-color: rgba(30,30,30,1);
+ background-color: rgba(7,15,25,1);
.code_title{
display: flex;
align-items: center;
- // justify-content: space-between;
- // background: #000;
- // background: #333333;
- background-color: rgba(48,48,48,1);
+ background-color: rgba(18,28,36,1);
color: #fff;
height: 56px;
padding: 0 30px;
.flex_strict{
flex: 1;
}
+
.flex_normal{
color: #E51C24;
cursor: pointer;
@@ -25,21 +23,21 @@
.flex_strict,
.flex_normal,
.code-icon{
- color: #888;
+ color: #666;
}
}
}
.setting_drawer{
- // .ant-drawer-body{
- // // height: calc(100vh - 120px);
- // // overflow-y: auto;
- // }
+ .ant-drawer-close{
+ color: #ffffff;
+ }
.ant-drawer-content{
top: 120px;
bottom: 56px;
height: calc(100vh - 176px);
- background: #333333;
+ // background: #333333;
+ background: rgba(7,15,25,1);
color: #fff;
.setting_h2{
color: #fff;
@@ -57,4 +55,17 @@
color: #fff;
}
}
+}
+
+.flex_has_save{
+ // animation: blink 3s line 3;
+ animation-name: blink;
+ animation-duration: .4s;
+ animation-iteration-count: 3;
+}
+
+@keyframes blink{
+ 50% {
+ color: #fff;
+ }
}
\ No newline at end of file
diff --git a/public/react/src/modules/developer/newOrEditTask/index.js b/public/react/src/modules/developer/newOrEditTask/index.js
index bc905fdf7..1c451c669 100644
--- a/public/react/src/modules/developer/newOrEditTask/index.js
+++ b/public/react/src/modules/developer/newOrEditTask/index.js
@@ -13,11 +13,11 @@ import { Button, Modal } from 'antd';
import LeftPane from './leftpane';
import RightPane from './rightpane';
import { withRouter } from 'react-router';
-import { toStore } from 'educoder';
+import { toStore, CNotificationHOC } from 'educoder';
import UserInfo from '../components/userInfo';
// import RightPane from './rightpane/index';
import actions from '../../../redux/actions';
-import {ModalConfirm} from '../../../common/components/ModalConfirm';
+// import {ModalConfirm} from '../../../common/components/ModalConfirm';
const NewOrEditTask = (props) => {
const {
@@ -69,10 +69,13 @@ const NewOrEditTask = (props) => {
// 模拟挑战
const imitationChallenge = () => {
+ // 调用 start 接口, 成功后跳转到模拟页面
+ startProgramQuestion(identifier, props);
}
// 开始挑战
const startChallenge = () => {
- // 调用 start 接口, 成功后跳转到模拟页面
+ // 调用 start 接口, 成功后跳转到开启实战
+ // TODO
startProgramQuestion(identifier, props);
}
@@ -82,27 +85,38 @@ const NewOrEditTask = (props) => {
props.clearOJFormStore();
// 清空描述信息
toStore('oj_description', '');
- setInterval(function () {
- props.history.push('/problems');
- }, 500);
+ props.history.push('/problems');
}
// 发布
const handleClickPublish = () => {
- ModalConfirm('提示', (发布后即可应用到自己管理的课堂
是否确认发布?
), () => {
- changePublishLoadingStatus(true);
- handlePublish(props, 'publish');
+ // ModalConfirm('提示', (发布后即可应用到自己管理的课堂
是否确认发布?
), () => {
+ // changePublishLoadingStatus(true);
+ // handlePublish(props, 'publish');
+ // });
+ props.confirm({
+ title: '提示',
+ content: (发布后即可应用到自己管理的课堂
是否确认发布?
),
+ onOk () {
+ changePublishLoadingStatus(true);
+ handlePublish(props, 'publish');
+ }
});
-
-
}
// 撤销发布
const handleClickCancelPublish = () => {
- ModalConfirm('提示', (是否确认撤销发布?
), () => {
- changePublishLoadingStatus(true);
- handleCancelPublish(props, identifier);
+ // ModalConfirm('提示', (是否确认撤销发布?
), () => {
+ // changePublishLoadingStatus(true);
+ // handleCancelPublish(props, identifier);
+ // });
+ props.confirm({
+ title: '提示',
+ content: ((是否确认撤销发布?
)),
+ onOk () {
+ changePublishLoadingStatus(true);
+ handleCancelPublish(props, identifier);
+ }
});
-
}
// 取消保存/取消按钮
@@ -125,6 +139,7 @@ const NewOrEditTask = (props) => {
const renderPubOrFight = () => {
const pubButton = isPublish
? (
- {/*
-
-
-
-
*/}
);
diff --git a/public/react/src/modules/developer/studentStudy/leftpane/index.scss b/public/react/src/modules/developer/studentStudy/leftpane/index.scss
index 9e6f019f6..1582c033f 100644
--- a/public/react/src/modules/developer/studentStudy/leftpane/index.scss
+++ b/public/react/src/modules/developer/studentStudy/leftpane/index.scss
@@ -13,6 +13,8 @@
bottom: 0px;
height: 56px;
width: 100%;
+ box-sizing: border-box;
+ border-top: 1px solid rgba(244,244,244,1);
// background: pink;
padding: 0 30px;
// background-color: rgba(250,250,250,1);
@@ -79,4 +81,9 @@
margin-right: 5px;
}
}
+}
+
+.add_editor_list_area{
+ box-sizing: border-box;
+ border-bottom: 1px solid rgba(244,244,244,1);
}
\ No newline at end of file
diff --git a/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js b/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js
index 28fe51765..981770b8c 100644
--- a/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js
+++ b/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js
@@ -4,14 +4,15 @@
* @Github:
* @Date: 2019-11-27 09:49:30
* @LastEditors: tangjiang
- * @LastEditTime: 2019-12-09 19:21:55
+ * @LastEditTime: 2019-12-19 09:22:52
*/
import '../index.scss';
import React from 'react';
import { Tag } from 'antd';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
-import QuillEditor from '../../../quillEditor';
+import QuillForEditor from '../../../../../common/quillForEditor';
+
import CONST from '../../../../../constants';
const {tagBackground, diffText} = CONST;
@@ -36,22 +37,15 @@ const TaskDescription = (props) => {
出题者:
- {username}
+ {username}
-
- {/* */}
- {/* */}
)
}
diff --git a/public/react/src/modules/developer/studentStudy/rightpane/index.js b/public/react/src/modules/developer/studentStudy/rightpane/index.js
index 669a8a693..af46d0aef 100644
--- a/public/react/src/modules/developer/studentStudy/rightpane/index.js
+++ b/public/react/src/modules/developer/studentStudy/rightpane/index.js
@@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 14:59:51
* @LastEditors: tangjiang
- * @LastEditTime: 2019-12-13 16:50:40
+ * @LastEditTime: 2019-12-19 19:13:05
*/
import React, { useState, useEffect } from 'react';
import {connect} from 'react-redux';
@@ -20,8 +20,11 @@ const RightPane = (props) => {
submitUserCode,
input,
hack,
+ notice,
updateCode,
+ hadCodeUpdate,
editor_code,
+ updateNotice,
saveUserInputCode,
restoreInitialCode,
saveUserCodeForInterval
@@ -29,6 +32,7 @@ const RightPane = (props) => {
const [editorCode, setEditorCode] = useState('');
+ let initFlag = true;
useEffect(() => {
if (editor_code) {
setEditorCode(editor_code);
@@ -48,7 +52,12 @@ const RightPane = (props) => {
// 代码块内容变化时
const handleCodeChange = (code) => {
// 保存用户提交的代码块
- console.log(code);
+ setEditorCode(code);
+ // 第一次回填代码内容时不更新;
+ if (initFlag) {
+ initFlag = false;
+ return;
+ }
if (!timer) {
timer = setInterval(() => {
clearInterval(timer);
@@ -69,13 +78,21 @@ const RightPane = (props) => {
restoreInitialCode(identifier, '恢复初始代码成功');
}
+ // 更新代码
+ const handleUpdateNotice = () => {
+ updateNotice && updateNotice();
+ };
+
return (
{
const mapStateToProps = (state) => {
- const {user_program_identifier, hack, userTestInput, editor_code} = state.ojForUserReducer;
+ const {
+ user_program_identifier,
+ hack,
+ userTestInput,
+ editor_code,
+ notice,
+ hadCodeUpdate
+ } = state.ojForUserReducer;
// const { language, code } = hack;
return {
hack,
+ notice,
+ hadCodeUpdate,
editor_code,
input: userTestInput,
submitInput: hack.input,
diff --git a/public/react/src/modules/tpm/TPMBanner.js b/public/react/src/modules/tpm/TPMBanner.js
index b498c4d22..672fff455 100644
--- a/public/react/src/modules/tpm/TPMBanner.js
+++ b/public/react/src/modules/tpm/TPMBanner.js
@@ -58,15 +58,6 @@ class TPMBanner extends Component {
}
}
- // star_info:[0, 0, 0, 0, 0, 0],
- // star_infos:[0, 0, 0, 0, 0, 0],
- // shixunsDetails:{},
- // shixunId: undefined,
- // componentWillReceiveProps(newProps, newContext){
- // this.setState({
- // shixunsDetails: newProps.shixunsDetails
- // });
- // }
IEVersion = () => {
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
@@ -118,31 +109,50 @@ class TPMBanner extends Component {
if (prevProps != this.props) {
let shixunopenprocess=window.localStorage.shixunopenprocess;
let openopenpublictype=window.localStorage.openopenpublictype;
- if(this.props.shixunsDetails&&this.props.shixunsDetails.shixun_status === 0 && this.props.identity < 5){
- if(shixunopenprocess===undefined||shixunopenprocess===false){
- this.setState({
- openknow:true
- })
- }else{
- this.setState({
- openknow:false
- })
+ if(this.props.status===0&&this.props.openknows===false){
+
+ if(this.props.shixunsDetails&&this.props.shixunsDetails.shixun_status === 0 && this.props.identity < 5){
+ if(shixunopenprocess===undefined||shixunopenprocess===false){
+ this.setState({
+ openknow:true
+ })
+ }else{
+ this.setState({
+ openknow:false
+ })
+ }
}
+ }else{
+ this.setState({
+ openknow:false
+ })
}
- if(this.props.shixunsDetails&&this.props.shixunsDetails.shixun_status === 2 && this.props.shixunsDetails&&this.props.shixunsDetails.public===0 && this.props.identity < 5){
- if(openopenpublictype===undefined||openopenpublictype===false){
- this.setState({
- openshowpublictype:true
- })
- }else{
- this.setState({
- openshowpublictype:false
- })
+
+
+ if(this.props.public===0&&this.props.status>1&&this.props.openknows===false){
+ if(this.props.shixunsDetails&&this.props.shixunsDetails.shixun_status === 2 && this.props.shixunsDetails&&this.props.shixunsDetails.public===0 && this.props.identity < 5){
+ if(openopenpublictype===undefined||openopenpublictype===false){
+ this.setState({
+ openshowpublictype:true
+ })
+ }else{
+ this.setState({
+ openshowpublictype:false
+ })
+ }
}
+ }else{
+ this.setState({
+ openshowpublictype:false
+ })
}
+
+
}
}
+
+
componentDidMount() {
let thiisie = this.IEVersion();
@@ -155,6 +165,7 @@ class TPMBanner extends Component {
isIE: false
})
}
+
}
/*
@@ -784,7 +795,8 @@ class TPMBanner extends Component {
};
//
// console.log(this.props.shixunsDetails&&this.props.shixunsDetails.is_jupyter)
-
+ // console.log(this.props)
+ // console.log(this.state)
return (
shixunsDetails === undefined ? "" :
@@ -796,6 +808,9 @@ class TPMBanner extends Component {
height: 180px !important;
padding-top:35px !important;
}
+ .ant-popover{
+ z-index:1000 !important;
+ }
`
}
diff --git a/public/react/src/modules/tpm/TPMIndex.js b/public/react/src/modules/tpm/TPMIndex.js
index d79bae95b..c44d8ce51 100644
--- a/public/react/src/modules/tpm/TPMIndex.js
+++ b/public/react/src/modules/tpm/TPMIndex.js
@@ -207,6 +207,7 @@ class TPMIndex extends Component {
propaedeutics:response.data.propaedeutics,
status: response.data.shixun_status,
secret_repository: response.data.secret_repository,
+ public:response.data.public,
is_jupyter:response.data.is_jupyter=== undefined||response.data.is_jupyter===null?false:response.data.is_jupyter,
});
@@ -295,10 +296,6 @@ class TPMIndex extends Component {
// this.getnavdatas()
}
- // componentDidUpdate=()=>{
- // this.getnavdatas()
- // }
-
setLoadingContent = (isLoadingContent) => {
this.setState({ loadingContent: isLoadingContent })
}
@@ -307,9 +304,6 @@ class TPMIndex extends Component {
getnavdatas=()=>{
let selectedKeys;
const {location} = this.props;
-
- console.log(location.pathname)
-
if(location.pathname.indexOf('/challenges')!=-1){
selectedKeys="1"
}else if(location.pathname.indexOf('/propaedeutics')!=-1){
@@ -385,6 +379,9 @@ class TPMIndex extends Component {
margin:0 40px 0 0;
padding:0px;
}
+ .ant-popover{
+ z-index:1000 !important;
+ }
`
}
diff --git a/public/react/src/modules/tpm/TPMsettings/LearningSettings.js b/public/react/src/modules/tpm/TPMsettings/LearningSettings.js
index 681cbc956..a98f68223 100644
--- a/public/react/src/modules/tpm/TPMsettings/LearningSettings.js
+++ b/public/react/src/modules/tpm/TPMsettings/LearningSettings.js
@@ -215,9 +215,9 @@ export default class Shixuninformation extends Component {
multi_webssh: false
})
} else {
- this.setState({
- multi_webssh: true
- })
+ // this.setState({
+ // multi_webssh: true
+ // })
}
this.setState({
opensshRadio: e.target.value
diff --git a/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js b/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js
index 200880019..66e1da8dd 100644
--- a/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js
+++ b/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js
@@ -50,6 +50,14 @@ class Shixuninformation extends Component {
}
componentDidMount() {
+ let query=this.props.location.search
+ const types = query.split('?edit=')
+ if(types[1]==="1"){
+ let anchorElement = document.getElementById("newcourseContentMD");
+ if(anchorElement){
+ this.scrollToAnchor("newcourseContentMD");
+ }
+ }
}
@@ -113,6 +121,7 @@ class Shixuninformation extends Component {
selectright: this.props.data && this.props.data.shixun.choice_small_type,
})
this.contentMdRef.current.setValue(this.props.data && this.props.data.shixun.description);
+
}
}
}
@@ -807,16 +816,20 @@ class Shixuninformation extends Component {
)}
+
+
+
diff --git a/public/react/src/modules/tpm/challengesnew/TPManswer.js b/public/react/src/modules/tpm/challengesnew/TPManswer.js
index 9c9a23a12..9187e09b0 100644
--- a/public/react/src/modules/tpm/challengesnew/TPManswer.js
+++ b/public/react/src/modules/tpm/challengesnew/TPManswer.js
@@ -302,11 +302,11 @@ export default class TPManswer extends Component {
className="color-grey-6 fr font-15 mt3">返回
{prev_challenge === undefined ? "" :
- 上一关
+ 上一关
}
{next_challenge === undefined ? "" :
- 下一关
+ 下一关
}
返回
{prev_challenge === undefined ? "" :
- 上一关
+ 上一关
}
{next_challenge === undefined ? "" :
- 下一关
+ 下一关
}
返回
{ next_challenge===undefined?"":
- 下一关
+ 下一关
}
{ prev_challenge===undefined?"":
- 上一关
+ 上一关
}
diff --git a/public/react/src/modules/tpm/challengesnew/TPMevaluation.js b/public/react/src/modules/tpm/challengesnew/TPMevaluation.js
index d70f22a0a..34eb1a075 100644
--- a/public/react/src/modules/tpm/challengesnew/TPMevaluation.js
+++ b/public/react/src/modules/tpm/challengesnew/TPMevaluation.js
@@ -824,11 +824,11 @@ export default class TPMevaluation extends Component {
className="color-grey-6 fr font-15 mt3">返回
{prev_challenge === undefined ? "" :
- 上一关
+ 上一关
}
{next_challenge === undefined ? "" :
- 下一关
+ 下一关
}
返回
{ prev_challenge===undefined?"":
- 上一关
+ 上一关
}
{ next_challenge===undefined?"":
- 下一关
+ 下一关
}
{
@@ -97,11 +99,11 @@ class TPMRightSection extends Component {
- {TPMRightSectionData&&TPMRightSectionData.complete_count!=null?
+ {this.props&&this.props.status>1?
学习统计
- 已完成 {TPMRightSectionData&&TPMRightSectionData.complete_count} 个 / 共 {TPMRightSectionData&&TPMRightSectionData.challenge_count} 关
+ 已完成 {TPMRightSectionData&&TPMRightSectionData.complete_count===null?0:TPMRightSectionData&&TPMRightSectionData.complete_count} 个 / 共 {TPMRightSectionData&&TPMRightSectionData.challenge_count} 关
diff --git a/public/react/src/modules/tpm/component/TPMright.css b/public/react/src/modules/tpm/component/TPMright.css
index a75160bf5..0d6b306fd 100644
--- a/public/react/src/modules/tpm/component/TPMright.css
+++ b/public/react/src/modules/tpm/component/TPMright.css
@@ -119,9 +119,14 @@
.padd252020px{
padding: 25px 20px 15px;
}
+
.rightjinengs{
height: 35px;
margin-top: 20px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
}
.borderbottomf4{
diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js
index 307823ee8..548e7224a 100644
--- a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js
+++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js
@@ -34,7 +34,8 @@ class Challenges extends Component {
operationstrue:false,
isSpin:false,
boxoffsetHeigh:0,
- opentitletype:true
+ opentitletype:true,
+ isopentitletype:"Less",
}
}
@@ -52,6 +53,13 @@ class Challenges extends Component {
ChallengesDataList: response.data,
sumidtype: false,
});
+
+ if(response.data.description=== ""||response.data.description===null||response.data.description===undefined){
+ this.setState({
+ isopentitletype:"Less",
+ })
+ }
+
}
}
}).catch((error) => {
@@ -71,17 +79,19 @@ class Challenges extends Component {
let box=document.getElementById("shixunchallengesid");
if(box){
boxoffsetHeigh=box.offsetHeight
- if(boxoffsetHeigh<260){
+ if(boxoffsetHeigh<300){
this.setState({
- opentitletype:false,
+ isopentitletype:"Less",
boxoffsetHeigh:boxoffsetHeigh
})
}else{
this.setState({
+ opentitletype:true,
+ isopentitletype:"greater",
boxoffsetHeigh:boxoffsetHeigh
})
}
-
+ console.log(boxoffsetHeigh)
}
}
@@ -322,7 +332,8 @@ class Challenges extends Component {
opentitle=()=>{
this.setState({
- opentitletype:!this.state.opentitletype
+ opentitletype:!this.state.opentitletype,
+
})
}
@@ -334,6 +345,7 @@ class Challenges extends Component {
}
let id = this.props.match.params.shixunId;
const antIcon =
;
+
return (
{AccountProfiletype===true?简介
{this.props.identity < 5 && ChallengesDataList&&ChallengesDataList.shixun_status < 3 ?
-
+
{/**/}
编辑
- :""}
+ :""}
{this.props.user && this.props.user.main_site === true ?
this.props.identity < 5?实训制作指南 : "":""}
@@ -407,7 +419,7 @@ class Challenges extends Component {
{
`
#shixunchallengesid{
- max-height: 260px;
+ max-height: 300px;
overflow: hidden;
}
`
@@ -427,14 +439,22 @@ class Challenges extends Component {
-
+ {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?
+
+ {this.props.identity < 5?
:
}
+
暂时还没有相关数据哦!
+
+ :
{ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"":
}
-
+ }
- {this.state.opentitletype===true?
this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}>
+
+ {this.state.isopentitletype==="Less"?"":this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}>
阅读全文
:this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}>
收起全文
diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js
index fcdbed408..e04ad17c9 100644
--- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js
+++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { Link } from "react-router-dom";
-import { markdownToHTML, configShareForCustom} from 'educoder'
+import { markdownToHTML, configShareForCustom,getImageUrl} from 'educoder'
import { Divider, Tooltip } from 'antd';
import LoadingSpin from '../../../../common/LoadingSpin';
import 'antd/lib/pagination/style/index.css';
@@ -23,7 +23,8 @@ class Challengesjupyter extends Component {
booljupyterurls:false,
loading:false,
boxoffsetHeigh:0,
- opentitletype:true
+ opentitletype:true,
+ isopentitletype:"Less",
}
}
@@ -41,6 +42,11 @@ class Challengesjupyter extends Component {
ChallengesDataList: response.data,
sumidtype: false,
});
+ if(response.data.description=== ""||response.data.description===null||response.data.description===undefined){
+ this.setState({
+ isopentitletype:"Less",
+ })
+ }
}
}
}).catch((error) => {
@@ -55,13 +61,15 @@ class Challengesjupyter extends Component {
let box=document.getElementById("shixunchallengesid");
if(box){
boxoffsetHeigh=box.offsetHeight
- if(boxoffsetHeigh<260){
+ if(boxoffsetHeigh<300){
this.setState({
- opentitletype:false,
+ isopentitletype:"Less",
boxoffsetHeigh:boxoffsetHeigh
})
}else{
this.setState({
+ isopentitletype:"greater",
+ opentitletype:true,
boxoffsetHeigh:boxoffsetHeigh
})
}
@@ -219,17 +227,17 @@ class Challengesjupyter extends Component {
{this.state.opentitletype===true?