diff --git a/app/controllers/concerns/git_helper.rb b/app/controllers/concerns/git_helper.rb
index c19c6fdd6..9242b87ac 100644
--- a/app/controllers/concerns/git_helper.rb
+++ b/app/controllers/concerns/git_helper.rb
@@ -23,7 +23,7 @@ module GitHelper
         Rails.logger.info "encoding: #{cd['encoding']} confidence: #{cd['confidence']}"
         # 字符编码问题,GB18030编码识别率不行
         decode_content =
-            if cd["encoding"] == 'GB18030' && cd['confidence'] == 1.0
+            if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8
               content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '})
             else
               content.force_encoding('UTF-8')
diff --git a/app/controllers/exercise_questions_controller.rb b/app/controllers/exercise_questions_controller.rb
index 57116a9e5..bb28fff54 100644
--- a/app/controllers/exercise_questions_controller.rb
+++ b/app/controllers/exercise_questions_controller.rb
@@ -494,20 +494,88 @@ class ExerciseQuestionsController < ApplicationController
   def adjust_score
     ActiveRecord::Base.transaction do
       begin
+        ex_all_scores = @exercise.exercise_questions.pluck(:question_score).sum
         ex_obj_score = @exercise_current_user.objective_score #全部客观题得分
         ex_subj_score = @exercise_current_user.subjective_score < 0.0 ? 0.0 : @exercise_current_user.subjective_score #全部主观题得分
         ex_answers = @exercise_question.exercise_answers.search_answer_users("user_id",@user_id)  #当前用户答案的得分
-        if @exercise_question.question_type == Exercise::COMPLETION  #当为填空题,更新问题的总分,
-          ex_answer_old = ex_answers.score_reviewed.pluck(:score).sum  #每一关的得分总和
-          each_right_score = (@c_score / ex_answers.count.to_f)   #调分后,平均每关的分数
-          new_obj_score = ex_obj_score - ex_answer_old + @c_score
+        if @exercise_question.question_type == Exercise::MULTIPLE
+          if ex_answers.present?   #学生有回答时 取学生的答题得分,否则0分
+            answer_choice_array = []
+            ex_answers.each do |a|
+              if a.try(:exercise_choice).try(:choice_position).present?
+                answer_choice_array.push(a&.exercise_choice&.choice_position) #学生答案的位置
+              end
+            end
+            user_answer_content = answer_choice_array.reject(&:blank?).sort
+            standard_answer = @exercise_question.exercise_standard_answers.pluck(:exercise_choice_id).sort
+            if standard_answer.size == 1  # 老数据需要判断学生答题是否正确, 正确取原题得分,否则是0分
+              standard_answer = standard_answer.first.to_s.split("").map(&:to_i).sort
+              if user_answer_content == standard_answer
+                ex_answer_old = @exercise_question.question_score
+              else
+                ex_answer_old = 0
+              end
+            else # 新多选题只需取第一条答题记录的得分
+              ex_answer_old = ex_answers.first.score > 0 ? ex_answers.first.score : 0
+            end
+            ex_answers.update_all(:score => @c_score)   #所有的正确选项需重新更新
+          else
+            answer_option = {
+              :user_id => @user_id,
+              :exercise_question_id => @exercise_question.id,
+              :score => @c_score,
+              :answer_text => ""
+            }
+            ExerciseAnswer.create(answer_option)
+            ex_answer_old = 0
+          end
+          if ex_obj_score <= 0.0
+            new_obj_score = @c_score
+          else
+            new_obj_score = ex_obj_score - ex_answer_old + @c_score
+          end
+
           total_scores = new_obj_score + ex_subj_score
+          if total_scores < 0.0
+            total_scores = 0.0
+          elsif total_scores > ex_all_scores
+            total_scores = ex_all_scores
+          end
+          ex_scores = {
+            :objective_score => new_obj_score,
+            :score => total_scores
+          }
+          @exercise_current_user.update_attributes(ex_scores)
+
+        elsif @exercise_question.question_type == Exercise::COMPLETION  #当为填空题,更新问题的总分,
+
+          if ex_answers.exists?
+            ex_answer_old = ex_answers.score_reviewed.pluck(:score).sum  #每一关的得分总和
+            each_right_score = (@c_score / ex_answers.count.to_f)   #调分后,平均每关的分数
+            new_obj_score = ex_obj_score - ex_answer_old + @c_score
+            ex_answers.update_all(:score => each_right_score)   #所有的正确选项需重新更新
+          else   #如果学生未答,则创建新的答题记录
+            answer_option = {
+              :user_id => @user_id,
+              :exercise_question_id => @exercise_question.id,
+              :score => @c_score,
+              :answer_text => ""
+            }
+            ExerciseAnswer.create(answer_option)
+            new_obj_score = ex_obj_score + @c_score
+          end
+
+          total_scores = new_obj_score + ex_subj_score
+          if total_scores < 0.0
+            total_scores = 0.0
+          elsif total_scores > ex_all_scores
+            total_scores = ex_all_scores
+          end
           ex_scores = {
               :objective_score => new_obj_score,
               :score => total_scores
           }
           @exercise_current_user.update_attributes(ex_scores)
-          ex_answers.update_all(:score => each_right_score)   #所有的正确选项需重新更新
         elsif @exercise_question.question_type == Exercise::SUBJECTIVE  #当为主观题时
           if ex_answers.exists?
             ex_answers_old_score = ex_answers.first.score > 0.0 ? ex_answers.first.score : 0.0  #原分数小于0,取0
@@ -524,6 +592,11 @@ class ExerciseQuestionsController < ApplicationController
             new_sub_score = ex_subj_score + @c_score
           end
           total_scores = ex_obj_score + new_sub_score
+          if total_scores < 0.0
+            total_scores = 0.0
+          elsif total_scores > ex_all_scores
+            total_scores = ex_all_scores
+          end
           ex_scores = {
               :subjective_score => new_sub_score,
               :score => total_scores
@@ -549,6 +622,11 @@ class ExerciseQuestionsController < ApplicationController
             new_obj_score = @c_score
           end
           total_scores = new_obj_score + ex_subj_score
+          if total_scores < 0.0
+            total_scores = 0.0
+          elsif total_scores > ex_all_scores
+            total_scores = ex_all_scores
+          end
           ex_scores = {
               :objective_score => new_obj_score,
               :score => total_scores
@@ -556,30 +634,33 @@ class ExerciseQuestionsController < ApplicationController
           @exercise_current_user.update_attributes(ex_scores)
         end
         comments = params[:comment]
-        question_comment = @exercise_question.exercise_answer_comments.first
+        question_comment = @exercise_question.exercise_answer_comments&.first
+
         if question_comment.present?
           comment_option = {
-              :comment => comments.present? ? comments : question_comment.comment,
+              :comment => comments,
               :score => @c_score,
-              :exercise_answer_id => ex_answers.present? ? ex_answers.first.id : nil
+              :exercise_answer_id => ex_answers.present? ? ex_answers.first.id : nil,
+              :user_id => current_user.id
           }
           question_comment.update_attributes(comment_option)
           @exercise_comments = question_comment
         else
+          ex_answer_comment_id = @exercise_question.exercise_answers.find_by(user_id: @user_id).try(:id)
           comment_option = {
               :user_id => current_user.id,
               :comment => comments,
               :score => @c_score,
               :exercise_question_id => @exercise_question.id,
               :exercise_shixun_answer_id => @shixun_a_id.present? ? @shixun_a_id : nil,
-              :exercise_answer_id => ex_answers.present? ? ex_answers.first.id : nil
+              :exercise_answer_id => ex_answer_comment_id
           }
           @exercise_comments = ExerciseAnswerComment.new(comment_option)
           @exercise_comments.save
         end
       rescue Exception => e
         uid_logger_error(e.message)
-        tip_exception("没有权限")
+        tip_exception(e.message)
         raise ActiveRecord::Rollback
       end
     end
@@ -703,8 +784,8 @@ class ExerciseQuestionsController < ApplicationController
       normal_status(-1,"用户不存在!")
     elsif @c_score.blank?
       normal_status(-1,"分数不能为空!")
-    elsif @exercise_question.question_type <= Exercise::JUDGMENT
-      normal_status(-1,"选择题/判断题不能调分!")
+    elsif @exercise_question.question_type == Exercise::SINGLE || @exercise_question.question_type == Exercise::JUDGMENT
+      normal_status(-1,"单选题/判断题不能调分!")
     elsif params[:comment].present? && params[:comment].length > 100
       normal_status(-1,"评语不能超过100个字符!")
     else
diff --git a/app/controllers/graduation_tasks_controller.rb b/app/controllers/graduation_tasks_controller.rb
index a159cff59..841b516bb 100644
--- a/app/controllers/graduation_tasks_controller.rb
+++ b/app/controllers/graduation_tasks_controller.rb
@@ -324,7 +324,7 @@ class GraduationTasksController < ApplicationController
     tip_exception("缺少截止时间参数") if params[:end_time].blank?
     tip_exception("截止时间必须晚于当前时间") if params[:end_time] <= strf_time(Time.now)
     tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
-      @course.end_date.present? && params[:end_time] > @course.end_date.end_of_day
+      @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
 
     # ActiveRecord::Base.transaction do
       begin
@@ -401,7 +401,7 @@ class GraduationTasksController < ApplicationController
             tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
             tip_exception("截止时间不能早于发布时间") if params[:publish_time] > params[:end_time]
             tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
-              @course.end_date.present? && params[:end_time] > @course.end_date.end_of_day
+              @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
 
             @task.publish_time = params[:publish_time]
             @task.end_time = params[:end_time]
@@ -414,7 +414,7 @@ class GraduationTasksController < ApplicationController
             tip_exception("截止时间不能为空") if params[:end_time].blank?
             tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
             tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
-              @course.end_date.present? && params[:end_time] > @course.end_date.end_of_day
+              @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
             @task.end_time = params[:end_time]
           end
 
@@ -426,7 +426,7 @@ class GraduationTasksController < ApplicationController
             tip_exception("补交结束时间不能为空") if params[:late_time].blank?
             tip_exception("补交结束时间不能早于截止时间") if params[:late_time] <= @task.end_time
             tip_exception("补交结束时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
-              @course.end_date.present? && params[:late_time] > @course.end_date.end_of_day
+              @course.end_date.present? && params[:late_time] > strf_time(@course.end_date.end_of_day)
             tip_exception("迟交扣分应为正整数") if params[:late_penalty] && params[:late_penalty].to_i < 0
 
             @task.allow_late = true
diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb
index fc5db713f..bf067b389 100644
--- a/app/controllers/myshixuns_controller.rb
+++ b/app/controllers/myshixuns_controller.rb
@@ -271,7 +271,11 @@ class MyshixunsController < ApplicationController
       unless @hide_code || @myshixun.shixun&.vnc_evaluate
         # 远程版本库文件内容
         last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
-        content = params[:content]
+        content = if @myshixun.mirror_name.select {|a| a.include?("MachineLearning") || a.include?("Python")}.present? && params[:content].present?
+                    params[:content].gsub(/\t/, '    ').gsub(/ /, ' ') # 这个不是空格,在windows机器上带来的问题
+                  else
+                    params[:content]
+                  end
         Rails.logger.info("###11222333####{content}")
         Rails.logger.info("###222333####{last_content}")
 
diff --git a/app/controllers/question_banks_controller.rb b/app/controllers/question_banks_controller.rb
index b4e98e05f..60b9a807c 100644
--- a/app/controllers/question_banks_controller.rb
+++ b/app/controllers/question_banks_controller.rb
@@ -264,8 +264,9 @@ class QuestionBanksController < ApplicationController
       #   new_exercise.create_exercise_list
       #   exercise.update_column(:quotes, exercise.quotes+1)
       # end
-      new_exercise if new_exercise.save!
+      new_exercise.save!
       exercise.update_column(:quotes, exercise.quotes+1)
+      new_exercise
     end
   end
 
@@ -292,8 +293,9 @@ class QuestionBanksController < ApplicationController
       #   new_poll.create_polls_list
       #   poll.update_column(:quotes, poll.quotes+1)
       # end
-      new_poll if new_poll.save!
+      new_poll.save!
       poll.update_column(:quotes, poll.quotes+1)
+      new_poll
     end
   end
 
diff --git a/app/controllers/shixun_lists_controller.rb b/app/controllers/shixun_lists_controller.rb
new file mode 100644
index 000000000..e92e857ad
--- /dev/null
+++ b/app/controllers/shixun_lists_controller.rb
@@ -0,0 +1,10 @@
+class ShixunListsController < ApplicationController
+  def index
+    @results = ShixunSearchService.call(search_params)
+  end
+
+  private
+  def search_params
+    params.permit(:keyword, :type, :page, :limit, :order, :type, :status, :diff)
+  end
+end
\ No newline at end of file
diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb
index 490b9e970..8a120d6bd 100644
--- a/app/controllers/shixuns_controller.rb
+++ b/app/controllers/shixuns_controller.rb
@@ -1,6 +1,7 @@
 class ShixunsController < ApplicationController
 	include ShixunsHelper
 	include ApplicationHelper
+	include ElasticsearchAble
 
 	before_action :require_login, :check_auth, except: [:download_file, :index, :menus, :show, :show_right, :ranking_list,
 																											:discusses, :collaborators, :fork_list, :propaedeutics]
@@ -131,8 +132,16 @@ class ShixunsController < ApplicationController
 		offset = (page.to_i - 1) * (limit.to_i)
 		order = params[:order] || "desc"
 		## 搜索关键字创建者、实训名称、院校名称
-		keyword = params[:search].blank? ? "*" : params[:search]
-		@shixuns = Shixun.search keyword, where: {id: @shixuns.pluck(:id)}, order: {"myshixuns_count" => order}, limit: limit, offset: offset
+		keyword = params[:keyword].to_s.strip.presence || '*'
+
+		model_options = {
+			index_name: [Shixun],
+			model_includes: Shixun.searchable_includes
+		}
+		model_options.merge(where: { id: @shixuns.pluck(:id) }).merge(order: {"myshixuns_count" => order}).merge(limit: limit, offset: offset)
+		model_options.merge(default_options)
+		@shixuns = Searchkick.search(keyword, model_options)
+		# @shixuns = Shixun.search keyword, where: {id: @shixuns.pluck(:id)}, order: {"myshixuns_count" => order}, limit: limit, offset: offset
 
 		@total_count = @shixuns.total_count
 	end
diff --git a/app/helpers/exercises_helper.rb b/app/helpers/exercises_helper.rb
index 2c417ea74..98a580ecc 100644
--- a/app/helpers/exercises_helper.rb
+++ b/app/helpers/exercises_helper.rb
@@ -16,18 +16,26 @@ module ExercisesHelper
       end
 
       if q_type <= Exercise::JUDGMENT
-        if answers_content.present?   #学生有回答时
-          answer_choice_array = []
-          answers_content.each do |a|
-            answer_choice_array.push(a.exercise_choice.choice_position)  #学生答案的位置
-          end
-          user_answer_content = answer_choice_array.sort
-          standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort  #该问题的标准答案,可能有多个
-          if user_answer_content == standard_answer  #答案一致,多选或单选才给分,答案不对不给分
-            ques_score = q.question_score
-          else
-            ques_score = 0.0
-          end
+        if answers_content.present?   #学生有回答时,分数已经全部存到exercise_answer 表,所以可以直接取第一个值
+          ques_score = answers_content.first.score
+          ques_score = ques_score < 0 ? 0.0 : ques_score
+          # answer_choice_array = []
+          # answers_content.each do |a|
+          #   answer_choice_array.push(a.exercise_choice.choice_position)  #学生答案的位置
+          # end
+          # user_answer_content = answer_choice_array.sort
+          # standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort  #该问题的标准答案,可能有多个
+          # if q_type == Exercise::MULTIPLE && standard_answer.size == 1 # 老数据的问题
+          #   ques_score = answers_content.first.score
+          # else
+          #
+          # end
+
+          # if user_answer_content == standard_answer  #答案一致,多选或单选才给分,答案不对不给分
+          #   ques_score = q.question_score
+          # else
+          #   ques_score = 0.0
+          # end
         else
           ques_score = 0.0
         end
@@ -58,7 +66,6 @@ module ExercisesHelper
     exercise_sub_status.each do |s|
       sub_answer = s.exercise_answers.search_answer_users("user_id",user_id)  #主观题只有一个回答
       if sub_answer.present? && sub_answer.first.score >= 0.0
-
         if s.question_score <= sub_answer.first.score
           stand_status = 1
         else
@@ -775,22 +782,24 @@ module ExercisesHelper
         user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : nil
       elsif ques_type == 5 || ques_type == 3
         user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : 0.0
-      else
-        if exercise_answers.present?   #判断题和选择题时,
-          answer_choice_array = []
-          exercise_answers.each do |a|
-            answer_choice_array.push(a.exercise_choice.choice_position)  #学生答案的位置
-          end
-          user_answer_content = answer_choice_array.sort
-          standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort  #该问题的标准答案,可能有多个
-          if user_answer_content == standard_answer  #答案一致,多选或单选才给分,答案不对不给分
-            user_score = q.question_score
-          else
-            user_score = 0.0
-          end
-        else
-          user_score = 0.0
-        end
+      else  #选择题,判断题根据第一个记录查分
+        user_score = user_score_pre.present? ? user_score_pre.first.score : 0.0
+
+        # if exercise_answers.present?   #判断题和选择题时,
+        #   answer_choice_array = []
+        #   exercise_answers.each do |a|
+        #     answer_choice_array.push(a.exercise_choice.choice_position)  #学生答案的位置
+        #   end
+        #   user_answer_content = answer_choice_array.sort
+        #   standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort  #该问题的标准答案,可能有多个
+        #   if user_answer_content == standard_answer  #答案一致,多选或单选才给分,答案不对不给分
+        #     user_score = q.question_score
+        #   else
+        #     user_score = 0.0
+        #   end
+        # else
+        #   user_score = 0.0
+        # end
       end
     end
 
diff --git a/app/models/exercise_answer_comment.rb b/app/models/exercise_answer_comment.rb
index 7da0ec4c7..4279ba445 100644
--- a/app/models/exercise_answer_comment.rb
+++ b/app/models/exercise_answer_comment.rb
@@ -3,7 +3,7 @@ class ExerciseAnswerComment < ApplicationRecord
   belongs_to :user
   belongs_to :exercise_question
   belongs_to :exercise_shixun_answer, optional: true
-  belongs_to :exercise_answer,optional: true
+  belongs_to :exercise_answer, optional: true
 
   scope :search_answer_comments, lambda {|name,ids| where("#{name}":ids)}
 end
diff --git a/app/models/searchable/shixun.rb b/app/models/searchable/shixun.rb
index c1584829d..41bc94b04 100644
--- a/app/models/searchable/shixun.rb
+++ b/app/models/searchable/shixun.rb
@@ -51,13 +51,12 @@ module Searchable::Shixun
       visits_count: visits,
       challenges_count: challenges_count,
       study_count: myshixuns_count,
-      description: description
     }
   end
 
   module ClassMethods
     def searchable_includes
-      { user: { user_extension: :school } }
+      [ :shixun_info, user: { user_extension: :school } ]
     end
   end
 end
diff --git a/app/models/subject.rb b/app/models/subject.rb
index 6ecb5ed18..d5ea3f433 100644
--- a/app/models/subject.rb
+++ b/app/models/subject.rb
@@ -46,8 +46,7 @@ class Subject < ApplicationRecord
 
   # 挑战过路径的成员数(金课统计去重后的报名人数)
   def member_count
-    excellent && CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).length > shixuns.pluck(:myshixuns_count).sum ?
-      CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).length : shixuns.pluck(:myshixuns_count).sum
+    excellent ? CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).length : shixuns.pluck(:myshixuns_count).sum
   end
 
   def all_score
diff --git a/app/models/tiding.rb b/app/models/tiding.rb
index d885f93fd..02692085a 100644
--- a/app/models/tiding.rb
+++ b/app/models/tiding.rb
@@ -22,4 +22,9 @@ class Tiding < ApplicationRecord
 
     value
   end
+
+  def anonymous?
+    (container_type == 'StudentWorksScore' && extra.to_i == 3) ||
+      (container_type == 'StudentWorksScoresAppeal' && parent_container_type == 'StudentWork' && tiding_type == 'System')
+  end
 end
\ No newline at end of file
diff --git a/app/services/concerns/elasticsearch_able.rb b/app/services/concerns/elasticsearch_able.rb
index 80ca5467e..015aac29b 100644
--- a/app/services/concerns/elasticsearch_able.rb
+++ b/app/services/concerns/elasticsearch_able.rb
@@ -28,9 +28,11 @@ module ElasticsearchAble
   end
 
   def body_options
-    {
-      min_score: EduSetting.get('es_min_score') || 10
-    }
+    hash = {}
+
+    hash[:min_score] = (EduSetting.get('es_min_score') || 10) if keyword != '*'
+
+    hash
   end
 
   def per_page
diff --git a/app/services/shixun_search_service.rb b/app/services/shixun_search_service.rb
new file mode 100644
index 000000000..911f341f8
--- /dev/null
+++ b/app/services/shixun_search_service.rb
@@ -0,0 +1,56 @@
+class ShixunSearchService < ApplicationService
+  include ElasticsearchAble
+
+  attr_reader :params
+
+  def initialize(params)
+    @params = params
+  end
+
+  def call
+    # 全部实训/我的实训
+    type = params[:type] || "all"
+    # 状态:已发布/未发布
+    status = params[:status] || "all"
+
+    # 超级管理员用户显示所有未隐藏的实训、非管理员显示所有已发布的实训(对本单位公开且未隐藏未关闭)
+    if type == "mine"
+      @shixuns = User.current.shixuns.none_closed
+    else
+      if User.current.admin? || User.current.business?
+        @shixuns = Shixun.none_closed.where(hidden: 0)
+      else
+        none_shixun_ids = ShixunSchool.where("school_id != #{User.current.school_id}").pluck(:shixun_id)
+
+        @shixuns = Shixun.where.not(id: none_shixun_ids).none_closed.where(hidden: 0)
+      end
+    end
+
+    unless status == "all"
+      @shixuns = status == "published" ? @shixuns.where(status: 2) : @shixuns.where(status: [0, 1])
+    end
+
+    ## 筛选 难度
+    if params[:diff].present? && params[:diff].to_i != 0
+      @shixuns = @shixuns.where(trainee: params[:diff])
+    end
+
+    Shixun.search(keyword, search_options)
+  end
+
+  private
+
+  def search_options
+    model_options = {
+      includes: [ :shixun_info, :challenges, :subjects, user: { user_extension: :school } ]
+    }
+    model_options.merge!(where: { id: @shixuns.pluck(:id) })
+    model_options.merge!(order: {"myshixuns_count" => sort_str})
+    model_options.merge!(default_options)
+    model_options
+  end
+
+  def sort_str
+    params[:order] || "desc"
+  end
+end
\ No newline at end of file
diff --git a/app/views/homework_commons/shixuns.json.jbuilder b/app/views/homework_commons/shixuns.json.jbuilder
index bd97f5e8d..79f22e42a 100644
--- a/app/views/homework_commons/shixuns.json.jbuilder
+++ b/app/views/homework_commons/shixuns.json.jbuilder
@@ -1,4 +1,4 @@
-# json.shixun_list @shixuns do |shixun|
+# json.shixun_lists @shixuns do |shixun|
 #   json.shixun_identifier shixun.identifier
 #   json.name shixun.name
 #   json.creator shixun.user&.full_name
diff --git a/app/views/shixun_lists/index.json.jbuilder b/app/views/shixun_lists/index.json.jbuilder
new file mode 100644
index 000000000..d6c651743
--- /dev/null
+++ b/app/views/shixun_lists/index.json.jbuilder
@@ -0,0 +1,22 @@
+json.shixuns_count @results.total_count
+
+json.shixun_list do
+  json.array! @results.with_highlights(multiple: true) do |obj, highlights|
+    json.merge! obj.to_searchable_json
+    json.challenge_names obj.challenges.pluck(:subject)
+
+    # 去除开头标点符号
+    reg = /^[,。?:;‘’!“”—……、]/
+    highlights[:description]&.first&.sub!(reg, '')
+    highlights[:content]&.first&.sub!(reg, '')
+
+    json.title highlights.delete(:name)&.join('...') || obj.searchable_title
+    json.description highlights[:description]&.join('...') || Util.extract_content(obj.description)[0..300]
+
+    json.content highlights
+    json.level level_to_s(obj.trainee)
+    json.subjects obj.subjects.uniq do |subject|
+      json.(subject, :id, :name)
+    end
+  end
+end
\ No newline at end of file
diff --git a/app/views/shixuns/shixun_list.json.jbuilder b/app/views/shixuns/shixun_list.json.jbuilder
index 54ac65a0a..2f1d4905c 100644
--- a/app/views/shixuns/shixun_list.json.jbuilder
+++ b/app/views/shixuns/shixun_list.json.jbuilder
@@ -10,7 +10,7 @@ json.shixun_list do
     # json.description highlights.values[0,5].each { |arr| arr.is_a?(Array) ? arr.join('...') : arr }.join('<br/>')
     json.content highlights
     json.level level_to_s(obj.trainee)
-    json.subjects obj.subjects do |subject|
+    json.subjects obj.subjects.uniq do |subject|
      json.(subject, :id, :name)
    end
   end
diff --git a/app/views/tidings/_tiding.json.jbuilder b/app/views/tidings/_tiding.json.jbuilder
index 959a96ebd..210e5c8f8 100644
--- a/app/views/tidings/_tiding.json.jbuilder
+++ b/app/views/tidings/_tiding.json.jbuilder
@@ -17,8 +17,13 @@ json.homework_type homework_type
 json.time tiding.how_long_time
 json.new_tiding tiding.unread?(@onclick_time)
 
+# 需要系统头像
+show_system_user = tiding.trigger_user_id.zero? ||
+  (tiding.trigger_user_id == 1 && tiding.tiding_type == 'System') ||
+  tiding.anonymous?
+
 json.trigger_user do
-  if tiding.trigger_user_id.zero? || (tiding.trigger_user_id == 1 && tiding.tiding_type == 'System')
+  if show_system_user
     json.id 0
     json.name "系统"
     json.login ""
diff --git a/config/locales/tidings/zh-CN.yml b/config/locales/tidings/zh-CN.yml
index e6e8e676d..21c020d04 100644
--- a/config/locales/tidings/zh-CN.yml
+++ b/config/locales/tidings/zh-CN.yml
@@ -202,6 +202,7 @@
         2_end: "别人对你的匿评发起的申诉申请:%s,审核未通过"
       StudentWork:
         Apply_end: "发起了匿评申诉申请:%s"
+        HomeworkCommon_end: "发起了匿评申诉申请:%s"
         System_end: "有人对你的匿评发起了申诉:%s"
     Department_end: "你选填的二级单位:%s(%s)因不符合规范,已被系统删除.请重新选择"
     Library:
diff --git a/config/routes.rb b/config/routes.rb
index f5c1a54d3..b786862ce 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -174,7 +174,10 @@ Rails.application.routes.draw do
       end
     end
 
+    resources :shixun_lists
+
     resources :shixuns, param: :identifier do
+
       collection do
         get :menus
         get :get_recommend_shixuns
@@ -182,7 +185,7 @@ Rails.application.routes.draw do
         get :get_mirror_script
         post :apply_shixun_mirror
         get :download_file
-        get :shixun_list
+        get :shixun_lists
       end
 
       member do
diff --git a/dump.rdb b/dump.rdb
index bcf064366..9f62f75c7 100644
Binary files a/dump.rdb and b/dump.rdb differ
diff --git a/lib/tasks/public_course_sync.rake b/lib/tasks/public_course_sync.rake
index a22a9f1f8..c26090e81 100644
--- a/lib/tasks/public_course_sync.rake
+++ b/lib/tasks/public_course_sync.rake
@@ -81,8 +81,10 @@ namespace :public_classes do
 
         homework.update_columns(publish_time: publish_time, end_time: end_time, created_at: created_at, updated_at: updated_at)
         homework.homework_detail_manual.update_columns(comment_status: 6, created_at: created_at, updated_at: updated_at)
+        homework.update_homework_work_score
+        homework.update_attribute('calculation_time', end_time)
 
-        homework.student_works.where("work_status !=0 and update_time > '#{end_time}'").update_all(update_time: end_time)
+        # homework.student_works.where("work_status !=0 and update_time > '#{end_time}'").update_all(update_time: end_time)
       end
     when 3
       # 试卷
diff --git a/public/editormd/lib/marked.min.js b/public/editormd/lib/marked.min.js
index 4db085adb..88ec3e856 100644
--- a/public/editormd/lib/marked.min.js
+++ b/public/editormd/lib/marked.min.js
@@ -10,7 +10,5 @@
    out+=this.renderer.em(this.output(cap[2]||cap[1]))   -->
    out+=this.renderer.em(this.output(cap[2]||cap[1]), cap.input)
  */
-(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g,"    ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else{if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else{if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose){loose=next}}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);
-this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:cap[1]==="pre"||cap[1]==="script"||cap[1]==="style",text:cap[0]});continue}if((!bq&&top)&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else{if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else{if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1].charAt(cap[1].length-1)==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text",text:cap[0]});continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else{if(this.options.pedantic){this.rules=inline.pedantic}}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else{if(this.inLink&&/^<\/a>/i.test(cap[0])){this.inLink=false}}src=src.substring(cap[0].length);out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]), cap.input);continue
-}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(this.smartypants(cap[0]));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants){return text}return text.replace(/--/g,"\u2014").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1\u2018").replace(/'/g,"\u2019").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1\u201c").replace(/"/g,"\u201d").replace(/\.{3}/g,"\u2026")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>0.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[i]};cell+=this.renderer.tablecell(this.inline.output(this.token.header[i]),{header:true,align:this.token.align[i]})
-}header+=this.renderer.tablerow(cell);for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];cell="";for(j=0;j<row.length;j++){cell+=this.renderer.tablecell(this.inline.output(row[j]),{header:false,align:this.token.align[j]})}body+=this.renderer.tablerow(cell)}return this.renderer.table(header,body);case"blockquote_start":var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body);case"list_start":var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered);case"list_item_start":var body="";while(this.next().type!=="list_item_end"){body+=this.token.type==="text"?this.parseText():this.tok()}return this.renderer.listitem(body);case"loose_item_start":var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body);case"html":var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html);case"paragraph":return this.renderer.paragraph(this.inline.output(this.token.text));case"text":return this.renderer.paragraph(this.parseText())}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon"){return":"}if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name){return new RegExp(regex,opt)}val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key]}}}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}opt=merge({},marked.defaults,opt||{});var highlight=opt.highlight,tokens,pending,i=0;try{tokens=Lexer.lex(src,opt)}catch(e){return callback(e)}pending=tokens.length;var done=function(err){if(err){opt.highlight=highlight;return callback(err)}var out;try{out=Parser.parse(tokens,opt)}catch(e){err=e}opt.highlight=highlight;return err?callback(err):callback(null,out)};if(!highlight||highlight.length<3){return done()}delete opt.highlight;if(!pending){return done()}for(;i<tokens.length;i++){(function(token){if(token.type!=="code"){return --pending||done()}return highlight(token.text,token.lang,function(err,code){if(err){return done(err)}if(code==null||code===token.text){return --pending||done()}token.text=code;token.escaped=true;--pending||done()})})(tokens[i])}return}try{if(opt){opt=merge({},marked.defaults,opt)}return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occured:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else{if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
+// 0.4.0  /^ *(#{1,6}) ——》/^ *(#{1,6})   去掉了一个空格 TODO 行内公式带_
+!function(e){"use strict";var t={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:d,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ *(#{1,6})*([^\n]+?) *(?:#+ *)?(?:\n+|$)/,nptable:d,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|<![A-Z][\\s\\S]*?>\\n*|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>\\n*|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,table:d,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,text:/^[^\n]+/};function n(e){this.tokens=[],this.tokens.links={},this.options=e||m.defaults,this.rules=t.normal,this.options.pedantic?this.rules=t.pedantic:this.options.gfm&&(this.options.tables?this.rules=t.tables:this.rules=t.gfm)}t._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,t._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,t.def=p(t.def).replace("label",t._label).replace("title",t._title).getRegex(),t.bullet=/(?:[*+-]|\d+\.)/,t.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,t.item=p(t.item,"gm").replace(/bull/g,t.bullet).getRegex(),t.list=p(t.list).replace(/bull/g,t.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+t.def.source+")").getRegex(),t._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",t._comment=/<!--(?!-?>)[\s\S]*?-->/,t.html=p(t.html,"i").replace("comment",t._comment).replace("tag",t._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),t.paragraph=p(t.paragraph).replace("hr",t.hr).replace("heading",t.heading).replace("lheading",t.lheading).replace("tag",t._tag).getRegex(),t.blockquote=p(t.blockquote).replace("paragraph",t.paragraph).getRegex(),t.normal=f({},t),t.gfm=f({},t.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6})+([^\n]+?) *#* *(?:\n+|$)/}),t.gfm.paragraph=p(t.paragraph).replace("(?!","(?!"+t.gfm.fences.source.replace("\\1","\\2")+"|"+t.list.source.replace("\\1","\\3")+"|").getRegex(),t.tables=f({},t.gfm,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/}),t.pedantic=f({},t.normal,{html:p("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:\"[^\"]*\"|'[^']*'|\\s[^'\"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",t._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/}),n.rules=t,n.lex=function(e,t){return new n(t).lex(e)},n.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g,"    ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},n.prototype.token=function(e,n){var r,s,i,l,o,a,h,p,u,c,g,d,f;for(e=e.replace(/^ +$/gm,"");e;)if((i=this.rules.newline.exec(e))&&(e=e.substring(i[0].length),i[0].length>1&&this.tokens.push({type:"space"})),i=this.rules.code.exec(e))e=e.substring(i[0].length),i=i[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",text:this.options.pedantic?i:i.replace(/\n+$/,"")});else if(i=this.rules.fences.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"code",lang:i[2],text:i[3]||""});else if(i=this.rules.heading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"heading",depth:i[1].length,text:i[2]});else if(n&&(i=this.rules.nptable.exec(e))&&(a={type:"table",header:b(i[1].replace(/^ *| *\| *$/g,"")),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3]?i[3].replace(/\n$/,"").split("\n"):[]}).header.length===a.align.length){for(e=e.substring(i[0].length),p=0;p<a.align.length;p++)/^ *-+: *$/.test(a.align[p])?a.align[p]="right":/^ *:-+: *$/.test(a.align[p])?a.align[p]="center":/^ *:-+ *$/.test(a.align[p])?a.align[p]="left":a.align[p]=null;for(p=0;p<a.cells.length;p++)a.cells[p]=b(a.cells[p],a.header.length);this.tokens.push(a)}else if(i=this.rules.hr.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"hr"});else if(i=this.rules.blockquote.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"blockquote_start"}),i=i[0].replace(/^ *> ?/gm,""),this.token(i,n),this.tokens.push({type:"blockquote_end"});else if(i=this.rules.list.exec(e)){for(e=e.substring(i[0].length),g=(l=i[2]).length>1,this.tokens.push({type:"list_start",ordered:g,start:g?+l:""}),r=!1,c=(i=i[0].match(this.rules.item)).length,p=0;p<c;p++)h=(a=i[p]).length,~(a=a.replace(/^ *([*+-]|\d+\.) +/,"")).indexOf("\n ")&&(h-=a.length,a=this.options.pedantic?a.replace(/^ {1,4}/gm,""):a.replace(new RegExp("^ {1,"+h+"}","gm"),"")),this.options.smartLists&&p!==c-1&&(l===(o=t.bullet.exec(i[p+1])[0])||l.length>1&&o.length>1||(e=i.slice(p+1).join("\n")+e,p=c-1)),s=r||/\n\n(?!\s*$)/.test(a),p!==c-1&&(r="\n"===a.charAt(a.length-1),s||(s=r)),f=void 0,(d=/^\[[ xX]\] /.test(a))&&(f=" "!==a[1],a=a.replace(/^\[[ xX]\] +/,"")),this.tokens.push({type:s?"loose_item_start":"list_item_start",task:d,checked:f}),this.token(a,!1),this.tokens.push({type:"list_item_end"});this.tokens.push({type:"list_end"})}else if(i=this.rules.html.exec(e))e=e.substring(i[0].length),this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&("pre"===i[1]||"script"===i[1]||"style"===i[1]),text:i[0]});else if(n&&(i=this.rules.def.exec(e)))e=e.substring(i[0].length),i[3]&&(i[3]=i[3].substring(1,i[3].length-1)),u=i[1].toLowerCase().replace(/\s+/g," "),this.tokens.links[u]||(this.tokens.links[u]={href:i[2],title:i[3]});else if(n&&(i=this.rules.table.exec(e))&&(a={type:"table",header:b(i[1].replace(/^ *| *\| *$/g,"")),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3]?i[3].replace(/(?: *\| *)?\n$/,"").split("\n"):[]}).header.length===a.align.length){for(e=e.substring(i[0].length),p=0;p<a.align.length;p++)/^ *-+: *$/.test(a.align[p])?a.align[p]="right":/^ *:-+: *$/.test(a.align[p])?a.align[p]="center":/^ *:-+ *$/.test(a.align[p])?a.align[p]="left":a.align[p]=null;for(p=0;p<a.cells.length;p++)a.cells[p]=b(a.cells[p].replace(/^ *\| *| *\| *$/g,""),a.header.length);this.tokens.push(a)}else if(i=this.rules.lheading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"heading",depth:"="===i[2]?1:2,text:i[1]});else if(n&&(i=this.rules.paragraph.exec(e)))e=e.substring(i[0].length),this.tokens.push({type:"paragraph",text:"\n"===i[1].charAt(i[1].length-1)?i[1].slice(0,-1):i[1]});else if(i=this.rules.text.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"text",text:i[0]});else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0));return this.tokens};var r={escape:/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:d,tag:"^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>",link:/^!?\[(label)\]\(href(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong:/^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)|^__([^\s])__(?!_)|^\*\*([^\s])\*\*(?!\*)/,em:/^_([^\s][\s\S]*?[^\s_])_(?!_)|^_([^\s_][\s\S]*?[^\s])_(?!_)|^\*([^\s][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*][\s\S]*?[^\s])\*(?!\*)|^_([^\s_])_(?!_)|^\*([^\s*])\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`]?)\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:d,text:/^[\s\S]+?(?=[\\<!\[`*]|\b_| {2,}\n|$)/};function s(e,t){if(this.options=t||m.defaults,this.links=e,this.rules=r.normal,this.renderer=this.options.renderer||new i,this.renderer.options=this.options,!this.links)throw new Error("Tokens array requires a `links` property.");this.options.pedantic?this.rules=r.pedantic:this.options.gfm&&(this.options.breaks?this.rules=r.breaks:this.rules=r.gfm)}function i(e){this.options=e||m.defaults}function l(){}function o(e){this.tokens=[],this.token=null,this.options=e||m.defaults,this.options.renderer=this.options.renderer||new i,this.renderer=this.options.renderer,this.renderer.options=this.options}function a(e,t){return e.replace(t?/&/g:/&(?!#?\w+;)/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function h(e){return e.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi,function(e,t){return"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""})}function p(e,t){return e=e.source||e,t=t||"",{replace:function(t,n){return n=(n=n.source||n).replace(/(^|[^\[])\^/g,"$1"),e=e.replace(t,n),this},getRegex:function(){return new RegExp(e,t)}}}function u(e,t){return c[" "+e]||(/^[^:]+:\/*[^/]*$/.test(e)?c[" "+e]=e+"/":c[" "+e]=e.replace(/[^/]*$/,"")),e=c[" "+e],"//"===t.slice(0,2)?e.replace(/:[\s\S]*/,":")+t:"/"===t.charAt(0)?e.replace(/(:\/*[^/]*)[\s\S]*/,"$1")+t:e+t}r._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,r._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,r._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,r.autolink=p(r.autolink).replace("scheme",r._scheme).replace("email",r._email).getRegex(),r._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,r.tag=p(r.tag).replace("comment",t._comment).replace("attribute",r._attribute).getRegex(),r._label=/(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?/,r._href=/\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f()\\]*\)|[^\s\x00-\x1f()\\])*?)/,r._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,r.link=p(r.link).replace("label",r._label).replace("href",r._href).replace("title",r._title).getRegex(),r.reflink=p(r.reflink).replace("label",r._label).getRegex(),r.normal=f({},r),r.pedantic=f({},r.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link:p(/^!?\[(label)\]\((.*?)\)/).replace("label",r._label).getRegex(),reflink:p(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",r._label).getRegex()}),r.gfm=f({},r.normal,{escape:p(r.escape).replace("])","~|])").getRegex(),url:p(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("email",r._email).getRegex(),_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:p(r.text).replace("]|","~]|").replace("|","|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&'*+/=?^_`{\\|}~-]+@|").getRegex()}),r.breaks=f({},r.gfm,{br:p(r.br).replace("{2,}","*").getRegex(),text:p(r.gfm.text).replace("{2,}","*").getRegex()}),s.rules=r,s.output=function(e,t,n){return new s(t,n).output(e)},s.prototype.output=function(e){for(var t,n,r,i,l,o="";e;)if(l=this.rules.escape.exec(e))e=e.substring(l[0].length),o+=l[1];else if(l=this.rules.autolink.exec(e))e=e.substring(l[0].length),r="@"===l[2]?"mailto:"+(n=a(this.mangle(l[1]))):n=a(l[1]),o+=this.renderer.link(r,null,n);else if(this.inLink||!(l=this.rules.url.exec(e))){if(l=this.rules.tag.exec(e))!this.inLink&&/^<a /i.test(l[0])?this.inLink=!0:this.inLink&&/^<\/a>/i.test(l[0])&&(this.inLink=!1),e=e.substring(l[0].length),o+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(l[0]):a(l[0]):l[0];else if(l=this.rules.link.exec(e))e=e.substring(l[0].length),this.inLink=!0,r=l[2],this.options.pedantic?(t=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(r))?(r=t[1],i=t[3]):i="":i=l[3]?l[3].slice(1,-1):"",r=r.trim().replace(/^<([\s\S]*)>$/,"$1"),o+=this.outputLink(l,{href:s.escapes(r),title:s.escapes(i)}),this.inLink=!1;else if((l=this.rules.reflink.exec(e))||(l=this.rules.nolink.exec(e))){if(e=e.substring(l[0].length),t=(l[2]||l[1]).replace(/\s+/g," "),!(t=this.links[t.toLowerCase()])||!t.href){o+=l[0].charAt(0),e=l[0].substring(1)+e;continue}this.inLink=!0,o+=this.outputLink(l,t),this.inLink=!1}else if(l=this.rules.strong.exec(e))e=e.substring(l[0].length),o+=this.renderer.strong(this.output(l[4]||l[3]||l[2]||l[1]));else if(l=this.rules.em.exec(e))e=e.substring(l[0].length),o+=this.renderer.em(this.output(l[6]||l[5]||l[4]||l[3]||l[2]||l[1]));else if(l=this.rules.code.exec(e))e=e.substring(l[0].length),o+=this.renderer.codespan(a(l[2].trim(),!0));else if(l=this.rules.br.exec(e))e=e.substring(l[0].length),o+=this.renderer.br();else if(l=this.rules.del.exec(e))e=e.substring(l[0].length),o+=this.renderer.del(this.output(l[1]));else if(l=this.rules.text.exec(e))e=e.substring(l[0].length),o+=this.renderer.text(a(this.smartypants(l[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else l[0]=this.rules._backpedal.exec(l[0])[0],e=e.substring(l[0].length),"@"===l[2]?r="mailto:"+(n=a(l[0])):(n=a(l[0]),r="www."===l[1]?"http://"+n:n),o+=this.renderer.link(r,null,n);return o},s.escapes=function(e){return e?e.replace(s.rules._escapes,"$1"):e},s.prototype.outputLink=function(e,t){var n=t.href,r=t.title?a(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,a(e[1]))},s.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},s.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",r=e.length,s=0;s<r;s++)t=e.charCodeAt(s),Math.random()>.5&&(t="x"+t.toString(16)),n+="&#"+t+";";return n},i.prototype.code=function(e,t,n){if(this.options.highlight){var r=this.options.highlight(e,t);null!=r&&r!==e&&(n=!0,e=r)}return t?'<pre><code class="'+this.options.langPrefix+a(t,!0)+'">'+(n?e:a(e,!0))+"</code></pre>\n":"<pre><code>"+(n?e:a(e,!0))+"</code></pre>"},i.prototype.blockquote=function(e){return"<blockquote>\n"+e+"</blockquote>\n"},i.prototype.html=function(e){return e},i.prototype.heading=function(e,t,n){return this.options.headerIds?"<h"+t+' id="'+this.options.headerPrefix+n.toLowerCase().replace(/[^\w]+/g,"-")+'">'+e+"</h"+t+">\n":"<h"+t+">"+e+"</h"+t+">\n"},i.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"},i.prototype.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"</"+r+">\n"},i.prototype.listitem=function(e){return"<li>"+e+"</li>\n"},i.prototype.checkbox=function(e){return"<input "+(e?'checked="" ':"")+'disabled="" type="checkbox"'+(this.options.xhtml?" /":"")+"> "},i.prototype.paragraph=function(e){return"<p>"+e+"</p>\n"},i.prototype.table=function(e,t){return t&&(t="<tbody>"+t+"</tbody>"),"<table>\n<thead>\n"+e+"</thead>\n"+t+"</table>\n"},i.prototype.tablerow=function(e){return"<tr>\n"+e+"</tr>\n"},i.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"</"+n+">\n"},i.prototype.strong=function(e){return"<strong>"+e+"</strong>"},i.prototype.em=function(e){return"<em>"+e+"</em>"},i.prototype.codespan=function(e){return"<code>"+e+"</code>"},i.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"},i.prototype.del=function(e){return"<del>"+e+"</del>"},i.prototype.link=function(e,t,n){if(this.options.sanitize){try{var r=decodeURIComponent(h(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return n}if(0===r.indexOf("javascript:")||0===r.indexOf("vbscript:")||0===r.indexOf("data:"))return n}this.options.baseUrl&&!g.test(e)&&(e=u(this.options.baseUrl,e));try{e=encodeURI(e).replace(/%25/g,"%")}catch(e){return n}var s='<a href="'+a(e)+'"';return t&&(s+=' title="'+t+'"'),s+=">"+n+"</a>"},i.prototype.image=function(e,t,n){this.options.baseUrl&&!g.test(e)&&(e=u(this.options.baseUrl,e));var r='<img src="'+e+'" alt="'+n+'"';return t&&(r+=' title="'+t+'"'),r+=this.options.xhtml?"/>":">"},i.prototype.text=function(e){return e},l.prototype.strong=l.prototype.em=l.prototype.codespan=l.prototype.del=l.prototype.text=function(e){return e},l.prototype.link=l.prototype.image=function(e,t,n){return""+n},l.prototype.br=function(){return""},o.parse=function(e,t){return new o(t).parse(e)},o.prototype.parse=function(e){this.inline=new s(e.links,this.options),this.inlineText=new s(e.links,f({},this.options,{renderer:new l})),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},o.prototype.next=function(){return this.token=this.tokens.pop()},o.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},o.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},o.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,h(this.inlineText.output(this.token.text)));case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,s="",i="";for(n="",e=0;e<this.token.header.length;e++)n+=this.renderer.tablecell(this.inline.output(this.token.header[e]),{header:!0,align:this.token.align[e]});for(s+=this.renderer.tablerow(n),e=0;e<this.token.cells.length;e++){for(t=this.token.cells[e],n="",r=0;r<t.length;r++)n+=this.renderer.tablecell(this.inline.output(t[r]),{header:!1,align:this.token.align[r]});i+=this.renderer.tablerow(n)}return this.renderer.table(s,i);case"blockquote_start":for(i="";"blockquote_end"!==this.next().type;)i+=this.tok();return this.renderer.blockquote(i);case"list_start":i="";for(var l=this.token.ordered,o=this.token.start;"list_end"!==this.next().type;)i+=this.tok();return this.renderer.list(i,l,o);case"list_item_start":for(i="",this.token.task&&(i+=this.renderer.checkbox(this.token.checked));"list_item_end"!==this.next().type;)i+="text"===this.token.type?this.parseText():this.tok();return this.renderer.listitem(i);case"loose_item_start":for(i="";"list_item_end"!==this.next().type;)i+=this.tok();return this.renderer.listitem(i);case"html":return this.renderer.html(this.token.text);case"paragraph":return this.renderer.paragraph(this.inline.output(this.token.text));case"text":return this.renderer.paragraph(this.parseText())}};var c={},g=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function d(){}function f(e){for(var t,n,r=1;r<arguments.length;r++)for(n in t=arguments[r])Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e}function b(e,t){var n=e.replace(/([^\\])\|/g,"$1 |").split(/ +\| */),r=0;if(n.length>t)n.splice(t);else for(;n.length<t;)n.push("");for(;r<n.length;r++)n[r]=n[r].replace(/\\\|/g,"|");return n}function m(e,t,r){if(null==e)throw new Error("marked(): input parameter is undefined or null");if("string"!=typeof e)throw new Error("marked(): input parameter is of type "+Object.prototype.toString.call(e)+", string expected");if(r||"function"==typeof t){r||(r=t,t=null);var s,i,l=(t=f({},m.defaults,t||{})).highlight,h=0;try{s=n.lex(e,t)}catch(e){return r(e)}i=s.length;var p=function(e){if(e)return t.highlight=l,r(e);var n;try{n=o.parse(s,t)}catch(t){e=t}return t.highlight=l,e?r(e):r(null,n)};if(!l||l.length<3)return p();if(delete t.highlight,!i)return p();for(;h<s.length;h++)!function(e){"code"!==e.type?--i||p():l(e.text,e.lang,function(t,n){return t?p(t):null==n||n===e.text?--i||p():(e.text=n,e.escaped=!0,void(--i||p()))})}(s[h])}else try{return t&&(t=f({},m.defaults,t)),o.parse(n.lex(e,t),t)}catch(e){if(e.message+="\nPlease report this to https://github.com/markedjs/marked.",(t||m.defaults).silent)return"<p>An error occurred:</p><pre>"+a(e.message+"",!0)+"</pre>";throw e}}d.exec=d,m.options=m.setOptions=function(e){return f(m.defaults,e),m},m.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new i,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tables:!0,xhtml:!1}},m.defaults=m.getDefaults(),m.Parser=o,m.parser=o.parse,m.Renderer=i,m.TextRenderer=l,m.Lexer=n,m.lexer=n.lex,m.InlineLexer=s,m.inlineLexer=s.output,m.parse=m,"undefined"!=typeof module&&"object"==typeof exports?module.exports=m:"function"==typeof define&&define.amd?define(function(){return m}):e.marked=m}(this||("undefined"!=typeof window?window:global));
diff --git a/public/react/public/index.html b/public/react/public/index.html
index 166760eab..4fd2c4356 100755
--- a/public/react/public/index.html
+++ b/public/react/public/index.html
@@ -34,8 +34,9 @@
         // location.href = './compatibility'
         location.href = '/compatibility.html'  
       }
-      const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
-      if (isMobile) {
+      // const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
+      const isWeiXin = (/MicroMessenger/i.test(navigator.userAgent.toLowerCase()));
+      if (isWeiXin) {
         document.write('<script type="text/javascript" src="/javascripts/wx/jweixin-1.3.0.js"><\/script>');
       }
     </script>
diff --git a/public/react/src/App.js b/public/react/src/App.js
index ddb8de809..9b85acfa8 100644
--- a/public/react/src/App.js
+++ b/public/react/src/App.js
@@ -9,7 +9,7 @@ import {
 	Route,
 	Switch
 } from 'react-router-dom';
-import axios from 'axios';
+
 import '@icedesign/base/dist/ICEDesignBase.css';
 
 import '@icedesign/base/index.scss';
@@ -37,7 +37,7 @@ import {MuiThemeProvider, createMuiTheme} from 'material-ui/styles';
 
 import history from './history';
 
-import {SnackbarHOC, configShareForIndex} from 'educoder'
+import {SnackbarHOC} from 'educoder'
 import {initAxiosInterceptors} from './AppConfig'
 
 
@@ -303,47 +303,7 @@ class App extends Component {
 			mydisplay:true,
 		})
 	};
-	initWXShare = () => {
-		if (window.wx) {
-			const wx = window.wx
-			const url = '/wechats/js_sdk_signature.json'
-			const currentUrl = window.location.href.split('#')[0]
-			// window.encodeURIComponent()
-			axios.post(url, {
-				url: window.__testUrl || currentUrl,
-			}).then((response) => {
-				console.log('got res')
-				const data = response.data;
-				wx.config({
-					debug: false,
-					appId: data.appid,
-					timestamp: data.timestamp,
-					nonceStr: data.noncestr,
-					signature: data.signature,
-					jsApiList: [
-						'onMenuShareTimeline',//
-						'onMenuShareAppMessage',
-						'onMenuShareQQ',
-						'onMenuShareWeibo',
-						'onMenuShareQZone'
 	
-					]
-				});
-				wx.ready(function () {
-					console.log('wx is ready')
-					configShareForIndex('/')
-				});
-				wx.error(function (res) {
-					console.log('wx is error')
-					console.log(res)
-					//alert(res.errMsg);//错误提示
-			
-				});
-			}).catch((error) => {
-				console.log(error)
-			})
-		}
-	}
 	disableVideoContextMenu = () => {
 		window.$( "body" ).on( "mousedown", "video",  function(event) {
 			if(event.which === 3) {
@@ -365,7 +325,6 @@ class App extends Component {
 		});
 
 		initAxiosInterceptors(this.props)
-		this.initWXShare()
 		//
 		// axios.interceptors.response.use((response) => {
 		// 	// console.log("response"+response);
diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js
index 5d2373e84..cc8c7cf5f 100644
--- a/public/react/src/AppConfig.js
+++ b/public/react/src/AppConfig.js
@@ -10,7 +10,7 @@ broadcastChannelOnmessage('refreshPage', () => {
 })
 
 function locationurl(list){
-	debugger
+
   if (window.location.port === "3007") {
 
   } else {
diff --git a/public/react/src/common/Env.js b/public/react/src/common/Env.js
index 283e82c48..c80497509 100644
--- a/public/react/src/common/Env.js
+++ b/public/react/src/common/Env.js
@@ -3,4 +3,6 @@ export function isDev() {
 }
 
 // const isMobile 
-export const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
\ No newline at end of file
+export const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
+
+// const isWeiXin = (/MicroMessenger/i.test(navigator.userAgent.toLowerCase()));
diff --git a/public/react/src/common/util/ShareUtil.js b/public/react/src/common/util/ShareUtil.js
index 24fffbf15..e591effaf 100644
--- a/public/react/src/common/util/ShareUtil.js
+++ b/public/react/src/common/util/ShareUtil.js
@@ -1,4 +1,5 @@
-const host = window.location.host
+import axios from 'axios'
+const host = window.location.protocol + '//' + window.location.host
 const wx = window.wx
 function share(shareData) {
     try {
@@ -11,7 +12,47 @@ function share(shareData) {
         console.log(e)
     }
 }
+const urlDoneMap = {}
+function requestForSignatrue (callback) {
+    const currentUrl = window.location.href.split('#')[0]
 
+    if (window.wx && !urlDoneMap[currentUrl]) {
+        const wx = window.wx
+        const url = '/wechats/js_sdk_signature.json'
+        urlDoneMap[currentUrl] = true
+        // window.encodeURIComponent()
+        axios.post(url, {
+            url: window.__testUrl || currentUrl,
+        }).then((response) => {
+            console.log('got res')
+            const data = response.data;
+            wx.config({
+                debug: false,
+                appId: data.appid,
+                timestamp: data.timestamp,
+                nonceStr: data.noncestr,
+                signature: data.signature,
+                jsApiList: [
+                    'onMenuShareTimeline',//
+                    'onMenuShareAppMessage',
+                    'onMenuShareQQ',
+                    'onMenuShareWeibo',
+                    'onMenuShareQZone'
+                ]
+            });
+            wx.ready(function () {
+                callback && callback()
+            });
+            wx.error(function (res) {
+                console.log('wx is error')
+                console.log(res)
+                //alert(res.errMsg);//错误提示
+            });
+        }).catch((error) => {
+            console.log(error)
+        })
+    }
+}
 /**
     实践课程	平台提供涵盖基础入门、案例实践和创新应用的完整实训项目体系,通过由浅入深的实训路径,帮助学生快速提升实战能力。
     实训项目	覆盖不同专业的IT实验和实训,每周更新,无需配置本机实验环境,随时随地开启企业级真实实训。
@@ -19,60 +60,72 @@ function share(shareData) {
     单个课程和实训	获取课程/实训的简介	该课程或者实训展示的缩略图
 
  */
-export function configShareForIndex (path) {
-    if (!wx) return;
-    var shareData = {
-        title: 'EduCoder - 首页',
-        desc: 'Educoder是一个面向计算机类的互联网IT教育和实战平台,提供企业级工程实训,以实现工程化专业教学的自动化和智能化。高校和企业人员可以在此开展计算机实践性教学活动,将传统的知识传授和时兴的工程实战一体化。',
-        link: host + (path || ''),
-        imgUrl: window.__testImageUrl 
-            || host + '/react/build/images/share_logo_icon.jpg'
-    };
-    share(shareData)
+export function configShareForIndex (path) {  
+    requestForSignatrue(() => {
+        var shareData = {
+            title: 'EduCoder - 首页',
+            desc: 'Educoder是一个面向计算机类的互联网IT教育和实战平台,提供企业级工程实训,以实现工程化专业教学的自动化和智能化。高校和企业人员可以在此开展计算机实践性教学活动,将传统的知识传授和时兴的工程实战一体化。',
+            link: host + (path || ''),
+            imgUrl: window.__testImageUrl 
+                || host + '/react/build/images/share_logo_icon.jpg'
+        };
+        share(shareData)
+    })
 }
 export function configShareForPaths () {
-    if (!wx) return;
-    var shareData = {
-        title: 'EduCoder - 实践课程',
-        desc: '平台提供涵盖基础入门、案例实践和创新应用的完整实训项目体系,通过由浅入深的实训路径,帮助学生快速提升实战能力。',
-        link: `${host}/paths`,
-        imgUrl: window.__testImageUrl 
-            || host + '/react/build/images/share_logo_icon.jpg'
-    };
-    share(shareData)
+    requestForSignatrue(() => {
+        console.log('configShareForPaths', host)
+        var shareData = {
+            title: 'EduCoder - 实践课程',
+            desc: '平台提供涵盖基础入门、案例实践和创新应用的完整实训项目体系,通过由浅入深的实训路径,帮助学生快速提升实战能力。',
+            link: `${host}/paths`,
+            imgUrl: window.__testImageUrl 
+                || host + '/react/build/images/share_logo_icon.jpg'
+        };
+        share(shareData)
+    })
 }
 export function configShareForShixuns () {
-    if (!wx) return;
-    var shareData = {
-        title: 'EduCoder - 实训项目',
-        desc: '覆盖不同专业的IT实验和实训,每周更新,无需配置本机实验环境,随时随地开启企业级真实实训。',
-        link: `${host}/shixuns`,
-        imgUrl: window.__testImageUrl 
-            || host + '/react/build/images/share_logo_icon.jpg'
-    };
-    share(shareData)
+    requestForSignatrue(() => {
+        console.log('configShareForShixuns', host)
+
+        var shareData = {
+            title: 'EduCoder - 实训项目',
+            desc: '覆盖不同专业的IT实验和实训,每周更新,无需配置本机实验环境,随时随地开启企业级真实实训。',
+            link: `${host}/shixuns`,
+            imgUrl: window.__testImageUrl 
+                || host + '/react/build/images/share_logo_icon.jpg'
+        };
+        share(shareData)
+    })
 }
 export function configShareForCourses () {
-    if (!wx) return;
-    var shareData = {
-        title: 'EduCoder - 翻转课堂',
-        desc: '自动评测实训任务,支持技能统计,提供教学活动分析报告,减轻教师和助教的辅导压力,免去作业发布和批改的困扰,实时了解学生学习情况,全面提升教师施教效率和水平。',
-        link: `${host}/courses`,
-        imgUrl: window.__testImageUrl 
-            || host + '/react/build/images/share_logo_icon.jpg'
-    };
-    share(shareData)
+    requestForSignatrue(() => {
+        console.log('configShareForCourses', host)
+
+        var shareData = {
+            title: 'EduCoder - 翻转课堂',
+            desc: '自动评测实训任务,支持技能统计,提供教学活动分析报告,减轻教师和助教的辅导压力,免去作业发布和批改的困扰,实时了解学生学习情况,全面提升教师施教效率和水平。',
+            link: `${host}/courses`,
+            imgUrl: window.__testImageUrl 
+                || host + '/react/build/images/share_logo_icon.jpg'
+        };
+        share(shareData)
+    })
 }
 
 // detail
 export function configShareForCustom (title, desc, path, imgUrl) {
-    if (!wx) return;
-    var shareData = {
-        title: title,
-        desc: desc,
-        link: `${host}/${path}`,
-        imgUrl: imgUrl || window.__testImageUrl 
-            || host + '/react/build/images/share_logo_icon.jpg'
-    };
-    share(shareData)
+    requestForSignatrue(() => {
+        console.log('configShareForCustom', host)
+
+        var shareData = {
+            title: title,
+            desc: desc,
+            link: `${host}/${path}`,
+            imgUrl: imgUrl || window.__testImageUrl 
+                || host + '/react/build/images/share_logo_icon.jpg'
+        };
+        share(shareData)
+    })
 }
diff --git a/public/react/src/context/TPIContextProvider.js b/public/react/src/context/TPIContextProvider.js
index 2d58140e6..ee01c3c72 100644
--- a/public/react/src/context/TPIContextProvider.js
+++ b/public/react/src/context/TPIContextProvider.js
@@ -174,7 +174,7 @@ class TPIContextProvider extends Component {
         }
 		let testPath = ''
 		if (window.location.port == 3007) {
-			testPath = 'http://pre-newweb.educoder.net'
+			testPath = 'http://test-newweb.educoder.net'
 		}
 		// var url = `${testPath}/api/v1/games/${ game.identifier }/cost_time`
 		var url = `${testPath}/api/tasks/${ game.identifier }/cost_time`
diff --git a/public/react/src/modules/courses/ListPageIndex.js b/public/react/src/modules/courses/ListPageIndex.js
index e025004e0..c16959ab9 100644
--- a/public/react/src/modules/courses/ListPageIndex.js
+++ b/public/react/src/modules/courses/ListPageIndex.js
@@ -93,13 +93,13 @@ class ListPageIndex extends Component{
 
   }
   componentDidMount(){
-    console.log("77");
+    // console.log("77");
     var yslGuideone = window.localStorage.getItem('yslGuideone');
-    console.log("78");
-    console.log(yslGuideone);
+    // console.log("78");
+    // console.log(yslGuideone);
     try {
       if (yslGuideone === "true") {
-        console.log("true 字符串");
+        // console.log("true 字符串");
         this.setState({
           yslGuideone:true,
         })
@@ -107,7 +107,7 @@ class ListPageIndex extends Component{
         this.setState({
           yslGuideone:false,
         });
-        console.log("false 字符串");
+        // console.log("false 字符串");
       }
     }catch (e) {
       console.log(e);
@@ -133,8 +133,7 @@ class ListPageIndex extends Component{
      window.localStorage.setItem('yslGuideone', bool);
     try {
       if (bool === "true") {
-        console.log("115");
-        console.log("true 字符串");
+
         this.setState({
           yslGuideone:true,
         })
@@ -142,11 +141,10 @@ class ListPageIndex extends Component{
         this.setState({
           yslGuideone:false,
         });
-        console.log("124");
-        console.log("false 字符串");
+
       }
     }catch (e) {
-      console.log(e);
+      // console.log(e);
       this.setState({
         yslGuideone:false,
       });
diff --git a/public/react/src/modules/courses/coursesPublic/NewShixunModel.js b/public/react/src/modules/courses/coursesPublic/NewShixunModel.js
new file mode 100644
index 000000000..fbb97cbb5
--- /dev/null
+++ b/public/react/src/modules/courses/coursesPublic/NewShixunModel.js
@@ -0,0 +1,555 @@
+import React,{Component} from 'react';
+import { Modal,Checkbox,Select,Input,Tooltip,Spin,Icon,Drawer,Dropdown,Menu,Breadcrumb,Pagination,Button,notification} from "antd";
+import axios from'axios';
+import NoneData from "../coursesPublic/NoneData";
+import './Newshixunmodel.css';
+const Search = Input.Search;
+class NewShixunModel extends Component{
+	constructor(props){
+		super(props)
+		this.state={
+			shixun_list:undefined,
+			shixuns_count:undefined,
+			Grouplist:[],
+			allGrouplist:[{page:1,list:[]}],
+			page:1,
+			type:'all',
+			status:'all',
+			keyword:undefined,
+			order:'desc',
+			diff:0,
+			limit:15,
+		}
+	}
+	componentDidMount() {
+		let{page,type,keyword,order,diff,limit,status}=this.state;
+		this.getdatalist(page,type,status,keyword,order,diff,limit)
+	}
+
+	getdatalist=(page,type,newstatus,keyword,order,diff,limit,pagetype)=>{
+		this.setState({
+			isspinning:true
+		})
+		let status=this.props.statustype===undefined?newstatus:'published';
+		let url="/shixun_lists.json"
+		axios.get(url,{params:{
+				page,
+				type,
+				status,
+				keyword,
+				order,
+				diff,
+				limit
+			}}).then((response) => {
+			if(response.data){
+				if(pagetype===undefined){
+					this.setState({
+						shixun_list:response.data.shixun_list,
+						shixuns_count:response.data.shixuns_count,
+						Grouplist:[],
+						isspinning:false
+					})
+				}else if(pagetype==="pagetype"){
+					this.setState({
+						shixun_list:response.data.shixun_list,
+						shixuns_count:response.data.shixuns_count,
+						isspinning:false
+					})
+				}
+
+			}
+		}).catch((error) => {
+	     this.setState({
+				 isspinning:false
+			 })
+		})
+	}
+
+	DropdownClick=(diff)=>{
+    this.setState({
+			diff:diff
+		})
+		let{page,type,status,keyword,order,limit}=this.state;
+		this.getdatalist(page,type,status,keyword,order,diff,limit)
+	}
+
+	ItsCourse=(item)=>{
+  return <Menu>
+						{item.map((list,key)=>{
+							return(
+								<Menu.Item key={key} id={list.id}>
+										<a target="_blank" href={`/paths/${list.id}`} className={"newshixun500"} title={list.name}>{list.name}</a>
+								</Menu.Item>
+								)
+						})}
+		  	</Menu>
+	}
+
+	getGrouplist=(Grouplist)=>{
+		   let {page,allGrouplist}=this.state;
+	    	let newallGrouplist=allGrouplist;
+				var a=newallGrouplist.find((value,index,arr)=>{
+					return value.page==page
+				});
+
+       if(a!=undefined){
+				 newallGrouplist.map((item,key)=>{
+					 if(item.page===page){
+						 item.list=Grouplist
+					 }
+				 })
+			 }
+
+
+			 let newGrouplist=[];
+
+			newallGrouplist.map((item,key)=>{
+				item.list.map((items,ke)=>{
+					newGrouplist.push(items)
+				})
+			})
+
+
+		this.setState({
+			Grouplist: newGrouplist,
+			allGrouplist:newallGrouplist
+		})
+	}
+
+	PaginationCourse=(pageNumber)=>{
+	  let {allGrouplist}=this.state;
+		let newallGrouplist=allGrouplist;
+		var v=newallGrouplist.find((value,index,arr)=>{
+			return value.page==pageNumber
+		});
+
+		if(v===undefined){
+			newallGrouplist.push({page:pageNumber,list:[]})
+		}
+
+		let{type,status,keyword,order,diff,limit}=this.state;
+		this.getdatalist(pageNumber,type,status,keyword,order,diff,limit,"pagetype")
+		 this.setState({
+			 page:pageNumber,
+			 allGrouplist:newallGrouplist
+		 })
+
+	}
+
+	belongto=(value)=>{
+		this.setState({
+			type:value,
+			keyword:undefined,
+			page:1
+		})
+		let{status,order,diff,limit}=this.state;
+		this.getdatalist(1,value,status,undefined,order,diff,limit)
+	}
+
+	updatedlist=(order)=>{
+
+		if(order==="desc"){
+			this.setState({
+				order:"asc"
+			})
+			let{type,page,status,keyword,diff,limit}=this.state;
+			this.getdatalist(page,type,status,keyword,"asc",diff,limit)
+		}else{
+			this.setState({
+				order:"desc"
+			})
+			let{type,page,status,keyword,diff,limit}=this.state;
+			this.getdatalist(page,type,status,keyword,"desc",diff,limit)
+		}
+
+	}
+
+	setdatafunsval=(e)=>{
+   this.setState({
+		 keyword:e.target.value
+	 })
+	}
+
+	setdatafuns=(value)=>{
+
+		this.setState({
+			keyword:value,
+			type:undefined,
+			page:1,
+			status:'all',
+			order:'desc',
+			diff:0,
+			limit:15,
+		})
+		this.getdatalist(1,undefined,'all',value,'desc',0,15)
+	}
+
+	showNotification = (description, message = "提示", icon) => {
+		const data = {
+			message,
+			description
+		}
+		if (icon) {
+			data.icon = icon;
+		}
+		notification.open(data);
+	}
+	savecouseShixunModal=()=>{
+
+		this.setState({
+			hometypepvisible:true
+		})
+		let {coursesId}=this.props;
+    let{Grouplist}=this.state;
+		if(Grouplist.length===0){
+			this.setState({
+				hometypepvisible:false
+			})
+			this.showNotification("请先选择实训")
+			return
+		}
+
+		if (this.props.chooseShixun) {
+			if(Grouplist.length>1){
+				this.setState({
+					hometypepvisible:false
+				})
+				this.showNotification("试卷选择的实训数不能大于1")
+				return
+			}
+			this.props.chooseShixun(Grouplist)
+			this.setState({
+				hometypepvisible:false
+			})
+			return;
+		}
+
+		if (this.props.pathShixun) {
+			this.setState({
+				hometypepvisible:false
+			})
+			this.props.pathShixun(Grouplist)
+			return;
+		}
+		let url="/courses/"+coursesId+"/homework_commons/create_shixun_homework.json";
+		axios.post(url, {
+				category_id:this.props.category_id===null||this.props.category_id===undefined?undefined:parseInt(this.props.category_id),
+				shixun_ids:Grouplist,
+			}
+		).then((response) => {
+			if(response.data.status===-1){
+				// this.props.showNotification(response.data.message)
+
+			}else{
+				// this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids)
+				this.showNotification("操作成功")
+				this.props.homeworkupdatalists(this.props.Coursename,this.props.page,this.props.order);
+				this.props.hideNewShixunModelType()
+
+			}
+			this.setState({
+				hometypepvisible:false
+			})
+			// category_id: 3
+			// homework_ids: (5) [9171, 9172, 9173, 9174, 9175]
+		}).catch((error) => {
+			console.log(error)
+			this.setState({
+				hometypepvisible:false
+			})
+		})
+	}
+
+	poststatus=(status)=>{
+		this.setState({
+			status:status
+		})
+		let{page,type,keyword,order,diff,limit}=this.state;
+		this.getdatalist(page,type,status,keyword,order,diff,limit)
+	}
+
+	render() {
+
+	  let {diff,Grouplist,status,shixun_list,shixuns_count,page,type,order}=this.state;
+		// let {visible,patheditarry}=this.props;
+    //   console.log(Grouplist)
+		// 	console.log(allGrouplist)
+		const statusmenus=(
+			<Menu className="menus">
+				<Menu.Item>
+					<a className={status==="all"?"color-blue":""} onClick={()=>this.poststatus("all")}>
+						所有
+					</a>
+				</Menu.Item>
+
+				<Menu.Item >
+					<a className={status==="published"?"color-blue":""} onClick={()=>this.poststatus("published")} >
+						已发布
+					</a>
+				</Menu.Item>
+
+				<Menu.Item>
+					<a className={status==="unpublished"?"color-blue":""} onClick={()=>this.poststatus("unpublished")}>
+						未发布
+					</a>
+				</Menu.Item>
+
+			</Menu>
+		);
+		const menus = (
+			<Menu className="menus">
+				<Menu.Item>
+					<a className={diff===0?"color-blue":""} onClick={()=>this.DropdownClick(0)}>
+						所有
+					</a>
+				</Menu.Item>
+
+				<Menu.Item >
+					<a className={diff===1?"color-blue":""} onClick={()=>this.DropdownClick(1)} >
+		         初级
+					</a>
+				</Menu.Item>
+
+				<Menu.Item>
+					<a className={diff===2?"color-blue":""} onClick={()=>this.DropdownClick(2)}>
+					   中级
+					</a>
+				</Menu.Item>
+
+				<Menu.Item>
+					<a className={diff===3?"color-blue":""} onClick={()=>this.DropdownClick(3)}>
+				     高级
+					</a>
+				</Menu.Item>
+
+				<Menu.Item>
+					<a className={diff===4?"color-blue":""} onClick={()=>this.DropdownClick(4)}>
+					   顶级
+					</a>
+				</Menu.Item>
+			</Menu>
+		);
+
+
+
+		return(
+
+			<div>
+				<style>
+					{
+						`body{  overflow: hidden !important; }
+					   .ant-drawer-content{ overflow:auto !important; background: #f5f5f5; }
+					   .yslbottomsj{position: absolute;bottom: -8px;}
+					  `
+					}
+				</style>
+
+				<Drawer
+					placement="bottom"
+					closable={false}
+					destroyOnClose={true}
+					visible={this.props.NewShixunModelType}
+					height={'100%'}
+				>
+					<Spin spinning={this.state.isspinning}>
+					<div className={"clearfix educontent pr"}>
+
+						<div className={"square-list clearfix"}>
+
+							<div className="newshixunheadersear">
+								<div style={{height:"53px"}}></div>
+								<Search
+									style={{ width: "800px"}}
+									className="packinput"
+									placeholder="实训信息 / 院校名称 / 创建者"
+									value={this.state.keyword}
+									enterButton={<span>搜索</span>}
+									onInput={(e)=>this.setdatafunsval(e)}
+									onSearch={ (value)=>this.setdatafuns(value)} />
+							</div>
+
+							 <div className="clearfix font-12 mt30">
+
+								<div className="font-12 ml5 fl">
+
+									<span className="fl color-grey-9 mr20">已选   <span className={"color-blue"}>{Grouplist.length}</span>   个实训</span>
+									<span className="fl color-grey-9 mr20">共   <span className={"color-blue"}>{shixuns_count===undefined?"":shixuns_count}</span>  个实训</span>
+
+									<span className="fl color-grey-9 pointer mr30">
+										<a className={" color-grey-6"} onClick={()=>this.updatedlist(order)}>学习人数</a>
+										<sapn className="relativef ml5 " >
+											<i className={order==="desc"?"iconfont icon-sanjiaoxing-up font-12 ntopsj color-grey-9 color-blue":"iconfont icon-sanjiaoxing-up font-12 ntopsj  color-grey-9"}></i>
+											<i className={order==="asc"?"iconfont icon-sanjiaoxing-down font-12 nyslbottomsj color-grey-9 color-blue":"iconfont icon-sanjiaoxing-down font-12 nyslbottomsj  color-grey-9"}></i>
+										</sapn>
+									</span>
+
+									{this.props.statustype===undefined?<Dropdown overlay={statusmenus}>
+										<a className="ant-dropdown-link  color-grey-6 mr20">
+											{status==='all'?"发布状态":status==='published'?"已发布":status==="unpublished"?"未发布":""}<Icon type="down" className={"color-grey-6"}/>
+										</a>
+									</Dropdown>:""}
+
+									<Dropdown overlay={menus}>
+										<a className="ant-dropdown-link  color-grey-6">
+											{diff===0?"难度":diff===1?"初级":diff===2?"中级":diff===3?"高级":diff===4?"顶级":""}<Icon type="down" className={"color-grey-6"}/>
+										</a>
+									</Dropdown>
+								</div>
+
+								<div className="font-12 alltopiscright ml25 fr">
+									<span className={"fr pointer color-grey-3"}  onClick={()=>this.props.hideNewShixunModelType()}>返回</span>
+									<span className={type==="mine"?"fr mr30 topcsactive pointer color-grey-3 color-blue":"fr mr30 pointer color-grey-3"} onClick={()=>this.belongto("mine")}>我的实训</span>
+									<span className={type==="all"?"fr mr30 topcsactive pointer color-grey-3 color-blue":"fr mr30 pointer color-grey-3"}  onClick={()=>this.belongto("all")}>全部实训</span>
+								</div>
+
+							</div>
+
+							<Checkbox.Group onChange={this.getGrouplist} value={Grouplist} >
+
+							{shixun_list===undefined?"":shixun_list.length===0?"":shixun_list.map((item,key)=>{
+
+							return(
+								<div className="mt20 edu-back-white pd20 relativef newshixunlist" key={key}>
+									<div className="clearfix">
+										<div className="item-body">
+											<div className="clearfix ds pr contentSection">
+												<Checkbox
+													value={item.id}
+													key={item.id}
+													className="fl task-hide edu-txt-left mt3"
+													name="shixun_homework[]"
+												></Checkbox>
+												<a target="_blank" href={`/shixuns/${item.identifier}/challenges`} title={item.title} className="ml15 fl font-16  color-dark maxwidth1100"
+													 dangerouslySetInnerHTML={{__html: item.title}}
+												>
+												</a>
+
+												<div className="cl"></div>
+												<style>
+													{
+														`
+														 .newradioStyles{
+																 overflow: hidden;
+																text-overflow: ellipsis;
+																display: -webkit-box;
+																-webkit-line-clamp: 2;
+																-webkit-box-orient: vertical;
+																max-height: 42px;
+														 }
+														`
+													}
+												</style>
+												{JSON.stringify(item.description) == "{}"?"":<div className="newshixunmodelmidfont newradioStyles" title={item.description}  dangerouslySetInnerHTML={{__html: item.description}}>
+												</div>}
+
+												{item.challenge_names.length===0?"":<div className="newshixunmodelbotfont">
+													{item.challenge_names.map((item,key)=>{
+														return(
+                               <span>第{key+1}关:{item}</span>
+														)
+													})}
+												</div>}
+
+												<div className={"newshixunpd030"}>
+													<div className="xuxianpro"></div>
+												</div>
+
+												<div className="color-grey panel-lightgrey fl ml30">
+													<style>
+														{`
+														.ant-breadcrumb-separator{
+														   color: #D7D7D7 !important;
+														}
+														.panel-lightgrey, .panel-lightgrey span{
+														   color: #999 !important;
+														}
+														.ant-breadcrumb-link{
+														   margin-right:10px !important;
+														}
+														.ant-breadcrumb-separator{
+														   margin-right:20px !important;
+														}
+													`}
+													</style>
+													<Breadcrumb separator="|">
+														<Breadcrumb.Item>{item.author_name}</Breadcrumb.Item>
+														<Breadcrumb.Item>{item.author_school_name}</Breadcrumb.Item>
+														<Breadcrumb.Item>难度系数:{item.level}</Breadcrumb.Item>
+														<Breadcrumb.Item>学习人数:{item.study_count}</Breadcrumb.Item>
+													</Breadcrumb>
+
+												</div>
+												{item.subjects.length===0?"":<Dropdown overlay={()=>this.ItsCourse(item.subjects)}>
+													<a className="ant-dropdown-link fl ml30 newshixunfont12  color-blue" >
+														所属课程<Icon className={"color-blue"} type="down" />
+													</a>
+												</Dropdown>}
+
+											</div>
+										</div>
+									</div>
+								</div>
+							)})
+							}
+							</Checkbox.Group>
+
+							{shixun_list===undefined||shixuns_count===undefined?"":shixun_list.length===0||shixuns_count===0?"":shixuns_count>15?<div className={" edu-txt-center pd303010"}>
+								<Pagination
+									showQuickJumper
+									defaultCurrent={1}
+									pageSize={15}
+								  total={shixuns_count===undefined?"":shixuns_count}
+								  current={page}
+								  onChange={this.PaginationCourse}
+								/>
+							</div>:""}
+							{
+								shixun_list===undefined?
+										<div className={"minhegiht300"}>
+
+										</div>
+								:shixun_list.length===0? <NoneData></NoneData>:""
+							}
+
+							{
+								shixun_list===undefined?"":shixun_list.length===0?"":<div className={" edu-txt-center padding20-30"}>
+								<Button className={"mr20 newshixunmode"} onClick={()=>this.props.hideNewShixunModelType()}>取消</Button>
+								<Button className={"newshixunmode"} type="primary" onClick={()=>this.savecouseShixunModal()} loading={this.state.hometypepvisible}>确定</Button>
+							</div>}
+
+						</div>
+
+					</div>
+					</Spin>
+				</Drawer>
+			</div>
+
+		)
+	}
+}
+
+export default NewShixunModel;
+
+
+// {JSON.stringify(item.content) == "{}"?<div className="newshixunmodelmidfont newradioStyles" title={item.description} dangerouslySetInnerHTML={{__html: item.description}}>
+// </div>:<div className="newshixunmodelbotfont">
+// 	{item.content.description === undefined || item.content.description===0?"":item.content.description.map((item,key)=>{
+// 		return(
+// 			<span dangerouslySetInnerHTML={{__html: item}}>{}</span>
+// 		)
+// 	})}
+// </div>}
+//
+// {JSON.stringify(item.content) == "{}"?item.challenge_names.length===0?"":<div className="newshixunmodelbotfont">
+// 	{item.challenge_names.map((item,key)=>{
+// 		return(
+// 			<span>第{key+1}关:{item}</span>
+// 		)
+// 	})}
+// </div>:<div className="newshixunmodelbotfont">
+// 	{item.content.challenge_names === undefined || item.content.challenge_names===0?"":item.content.challenge_names.map((item,key)=>{
+// 		return(
+// 			<span dangerouslySetInnerHTML={{__html: item}}>{}</span>
+// 		)
+// 	})}
+// </div>}
\ No newline at end of file
diff --git a/public/react/src/modules/courses/coursesPublic/Newshixunmodel.css b/public/react/src/modules/courses/coursesPublic/Newshixunmodel.css
new file mode 100644
index 000000000..2e8abce53
--- /dev/null
+++ b/public/react/src/modules/courses/coursesPublic/Newshixunmodel.css
@@ -0,0 +1,250 @@
+.searchinput{
+    width: 800px;
+    margin-top: 53px;
+}
+.newshixunheadersear{
+    display: flex;
+    justify-content: center;
+}
+.packinput .ant-input{
+    height: 55px;
+    width:663px !important;
+    font-size: 14px;
+    /*color: #681616 !important;*/
+    border-color: #E1EDF8 !important;
+    padding-left: 20px;
+}
+
+.packinput .ant-input-group-addon .ant-btn{
+    width:137px !important;
+    font-size: 18px;
+    height: 53px;
+    background:rgba(76,172,255,1);
+
+}
+.tabtitle{
+    height: 62px !important;
+    box-shadow: 3px 10px 21px 0px rgba(76, 76, 76, 0.15);
+    border-radius: 6px;
+    background: #fff;
+    display: flex;
+    justify-content: center;
+}
+.tabtitles2{
+    background: #fff;
+    height: 62px !important;
+    width: 1200px;
+}
+
+.tabtitless{
+    height: 62px !important;
+    line-height: 62px !important;
+
+}
+.tabtitle1{
+
+}
+.tabtitle2{
+    margin-left: 30px !important;
+
+}
+
+
+.counttit{
+    display: flex;
+    justify-content: center;
+}
+
+.counttittext{
+    text-align: left;
+    width: 1200px;
+    height: 18px;
+    color: #888888;
+    font-size: 13px;
+    margin-top: 24px;
+
+
+}
+.counttittexts{
+    color: #4CACFF !important;
+    font-size: 13px;
+}
+
+.mainx{
+    display: flex;
+    justify-content: center;
+    margin-top: 17px;
+}
+.project-packages-list{
+
+}
+.project-package-item{
+    display: -webkit-flex;
+    display: flex;
+    flex-direction:column;
+    margin-bottom: 20px;
+    padding: 20px;
+    background: white;
+    /* box-shadow: 1px 3px 3px 1px rgba(156,156,156,0.16); */
+
+}
+.xuxianpro{
+    height: 20px;
+    border-bottom: 1px dashed;
+    border-color: #EAEAEA;
+    margin-bottom: 18px;
+}
+.magr11{
+    margin-top: 11px;
+}
+.highlight{
+    color: #4CACFF;
+}
+.fonttext{
+    font-size: 20px;
+    font-weight:bold;
+}
+
+.fontextcolor{
+    color:  #777777;
+}
+.tzbq{
+    margin-left: 68px;
+}
+.tzbqx{
+    /* margin-left: 24px; */
+}
+.bjyss{
+    background: #F8F8F8;
+}
+.zj{
+    overflow:hidden;
+    text-overflow:ellipsis;
+    white-space:nowrap
+}
+.ziticor{
+    color: #777777;
+    font-size: 13px;
+}
+.foohter{
+    margin-top: 20px;
+    display: flex;
+    flex-direction:row;
+}
+
+.maxwidth1100{
+    max-width: 1100px;
+    overflow:hidden;
+    text-overflow:ellipsis;
+    white-space:nowrap;
+    font-size: 18px !important;
+    font-weight: 500;
+    color: rgba(51,51,51,1) !important;
+}
+
+
+.newshixunmodelmidfont{
+    font-size: 14px;
+    font-weight: 400;
+    color: #999999;
+    margin-top: 15px;
+    margin-left: 30px;
+    max-width: 1100px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+}
+
+.newshixunmodelbotfont{
+    font-size:12px;
+    font-weight:400;
+    color:rgba(102,102,102,1);
+    margin-top: 15px;
+    margin-left: 30px;
+}
+
+.newshixunlist{
+    max-height:227px;
+    width: 1200px;
+}
+
+.xuxianpro {
+    height: 20px;
+    border-bottom: 1px dashed;
+    border-color: #eaeaea;
+    margin-bottom: 18px;
+}
+
+.newshixunpd030{
+    padding: 0px 30px;
+}
+
+.pd303010{
+    padding: 30px 30px 10px;
+}
+
+.newshixunfont12{
+    font-size: 12px;
+    color: rgba(76,172,255,1);
+    line-height: 21px;
+}
+
+.newshixunmode{
+    width: 100px;
+    height: 38px;
+    border-radius: 3px;
+    border: 1px solid rgba(191,191,191,1);
+}
+
+.ntopsj {
+    position: absolute;
+    top: -4px;
+}
+
+.nyslbottomsj {
+    position: absolute;
+    bottom: -6px;
+}
+
+.inherits .ant-dropdown-menu-item{
+    cursor: inherit !important;
+}
+
+.menus{
+    width: 91px;
+    text-align: center;
+}
+
+.newshixunmodelbotfont span{
+    display: inline-block;
+    margin-right: 34px;
+}
+
+.minhegiht300{
+    min-height: 300px;
+}
+
+.newshixunlist:hover{
+    box-shadow: 1px 6px 16px rgba(156,156,156,0.16);
+    opacity: 1;
+    border-radius: 2px;
+}
+
+.newshixun500{
+    max-width: 500px;
+    overflow: hidden;
+    -o-text-overflow: ellipsis;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.mt3 {
+    margin-top: 3px !important;
+}
+
+.highlight{
+    color: #4CACFF;
+}
+
diff --git a/public/react/src/modules/courses/coursesPublic/ShixunChooseModal.js b/public/react/src/modules/courses/coursesPublic/ShixunChooseModal.js
index cca75fc86..f4f00e5e0 100644
--- a/public/react/src/modules/courses/coursesPublic/ShixunChooseModal.js
+++ b/public/react/src/modules/courses/coursesPublic/ShixunChooseModal.js
@@ -1,120 +1,122 @@
-import React,{ Component } from "react";
-import { Modal,Checkbox,Select,Input,Tooltip} from "antd";
-import axios from'axios';
-import ShixunModal from './ShixunModal'
-
-const Option = Select.Option;
-const Search = Input.Search;
-class ShixunChooseModal extends Component{
-  constructor(props){
-    super(props);
-    this.state={
-      shixunmodal: false,
-      hometypepvisible: false,
-    }
-  }
-  setVisible = (visible) => {
-    if (visible) {
-      this.createCommonWork()
-    } else {
-      this.setState({ shixunmodal: visible })
-    }
-  }
-  hidecouseShixunModal = () => {
-    this.setVisible(false)
-  }
-  componentDidMount() {
-
-
-  }
-  funshixunmodallist=(search,type,loading,page)=>{
-    let{newshixunmodallist}=this.state;
-    let newshixunmodallists=[]
-    if(page>1){
-      newshixunmodallists=newshixunmodallist;
-    }
-    this.setState({
-      hometypepvisible:loading
-    })
-    let coursesId=this.props.match.params.coursesId;
-    let url = this.props.shixunsUrl || "/courses/"+coursesId+"/homework_commons/shixuns.json";
-
-    axios.get(url, {
-      params: {
-        search: search,
-        type:type,
-        page:page
-      }
-    }).then((result)=>{
-      if(result.status===200){
-
-        let  shixun_list=result.data.shixun_list;
-        for(var i=0; i<shixun_list.length;i++){
-          newshixunmodallists.push(shixun_list[i])
-        }
-        this.setState({
-          shixunmodal:true,
-          shixunmodallist:result.data,
-          newshixunmodallist:newshixunmodallists,
-          hometypepvisible:false
-        })
-      }
-    }).catch((error)=>{
-      console.log(error);
-    })
-  }
-  funpatheditarry=(list)=>{
-    this.setState({
-      patheditarry:list
-    })
-  }
-  createCommonWork=()=>{
-
-    this.setState({
-      hometypepvisible:true,
-      patheditarry:[]
-    })
-
-    let coursesId=this.props.match.params.coursesId;
-    let url = this.props.shixunsUrl || "/courses/"+coursesId+"/homework_commons/shixuns.json";
-
-    axios.get(url).then((result)=>{
-      if(result.status===200){
-        this.setState({
-          shixunmodal:true,
-          shixunmodallist:result.data,
-          hometypepvisible:false,
-          newshixunmodallist:result.data.shixun_list,
-        })
-      }
-    }).catch((error)=>{
-      console.log(error);
-    })
-  }
-  render(){
-     let {Searchvalue,type,category_id, datas, shixunmodal, shixunmodallist
-          , hometypepvisible, newshixunmodallist, patheditarry }=this.state;
-     let {visible}=this.props;
-
-     // console.log(patheditarry)
-    return(
-      <ShixunModal
-        datas={datas}
-        category_id={this.props.match.params.category_id}
-        visible={shixunmodal}
-        shixunmodallist={shixunmodallist}
-        funshixunmodallist={(search,type,loading,page)=>this.funshixunmodallist(search,type,loading,page)}
-        hometypepvisible={hometypepvisible}
-        hidecouseShixunModal={this.hidecouseShixunModal}
-        newshixunmodallist={newshixunmodallist}
-        coursesId={this.props.match.params.coursesId}
-        courseshomeworkstart={(category_id,homework_ids)=> this.props.newhomeworkstart 
-                && this.props.newhomeworkstart(category_id,homework_ids)}
-        funpatheditarry={(patheditarry)=>this.funpatheditarry(patheditarry)}
-        patheditarry={patheditarry}
-        {...this.props}
-      ></ShixunModal>
-    )
-  }
-}
+import React,{ Component } from "react";
+import { Modal,Checkbox,Select,Input,Tooltip} from "antd";
+import axios from'axios';
+import NewShixunModel from '../coursesPublic/NewShixunModel';
+
+const Option = Select.Option;
+const Search = Input.Search;
+class ShixunChooseModal extends Component{
+  constructor(props){
+    super(props);
+    this.state={
+      shixunmodal: false,
+      hometypepvisible: false,
+    }
+  }
+  setVisible = (visible) => {
+    // if (visible) {
+    //   this.createCommonWork()
+    // } else {
+    //
+    // }
+		this.setState({ shixunmodal: visible })
+  }
+  hidecouseShixunModal = () => {
+    this.setVisible(false)
+  }
+  componentDidMount() {
+
+
+  }
+  funshixunmodallist=(search,type,loading,page)=>{
+    let{newshixunmodallist}=this.state;
+    let newshixunmodallists=[]
+    if(page>1){
+      newshixunmodallists=newshixunmodallist;
+    }
+    this.setState({
+      hometypepvisible:loading
+    })
+    let coursesId=this.props.match.params.coursesId;
+    let url = this.props.shixunsUrl || "/courses/"+coursesId+"/homework_commons/shixuns.json";
+
+    axios.get(url, {
+      params: {
+        search: search,
+        type:type,
+        page:page
+      }
+    }).then((result)=>{
+      if(result.status===200){
+
+        let  shixun_list=result.data.shixun_list;
+        for(var i=0; i<shixun_list.length;i++){
+          newshixunmodallists.push(shixun_list[i])
+        }
+        this.setState({
+          shixunmodal:true,
+          shixunmodallist:result.data,
+          newshixunmodallist:newshixunmodallists,
+          hometypepvisible:false
+        })
+      }
+    }).catch((error)=>{
+      console.log(error);
+    })
+  }
+  funpatheditarry=(list)=>{
+    this.setState({
+      patheditarry:list
+    })
+  }
+  createCommonWork=()=>{
+
+    this.setState({
+      hometypepvisible:true,
+      patheditarry:[]
+    })
+
+    let coursesId=this.props.match.params.coursesId;
+    let url = this.props.shixunsUrl || "/courses/"+coursesId+"/homework_commons/shixuns.json";
+
+    axios.get(url).then((result)=>{
+      if(result.status===200){
+        this.setState({
+          shixunmodal:true,
+          shixunmodallist:result.data,
+          hometypepvisible:false,
+          newshixunmodallist:result.data.shixun_list,
+        })
+      }
+    }).catch((error)=>{
+      console.log(error);
+    })
+  }
+  render(){
+     let {Searchvalue,type,category_id, datas, shixunmodal, shixunmodallist
+          , hometypepvisible, newshixunmodallist, patheditarry }=this.state;
+     let {visible}=this.props;
+
+     // console.log(patheditarry)
+    return(
+			shixunmodal===true?<NewShixunModel
+				statustype={'published'}
+        datas={datas}
+        category_id={this.props.match.params.category_id}
+				NewShixunModelType={shixunmodal}
+        shixunmodallist={shixunmodallist}
+        funshixunmodallist={(search,type,loading,page)=>this.funshixunmodallist(search,type,loading,page)}
+        hometypepvisible={hometypepvisible}
+				hideNewShixunModelType={this.hidecouseShixunModal}
+        newshixunmodallist={newshixunmodallist}
+        coursesId={this.props.match.params.coursesId}
+        courseshomeworkstart={(category_id,homework_ids)=> this.props.newhomeworkstart 
+                && this.props.newhomeworkstart(category_id,homework_ids)}
+        funpatheditarry={(patheditarry)=>this.funpatheditarry(patheditarry)}
+        patheditarry={patheditarry}
+        {...this.props}
+      ></NewShixunModel>:""
+    )
+  }
+}
 export default ShixunChooseModal;
\ No newline at end of file
diff --git a/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js b/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js
index 930593c15..f45de9b64 100644
--- a/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js
+++ b/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js
@@ -77,7 +77,9 @@ class ExerciseReviewAndAnswer extends Component{
         exerciseTotalScore:undefined,
 
         // 加载效果
-        isSpin:false
+        isSpin:false,
+        // 调分数组
+        ajustSore:undefined
       }
   }
   componentDidUpdate (prevProps) {
@@ -190,7 +192,23 @@ class ExerciseReviewAndAnswer extends Component{
             user_exercise_status:1,
             Id:result.data.exercise_answer_user.user_id,
             exerciseTotalScore:result.data.exercise_answer_user.score,
-            isSpin:false
+            isSpin:false,
+          })
+          // 先将未批的简答题放入到调分数组中
+          let ajustSore = [];
+          result.data && result.data.exercise_questions.length>0 && result.data.exercise_questions.map((item,key)=>{
+            if( item.question_type == 4 && item.answer_status == 0 ){
+              ajustSore.push({
+                 inputSore:0,
+                 desc:undefined,
+                 id:item.question_id,
+                 position:item.q_position,
+                 setTip:""
+              })
+            }
+          })
+          this.setState({
+            ajustSore
           })
         }
       }).catch((error)=>{
@@ -227,7 +245,7 @@ class ExerciseReviewAndAnswer extends Component{
   }
   scrollToAnchor=(index)=>{
     let name="Anchor_"+index;
-    console.log($("#Anchor_"+index).scrollTop());
+    // console.log($("#Anchor_"+index).scrollTop());
     if (index) {
       // let anchorElement = document.getElementById(name);
       // if(anchorElement) { anchorElement.scrollIntoView(); }
@@ -244,62 +262,115 @@ class ExerciseReviewAndAnswer extends Component{
     )
   }
   // 调分
-  showSetScore=(key,flag,setId)=>{
+  showSetScore=(key,flag,position,type,id)=>{
     this.setState(
       (prevState) => ({ 
         exercise_questions : update(prevState.exercise_questions, {[key]: { setScore: {$set: flag == undefined || flag==false ? true : false}}})
       }),()=>{
-        if (setId && (flag == undefined || flag==false)) {
-          $("html").animate({ scrollTop: $("#Anchor_"+setId).offset().top - 150 })
+        if (position && type && (flag == undefined || flag==false)) {
+          $("#input_"+position+"_"+type).focus();
+          $("html").animate({ scrollTop: $("#Anchor_"+position+"_"+type).offset().top - 150 });
+          if(id){
+            let { ajustSore } = this.state;
+            let obj = ajustSore.filter(obj => obj.id === id).length > 0;
+            if(!obj){
+              ajustSore.push({
+                id,
+                inputSore:0,
+                desc:undefined,
+                position:position,
+                setTip:""
+              })
+            }
+          }
         }
       }
     )
-    this.setState({
-      score:undefined
-    })
+    // this.setState({
+    //   score:undefined
+    // })
   }
 
-  inputScore=(value)=>{
-    
+  inputScore=(value,id)=>{
+    let { ajustSore } = this.state;
+    var index = ajustSore.map(function (item) { return item.id; }).indexOf(id);
     let reg = /^[0-9]+.?[0-9]*$/;
     if(reg.test(value)==false){
-      this.setState({
-        setTip:"请输入数字"
-      })
+      // this.setState({
+      //   setTip:"请输入数字"
+      // })
+      this.setState(
+        (prevState) => ({ 
+          ajustSore : update(prevState.ajustSore, {[index]: { setTip: {$set: "请输入数字"}}})
+        })
+      )
       return;
     }else{
-      this.setState({
-        setTip:"",
-        score:value
-      })
+      // this.setState({
+      //   setTip:"",
+      //   score:value
+      // })
+      this.setState(
+        (prevState) => ({ 
+          ajustSore : update(prevState.ajustSore, {[index]: { inputSore: {$set: value},setTip:{$set: ""}}})
+        })
+      )
     }
   }
-  changeScoreReasons=(e)=>{
-    console.log(e.target.value);
-    this.setState({
-      setScoreReason:e.target.value
-    })
+  changeScoreReasons=(e,id)=>{
+    // console.log(e.target.value);
+    // this.setState({
+    //   setScoreReason:e.target.value
+    // })
+    let value =  e.target.value;
+    let { ajustSore } = this.state;
+    var index = ajustSore.map(function (item) { return item.id; }).indexOf(id);
+    this.setState(
+      (prevState) => ({ 
+        ajustSore : update(prevState.ajustSore, {[index]: { desc: {$set: value}}})
+      })
+    )
   }
 //确认调分
-  setAction=(key,q_id,maxScore)=>{
-    
-    let{ score,setScoreReason ,setTip }=this.state;
+  setAction=(key,q_id,maxScore,oldScore)=>{
+    let {ajustSore}=this.state;
+    let list = ajustSore.filter(obj => obj.id == q_id);
+    let index = ajustSore.map(function (item) { return item.id; }).indexOf(q_id);
+
+    let score = list[0].inputSore;
+    let setScoreReason = list[0].desc;
+    let{ setTip }=this.state;
     if(!score && score != 0){
-      this.setState({
-        setTip:"请输入分数"
-      })
+      // this.setState({
+      //   setTip:"请输入分数"
+      // })
+      this.setState(
+        (prevState) => ({ 
+          ajustSore : update(prevState.ajustSore, {[index]: { setTip: {$set: "请输入分数"}}})
+        })
+      )
       return;
     }
     if(score < 0){
-      this.setState({
-        setTip:"分数必须大于或者等于0"
-      })
+      // this.setState({
+      //   setTip:"分数必须大于或者等于0"
+      // })
+      this.setState(
+        (prevState) => ({ 
+          ajustSore : update(prevState.ajustSore, {[index]: { setTip: {$set: "分数必须大于或者等于0"}}})
+        })
+      )
       return;
     }
     if(score > maxScore){
-      this.setState({
-        setTip:"分数不能大于当前题目的分数"
-      })
+      // this.setState({
+      //   setTip:"分数不能大于当前题目的分数"
+      // })
+      this.setState(
+        (prevState) => ({ 
+          ajustSore : update(prevState.ajustSore, {[index]: { setTip: {$set: "分数不能大于当前题目的分数"}}})
+        })
+      )
       return;
     }
     if(setTip==""){
@@ -311,21 +382,26 @@ class ExerciseReviewAndAnswer extends Component{
       }).then((result)=>{
         if(result.status==200){
           this.props.showNotification('调分成功');
-          console.log(this.state.exercise_questions);
-          let statusScore = score==0 ? 0 : score > 0 && score < maxScore ? 2 : 1;
-          console.log(statusScore);
-          this.setState(
-            (prevState) => ({ 
-              exercise_questions : update(prevState.exercise_questions, {[key]: { user_score: {$set: score},answer_status : {$set: statusScore},question_comments:{$set:result.data.question_comments} }}),
-            })
-          )
-          console.log(this.state.exercise_questions);
-          this.setState({
-            score:undefined,
-            setTip:"",
-            setScoreReason:undefined
-          })
-          this.showSetScore(key,true);
+          this.getInfo();
+          // let statusScore = score==0 ? 0 : score > 0 && score < maxScore ? 2 : 1;
+          
+          // this.setState(
+          //   (prevState) => ({ 
+          //     exercise_questions : update(prevState.exercise_questions, {[key]: { user_score: {$set: parseFloat(score).toFixed(1)},answer_status : {$set: statusScore},question_comments:{$set:result.data.question_comments} }}),
+          //   })
+          // )
+          
+          // this.setState(
+          //   (prevState) => ({ 
+          //     ajustSore : update(prevState.ajustSore, {[index]: { desc: {$set: undefined},inputSore:{ $set:undefined }}})
+          //   })
+          // )
+          // let {exerciseTotalScore} = this.state;
+          // let newScore = parseFloat(parseFloat(exerciseTotalScore)+parseFloat(score)-parseFloat(oldScore)).toFixed(1);
+          // this.setState({
+          //   exerciseTotalScore:newScore
+          // })
+          // this.showSetScore(key,true);
         }
       }).catch((error)=>{
         console.log(error);
@@ -518,12 +594,13 @@ class ExerciseReviewAndAnswer extends Component{
       ModalSave,
       Loadtype,
       exerciseTotalScore,
-      isSpin
+      isSpin,
+      ajustSore
     }=this.state
     let isAdmin = this.props.isAdmin();
     let isStudent =this.props.isStudent();
     const { current_user } = this.props
-    console.log(data&&data.exercise.user_name)
+    // console.log(data&&data.exercise.user_name)
     return(
       <div className="newMain" style={{paddingTop:"0px"}}>
         <Spin size="large" spinning={isSpin}>
@@ -709,6 +786,7 @@ class ExerciseReviewAndAnswer extends Component{
             <div>
               {
                 exercise_questions && exercise_questions.map((item,key)=>{
+                  let list = ajustSore && ajustSore.filter(obj => obj.id === item.question_id);
                   return(
                     <div className="bor-top-greyE pt30 pb30" id={"Anchor_"+parseInt(key+1)}>
                       <p className="clearfix font-16 pl30 pr30">
@@ -716,32 +794,32 @@ class ExerciseReviewAndAnswer extends Component{
                         <span className="fr">
                           {
                             // 填空(一直都有调分),和简答题调分:老师身份 已经评分的才能出现调分按钮
-                            isAdmin && ((parseInt(item.answer_status) != 0 && item.question_type == 4) || item.question_type == 3) ? 
-                            <WordsBtn style="blue" className="mr20 font-16 fl" onClick={()=>this.showSetScore(key,item.setScore,item.q_position+"_"+item.question_type)}>调分</WordsBtn>:""
+                            isAdmin && ((parseInt(item.answer_status) != 0 && item.question_type == 4) || item.question_type == 3 || item.question_type == 1) ? 
+                            <WordsBtn style="blue" className="ml20 font-16 fl" onClick={()=>this.showSetScore(key,item.setScore,item.q_position,item.question_type,item.question_id)}>调分</WordsBtn>:""
                           }
                           {
                             // 简答题,未评分的显示未批
                             isAdmin && parseInt(item.answer_status) == 0 && item.question_type == 4 ? 
-                            <span className="color-red fl mr20">未批</span>:""
+                            <span className="color-red fl ml20">未批</span>:""
                           }
                           {
                             // 客观题:老师||学生(试卷已截止且答案公开)显示正确答案
                             item.question_type < 3 && item.standard_answer_show ?
-                            <span className="font-16 ml20">
+                            <span className="font-16 fl ml20">
                               正确答案:{ item.standard_answer_show }
                             </span>:""
                           }
                           {
                             //(老师身份且除实训题外) || (学生身份且试卷已经截止)就显示用户当前题目所得分数
                           ( isAdmin || (isStudent && exercise.exercise_status == 3)) && item.question_type != 5 && item.user_score ?
-                            <span className="font-16 ml20">
+                            <span className="font-16 ml20 fl">
                               <span><span className={parseInt(item.answer_status) == 0 ?"color-red":parseInt(item.answer_status) == 1 ?"color-green":"color-orange-tip"}>{item.user_score}</span> 分</span>
                             </span> : ""
                           }
                           {
                             //实训题 ,答题
                             item.question_type == 5 &&
-                            <a href={"/shixuns/"+item.shixun_identifier+"/challenges"} target="_blank" class="font-16 color-blue" target={"_blank"}>实训详情</a>
+                            <a href={"/shixuns/"+item.shixun_identifier+"/challenges"} target="_blank" class="font-16 color-blue fl" target={"_blank"}>实训详情</a>
                           }
                         </span>
                       </p>
@@ -825,7 +903,7 @@ class ExerciseReviewAndAnswer extends Component{
                       
                     {
                       //调分理由部分
-                      item.question_comments && item.question_comments.comment && (item.question_type == 3 || item.question_type == 4) && 
+                      item.question_comments && item.question_comments.comment && (item.question_type == 3 || item.question_type == 4 || item.question_type == 1) && 
                       <div className="ml30 mr30 bor-top-greyE pt30 mt20 clearfix df">
                         <img src={getImageUrl(`images/${item.question_comments.user_picture}`)} width="48" height="48" className="radius mr10"/>
                         <div className="flex1">
@@ -839,7 +917,7 @@ class ExerciseReviewAndAnswer extends Component{
                     }
                     {
                       // 调分输入部分
-                      isAdmin && ((item.setScore && item.question_type == 3) || ((item.setScore || parseInt(item.answer_status) == 0) && item.question_type == 4))?
+                      isAdmin && ((item.setScore && item.question_type == 3) || (item.setScore && item.question_type == 1) || ((item.setScore || parseInt(item.answer_status) == 0) && item.question_type == 4))?
                         <div className="ml30 mr30 bor-top-greyE pt20 mt20" id={`${"Anchor_"+item.q_position+"_"+item.question_type}`}>
                           <div className="edu-txt-right">
                             <span><span className="color-red">*</span>调分:</span>
@@ -848,25 +926,26 @@ class ExerciseReviewAndAnswer extends Component{
                                 <InputNumber 
                                   placeholder="请填写分数" 
                                   min={0} 
-                                  max={item.question_score} 
-                                  value={score} 
+                                  // max={item.question_score} 
+                                  value={list && list.length>0 && list[0].inputSore} 
                                   step={0.1} 
                                   precision={1}
-                                  className={ setTip !="" ? "edu-txt-center winput-115-40 fl mt3 noticeTip inputNumber30" : "edu-txt-center winput-115-40 fl mt3 inputNumber30"} 
-                                  onChange={this.inputScore}
+                                  className={ list && list.length>0 && list[0].setTip !="" ? "edu-txt-center winput-115-40 fl mt3 noticeTip inputNumber30" : "edu-txt-center winput-115-40 fl mt3 inputNumber30"} 
+                                  onChange={(value)=>this.inputScore(value,item.question_id)}
+                                  id={`${"input_"+item.q_position+"_"+item.question_type}`}
                                 ></InputNumber>
                                 <span className="ml5">分</span>
                                 {
                                   parseInt(item.answer_status) == 0 && item.question_type == 4 ? <span className="color-red ml10 font-16">未评分</span> : ''
                                 }
-                                <ActionBtn style="blue" className="middle ml20" onClick={()=>this.setAction(key,item.question_id,item.question_score)}>确认</ActionBtn>
+                                <ActionBtn style="blue" className="middle ml20" onClick={()=>this.setAction(key,item.question_id,item.question_score,item.user_score)}>确认</ActionBtn>
                               </p>
                               {
-                                setTip !="" ? <p className="color-red edu-txt-left">{setTip}</p> :""
+                                list && list.length > 0 && list[0].setTip !="" ? <p className="color-red edu-txt-left">{ list[0].setTip }</p> :""
                               }
                             </li>
                           </div>
-                        <Textarea className="winput-100-150 mt20" value={setScoreReason} style={{height:"180px"}} maxLength="100" onChange={this.changeScoreReasons} placeholder="请您输入评语,最大限制100个字符"></Textarea>
+                        <Textarea className="winput-100-150 mt20" value={list && list.length>0 && list[0].desc} style={{height:"180px"}} maxLength="100" onChange={(e)=>this.changeScoreReasons(e,item.question_id)} placeholder="请您输入评语,最大限制100个字符"></Textarea>
                         </div>:""
                       }
                     </div>
diff --git a/public/react/src/modules/courses/shixunHomework/ShixunWorkDetails.js b/public/react/src/modules/courses/shixunHomework/ShixunWorkDetails.js
index 967a6ca61..8254b148e 100644
--- a/public/react/src/modules/courses/shixunHomework/ShixunWorkDetails.js
+++ b/public/react/src/modules/courses/shixunHomework/ShixunWorkDetails.js
@@ -35,10 +35,15 @@ class ShixunWorkDetails extends Component {
 			}
 		}).then((result) => {
 			if (result.status === 200) {
-				this.setState({
-					data:result.data,
-					spinning:false
-				})
+				if (result.data.status === 403 || result.data.status === 401 || result.data.status === 407 || result.data.status === 408|| result.data.status === 409 || result.data.status === 500) {
+
+				}else{
+					this.setState({
+						data:result.data,
+						spinning:false
+					})
+				}
+
 			}
 		}).catch((error) => {
 			console.log(error)
@@ -50,7 +55,33 @@ class ShixunWorkDetails extends Component {
 			shixuntypes:type[3]
 		})
 	}
+  updatas=()=>{
+		this.setState({
+			spinning:true
+		})
+		let homeworkid=this.props.match.params.homeworkid;
+		let userid=this.props.match.params.userid;
+		let url = "/homework_commons/"+homeworkid+"/code_review_detail.json";
+		axios.get(url,{
+			params: {
+				user_id:userid,
+			}
+		}).then((result) => {
+			if (result.status === 200) {
+				if (result.data.status === 403 || result.data.status === 401 || result.data.status === 407 || result.data.status === 408|| result.data.status === 409 || result.data.status === 500) {
 
+				}else{
+					this.setState({
+						data:result.data,
+						spinning:false
+					})
+				}
+
+			}
+		}).catch((error) => {
+			console.log(error)
+		})
+	}
 	goback=(sum)=>{
 		// let{data}=this.state
 		// if(sum===1){
@@ -102,14 +133,18 @@ class ShixunWorkDetails extends Component {
 						<span className="fl color-orange font-14">非编程类型任务,不参与查重</span>
 						<span className="fr mt4">
 							<span className={"color656565"}>被查作品:</span>
-							<span className={"mr20"}>{data&&data.username}</span>
-							<span className={"color-orange"}>{data&&data.final_score}分</span>
+							<span className={"mr50"}><span className={"color-orange"}>{data&&data.username}</span></span>
+							{data&&data.eff_score===null||data&&data.eff_score===undefined||data&&data.eff_score_full===null||data&&data.eff_score_full===undefined?"":<span className={"mr50"}>效率分:<span className={"color-orange"}>{data&&data.eff_score}</span>/{data&&data.eff_score_full}</span>}
+							<span className={""}>最终成绩:<span className={"color-orange"}>{data&&data.final_score}</span>分</span>
 						</span>
 					</div>
 
 					<div className="stud-class-set bor-bottom-greyE">
 						<div className="clearfix edu-back-white poll_list">
 							<ShixunCustomsPass
+								{...this.props}
+								{...this.state}
+								updatas={()=>this.updatas()}
 								data={data}
 							/>
 						</div>
diff --git a/public/react/src/modules/courses/shixunHomework/Shixunworkdetails/ShixunCustomsPass.js b/public/react/src/modules/courses/shixunHomework/Shixunworkdetails/ShixunCustomsPass.js
index 8ffa8a1dd..0b5b04cfc 100644
--- a/public/react/src/modules/courses/shixunHomework/Shixunworkdetails/ShixunCustomsPass.js
+++ b/public/react/src/modules/courses/shixunHomework/Shixunworkdetails/ShixunCustomsPass.js
@@ -1,10 +1,10 @@
 import React, {Component} from "react";
 import {WordsBtn} from 'educoder';
-import {Table} from "antd";
+import {Table,InputNumber} from "antd";
 import {Link,Switch,Route,Redirect} from 'react-router-dom';
 import moment from 'moment';
 import { MonacoDiffEditor } from 'react-monaco-editor';
-
+import axios from 'axios';
 class ShixunCustomsPass extends Component {
 
 	constructor(props) {
@@ -18,10 +18,51 @@ class ShixunCustomsPass extends Component {
 	componentDidMount() {
 
 	}
+	editgame_scores=(e,id,maxsum,code_rate,copy_user_id)=>{
+
+		let{datas}=this.state;
+		let newdatas=datas;
+		let score=e.target.value;
+
+		if(score!=null&&score!=undefined&&score!=""){
+			if(score<0){
+				this.props.showNotification("不能小于0");
+				this.setState({
+					customsids:id
+				})
+			}else if(score>maxsum){
+				this.props.showNotification(`不能大于关卡分值${maxsum}`);
+				this.setState({
+					customsids:id
+				})
+			}else{
+				let work_id=this.props.data.work_id;
+				let url=`/student_works/${work_id}/adjust_review_score.json`
+				axios.post(url,{
+					type:"review",
+					score:score,
+					challenge_id:id,
+					code_rate:code_rate,
+					copy_user_id:copy_user_id
+				}).then((result)=>{
+					if(result.data.status===0){
+						this.props.updatas();
+						this.props.showNotification(result.data.message);
+					}else{
+						this.props.showNotification(result.data.message);
+					}
+				}).catch((error)=>{
 
+				})
+			}
+		}else{
+			this.props.showNotification("调分为空将不会修改之前的分数");
+		}
+	}
 	render() {
 		let {data}=this.props;
-		console.log(data)
+		let {customsids}=this.state;
+		// console.log(data)
     let datas=[];
 
 		data&&data.challenge_list.forEach((item,key)=>{
@@ -33,6 +74,8 @@ class ShixunCustomsPass extends Component {
 				finishtime:item.copy_username,
 				elapsedtime:item.copy_end_time===null?"无":item.copy_end_time===undefined?"无":item.copy_end_time===""?"无":moment(item.copy_end_time).format('YYYY-MM-DD HH:mm:ss'),
 				empvalue:item.code_rate,
+				challenge_id:{id:item.id},
+				copy_user_id:item.copy_user_id
 				// adjustmentminute:asdasd
 			})
 		})
@@ -112,6 +155,22 @@ class ShixunCustomsPass extends Component {
 			render: (text, record) => (
 				<span className={"color-grey-9"}>
 					  {record.elapsedtime}
+        </span>
+			),
+		},{
+			title: '调分',
+			key: 'adjustmentminute',
+			dataIndex: 'adjustmentminute',
+
+			render: (text, record) => (
+				<span>
+			       <a>
+							 {record.copy_user_id===null?"":<InputNumber size="small" className={customsids===record.challenge_id.id?"bor-red":""} defaultValue={record.evaluating.final_score}
+														 onBlur={(e) => this.editgame_scores(e,record.challenge_id.id,record.evaluating.all_score,record.empvalue,record.copy_user_id)}
+							 // min={0} max={record.game_scores.game_score_full}
+							 />}
+			       </a>
+					{/*<a style={{textAlign: "center"}} className="color-blue font-14 mr20">查看</a>*/}
         </span>
 			),
 		}, {
@@ -138,7 +197,15 @@ class ShixunCustomsPass extends Component {
 		// },
 
 
-
+		if(this.props.isAdmin()===false){
+			columns.some((item,key)=> {
+					if (item.title === "调分") {
+						columns.splice(key, 1)
+						return true
+					}
+				}
+			)
+		}
 		return (
 			<div>
 
@@ -177,6 +244,9 @@ class ShixunCustomsPass extends Component {
 					.customsPass{
             text-align: left !important;
 					}
+					.ant-table-thead > tr > th, .ant-table-tbody > tr > td {
+							padding: 16px 12px;
+					}
 			`}
 				</style>
 				{datas===undefined?"":<Table
diff --git a/public/react/src/modules/courses/shixunHomework/shixunHomework.js b/public/react/src/modules/courses/shixunHomework/shixunHomework.js
index a2cd5a938..55dfac7fc 100644
--- a/public/react/src/modules/courses/shixunHomework/shixunHomework.js
+++ b/public/react/src/modules/courses/shixunHomework/shixunHomework.js
@@ -6,6 +6,7 @@ import axios from'axios';
 import HomeworkModal from "../coursesPublic/HomeworkModal";
 import ShixunModal from "../coursesPublic/ShixunModal";
 import PathModal from "../coursesPublic/PathModal";
+import NewShixunModel from '../coursesPublic/NewShixunModel';
 import AddcoursesNav from "../coursesPublic/AddcoursesNav";
 import Modals from '../../modals/Modals';
 import moment from 'moment';
@@ -445,18 +446,18 @@ class ShixunHomework extends Component{
   }
 
 
-  // 选用实训
-  createCommonWork=()=>{
-
-    this.setState({
-      hometypepvisible:true,
-      shixunmodal:true,
-      patheditarry:[],
-			checkBoxValues:[]
-    })
-
-
-  }
+  // // 选用实训
+  // createCommonWork=()=>{
+	//
+  //   this.setState({
+  //     hometypepvisible:true,
+  //     shixunmodal:true,
+  //     patheditarry:[],
+	// 		checkBoxValues:[]
+  //   })
+	//
+	//
+  // }
 
   // 选用实训路径
   createCommonpath=()=>{
@@ -502,9 +503,9 @@ class ShixunHomework extends Component{
   //   }).then((result)=>{
   //     if(result.status===200){
 	//
-  //       let  shixun_list=result.data.shixun_list;
-  //       for(var i=0; i<shixun_list.length;i++){
-  //         newshixunmodallists.push(shixun_list[i])
+  //       let  shixun_lists=result.data.shixun_lists;
+  //       for(var i=0; i<shixun_lists.length;i++){
+  //         newshixunmodallists.push(shixun_lists[i])
   //       }
   //       this.setState({
   //         shixunmodal:true,
@@ -540,9 +541,9 @@ class ShixunHomework extends Component{
   //   }).then((result)=>{
   //     if(result.status===200){
 	//
-  //       let  shixun_list=result.data.subject_list;
-  //       for(var i=0; i<shixun_list.length;i++){
-  //         newshixunmodallists.push(shixun_list[i])
+  //       let  shixun_lists=result.data.subject_list;
+  //       for(var i=0; i<shixun_lists.length;i++){
+  //         newshixunmodallists.push(shixun_lists[i])
   //       }
   //       this.setState({
   //         shixunpath:true,
@@ -896,6 +897,18 @@ class ShixunHomework extends Component{
       this.props.history.push(this.props.current_user.first_category_url);
     }
   }
+ showNewShixunModelType=()=>{
+	 this.setState({
+		 NewShixunModelType:true,
+		 patheditarry:[],
+		 checkBoxValues:[]
+	 })
+ }
+  hideNewShixunModelType=()=>{
+   this.setState({
+		 NewShixunModelType:false
+	 })
+	}
   render(){
     let {
       modalname,
@@ -931,7 +944,7 @@ class ShixunHomework extends Component{
       course_modules,
       shixunpath,
       order,
-			antIcon,
+			NewShixunModelType,
     }=this.state;
 
 		let main_id=this.props.match.params.main_id;
@@ -940,6 +953,23 @@ class ShixunHomework extends Component{
     return(
       <React.Fragment  >
       <div>
+
+				 {/*新版实训model*/}
+				{NewShixunModelType===true?<NewShixunModel
+					{...this.props}
+					{...this.state}
+					category_id={this.props.match.params.category_id}
+					type={'shixuns'}
+					hideNewShixunModelType={()=>this.hideNewShixunModelType()}
+					coursesId={this.props.match.params.coursesId}
+					homeworkupdatalists={(Coursename,page,order)=>this.homeworkupdatalist(Coursename,page,order)}
+					Coursename={Coursename}
+					page={page}
+					order={order}
+					statustype={'published'}
+				/>:""}
+
+
         {/*提示*/}
         {Modalstype&&Modalstype===true?<Modals
           modalsType={this.state.Modalstype}
@@ -973,23 +1003,23 @@ class ShixunHomework extends Component{
           getcourse_groupslist={(id)=>this.getcourse_groupslist(id)}
         />:""}
 
-        {/*选择实训*/}
-        {shixunmodal===true?<ShixunModal
-					{...this.props}
-					{...this.state}
-          datas={datas}
-          category_id={this.props.match.params.category_id}
-          visible={shixunmodal}
-          shixunmodallist={shixunmodallist}
-					homeworkupdatalists={(Coursename,page,order)=>this.homeworkupdatalist(Coursename,page,order)}
-          hometypepvisible={hometypepvisible}
-          hidecouseShixunModal={this.hidecouseShixunModal}
-          newshixunmodallist={newshixunmodallist}
-          coursesId={this.props.match.params.coursesId}
-          courseshomeworkstart={(category_id,homework_ids)=>this.newhomeworkstart(category_id,homework_ids)}
-          funpatheditarry={(patheditarry)=>this.funpatheditarry(patheditarry)}
-          patheditarry={patheditarry}
-        />:""}
+        {/*/!*选择实训*!/*/}
+        {/*{shixunmodal===true?<ShixunModal*/}
+					{/*{...this.props}*/}
+					{/*{...this.state}*/}
+          {/*datas={datas}*/}
+          {/*category_id={this.props.match.params.category_id}*/}
+          {/*visible={shixunmodal}*/}
+          {/*shixunmodallist={shixunmodallist}*/}
+					{/*homeworkupdatalists={(Coursename,page,order)=>this.homeworkupdatalist(Coursename,page,order)}*/}
+          {/*hometypepvisible={hometypepvisible}*/}
+          {/*hidecouseShixunModal={this.hidecouseShixunModal}*/}
+          {/*newshixunmodallist={newshixunmodallist}*/}
+          {/*coursesId={this.props.match.params.coursesId}*/}
+          {/*courseshomeworkstart={(category_id,homework_ids)=>this.newhomeworkstart(category_id,homework_ids)}*/}
+          {/*funpatheditarry={(patheditarry)=>this.funpatheditarry(patheditarry)}*/}
+          {/*patheditarry={patheditarry}*/}
+        {/*/>:""}*/}
 
         {shixunmodal===true||shixunpath===true?<style>
             {
@@ -1051,7 +1081,7 @@ class ShixunHomework extends Component{
                   </span>:
                   <WordsBtn style="blue" onClick={()=>this.editDir(datas&&datas.category_name)} className={"mr30 font-16"}>目录重命名</WordsBtn>:""}
               {this.props.isAdmin()===true?datas&&datas.category_name===undefined||datas&&datas.category_name===null?<WordsBtn style="blue" className="mr30 font-16" onClick={this.createCommonpath}>选用实践课程</WordsBtn>:"":""}
-              {this.props.isAdmin()===true?<a className={"btn colorblue font-16"} onClick={()=>this.createCommonWork()}>选用实训</a>:""}
+              {this.props.isAdmin()===true?<a className={"btn colorblue font-16"} onClick={()=>this.showNewShixunModelType()}>选用实训</a>:""}
             </li>
             </p>
 
diff --git a/public/react/src/modules/page/MainContentContainer.js b/public/react/src/modules/page/MainContentContainer.js
index 8d6153186..50eacdd4b 100644
--- a/public/react/src/modules/page/MainContentContainer.js
+++ b/public/react/src/modules/page/MainContentContainer.js
@@ -391,9 +391,16 @@ class MainContentContainer extends Component {
 		// 		var fileUpdatePromise = this.doFileUpdateRequest(true)
 		// 	});
 		// }
+
+		window.addEventListener("beforeunload", this.beforeunload);
+           
 	}
 	componentWillUnmount() {
 		// window.$(window).off( "unload" )
+		 window.removeEventListener("beforeunload", this.beforeunload);
+	}
+	beforeunload = () => {
+		this.doFileUpdateRequestOnCodeMirrorBlur()
 	}
 	
 
diff --git a/public/react/src/modules/paths/PathDetail/DetailCardsEditAndAdd.js b/public/react/src/modules/paths/PathDetail/DetailCardsEditAndAdd.js
index 87e398888..433146b8c 100644
--- a/public/react/src/modules/paths/PathDetail/DetailCardsEditAndAdd.js
+++ b/public/react/src/modules/paths/PathDetail/DetailCardsEditAndAdd.js
@@ -1,10 +1,11 @@
 import React, { Component } from 'react';
 import {getImageUrl} from 'educoder';
-import {Modal,Input,Checkbox,Tooltip,Spin} from "antd";
+import {Modal,Input,Checkbox,Tooltip,Spin,notification} from "antd";
 import { DragDropContext ,  Draggable, Droppable} from 'react-beautiful-dnd';
 import Modals from '../../modals/Modals';
 import '../ShixunPaths.css';
 import axios from 'axios';
+import NewShixunModel from '../../courses/coursesPublic/NewShixunModel';
 const $ = window.$;
 const Search = Input.Search;
 
@@ -60,36 +61,34 @@ class DetailCardsEditAndAdd extends Component{
     this.setState({
       selectShixun:true,
       patheditarry:[],
-			page:1
     })
-    this.changeTag(0,"");
+    // this.changeTag(0,"");
   }
 
   //关闭选择实训弹框
   cloasShixunBox =()=>{
     this.setState({
       selectShixun:false,
-			page:1,
       patheditarry:[]
     })
   }
-  clickShixunchoose=()=>{
-
-    let{patheditarry,shixuns_listeditlist,shixuns_listedit}=this.state
+	showNotification = (description, message = "提示", icon) => {
+		const data = {
+			message,
+			description
+		}
+		if (icon) {
+			data.icon = icon;
+		}
+		notification.open(data);
+	}
+  clickShixunchoose=(patheditarry)=>{
+
+    let{shixuns_listeditlist,shixuns_listedit}=this.state
 
     let newshixuns_listedit=shixuns_listedit;
     let list=shixuns_listeditlist
 
-    if(patheditarry.length===0){
-      this.setState({
-        Modalstype:true,
-        Modalstopval:'请选择实训',
-        cardsModalsave:this.cardsModalsave
-      })
-
-      return
-    }
-
     let url='/paths/append_to_stage.json'
     axios.post(url,{
       shixun_id:patheditarry
@@ -98,6 +97,19 @@ class DetailCardsEditAndAdd extends Component{
         if(response.data){
           let newshixun_lists=response.data.shixun_lists;
 
+					for(var j=0; j<newshixuns_listedit.length; j++){
+						for(var a=0; a<newshixun_lists.length; a++){
+							if(newshixuns_listedit[j].shixun_id===newshixun_lists[a].shixun_id){
+								// this.setState({
+								//   Modalstype:true,
+								//   Modalstopval:'请勿重复选择'+newshixun_lists[a].shixun_name+'实训',
+								// })
+								this.showNotification('请勿重复选择:'+newshixun_lists[a].shixun_name+'实训')
+								return
+							}
+						}
+					}
+
           for(var z=0; z<newshixun_lists.length; z++){
             newshixuns_listedit.push(newshixun_lists[z]);
           }
@@ -148,38 +160,7 @@ class DetailCardsEditAndAdd extends Component{
     })
   }
 
-  //打开选择实训弹框初始化tag标签和列表
-  changeTag=(id,search)=>{
-
-		this.setState({
-			ChooseShixunListshixun_list:[],
-			page:1,
-			hometypepvisible:true,
-		})
 
-		let pathId=this.props.pathid;
-
-		let url='/paths/'+pathId+'/choose_subject_shixun.json?page='+1
-    if(search!="" && search!=undefined){
-      url+="&search="+search;
-    }
-    if(id!=0){
-      url+="&type="+id;
-    }
-
-    axios.get(encodeURI(url)).then((result)=>{
-      if(result.status===200){
-        this.setState({
-          ChooseShixunList:result.data,
-          hometypepvisible:false,
-          type:id,
-          ChooseShixunListshixun_list:result.data.shixun_list
-        })
-      }
-    }).catch((error)=>{
-      console.log(error);
-    })
-  }
 
   //勾选实训
   shixunhomeworkedit=(list)=>{
@@ -307,57 +288,7 @@ class DetailCardsEditAndAdd extends Component{
   }
 
 
-  contentViewScrolladd=(e)=>{
-  	const {ChooseShixunList}=this.state;
-    //滑动到底判断
-		let newscrollTop=parseInt(e.currentTarget.scrollTop);
-		let allclientHeight=e.currentTarget.clientHeight+newscrollTop;
-
-		if(e.currentTarget.scrollHeight-allclientHeight===0||e.currentTarget.scrollHeight-allclientHeight===1||e.currentTarget.scrollHeight-allclientHeight===-1){
-
-       if(ChooseShixunList.shixun_list.length===0){
-       	return
-			 }else{
-				 // console.log("到达底部");
-				 this.setState({
-					 hometypepvisible:true
-				 })
-				 let pathId=this.props.pathid;
-				 let {search,page,type,ChooseShixunListshixun_list}=this.state;
-				 let newpage=page+1;
-				 let newChooseShixunListshixun_list=ChooseShixunListshixun_list;
-				 let url='/paths/'+pathId+'/choose_subject_shixun.json?page='+newpage
-				 if(search!="" && search!=undefined){
-					 url+="&search="+search;
-				 }
-				 if(type!=0){
-					 url+="&type="+type;
-				 }
-				 axios.get(encodeURI(url)).then((result)=>{
-					 if(result.status===200){
-						 let list =result.data.shixun_list;
-
-						 for(var i=0; i<list.length; i++){
-							 newChooseShixunListshixun_list.push(list[i])
-						 }
-						 this.setState({
-							 ChooseShixunList:result.data,
-							 hometypepvisible:false,
-							 type:type,
-							 search:search,
-							 page:newpage,
-							 ChooseShixunListshixun_list:newChooseShixunListshixun_list
-						 })
-					 }
-				 }).catch((error)=>{
-					 console.log(error);
-				 })
-
-			 }
 
-    }
-
-  }
   onDragEnd (result) {
 
     let {shixuns_listedit,shixuns_listeditlist} =this.state;
@@ -456,99 +387,13 @@ class DetailCardsEditAndAdd extends Component{
               `
                 }
               </style>:""}
+							{selectShixun===true?<NewShixunModel
+							NewShixunModelType={selectShixun}
+							hideNewShixunModelType={this.cloasShixunBox}
+							pathShixun={this.clickShixunchoose}
+							{...this.props}
+						></NewShixunModel>:""}
 
-              <Modal
-                keyboard={false}
-                title="选择实训"
-                visible={selectShixun}
-                closable={false}
-                footer={null}
-                width="840px"
-                destroyOnClose={true}
-              >
-									<Spin spinning={hometypepvisible}  size="large" style={{marginTop:'15%'}}>
-                  <div className="newupload_conbox">
-                    <div className="clearfix mb20 shixun_work_div newshixun_tab_div cdefault" style={{"marginRight":"4px"}} id="shixun_tab_div">
-                      <li className="fl mr5 mt5"> <a onClick={()=>this.changeTag(0,`${search}`)} className={ parseInt(type)===0 ? "active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>全部</a></li>
-                      {
-                        ChooseShixunList && ChooseShixunList.tags.map((item,key)=>{
-                          return(
-                            <li className="fl mr5 mt5" key={key}>
-                              <a onClick={()=>this.changeTag(`${item.tag_id}`,`${search}`)} className={ parseInt(type) === parseInt(item.tag_id) ? "active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>{item.tag_name}</a>
-                            </li>
-                          )
-                        })
-                      }
-
-
-                    </div>
-                    <div className="clearfix mb20" id="shixun_search_form_div">
-                    <span className="fl color-grey-9 font-16 mt3">
-                      <span>共</span>
-                      <span className="color-orange-tip">{ChooseShixunList && ChooseShixunList.shixuns_count}</span>
-                      <span>个实训</span>
-                    </span>
-                      <div className="fr search-new mb0">
-                        <Search
-                          placeholder="请输入创建者或者实训名称进行搜索"
-                          onInput={this.searchNameInput}
-                          onSearch={()=>this.changeTag(`${type}`,`${search}`)}
-													style={{width: '115%'}}
-                        ></Search>
-                      </div>
-                    </div>
-                    <ul className="clearfix greybackHead edu-txt-center" style={{marginBottom: '0px'}}>
-                      <li className="fl with40 paddingleft22">实训名称</li>
-                      <li className="fl with30 edu-txt-left">使用院校</li>
-                      <li className="fl with10">使用人数</li>
-                      <li className="fl with10">评价等级</li>
-                      <li className="fl with10"></li>
-                    </ul>
-
-	                  <style>
-		                  {
-			                  `
-                      .over180{min-height: 180px;max-height: 180px;overflow-y: auto}
-                      `
-		                  }
-	                  </style>
-										{ChooseShixunListshixun_list && ChooseShixunListshixun_list.length===0?"": <div className="over180 pl20 pr20"
-                         onScroll={this.contentViewScrolladd}
-                      >
-                      <Checkbox.Group style={{ width: '100%' }}   onChange={this.shixunhomeworkedit}>
-                        {
-                          ChooseShixunListshixun_list && ChooseShixunListshixun_list.map((item,key)=>{
-                            return(
-                              <div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE" key={key}>
-                                <li className="fl with40">
-                                  <Checkbox
-                                    id={"shixun_input_"+item.shixun_id}
-																		value={item.shixun_id}
-																		key={item.shixun_id}
-                                    className="fl task-hide edu-txt-left"
-                                    style={{"width":"298px"}}
-                                    name="shixun_homework[]"
-                                  >
-                                    <label style={{"textAlign":"left","color":"#05101A"}} className="task-hide color-grey-name" title={item.shixun_name}>{item.shixun_name}</label>
-                                  </Checkbox>
-                                </li>
-                                <li className="fl with30 edu-txt-left task-hide paddingl5">{item.school_users}</li>
-                                <li className="fl with10 paddingl10">{item.myshixuns_count}</li>
-                                <li className="fl with10 color-orange-tip paddingl10">{item.preference}</li>
-                                <li className="fl with10"><a className="color-blue" href={"/shixuns/"+item.identifier+"/challenges"} target="_blank">详情</a></li>
-                              </div>
-                            )
-                          })
-                        }
-                      </Checkbox.Group>
-                    </div>}
-                    <div className="mt20 marginauto clearfix edu-txt-center">
-                      <a className="pop_close task-btn mr30 margin-tp26" onClick={this.cloasShixunBox}>取消</a>
-                      <a className="task-btn task-btn-orange margin-tp26" id="submit_send_shixun"  onClick={this.clickShixunchoose}>确定</a>
-                    </div>
-                  </div>
-                </Spin>
-              </Modal>
             </div>
 
             {/* 可拖拽选择实训列表*/}
@@ -650,4 +495,185 @@ class DetailCardsEditAndAdd extends Component{
     )
   }
 }
-export default DetailCardsEditAndAdd;
\ No newline at end of file
+export default DetailCardsEditAndAdd;
+
+
+
+
+//
+// <Modal
+// 	keyboard={false}
+// 	title="选择实训"
+// 	visible={selectShixun}
+// 	closable={false}
+// 	footer={null}
+// 	width="840px"
+// 	destroyOnClose={true}
+// >
+// 	<Spin spinning={hometypepvisible}  size="large" style={{marginTop:'15%'}}>
+// 		<div className="newupload_conbox">
+// 			<div className="clearfix mb20 shixun_work_div newshixun_tab_div cdefault" style={{"marginRight":"4px"}} id="shixun_tab_div">
+// 				<li className="fl mr5 mt5"> <a onClick={()=>this.changeTag(0,`${search}`)} className={ parseInt(type)===0 ? "active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>全部</a></li>
+// 				{
+// 					ChooseShixunList && ChooseShixunList.tags.map((item,key)=>{
+// 						return(
+// 							<li className="fl mr5 mt5" key={key}>
+// 								<a onClick={()=>this.changeTag(`${item.tag_id}`,`${search}`)} className={ parseInt(type) === parseInt(item.tag_id) ? "active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>{item.tag_name}</a>
+// 							</li>
+// 						)
+// 					})
+// 				}
+//
+//
+// 			</div>
+// 			<div className="clearfix mb20" id="shixun_search_form_div">
+//                     <span className="fl color-grey-9 font-16 mt3">
+//                       <span>共</span>
+//                       <span className="color-orange-tip">{ChooseShixunList && ChooseShixunList.shixuns_count}</span>
+//                       <span>个实训</span>
+//                     </span>
+// 				<div className="fr search-new mb0">
+// 					<Search
+// 						placeholder="请输入创建者或者实训名称进行搜索"
+// 						onInput={this.searchNameInput}
+// 						onSearch={()=>this.changeTag(`${type}`,`${search}`)}
+// 						style={{width: '115%'}}
+// 					></Search>
+// 				</div>
+// 			</div>
+// 			<ul className="clearfix greybackHead edu-txt-center" style={{marginBottom: '0px'}}>
+// 				<li className="fl with40 paddingleft22">实训名称</li>
+// 				<li className="fl with30 edu-txt-left">使用院校</li>
+// 				<li className="fl with10">使用人数</li>
+// 				<li className="fl with10">评价等级</li>
+// 				<li className="fl with10"></li>
+// 			</ul>
+//
+// 			<style>
+// 				{
+// 					`
+//                       .over180{min-height: 180px;max-height: 180px;overflow-y: auto}
+//                       `
+// 				}
+// 			</style>
+// 			{ChooseShixunListshixun_list && ChooseShixunListshixun_list.length===0?"": <div className="over180 pl20 pr20"
+// 																																											onScroll={this.contentViewScrolladd}
+// 			>
+// 				<Checkbox.Group style={{ width: '100%' }}   onChange={this.shixunhomeworkedit}>
+// 					{
+// 						ChooseShixunListshixun_list && ChooseShixunListshixun_list.map((item,key)=>{
+// 							return(
+// 								<div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE" key={key}>
+// 									<li className="fl with40">
+// 										<Checkbox
+// 											id={"shixun_input_"+item.shixun_id}
+// 											value={item.shixun_id}
+// 											key={item.shixun_id}
+// 											className="fl task-hide edu-txt-left"
+// 											style={{"width":"298px"}}
+// 											name="shixun_homework[]"
+// 										>
+// 											<label style={{"textAlign":"left","color":"#05101A"}} className="task-hide color-grey-name" title={item.shixun_name}>{item.shixun_name}</label>
+// 										</Checkbox>
+// 									</li>
+// 									<li className="fl with30 edu-txt-left task-hide paddingl5">{item.school_users}</li>
+// 									<li className="fl with10 paddingl10">{item.myshixuns_count}</li>
+// 									<li className="fl with10 color-orange-tip paddingl10">{item.preference}</li>
+// 									<li className="fl with10"><a className="color-blue" href={"/shixuns/"+item.identifier+"/challenges"} target="_blank">详情</a></li>
+// 								</div>
+// 							)
+// 						})
+// 					}
+// 				</Checkbox.Group>
+// 			</div>}
+// 			<div className="mt20 marginauto clearfix edu-txt-center">
+// 				<a className="pop_close task-btn mr30 margin-tp26" onClick={this.cloasShixunBox}>取消</a>
+// 				<a className="task-btn task-btn-orange margin-tp26" id="submit_send_shixun"  onClick={this.clickShixunchoose}>确定</a>
+// 			</div>
+// 		</div>
+// 	</Spin>
+// </Modal>
+// contentViewScrolladd=(e)=>{
+// 	const {ChooseShixunList}=this.state;
+// 	//滑动到底判断
+// 	let newscrollTop=parseInt(e.currentTarget.scrollTop);
+// 	let allclientHeight=e.currentTarget.clientHeight+newscrollTop;
+//
+// 	if(e.currentTarget.scrollHeight-allclientHeight===0||e.currentTarget.scrollHeight-allclientHeight===1||e.currentTarget.scrollHeight-allclientHeight===-1){
+//
+// 		if(ChooseShixunList.shixun_list.length===0){
+// 			return
+// 		}else{
+// 			// console.log("到达底部");
+// 			this.setState({
+// 				hometypepvisible:true
+// 			})
+// 			let pathId=this.props.pathid;
+// 			let {search,page,type,ChooseShixunListshixun_list}=this.state;
+// 			let newpage=page+1;
+// 			let newChooseShixunListshixun_list=ChooseShixunListshixun_list;
+// 			let url='/paths/'+pathId+'/choose_subject_shixun.json?page='+newpage
+// 			if(search!="" && search!=undefined){
+// 				url+="&search="+search;
+// 			}
+// 			if(type!=0){
+// 				url+="&type="+type;
+// 			}
+// 			axios.get(encodeURI(url)).then((result)=>{
+// 				if(result.status===200){
+// 					let list =result.data.shixun_list;
+//
+// 					for(var i=0; i<list.length; i++){
+// 						newChooseShixunListshixun_list.push(list[i])
+// 					}
+// 					this.setState({
+// 						ChooseShixunList:result.data,
+// 						hometypepvisible:false,
+// 						type:type,
+// 						search:search,
+// 						page:newpage,
+// 						ChooseShixunListshixun_list:newChooseShixunListshixun_list
+// 					})
+// 				}
+// 			}).catch((error)=>{
+// 				console.log(error);
+// 			})
+//
+// 		}
+//
+// 	}
+//
+// }
+//
+// //打开选择实训弹框初始化tag标签和列表
+// changeTag=(id,search)=>{
+//
+// 	this.setState({
+// 		ChooseShixunListshixun_list:[],
+// 		page:1,
+// 		hometypepvisible:true,
+// 	})
+//
+// 	let pathId=this.props.pathid;
+//
+// 	let url='/paths/'+pathId+'/choose_subject_shixun.json?page='+1
+// 	if(search!="" && search!=undefined){
+// 		url+="&search="+search;
+// 	}
+// 	if(id!=0){
+// 		url+="&type="+id;
+// 	}
+//
+// 	axios.get(encodeURI(url)).then((result)=>{
+// 		if(result.status===200){
+// 			this.setState({
+// 				ChooseShixunList:result.data,
+// 				hometypepvisible:false,
+// 				type:id,
+// 				ChooseShixunListshixun_list:result.data.shixun_list
+// 			})
+// 		}
+// 	}).catch((error)=>{
+// 		console.log(error);
+// 	})
+// }
\ No newline at end of file
diff --git a/public/react/src/modules/paths/PathDetail/DetailCardsEditAndEdit.js b/public/react/src/modules/paths/PathDetail/DetailCardsEditAndEdit.js
index e52ad0ad6..3d1559797 100644
--- a/public/react/src/modules/paths/PathDetail/DetailCardsEditAndEdit.js
+++ b/public/react/src/modules/paths/PathDetail/DetailCardsEditAndEdit.js
@@ -1,8 +1,9 @@
 import React, { Component } from 'react';
 import {getImageUrl} from 'educoder';
-import {Modal,Input,Checkbox,Tooltip,Spin} from "antd";
+import {Modal,Input,Checkbox,Tooltip,Spin,notification} from "antd";
 import { DragDropContext,Draggable, Droppable} from 'react-beautiful-dnd';
 import Modals from '../../modals/Modals';
+import NewShixunModel from '../../courses/coursesPublic/NewShixunModel';
 import '../ShixunPaths.css';
 import axios from 'axios';
 const $ = window.$;
@@ -63,7 +64,7 @@ class DetailCardsEditAndEdit extends Component{
       selectShixun:true,
       patheditarry:[]
     })
-    this.changeTag(0,"");
+    // this.changeTag(0,"");
   }
   //关闭选择实训弹框
   cloasShixunBox =()=>{
@@ -79,36 +80,7 @@ class DetailCardsEditAndEdit extends Component{
     })
   }
 
-  //打开选择实训弹框初始化tag标签和列表
-  changeTag(id,search){
 
-    this.setState({
-			ChooseShixunListshixun_list:[],
-			page:1,
-      hometypepvisible:true
-    })
-    let pathId=this.props.pathid;
-    let url='/paths/'+pathId+'/choose_subject_shixun.json?page='+1
-    if(search!="" && search!=undefined){
-      url+="&search="+search;
-    }
-    if(id!=0){
-      url+="&type="+id;
-    }
-    axios.get(encodeURI(url)).then((result)=>{
-      if(result.status===200){
-        this.setState({
-          ChooseShixunList:result.data,
-          hometypepvisible:false,
-          type:id,
-          search:search,
-          ChooseShixunListshixun_list:result.data.shixun_list
-        })
-      }
-    }).catch((error)=>{
-      console.log(error);
-    })
-  }
 
   shixunhomeworkedit=(list)=>{
 
@@ -158,22 +130,12 @@ class DetailCardsEditAndEdit extends Component{
 
   }
 
-  clickShixunchoose=()=>{
+  clickShixunchoose=(patheditarry)=>{
 
-    let{patheditarry,shixuns_listedit,shixuns_listeditlist}=this.state
+    let{shixuns_listedit,shixuns_listeditlist}=this.state
     let newshixuns_listedit=shixuns_listedit;
     let list=shixuns_listeditlist
 
-    if(patheditarry.length===0){
-      this.setState({
-        Modalstype:true,
-        Modalstopval:'请选择实训',
-
-      })
-
-      return
-    }
-
     let url='/paths/append_to_stage.json'
     axios.post(url,{
       shixun_id:patheditarry
@@ -184,10 +146,11 @@ class DetailCardsEditAndEdit extends Component{
       for(var j=0; j<newshixuns_listedit.length; j++){
         for(var a=0; a<newshixun_lists.length; a++){
           if(newshixuns_listedit[j].shixun_id===newshixun_lists[a].shixun_id){
-            this.setState({
-              Modalstype:true,
-              Modalstopval:'请勿重复选择'+newshixun_lists[a].shixun_name+'实训',
-            })
+            // this.setState({
+            //   Modalstype:true,
+            //   Modalstopval:'请勿重复选择'+newshixun_lists[a].shixun_name+'实训',
+            // })
+						this.showNotification('请勿重复选择:'+newshixun_lists[a].shixun_name+'实训')
             return
           }
         }
@@ -338,69 +301,16 @@ class DetailCardsEditAndEdit extends Component{
     })
   }
 
-  contentViewScrolledit=(e)=>{
-    //滑动到底判断
-		const {ChooseShixunList}=this.state;
-		let newscrollTop=parseInt(e.currentTarget.scrollTop);
-		let allclientHeight=e.currentTarget.clientHeight+newscrollTop;
-
-		if(e.currentTarget.scrollHeight-allclientHeight===0||e.currentTarget.scrollHeight-allclientHeight===1||e.currentTarget.scrollHeight-allclientHeight===-1){
-
-			if(ChooseShixunList.shixun_list.length===0){
-				return
-			}else{
-				this.setState({
-					hometypepvisible:true
-				})
-				// console.log("到达底部");
-
-				let {page,type,search,ChooseShixunListshixun_list}=this.state;
-
-				let newpage=page+1;
-
-				let pathId=this.props.pathid;
-
-				let newChooseShixunListshixun_list=ChooseShixunListshixun_list;
-
-				let url='/paths/'+pathId+'/choose_subject_shixun.json?page='+newpage
-
-				if(search!="" && search!=undefined){
-					url+="&search="+search;
-				}
-
-				if(type!=0){
-					url+="&type="+type;
-				}
-				axios.get(encodeURI(url)).then((result)=>{
-					if(result.status===200){
-
-						let list =result.data.shixun_list;
-
-						for(var i=0; i<list.length; i++){
-							newChooseShixunListshixun_list.push(list[i])
-						}
-						this.setState({
-							ChooseShixunList:result.data,
-							hometypepvisible:false,
-							type:type,
-							page:newpage,
-							search:search,
-							ChooseShixunListshixun_list:newChooseShixunListshixun_list
-						})
-					}
-				}).catch((error)=>{
-					console.log(error);
-				})
-
-
-			}
-
-
-
-    }
-
-  }
-
+	showNotification = (description, message = "提示", icon) => {
+		const data = {
+			message,
+			description
+		}
+		if (icon) {
+			data.icon = icon;
+		}
+		notification.open(data);
+	}
 
   render(){
     let {selectShixun,
@@ -483,99 +393,13 @@ class DetailCardsEditAndEdit extends Component{
                 }
               </style>:""}
 
+							{selectShixun===true?<NewShixunModel
+								NewShixunModelType={selectShixun}
+								hideNewShixunModelType={this.cloasShixunBox}
+								pathShixun={this.clickShixunchoose}
+								{...this.props}
+							></NewShixunModel>:""}
 
-              <Modal
-                keyboard={false}
-                title="选择实训"
-                visible={selectShixun}
-                closable={false}
-                footer={null}
-                width="840px"
-                destroyOnClose={true}
-              >
-								<Spin spinning={hometypepvisible}  size="large" style={{marginTop:'15%'}}>
-                <div className="newupload_conbox">
-                  <div className="clearfix mb20 shixun_work_div newshixun_tab_div cdefault" style={{"marginRight":"4px"}} id="shixun_tab_div">
-                    <li className="fl mr5 mt5"> <a onClick={()=>this.changeTag(0,`${search}`)} className={ parseInt(type)===0 ? "active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>全部</a></li>
-                    {
-                      ChooseShixunList && ChooseShixunList.tags.map((item,key)=>{
-                        return(
-                          <li className="fl mr5 mt5" key={key}> 
-                            <a onClick={()=>this.changeTag(`${item.tag_id}`,`${search}`)} className={ parseInt(type) === parseInt(item.tag_id) ? "active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>{item.tag_name}</a>
-                          </li>
-                        )
-                      })
-                    }
-                    
-
-                  </div>
-                  <div className="clearfix mb20" id="shixun_search_form_div">
-                    <span className="fl color-grey-9 font-16 mt3">
-                      <span>共</span>
-                      <span className="color-orange-tip">{ChooseShixunList && ChooseShixunList.shixuns_count}</span>
-                      <span>个实训</span>
-                    </span>
-                    <div className="fr search-new mb0">
-                      <Search 
-                        placeholder="请输入创建者或者实训名称进行搜索"
-                        onInput={this.searchNameInput}
-                        onSearch={()=>this.changeTag(`${type}`,`${search}`)}
-												style={{width: '115%'}}
-                      ></Search>
-                    </div>
-                  </div>
-                  <ul className="clearfix greybackHead edu-txt-center" style={{marginBottom: '0px'}}>
-                    <li className="fl with40 paddingleft22">实训名称</li>
-                    <li className="fl with30 edu-txt-left">使用院校</li>
-                    <li className="fl with10">使用人数</li>
-                    <li className="fl with10">评价等级</li>
-                    <li className="fl with10"></li>
-                  </ul>
-
-                  <style>
-                    {
-                      `
-                      .over180{min-height: 180px;max-height: 180px;overflow-y: auto}
-                      `
-                    }
-                  </style>
-									{ChooseShixunListshixun_list && ChooseShixunListshixun_list.length===0?"":<div className="over180 pl20 pr20"
-                       onScroll={this.contentViewScrolledit}
-                     >
-                    <Checkbox.Group style={{ width: '100%' }}   onChange={this.shixunhomeworkedit}>
-                      {
-                        ChooseShixunListshixun_list && ChooseShixunListshixun_list.map((item,key)=>{
-                          return(
-                            <div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE" key={key}>
-                              <li className="fl with40">
-                                <Checkbox
-                                  id={"shixun_input_"+item.shixun_id}
-																	value={item.shixun_id}
-																	key={item.shixun_id}
-                                  className="fl task-hide edu-txt-left"
-                                  style={{"width":"298px"}}
-                                  name="shixun_homework[]"
-                                >
-                                  <label style={{"textAlign":"left","color":"#05101A"}} className="task-hide color-grey-name" title={item.shixun_name}>{item.shixun_name}</label>
-                                </Checkbox>
-                              </li>
-                              <li className="fl with30 edu-txt-left task-hide paddingl5">{item.school_users}</li>
-                              <li className="fl with10 paddingl10">{item.myshixuns_count}</li>
-                              <li className="fl with10 color-orange-tip paddingl10">{item.preference}</li>
-                              <li className="fl with10"><a className="color-blue" href={"/shixuns/"+item.identifier+"/challenges"} target="_blank">详情</a></li>
-                            </div>
-                          )
-                        })
-                      }
-                    </Checkbox.Group>
-                  </div>}
-                  <div className="mt20 marginauto clearfix edu-txt-center">
-                    <a className="pop_close task-btn mr30 margin-tp26" onClick={this.cloasShixunBox}>取消</a>
-                    <a className="task-btn task-btn-orange margin-tp26" id="submit_send_shixun" onClick={this.clickShixunchoose}>确定</a>
-                  </div>
-                </div>
-									</Spin>
-              </Modal>
             </div>
 
             {/* 可拖拽选择实训列表*/}
@@ -716,4 +540,191 @@ export default DetailCardsEditAndEdit;
 //       </div>
 //     )
 //   })
-// }
\ No newline at end of file
+// }
+
+//           <Modal
+//                 keyboard={false}
+//                 title="选择实训"
+//                 visible={selectShixun}
+//                 closable={false}
+//                 footer={null}
+//                 width="840px"
+//                 destroyOnClose={true}
+//               >
+// 								<Spin spinning={hometypepvisible}  size="large" style={{marginTop:'15%'}}>
+//                 <div className="newupload_conbox">
+//                   <div className="clearfix mb20 shixun_work_div newshixun_tab_div cdefault" style={{"marginRight":"4px"}} id="shixun_tab_div">
+//                     <li className="fl mr5 mt5"> <a onClick={()=>this.changeTag(0,`${search}`)} className={ parseInt(type)===0 ? "active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>全部</a></li>
+//                     {
+//                       ChooseShixunList && ChooseShixunList.tags.map((item,key)=>{
+//                         return(
+//                           <li className="fl mr5 mt5" key={key}>
+//                             <a onClick={()=>this.changeTag(`${item.tag_id}`,`${search}`)} className={ parseInt(type) === parseInt(item.tag_id) ? "active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>{item.tag_name}</a>
+//                           </li>
+//                         )
+//                       })
+//                     }
+//
+//
+//                   </div>
+//                   <div className="clearfix mb20" id="shixun_search_form_div">
+//                     <span className="fl color-grey-9 font-16 mt3">
+//                       <span>共</span>
+//                       <span className="color-orange-tip">{ChooseShixunList && ChooseShixunList.shixuns_count}</span>
+//                       <span>个实训</span>
+//                     </span>
+//                     <div className="fr search-new mb0">
+//                       <Search
+//                         placeholder="请输入创建者或者实训名称进行搜索"
+//                         onInput={this.searchNameInput}
+//                         onSearch={()=>this.changeTag(`${type}`,`${search}`)}
+// 												style={{width: '115%'}}
+//                       ></Search>
+//                     </div>
+//                   </div>
+//                   <ul className="clearfix greybackHead edu-txt-center" style={{marginBottom: '0px'}}>
+//                     <li className="fl with40 paddingleft22">实训名称</li>
+//                     <li className="fl with30 edu-txt-left">使用院校</li>
+//                     <li className="fl with10">使用人数</li>
+//                     <li className="fl with10">评价等级</li>
+//                     <li className="fl with10"></li>
+//                   </ul>
+//
+//                   <style>
+//                     {
+//                       `
+//                       .over180{min-height: 180px;max-height: 180px;overflow-y: auto}
+//                       `
+//                     }
+//                   </style>
+// 									{ChooseShixunListshixun_list && ChooseShixunListshixun_list.length===0?"":<div className="over180 pl20 pr20"
+//                        onScroll={this.contentViewScrolledit}
+//                      >
+//                     <Checkbox.Group style={{ width: '100%' }}   onChange={this.shixunhomeworkedit}>
+//                       {
+//                         ChooseShixunListshixun_list && ChooseShixunListshixun_list.map((item,key)=>{
+//                           return(
+//                             <div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE" key={key}>
+//                               <li className="fl with40">
+//                                 <Checkbox
+//                                   id={"shixun_input_"+item.shixun_id}
+// 																	value={item.shixun_id}
+// 																	key={item.shixun_id}
+//                                   className="fl task-hide edu-txt-left"
+//                                   style={{"width":"298px"}}
+//                                   name="shixun_homework[]"
+//                                 >
+//                                   <label style={{"textAlign":"left","color":"#05101A"}} className="task-hide color-grey-name" title={item.shixun_name}>{item.shixun_name}</label>
+//                                 </Checkbox>
+//                               </li>
+//                               <li className="fl with30 edu-txt-left task-hide paddingl5">{item.school_users}</li>
+//                               <li className="fl with10 paddingl10">{item.myshixuns_count}</li>
+//                               <li className="fl with10 color-orange-tip paddingl10">{item.preference}</li>
+//                               <li className="fl with10"><a className="color-blue" href={"/shixuns/"+item.identifier+"/challenges"} target="_blank">详情</a></li>
+//                             </div>
+//                           )
+//                         })
+//                       }
+//                     </Checkbox.Group>
+//                   </div>}
+//                   <div className="mt20 marginauto clearfix edu-txt-center">
+//                     <a className="pop_close task-btn mr30 margin-tp26" onClick={this.cloasShixunBox}>取消</a>
+//                     <a className="task-btn task-btn-orange margin-tp26" id="submit_send_shixun" onClick={this.clickShixunchoose}>确定</a>
+//                   </div>
+//                 </div>
+// 									</Spin>
+//               </Modal>
+
+//  //打开选择实训弹框初始化tag标签和列表
+//   changeTag(id,search){
+//
+//     this.setState({
+// 			ChooseShixunListshixun_list:[],
+// 			page:1,
+//       hometypepvisible:true
+//     })
+//     let pathId=this.props.pathid;
+//     let url='/paths/'+pathId+'/choose_subject_shixun.json?page='+1
+//     if(search!="" && search!=undefined){
+//       url+="&search="+search;
+//     }
+//     if(id!=0){
+//       url+="&type="+id;
+//     }
+//     axios.get(encodeURI(url)).then((result)=>{
+//       if(result.status===200){
+//         this.setState({
+//           ChooseShixunList:result.data,
+//           hometypepvisible:false,
+//           type:id,
+//           search:search,
+//           ChooseShixunListshixun_list:result.data.shixun_list
+//         })
+//       }
+//     }).catch((error)=>{
+//       console.log(error);
+//     })
+//   }
+
+//  contentViewScrolledit=(e)=>{
+//     //滑动到底判断
+// 		const {ChooseShixunList}=this.state;
+// 		let newscrollTop=parseInt(e.currentTarget.scrollTop);
+// 		let allclientHeight=e.currentTarget.clientHeight+newscrollTop;
+//
+// 		if(e.currentTarget.scrollHeight-allclientHeight===0||e.currentTarget.scrollHeight-allclientHeight===1||e.currentTarget.scrollHeight-allclientHeight===-1){
+//
+// 			if(ChooseShixunList.shixun_list.length===0){
+// 				return
+// 			}else{
+// 				this.setState({
+// 					hometypepvisible:true
+// 				})
+// 				// console.log("到达底部");
+//
+// 				let {page,type,search,ChooseShixunListshixun_list}=this.state;
+//
+// 				let newpage=page+1;
+//
+// 				let pathId=this.props.pathid;
+//
+// 				let newChooseShixunListshixun_list=ChooseShixunListshixun_list;
+//
+// 				let url='/paths/'+pathId+'/choose_subject_shixun.json?page='+newpage
+//
+// 				if(search!="" && search!=undefined){
+// 					url+="&search="+search;
+// 				}
+//
+// 				if(type!=0){
+// 					url+="&type="+type;
+// 				}
+// 				axios.get(encodeURI(url)).then((result)=>{
+// 					if(result.status===200){
+//
+// 						let list =result.data.shixun_list;
+//
+// 						for(var i=0; i<list.length; i++){
+// 							newChooseShixunListshixun_list.push(list[i])
+// 						}
+// 						this.setState({
+// 							ChooseShixunList:result.data,
+// 							hometypepvisible:false,
+// 							type:type,
+// 							page:newpage,
+// 							search:search,
+// 							ChooseShixunListshixun_list:newChooseShixunListshixun_list
+// 						})
+// 					}
+// 				}).catch((error)=>{
+// 					console.log(error);
+// 				})
+//
+//
+// 			}
+//
+//
+//
+//     }
+//
+//   }
\ No newline at end of file
diff --git a/public/react/src/modules/paths/PathDetail/PathDetailIndex.js b/public/react/src/modules/paths/PathDetail/PathDetailIndex.js
index 86c3f68a9..c8cece9fd 100644
--- a/public/react/src/modules/paths/PathDetail/PathDetailIndex.js
+++ b/public/react/src/modules/paths/PathDetail/PathDetailIndex.js
@@ -362,6 +362,9 @@ class PathDetailIndex extends Component{
 							.head-right{
     						line-height: 30px;
 							}
+							.padding40-20-30{
+							  padding:40px 20px 30px;
+							}
 						`
 					}
 				</style>
@@ -457,7 +460,7 @@ class PathDetailIndex extends Component{
 							}
 							{
 								this.props.checkIfLogin()===false?"":progress === undefined ? "" : progress === null ? "" :
-									<div className="edu-back-white myProgress padding40-20 mb10">
+									<div className="edu-back-white myProgress padding40-20-30 mb10">
 										<p className="mb20">
 											<span className="font-16 mr10">关卡数</span>
 											<Tooltip placement="bottom" title="已通关数/关卡总数">
@@ -468,7 +471,8 @@ class PathDetailIndex extends Component{
 											<span className="fl color-green">已学 {progress.learned}%</span>
 											<span className="fr color-grey-9" id="time-consuming">学习耗时{this.timeStamp(progress.time)} </span>
 										</p>
-										<div className="myProgressNav"><div className="myProgressGreen" style={{"width":`${progress.learned+"%"}`}}></div></div>
+										<div className="myProgressNav mb20"><div className="myProgressGreen" style={{"width":`${progress.learned+"%"}`}}></div></div>
+										<span className="font-14 color-grey-8">注: “我的进展”以已发布的实训详情关卡数为准。</span>
 									</div>
 							}
 
diff --git a/public/react/src/modules/paths/ShixunPaths.js b/public/react/src/modules/paths/ShixunPaths.js
index c2bc0d869..d943634b3 100644
--- a/public/react/src/modules/paths/ShixunPaths.js
+++ b/public/react/src/modules/paths/ShixunPaths.js
@@ -8,6 +8,7 @@ class ShixunPath extends Component{
       super(props)
   }
   componentDidMount() {
+    console.log('configShareForPaths')
     configShareForPaths()
   }
   
diff --git a/public/react/src/modules/tpm/TPMsettings/TPMsettings.js b/public/react/src/modules/tpm/TPMsettings/TPMsettings.js
index f78d62637..b2767887d 100644
--- a/public/react/src/modules/tpm/TPMsettings/TPMsettings.js
+++ b/public/react/src/modules/tpm/TPMsettings/TPMsettings.js
@@ -220,6 +220,7 @@ export default class TPMsettings extends Component {
       can_copy: undefined,
       task_pass: undefined,
       test_set_permission: undefined,
+	  code_edit_permission: undefined,
       hide_code: undefined,
       code_hidden: undefined,
       forbid_copy: undefined,
@@ -352,6 +353,7 @@ export default class TPMsettings extends Component {
           task_pass: response.data.shixun.task_pass,
           test_set_permission: response.data.shixun.test_set_permission,
           hide_code: response.data.shixun.hide_code,
+		  code_edit_permission: response.data.shixun.code_edit_permission,
           code_hidden: response.data.shixun.code_hidden,
           is_secret_repository: response.data.shixun.is_secret_repository,
 		  init_is_secret_repository: response.data.shixun.is_secret_repository,
@@ -546,7 +548,11 @@ export default class TPMsettings extends Component {
     });
 
   }
-
+  code_edit_permission = (e) => {
+	  this.setState({
+		  code_edit_permission: e.target.checked
+	  })
+  }
   code_hidden=(e)=>{
     let sum = ""
     if (e.target.checked === false) {
@@ -869,7 +875,7 @@ export default class TPMsettings extends Component {
     let {
       name, choice_main_type, choice_small_type, choice_standard_scripts, scope_partment, choice_standard_scriptssum, vnc_evaluate,
       evaluate_script, webssh, use_scope, trainee, can_copy, task_pass, test_set_permission, hide_code, code_hidden, forbid_copy, vnc,multi_webssh,
-      opening_time,shixunmemoMDvalue,shixun_service_configlist, is_secret_repository
+      opening_time,shixunmemoMDvalue,shixun_service_configlist, is_secret_repository, code_edit_permission
     } = this.state;
 
 		let newshixun_service_configlist = shixun_service_configlist.map(v => {
@@ -982,6 +988,7 @@ export default class TPMsettings extends Component {
 				vnc_evaluate: vnc_evaluate===null?undefined:vnc_evaluate,
 				test_set_permission: test_set_permission,
 				code_hidden: code_hidden,
+				code_edit_permission: code_edit_permission,
 				trainee: trainee,
 				task_pass: task_pass,
 				hide_code: hide_code,
@@ -1563,6 +1570,7 @@ export default class TPMsettings extends Component {
       test_set_permission,
       hide_code,
       forbid_copy,
+	  code_edit_permission,
       code_hidden,
       vnc,
 	  vnc_evaluate,
@@ -2274,6 +2282,15 @@ export default class TPMsettings extends Component {
 													</span>
 						</div>
 
+						{!code_hidden && !hide_code && <div className="clearfix mt20 ml30">
+							<span className="color-grey-6 mt5 fl" style={{minWidth: '95px'}}>代码开放修改:</span>
+							<span className="fl mt5">
+															<Checkbox checked={code_edit_permission === undefined ? false : code_edit_permission}
+																				onChange={this.code_edit_permission}></Checkbox>
+															<label style={{top:'6px'}} className="color-grey-9 ml10" >勾选则学员可以修改版本库目录中的任意文件内容</label>
+													</span>
+						</div>}
+
 						<div className="clearfix mt20 ml30">
 							<span className="color-grey-6 mt5 fl" style={{minWidth: '95px'}}>隐藏代码窗口:</span>
 							<span className="fl mt5">
diff --git a/public/react/src/modules/tpm/challengesnew/TPMMDEditor.js b/public/react/src/modules/tpm/challengesnew/TPMMDEditor.js
index ba4f1bc21..c4a08e171 100644
--- a/public/react/src/modules/tpm/challengesnew/TPMMDEditor.js
+++ b/public/react/src/modules/tpm/challengesnew/TPMMDEditor.js
@@ -16,8 +16,8 @@ require('codemirror/lib/codemirror.css');
 
 let origin = getUrl();
 
-let path = getUrl("/editormd/lib/")
-
+let path = '/editormd/lib/'
+    path = getUrl("/editormd/lib/")
 const $ = window.$;
 
 let timeout;
@@ -171,7 +171,7 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback, initV
             $("#" + _id + " [type=\"inline\"]").bind("click", function () {
                 _editorName.cm.replaceSelection("`$$$$`");
                 var __Cursor = _editorName.cm.getDoc().getCursor();
-                _editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
+                _editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3);
                 _editorName.cm.focus();
             });
             $("[type=\"inline\"]").attr("title", "行内公式");
diff --git a/public/react/src/search/searchc.css b/public/react/src/search/searchc.css
index 99f35738a..15c34650b 100644
--- a/public/react/src/search/searchc.css
+++ b/public/react/src/search/searchc.css
@@ -12,7 +12,7 @@
     height: 55px;
     width:663px !important;
     font-size: 18px;
-    color: #681616 !important;
+    /*color: #681616 !important;*/
     border-color: #E1EDF8 !important;
 }