diff --git a/app/controllers/concerns/paginate_helper.rb b/app/controllers/concerns/paginate_helper.rb
index bbe84a348..7233adebf 100644
--- a/app/controllers/concerns/paginate_helper.rb
+++ b/app/controllers/concerns/paginate_helper.rb
@@ -3,6 +3,10 @@ module PaginateHelper
     page     = params[:page].to_i <= 0 ? 1 : params[:page].to_i
     per_page = params[:per_page].to_i > 0 && params[:per_page].to_i < 50 ? params[:per_page].to_i : opts[:per_page] || 20
 
-    Kaminari.paginate_array(objs).page(page).per(per_page)
+    if objs.is_a?(Array)
+      Kaminari.paginate_array(objs).page(page).per(per_page)
+    else
+      objs.page(page).per(per_page)
+    end
   end
 end
\ No newline at end of file
diff --git a/app/controllers/ecs/base_controller.rb b/app/controllers/ecs/base_controller.rb
index 2cded249a..1ad40d7b3 100644
--- a/app/controllers/ecs/base_controller.rb
+++ b/app/controllers/ecs/base_controller.rb
@@ -47,6 +47,10 @@ class Ecs::BaseController < ApplicationController
     page     = params[:page].to_i <= 0 ? 1 : params[:page].to_i
     per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 20
 
-    Kaminari.paginate_array(objs).page(page).per(per_page)
+    if objs.is_a?(Array)
+      Kaminari.paginate_array(objs).page(page).per(per_page)
+    else
+      objs.page(page).per(per_page)
+    end
   end
 end
\ No newline at end of file
diff --git a/app/controllers/ecs/ec_graduation_requirements_controller.rb b/app/controllers/ecs/ec_graduation_requirements_controller.rb
index 95dafdb3c..0647a7914 100644
--- a/app/controllers/ecs/ec_graduation_requirements_controller.rb
+++ b/app/controllers/ecs/ec_graduation_requirements_controller.rb
@@ -15,19 +15,31 @@ class Ecs::EcGraduationRequirementsController < Ecs::BaseController
   end
 
   def create
-    graduation_requirement = current_year.graduation_requirements.new
+    graduation_requirement = current_year.ec_graduation_requirements.new
     @graduation_requirement = Ecs::SaveGraduationRequirementeService.call(graduation_requirement, create_params)
     render 'show'
   end
 
   def update
-    graduation_requirement = current_year.graduation_requirements.find(params[:id])
-    @graduation_requirement = Ecs::SaveGraduationRequirementeService.call(graduation_requirement, update_params)
+    @graduation_requirement = Ecs::SaveGraduationRequirementeService.call(current_graduation_requirement, update_params)
     render 'show'
   end
 
+  def destroy
+    ActiveRecord::Base.transaction do
+      current_graduation_requirement.destroy!
+      current_year.ec_graduation_requirements.where('position > ?', current_graduation_requirement.position)
+        .update_all('position = position - 1')
+    end
+    render_ok
+  end
+
   private
 
+  def current_graduation_requirement
+    @_current_graduation_requirement ||= current_year.ec_graduation_requirements.find(params[:id])
+  end
+
   def create_params
     params.permit(:position, :content, graduation_subitems: [:content])
   end
diff --git a/app/controllers/ecs/ec_major_schools_controller.rb b/app/controllers/ecs/ec_major_schools_controller.rb
index 058bc888e..c5f187af0 100644
--- a/app/controllers/ecs/ec_major_schools_controller.rb
+++ b/app/controllers/ecs/ec_major_schools_controller.rb
@@ -1,4 +1,6 @@
 class Ecs::EcMajorSchoolsController < Ecs::BaseController
+  skip_before_action :check_user_permission!, only: [:show]
+
   def index
     major_schools = current_school.ec_major_schools.not_template
 
@@ -20,7 +22,18 @@ class Ecs::EcMajorSchoolsController < Ecs::BaseController
     @count         = major_schools.count   #检索后的数量,小于或等于全部数量
     @major_schools = paginate(major_schools.includes(:users, :ec_major))
 
-    @template_major_school = current_school.ec_major_schools.is_template.first  #示例专业
+    @template_major_school = EcMajorSchool.is_template.first  #示例专业
+  end
+
+  # :show是 /api/ec_major_schools/:id
+  def show
+    @major = EcMajorSchool.find(params[:id])
+    school = @major.school
+
+    return if current_user.admin? || school.manager?(current_user)
+    return if @major.manager?(current_user)
+
+    render_forbidden
   end
 
   def create
diff --git a/app/controllers/ecs/ec_majors_controller.rb b/app/controllers/ecs/ec_majors_controller.rb
index 7b14237dc..e8daaf008 100644
--- a/app/controllers/ecs/ec_majors_controller.rb
+++ b/app/controllers/ecs/ec_majors_controller.rb
@@ -1,7 +1,7 @@
 class Ecs::EcMajorsController < Ecs::BaseController
   def index
-    school_major_subquery = current_school.ec_major_schools.select(:ec_major_id)  #学校已选择的专业
-    ec_majors = EcMajor.where.not(id: school_major_subquery)
+    @major_ids = current_school.ec_major_schools.pluck(:ec_major_id)  #学校已选择的专业
+    ec_majors = EcMajor.all
 
     if params[:search].present?
       ec_majors = ec_majors.search_name_or_code(params[:search])
diff --git a/app/controllers/ecs/ec_training_objectives_controller.rb b/app/controllers/ecs/ec_training_objectives_controller.rb
index 318faa6ff..79b232822 100644
--- a/app/controllers/ecs/ec_training_objectives_controller.rb
+++ b/app/controllers/ecs/ec_training_objectives_controller.rb
@@ -2,7 +2,7 @@ class Ecs::EcTrainingObjectivesController < Ecs::BaseController
   before_action :check_major_manager_permission!, only: [:create]
 
   def show
-    @training_objective = current_year.ec_training_objective
+    @training_objective = current_year.ec_training_objective || current_year.build_ec_training_objective
 
     respond_to do |format|
       format.json
diff --git a/app/controllers/ecs/ec_years_controller.rb b/app/controllers/ecs/ec_years_controller.rb
index 2257911a7..9764e451d 100644
--- a/app/controllers/ecs/ec_years_controller.rb
+++ b/app/controllers/ecs/ec_years_controller.rb
@@ -10,7 +10,7 @@ class Ecs::EcYearsController < Ecs::BaseController
     end
 
     @count    = ec_years.count
-    @ec_years = paginate ec_years
+    @ec_years = paginate ec_years.order(year: :desc)
 
     return if @ec_years.blank?
 
@@ -27,13 +27,17 @@ class Ecs::EcYearsController < Ecs::BaseController
                                       .where(ec_graduation_requirements: { ec_year_id: year_ids }).group('ec_year_id').count
   end
 
+  def show
+    @year = current_year
+  end
+
   def create
     if current_major_school.ec_years.exists?(year: params[:year].to_i)
       render_error('届别已存在')
       return
     end
 
-    @ec_year = CopyEcYearService.call(current_major_school, params[:year].to_i)
+    @ec_year = Ecs::CopyEcYearService.call(current_major_school, params[:year].to_i)
   end
 
   def destroy
diff --git a/app/controllers/ecs/major_managers_controller.rb b/app/controllers/ecs/major_managers_controller.rb
index da5682734..d2515745b 100644
--- a/app/controllers/ecs/major_managers_controller.rb
+++ b/app/controllers/ecs/major_managers_controller.rb
@@ -3,7 +3,8 @@ class Ecs::MajorManagersController < Ecs::BaseController
   before_action :check_manager_permission!
 
   def create
-    @user = Ecs::CreateMajorManagerService.call(current_major_school, params[:user_id])
+    Ecs::CreateMajorManagerService.call(current_major_school, params[:user_ids])
+    render_ok
   rescue Ecs::CreateMajorManagerService::Error => ex
     render_error(ex.message)
   end
diff --git a/app/controllers/ecs/reach_evaluations_controller.rb b/app/controllers/ecs/reach_evaluations_controller.rb
index 97576447c..25ac24656 100644
--- a/app/controllers/ecs/reach_evaluations_controller.rb
+++ b/app/controllers/ecs/reach_evaluations_controller.rb
@@ -14,5 +14,13 @@ class Ecs::ReachEvaluationsController < Ecs::BaseController
   end
 
   def create
+    relations = current_year.ec_graduation_requirements.joins(ec_graduation_subitems: :ec_course_support)
+    ec_course_ids = relations.pluck('ec_course_supports.ec_course_id').uniq
+
+    EcCourse.where(id: ec_course_ids).each do |ec_course|
+      Ecs::CalculateCourseEvaluationService.call(ec_course)
+    end
+
+    render_ok
   end
 end
diff --git a/app/controllers/ecs/users_controller.rb b/app/controllers/ecs/users_controller.rb
new file mode 100644
index 000000000..139893efc
--- /dev/null
+++ b/app/controllers/ecs/users_controller.rb
@@ -0,0 +1,22 @@
+class Ecs::UsersController < Ecs::BaseController
+  skip_before_action :check_user_permission!
+  before_action :check_manager_permission!
+
+  def index
+    users = UserQuery.call(params)
+
+    @count = users.count
+    @users = paginate users.includes(user_extension: [:school, :department])
+    @manager_ids = current_major_school.ec_major_school_users.pluck(:user_id)
+  end
+
+  private
+
+  def current_major_school
+    @_ec_major_school ||= EcMajorSchool.find(params[:ec_major_school_id])
+  end
+
+  def current_school
+    @_current_school ||= current_major_school.school
+  end
+end
diff --git a/app/controllers/users/base_controller.rb b/app/controllers/users/base_controller.rb
index 3ba6940f5..128dc539b 100644
--- a/app/controllers/users/base_controller.rb
+++ b/app/controllers/users/base_controller.rb
@@ -55,7 +55,13 @@ class Users::BaseController < ApplicationController
     page     = page_value
     per_page = per_page_value
 
-    return Kaminari.paginate_array(objs).page(page).per(per_page) unless opts[:special] && observed_logged_user?
+    unless opts[:special] && observed_logged_user?
+      if objs.is_a?(Array)
+        return Kaminari.paginate_array(objs).page(page).per(per_page)
+      else
+        return objs.page(page).per(per_page)
+      end
+    end
 
     # note: 为实现第一页少一条记录,让前端放置新建入口
     if page == 1
diff --git a/app/helpers/ecs/ec_years_helper.rb b/app/helpers/ecs/ec_years_helper.rb
new file mode 100644
index 000000000..108abb0e7
--- /dev/null
+++ b/app/helpers/ecs/ec_years_helper.rb
@@ -0,0 +1,22 @@
+module Ecs::EcYearsHelper
+  def achieved_graduation_course_count(ec_year)
+    return 0 if ec_year.ec_courses.count.zero?
+
+    course_ids = ec_year.ec_courses.map(&:id)
+    target_count_map = EcCourseTarget.where(ec_course_id: course_ids).group(:ec_course_id).count
+
+    ec_year.ec_courses.sum { |course| course.complete_target_count == target_count_map[course.id] ? 1 : 0 }
+  end
+
+  def achieved_graduation_objective_count(ec_year)
+    return 0 if ec_year.ec_graduation_subitems.count.zero?
+
+    subitem_ids = ec_year.ec_graduation_subitems.reorder(nil).pluck(:id)
+
+    relations = EcGraduationRequirementCalculation.joins(:ec_course_support).where(ec_course_supports: { ec_graduation_subitem_id: subitem_ids })
+
+    reached_map = relations.where(status: true).group('ec_graduation_subitem_id').count
+
+    reached_map.keys.size
+  end
+end
\ No newline at end of file
diff --git a/app/libs/util.rb b/app/libs/util.rb
index f39ce2b58..ae2e4b80b 100644
--- a/app/libs/util.rb
+++ b/app/libs/util.rb
@@ -45,6 +45,8 @@ module Util
 
   def conceal(str, type = nil)
     str = str.to_s
+    return if str.blank?
+
     case type
     when :phone then "#{str[0..2]}***#{str[-4..-1]}"
     when :email then "#{str[0..2]}***#{str[str.rindex('@')..-1]}"
diff --git a/app/models/ec_course_student_score.rb b/app/models/ec_course_student_score.rb
index 5b45e34a9..57d524b46 100644
--- a/app/models/ec_course_student_score.rb
+++ b/app/models/ec_course_student_score.rb
@@ -1,7 +1,6 @@
 class EcCourseStudentScore < ApplicationRecord
   belongs_to :ec_year_student
   belongs_to :ec_course
-  belongs_to :ec_course_target
 
   has_many :ec_student_score_targets, dependent: :delete_all
 end
\ No newline at end of file
diff --git a/app/models/ec_course_support.rb b/app/models/ec_course_support.rb
index a6ca96ea9..518fc1385 100644
--- a/app/models/ec_course_support.rb
+++ b/app/models/ec_course_support.rb
@@ -1,9 +1,10 @@
 class EcCourseSupport < ApplicationRecord
   default_scope { order(position: :asc) }
 
+  alias_attribute :weights, :weigths
+
   belongs_to :ec_course
   belongs_to :ec_graduation_subitem
-  # TODO: 将 ec_graduation_subitem_courses 移除,这个表作为关系表
 
   has_one :ec_graduation_requirement_calculation, dependent: :destroy
 
diff --git a/app/models/ec_course_target.rb b/app/models/ec_course_target.rb
index 9b93cb73c..b13c81059 100644
--- a/app/models/ec_course_target.rb
+++ b/app/models/ec_course_target.rb
@@ -1,4 +1,3 @@
-# TODO:: change table column :weigths => :weight
 class EcCourseTarget < ApplicationRecord
   belongs_to :ec_course
 
@@ -8,6 +7,8 @@ class EcCourseTarget < ApplicationRecord
   has_many :ec_course_achievement_methods, dependent: :destroy
   has_many :ec_achievement_evaluation_relates, dependent: :destroy
 
+  alias_attribute :weight, :weigths
+
   validates :content, presence: true
   validates :standard_grade, numericality: { only_integer: true, greater_than: 0 }
   validates :weight, presence: true, numericality: { less_than_or_equal_to: 1, greater_than_or_equal_to: 0 }
diff --git a/app/models/ec_graduation_requirement.rb b/app/models/ec_graduation_requirement.rb
index d0f4195d0..f9c65e28e 100644
--- a/app/models/ec_graduation_requirement.rb
+++ b/app/models/ec_graduation_requirement.rb
@@ -1,4 +1,6 @@
 class EcGraduationRequirement < ApplicationRecord
+  default_scope { order(position: :asc) }
+
   belongs_to :ec_year
 
   has_many :ec_graduation_subitems, dependent: :destroy
@@ -7,5 +9,5 @@ class EcGraduationRequirement < ApplicationRecord
   validates :position, presence: true, numericality: { only_integer: true, greater_than: 0 }
   validates :content, presence: true
 
-  default_scope { order(position: :asc) }
+  accepts_nested_attributes_for :ec_graduation_subitems, allow_destroy: true
 end
diff --git a/app/models/ec_major_school.rb b/app/models/ec_major_school.rb
index 41a835f63..5cfc4df9e 100644
--- a/app/models/ec_major_school.rb
+++ b/app/models/ec_major_school.rb
@@ -12,6 +12,8 @@ class EcMajorSchool < ApplicationRecord
   scope :is_template, -> { where(template_major: true) }
   scope :not_template, -> { where(template_major: false) }
 
+  delegate :code, :name, to: :ec_major
+
   # 是否为该专业管理员
   def manager?(user)
     ec_major_school_users.exists?(user_id: user.id)
diff --git a/app/models/ec_training_subitem.rb b/app/models/ec_training_subitem.rb
index 0c9c61fbc..736e3f0da 100644
--- a/app/models/ec_training_subitem.rb
+++ b/app/models/ec_training_subitem.rb
@@ -1,4 +1,6 @@
 class EcTrainingSubitem < ApplicationRecord
+  default_scope { order(position: :asc) }
+
   belongs_to :ec_training_objective
 
   has_many :ec_requirement_vs_objectives, foreign_key: :ec_training_objective_id, dependent: :destroy
diff --git a/app/models/ec_year.rb b/app/models/ec_year.rb
index 69ae4c291..6a3d97340 100644
--- a/app/models/ec_year.rb
+++ b/app/models/ec_year.rb
@@ -9,4 +9,11 @@ class EcYear < ApplicationRecord
   has_many :ec_graduation_requirements, dependent: :destroy
   has_many :ec_graduation_subitems, through: :ec_graduation_requirements
   has_many :ec_year_students, dependent: :destroy
+
+  has_many :ec_course_users, dependent: :destroy
+  has_many :managers, through: :ec_course_users, source: :user
+
+  def prev_year
+    self.class.find_by(year: year.to_i - 1)
+  end
 end
diff --git a/app/queries/application_query.rb b/app/queries/application_query.rb
index 3a92cc6e8..c66af94c0 100644
--- a/app/queries/application_query.rb
+++ b/app/queries/application_query.rb
@@ -1,3 +1,9 @@
 class ApplicationQuery
   include Callable
+
+  private
+
+  def strip_param(key)
+    params[key].to_s.strip.presence
+  end
 end
\ No newline at end of file
diff --git a/app/queries/user_query.rb b/app/queries/user_query.rb
new file mode 100644
index 000000000..326665fe9
--- /dev/null
+++ b/app/queries/user_query.rb
@@ -0,0 +1,28 @@
+class UserQuery < ApplicationQuery
+  attr_reader :params
+
+  def initialize(params)
+    @params = params
+  end
+
+  def call
+    users = User.where(type: 'User')
+
+    # 真实姓名
+    if name = strip_param(:name)
+      users = users.where('LOWER(CONCAT(users.lastname, users.firstname)) LIKE ?', "%#{name.downcase}%")
+    end
+
+    # 单位名称
+    if school = strip_param(:school)
+      users = users.joins(user_extension: :school).where('schools.name LIKE ?', "%#{school}%")
+    end
+
+    # 职业
+    if (identity = strip_param(:identity)) && UserExtension.identities.keys.include?(identity)
+      users = users.joins(:user_extension).where(user_extensions: { identity: identity })
+    end
+
+    users
+  end
+end
\ No newline at end of file
diff --git a/app/services/ecs/copy_ec_year_service.rb b/app/services/ecs/copy_ec_year_service.rb
index 87cbe0845..462681eba 100644
--- a/app/services/ecs/copy_ec_year_service.rb
+++ b/app/services/ecs/copy_ec_year_service.rb
@@ -1,4 +1,4 @@
-class CopyEcYearService < ApplicationService
+class Ecs::CopyEcYearService < ApplicationService
   attr_reader :major_school, :to_year
 
   def initialize(major_school, year)
diff --git a/app/services/ecs/create_course_service.rb b/app/services/ecs/create_course_service.rb
index dba162189..3e3828c6f 100644
--- a/app/services/ecs/create_course_service.rb
+++ b/app/services/ecs/create_course_service.rb
@@ -27,7 +27,7 @@ class Ecs::CreateCourseService < ApplicationService
   private
 
   def create_default_score_levels!(ec_course)
-    EcScoreLevel.bulk_insert(:ec_course_id, :score, :level, :position) do |worker|
+    EcScoreLevel.bulk_insert(:ec_course_id, :score, :level, :position, :created_at, :updated_at) do |worker|
       [
         { ec_course_id: ec_course.id, score: 90, level: '优秀',   position: 1 },
         { ec_course_id: ec_course.id, score: 80, level: '良好',   position: 2 },
diff --git a/app/services/ecs/create_major_manager_service.rb b/app/services/ecs/create_major_manager_service.rb
index befe80706..c955bffed 100644
--- a/app/services/ecs/create_major_manager_service.rb
+++ b/app/services/ecs/create_major_manager_service.rb
@@ -3,29 +3,30 @@ class Ecs::CreateMajorManagerService < ApplicationService
 
   MAJOR_MANAGER_COUNT_LIMIT = 5  # 专业管理员数量限制
 
-  attr_reader :major_school, :user_id
+  attr_reader :major_school, :user_ids
 
-  def initialize(major_school, user_id)
+  def initialize(major_school, user_ids)
     @major_school = major_school
-    @user_id      = user_id
+    @user_ids     = user_ids
   end
 
   def call
     raise Error, '示例专业不能添加管理员' if major_school.template_major?
 
-    user = User.find_by(id: params[:user_id])
-    raise Error, '该用户不存在' if user.blank?
+    @user_ids = User.where(id: user_ids).pluck(:id)
 
-    if major_school.ec_major_school_users.exists?(user_id: user.id)
-      raise Error, '该用户已经是该专业的管理员了'
+    if major_school.ec_major_school_users.exists?(user_id: user_ids)
+      raise Error, '所选用户中存在该专业的管理员'
     end
 
-    if major_school.ec_major_school_users.count >= MAJOR_MANAGER_COUNT_LIMIT
-      raise Error, '该专业管理员数量已达上限'
+    if major_school.ec_major_school_users.count + user_ids.count > MAJOR_MANAGER_COUNT_LIMIT
+      raise Error, "该专业管理员数量超过上限(#{MAJOR_MANAGER_COUNT_LIMIT}人)"
     end
 
-    major_school.ec_major_school_users.create!(user: user)
-
-    user
+    ActiveRecord::Base.transaction do
+      user_ids.each do |user_id|
+        major_school.ec_major_school_users.create!(user_id: user_id)
+      end
+    end
   end
 end
\ No newline at end of file
diff --git a/app/services/ecs/create_training_objective_service.rb b/app/services/ecs/create_training_objective_service.rb
index c3dc3c8a6..effbf5420 100644
--- a/app/services/ecs/create_training_objective_service.rb
+++ b/app/services/ecs/create_training_objective_service.rb
@@ -11,13 +11,16 @@ class Ecs::CreateTrainingObjectiveService < ApplicationService
   def call
     training_objective.content = params[:content].to_s.strip
 
-    attributes = build_accepts_nested_attributes(
-      training_objective,
-      training_objective.ec_training_subitems,
-      params[:training_subitems],
-      &method(:training_subitem_param_handler)
-    )
-    training_objective.assign_attributes(ec_training_subitems_attributes: attributes)
+    if params.key?(:training_subitems)
+      attributes = build_accepts_nested_attributes(
+        training_objective,
+        training_objective.ec_training_subitems,
+        params[:training_subitems],
+        &method(:training_subitem_param_handler)
+      )
+      attributes.each_with_index { |attr, index| attr[:position] = index + 1 }
+      training_objective.assign_attributes(ec_training_subitems_attributes: attributes)
+    end
 
     training_objective.save!
     training_objective
diff --git a/app/services/ecs/query_course_evaluation_service.rb b/app/services/ecs/query_course_evaluation_service.rb
index 8c76da438..22e0ce1f4 100644
--- a/app/services/ecs/query_course_evaluation_service.rb
+++ b/app/services/ecs/query_course_evaluation_service.rb
@@ -17,12 +17,12 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
   end
 
   def graduation_subitem_evaluations
-    student_scores = ec_course.ec_course_student_scores.joins(:ec_course_target).group(:ec_course_target_id)
+    student_scores = ec_course.ec_course_student_scores.joins(ec_student_score_targets: :ec_course_target).group(:ec_course_target_id)
     student_scores = student_scores.select('AVG(score) as average_score, ec_course_target_id')
     student_score_map = student_scores.group_by { |item| item.ec_course_target_id }
 
     subitem_targets = ec_course.ec_graduation_subitem_course_targets
-                        .includes(ec_graduation_subitem: :ec_graduation_requirement)
+                        .includes(:ec_course_target, ec_graduation_subitem: :ec_graduation_requirement)
 
     subitem_targets.group_by(&:ec_graduation_subitem_id).map do |_id, arr|
       subitem = arr.first.ec_graduation_subitem
@@ -37,7 +37,7 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
 
       arr.map(&:ec_course_target).uniq.each do |target|
         target_total_rates += target.weight.to_f
-        student_score = student_score_map[target.id]
+        student_score = student_score_map[target.id]&.first
 
         reach_real_target += student_score.average_score.to_f * target.weight.to_f if student_score
       end
@@ -60,8 +60,19 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
 
   def score_levels_map
     @_score_levels_map ||= begin
+      index = 0
       ec_course.ec_score_levels.each_with_object({}) do |level, obj|
-        obj[level.id.to_s] = level.as_json(only: %i[id position score level])
+        hash = level.as_json(only: %i[id position score level])
+
+        hash[:description] =
+          case index
+          when 0 then "#{level.score}分以上"
+          when ec_course.ec_score_levels.to_a.size - 1 then "低于#{level.score}分"
+          else "#{level.score}~#{ec_course.ec_score_levels[index - 1].score - 1}分"
+          end
+
+        index += 1
+        obj[level.id.to_s] = hash
       end
     end
   end
@@ -87,23 +98,29 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
       @_course_achievement += data[:average_score].to_f * course_target.weight.to_f
 
       # 计算学生成绩分布区间
+      student_count = 0
       data[:score_levels] = score_levels.map do |score_level|
         level_condition_proc =
           if (score_level.position - 1).zero? # 第一区间
             -> (score_target){ score_target.score >= score_level.score ? 1 : 0 }
-          elsif score_levels.position == score_levels.size # 末尾区间
+          elsif score_level.position == score_levels.size # 末尾区间
             -> (score_target){ score_target.score < score_level.score ? 1 : 0 }
           else
             # 中间区间
-            -> (score_target){ score_target.score >= score_level.score && score_target.score < score_targets[score_level.position - 1] ? 1 : 0 }
+            -> (score_target){ score_target.score >= score_level.score && score_target.score < score_levels[score_level.position - 1].score ? 1 : 0 }
           end
 
         # 计算该成绩区间人数
         count = score_targets.sum(&level_condition_proc)
+        student_count += count
 
         { id: score_level.id, count: count }
       end
 
+      data[:score_levels].each do |score_level|
+        score_level[:rate] = score_level[:count].fdiv(student_count).round(2)
+      end
+
       data
     end
   end
diff --git a/app/views/ecs/course_evaluations/average_score_import_template.xlsx.axlsx b/app/views/ecs/course_evaluations/average_score_import_template.xlsx.axlsx
index 900ff5888..934e1c4be 100644
--- a/app/views/ecs/course_evaluations/average_score_import_template.xlsx.axlsx
+++ b/app/views/ecs/course_evaluations/average_score_import_template.xlsx.axlsx
@@ -13,7 +13,7 @@ wb.styles do |style|
     name       = course_evaluation.name
     items_size = course_evaluation.ec_course_evaluation_subitems.count
 
-    sheet.add_row name, style: bg_style
+    sheet.add_row [name], style: bg_style
     sheet.merge_cells wb.rows.first.cells[(1..(items_size * course_evaluation.evaluation_count))]
 
     data       = []
diff --git a/app/views/ecs/course_evaluations/index.json.jbuilder b/app/views/ecs/course_evaluations/index.json.jbuilder
index e1c63d44d..b120bccc2 100644
--- a/app/views/ecs/course_evaluations/index.json.jbuilder
+++ b/app/views/ecs/course_evaluations/index.json.jbuilder
@@ -1 +1 @@
-json.course_evaluations @course_evaluations, partial: 'shared/ec_course_evaluation', as: :ec_course_evaluation
+json.course_evaluations @course_evaluations, partial: 'ecs/course_evaluations/shared/ec_course_evaluation', as: :ec_course_evaluation
diff --git a/app/views/ecs/course_evaluations/show.json.jbuilder b/app/views/ecs/course_evaluations/show.json.jbuilder
index b03ddc076..f67053183 100644
--- a/app/views/ecs/course_evaluations/show.json.jbuilder
+++ b/app/views/ecs/course_evaluations/show.json.jbuilder
@@ -1 +1 @@
-json.partial! 'shared/ec_course_evaluation', ec_course_evaluation: @course_evaluation
+json.partial! 'ecs/course_evaluations/shared/ec_course_evaluation', ec_course_evaluation: @course_evaluation
diff --git a/app/views/ecs/course_evaluations/slimmer.json.jbuilder b/app/views/ecs/course_evaluations/slimmer.json.jbuilder
index 929cfe7be..6e0faef3e 100644
--- a/app/views/ecs/course_evaluations/slimmer.json.jbuilder
+++ b/app/views/ecs/course_evaluations/slimmer.json.jbuilder
@@ -1 +1 @@
-json.course_evaluations @course_evaluations, partial: 'shared/ec_course_evaluation_slim', as: :ec_course_evaluation
+json.course_evaluations @course_evaluations, partial: 'ecs/course_evaluations/shared/ec_course_evaluation_slim', as: :ec_course_evaluation
diff --git a/app/views/ecs/course_targets/index.json.jbuilder b/app/views/ecs/course_targets/index.json.jbuilder
index 6590ecc10..9ec4af823 100644
--- a/app/views/ecs/course_targets/index.json.jbuilder
+++ b/app/views/ecs/course_targets/index.json.jbuilder
@@ -1,2 +1,2 @@
 
-json.course_targets @course_targets, partial: 'shared/course_target', as: :ec_course_target
+json.course_targets @course_targets, partial: 'ecs/course_targets/shared/course_target', as: :ec_course_target
diff --git a/app/views/ecs/course_targets/index.xlsx.axlsx b/app/views/ecs/course_targets/index.xlsx.axlsx
index a188ad95c..ef4215b03 100644
--- a/app/views/ecs/course_targets/index.xlsx.axlsx
+++ b/app/views/ecs/course_targets/index.xlsx.axlsx
@@ -15,7 +15,7 @@ wb.styles do |style|
 
   name = "#{@_current_course.name}课程目标"
   wb.add_worksheet(name: name) do |sheet|
-    sheet.add_row name, style: title_style
+    sheet.add_row [name], style: title_style
 
     sheet.add_row []
     sheet.add_row []
diff --git a/app/views/ecs/ec_courses/search.json.jbuilder b/app/views/ecs/ec_courses/search.json.jbuilder
index fc22586d7..cf00a2b98 100644
--- a/app/views/ecs/ec_courses/search.json.jbuilder
+++ b/app/views/ecs/ec_courses/search.json.jbuilder
@@ -1,2 +1,2 @@
 json.count @count
-json.ec_courses @ec_courses, partial: 'shared/ec_course_slim', as: :ec_course
\ No newline at end of file
+json.ec_courses @ec_courses, partial: 'ecs/ec_courses/shared/ec_course_slim', as: :ec_course
\ No newline at end of file
diff --git a/app/views/ecs/ec_graduation_requirements/index.json.jbuilder b/app/views/ecs/ec_graduation_requirements/index.json.jbuilder
index 6fbbf249b..ffb83ed23 100644
--- a/app/views/ecs/ec_graduation_requirements/index.json.jbuilder
+++ b/app/views/ecs/ec_graduation_requirements/index.json.jbuilder
@@ -1,3 +1,3 @@
 
 json.count @graduation_requirements.size
-json.graduation_requirements @graduation_requirements, partial: 'shared/ec_graduation_requirement', as: :ec_graduation_requirement
+json.graduation_requirements @graduation_requirements, partial: '/ecs/ec_graduation_requirements/shared/ec_graduation_requirement', as: :ec_graduation_requirement
diff --git a/app/views/ecs/ec_graduation_requirements/index.xlsx.axlsx b/app/views/ecs/ec_graduation_requirements/index.xlsx.axlsx
index aeb802329..9a2081861 100644
--- a/app/views/ecs/ec_graduation_requirements/index.xlsx.axlsx
+++ b/app/views/ecs/ec_graduation_requirements/index.xlsx.axlsx
@@ -6,15 +6,15 @@ wb = xlsx_package.workbook
 wb.styles do |style|
   title_style = style.add_style(sz: 16, height: 20, b: true)
   ec_year_style = style.add_style(sz: 10, height: 14)
-  label_style = style.add_style(sz: 11, b: true, bg_color: '90EE90', alignment: { horizontal: :center })
+  label_style = style.add_style(sz: 11, b: true, bg_color: '90EE90', alignment: { horizontal: :center, vertical: :center })
   content_style = style.add_style(sz: 11, height: 16, border: { style: :thin, color: '000000' })
 
   wb.add_worksheet(:name => '毕业要求及指标点') do |sheet|
-    sheet.add_row '毕业要求及指标点', style: title_style
+    sheet.add_row ['毕业要求及指标点'], style: title_style
 
     sheet.add_row []
 
-    sheet.add_row ['专业代码', major.code], style: ec_year_style
+    sheet.add_row ['专业代码', major.code.to_s + ' '], style: ec_year_style
     sheet.add_row ['专业名称', major.name], style: ec_year_style
     sheet.add_row ['学年', "#{ec_year.year}学年"], style: ec_year_style
 
@@ -32,12 +32,15 @@ wb.styles do |style|
       end
 
       items_size = requirement.ec_graduation_subitems.size
-      sheet.merge_cells("A#{index}:A#{index + items_size}")
-      sheet.merge_cells("B#{index}:B#{index + items_size}")
+      if items_size.zero?
+        sheet.add_row [requirement_content, ''], style: content_style
+      else
+        sheet.merge_cells("A#{index + 1}:A#{index + items_size}")
+      end
 
       index += items_size
     end
 
-    sheet.column_widths [400, 400]
+    sheet.column_widths 100, 100
   end
 end
\ No newline at end of file
diff --git a/app/views/ecs/ec_graduation_requirements/show.json.jbuilder b/app/views/ecs/ec_graduation_requirements/show.json.jbuilder
index 562c255a9..d3a8db1fc 100644
--- a/app/views/ecs/ec_graduation_requirements/show.json.jbuilder
+++ b/app/views/ecs/ec_graduation_requirements/show.json.jbuilder
@@ -1,2 +1,2 @@
 
-json.partial! 'shared/ec_graduation_requirement', ec_graduation_requirement: @graduation_requirement
+json.partial! 'ecs/ec_graduation_requirements/shared/ec_graduation_requirement', ec_graduation_requirement: @graduation_requirement
diff --git a/app/views/ecs/ec_major_schools/index.json.jbuilder b/app/views/ecs/ec_major_schools/index.json.jbuilder
index 0924b71ea..312abd26b 100644
--- a/app/views/ecs/ec_major_schools/index.json.jbuilder
+++ b/app/views/ecs/ec_major_schools/index.json.jbuilder
@@ -3,7 +3,7 @@ json.count @count
 
 # 示例专业
 json.template_ec_major_school do
-  json.partial! 'ecs/ec_major_schools/shared/ec_major_school', ec_major_school: @template_major_school
+  json.partial! 'ecs/ec_major_schools/shared/ec_major_school', ec_major_school: @template_major_school if @template_major_school
 end
 
 # 专业
@@ -11,5 +11,5 @@ json.ec_major_schools @major_schools do |ec_major_school|
   json.partial! 'ecs/ec_major_schools/shared/ec_major_school', ec_major_school: ec_major_school
 
   # 专业管理员
-  json.major_managers ec_major_school.users, partial: 'ecs/ec_major_schools/shared/ec_major_school', as: :user
+  json.major_managers ec_major_school.users, partial: 'users/user_simple', as: :user
 end
diff --git a/app/views/ecs/ec_major_schools/show.json.jbuilder b/app/views/ecs/ec_major_schools/show.json.jbuilder
new file mode 100644
index 000000000..7c911d824
--- /dev/null
+++ b/app/views/ecs/ec_major_schools/show.json.jbuilder
@@ -0,0 +1,6 @@
+json.extract! @major, :id, :code, :name, :template_major
+json.school_id @major.school.id
+json.school_name @major.school.name
+
+can_manager = @major.manager?(current_user) || @major.school.manager?(current_user) || current_user.admin_or_business?
+json.can_manager can_manager
\ No newline at end of file
diff --git a/app/views/ecs/ec_majors/index.json.jbuilder b/app/views/ecs/ec_majors/index.json.jbuilder
index 34ee9a907..df3373fed 100644
--- a/app/views/ecs/ec_majors/index.json.jbuilder
+++ b/app/views/ecs/ec_majors/index.json.jbuilder
@@ -1,2 +1,7 @@
 json.count @count
-json.es_majors @ec_majors, partial: 'ecs/majors/shared/ec_major', as: :ec_major
+json.ec_majors do
+  json.array! @ec_majors.each do |major|
+    json.extract! major, :id, :name, :code
+    json.selected @major_ids.include?(major.id)
+  end
+end
diff --git a/app/views/ecs/ec_training_objectives/shared/_ec_training_objective.json.jbuilder b/app/views/ecs/ec_training_objectives/shared/_ec_training_objective.json.jbuilder
index 83414d2f4..61992d8e1 100644
--- a/app/views/ecs/ec_training_objectives/shared/_ec_training_objective.json.jbuilder
+++ b/app/views/ecs/ec_training_objectives/shared/_ec_training_objective.json.jbuilder
@@ -1,3 +1,3 @@
 json.extract! ec_training_objective, :id, :content
 
-json.ec_training_items ec_training_objective.ec_training_subitems, partial: 'ec_training_subitem', as: :ec_training_subitem
+json.ec_training_items ec_training_objective.ec_training_subitems, partial: '/ecs/ec_training_objectives/shared/ec_training_subitem', as: :ec_training_subitem
diff --git a/app/views/ecs/ec_training_objectives/show.json.jbuilder b/app/views/ecs/ec_training_objectives/show.json.jbuilder
index a37fa1c09..00825be4c 100644
--- a/app/views/ecs/ec_training_objectives/show.json.jbuilder
+++ b/app/views/ecs/ec_training_objectives/show.json.jbuilder
@@ -1 +1 @@
-json.partial! 'shared/ec_training_objective', ec_training_objective: @training_objective
+json.partial! '/ecs/ec_training_objectives/shared/ec_training_objective', ec_training_objective: @training_objective
diff --git a/app/views/ecs/ec_training_objectives/show.xlsx.axlsx b/app/views/ecs/ec_training_objectives/show.xlsx.axlsx
index 4746be0ea..130e80e6b 100644
--- a/app/views/ecs/ec_training_objectives/show.xlsx.axlsx
+++ b/app/views/ecs/ec_training_objectives/show.xlsx.axlsx
@@ -6,11 +6,11 @@ wb = xlsx_package.workbook
 wb.styles do |style|
   title_style = style.add_style(sz: 16, height: 20, b: true)
   ec_year_style = style.add_style(sz: 10, height: 14)
-  label_style = style.add_style(sz: 11, b: true, bg_color: '90EE90', alignment: { horizontal: :center })
+  label_style = style.add_style(sz: 11, b: true, bg_color: '90EE90', border: { style: :thin, color: '000000' }, alignment: { horizontal: :center, vertical: :center })
   content_style = style.add_style(sz: 11, height: 16, border: { style: :thin, color: '000000' })
 
   wb.add_worksheet(:name => '培养目标及目标分解') do |sheet|
-    sheet.add_row '培养目标及目标分解', style: title_style
+    sheet.add_row ['培养目标及目标分解'], style: title_style
 
     sheet.add_row []
     sheet.add_row []
@@ -27,6 +27,6 @@ wb.styles do |style|
     end
 
     items_size = training_objective.ec_training_subitems.size
-    sheet.merge_cells("A9:A#{9 + items_size}")
+    sheet.merge_cells("A9:A#{9 + items_size - 1}")
   end
 end
\ No newline at end of file
diff --git a/app/views/ecs/ec_years/index.json.jbuilder b/app/views/ecs/ec_years/index.json.jbuilder
index c5c89cd06..b0a8985b2 100644
--- a/app/views/ecs/ec_years/index.json.jbuilder
+++ b/app/views/ecs/ec_years/index.json.jbuilder
@@ -8,7 +8,16 @@ json.ec_years do
     json.training_subitem_count @training_subitem_count_map.fetch(ec_year.id, 0)
     json.graduation_requirement_count @graduation_requirement_count_map.fetch(ec_year.id, 0)
     json.course_count @course_count_map.fetch(ec_year.id, 0)
-    json.course_target_count @course_target_count_map.fetch(ec_year.id, 0)
-    json.graduation_subitem_count @graduation_subitem_count_map.fetch(ec_year.id, 0)
+
+    course_target = @course_target_count_map.fetch(ec_year.id, 0)
+    graduation_subitem = @graduation_subitem_count_map.fetch(ec_year.id, 0)
+    achieved_course = achieved_graduation_course_count(ec_year)
+    achieved_objective = achieved_graduation_objective_count(ec_year)
+
+    json.course_target_count course_target
+    json.graduation_subitem_count graduation_subitem
+    json.achieved_graduation_course_count achieved_course
+    json.achieved_graduation_objective_count achieved_objective
+    json.status graduation_subitem == achieved_objective ? 'achieved' : 'not_achieved'
   end
 end
\ No newline at end of file
diff --git a/app/views/ecs/ec_years/show.json.jbuilder b/app/views/ecs/ec_years/show.json.jbuilder
new file mode 100644
index 000000000..ba8333086
--- /dev/null
+++ b/app/views/ecs/ec_years/show.json.jbuilder
@@ -0,0 +1,13 @@
+json.extract! @year, :id, :year
+
+major = @year.ec_major_school
+json.major_id major.id
+json.major_name major.name
+json.major_code major.code
+
+school = major.school
+json.school_id school.id
+json.school_name school.name
+
+can_manager = major.manager?(current_user) || school.manager?(current_user) || current_user.admin_or_business?
+json.can_manager can_manager
\ No newline at end of file
diff --git a/app/views/ecs/graduation_course_supports/create.json.jbuilder b/app/views/ecs/graduation_course_supports/create.json.jbuilder
index c05024911..d8749a5dc 100644
--- a/app/views/ecs/graduation_course_supports/create.json.jbuilder
+++ b/app/views/ecs/graduation_course_supports/create.json.jbuilder
@@ -1 +1 @@
-json.partial! 'shared/ec_graduation_subitem', ec_graduation_subitem: @graduation_subitem
+json.partial! 'ecs/graduation_course_supports/shared/ec_graduation_subitem', ec_graduation_subitem: @graduation_subitem
diff --git a/app/views/ecs/graduation_course_supports/shared/_ec_graduation_subitem.json.jbuilder b/app/views/ecs/graduation_course_supports/shared/_ec_graduation_subitem.json.jbuilder
index 1ffe12ec4..aee77c5b7 100644
--- a/app/views/ecs/graduation_course_supports/shared/_ec_graduation_subitem.json.jbuilder
+++ b/app/views/ecs/graduation_course_supports/shared/_ec_graduation_subitem.json.jbuilder
@@ -3,3 +3,4 @@ json.extract! ec_graduation_subitem, :id, :position, :content, :ec_graduation_re
 json.graduation_requirement_position ec_graduation_subitem.ec_graduation_requirement.position
 
 json.course_supports ec_graduation_subitem.ec_course_supports, partial: 'ec_course_support', as: :ec_course_support
+json.weights_total ec_graduation_subitem.ec_course_supports.to_a.sum(&:weights)
diff --git a/app/views/ecs/graduation_course_supports/show.json.jbuilder b/app/views/ecs/graduation_course_supports/show.json.jbuilder
index a9e4bdc22..495f9c6a9 100644
--- a/app/views/ecs/graduation_course_supports/show.json.jbuilder
+++ b/app/views/ecs/graduation_course_supports/show.json.jbuilder
@@ -1,3 +1,3 @@
 json.course_count @course_count
-json.graduation_subitems @graduation_subitems, partial: 'shared/ec_graduation_subitem', as: :ec_graduation_subitem
+json.graduation_subitems @graduation_subitems, partial: 'ecs/graduation_course_supports/shared/ec_graduation_subitem', as: :ec_graduation_subitem
 json.count @graduation_subitems.size
diff --git a/app/views/ecs/graduation_course_supports/show.xlsx.axlsx b/app/views/ecs/graduation_course_supports/show.xlsx.axlsx
index fd1a44935..e2c2599ec 100644
--- a/app/views/ecs/graduation_course_supports/show.xlsx.axlsx
+++ b/app/views/ecs/graduation_course_supports/show.xlsx.axlsx
@@ -14,7 +14,7 @@ wb.styles do |style|
   tip_style = style.add_style(sz: 11, height: 16, color: 'FFA07A')
 
   wb.add_worksheet(:name => '课程体系对毕业要求的支撑') do |sheet|
-    sheet.add_row '课程体系VS毕业要求', style: title_style
+    sheet.add_row ['课程体系VS毕业要求'], style: title_style
     sheet.merge_cells wb.rows.first.cells[(1..(3 + max_support_length - 1))]
 
     sheet.add_row []
diff --git a/app/views/ecs/homes/index.json.jbuilder b/app/views/ecs/homes/index.json.jbuilder
index 9bf21f056..8546f6c4a 100644
--- a/app/views/ecs/homes/index.json.jbuilder
+++ b/app/views/ecs/homes/index.json.jbuilder
@@ -13,4 +13,4 @@ json.school do
   json.name current_school.name
 end
 
-json.school_managers @school_managers, partial: 'ecs/shared/user', as: :user
+json.school_managers @school_managers, partial: 'users/user_simple', as: :user
diff --git a/app/views/ecs/major_managers/create.json.jbuilder b/app/views/ecs/major_managers/create.json.jbuilder
deleted file mode 100644
index ff7ff01e5..000000000
--- a/app/views/ecs/major_managers/create.json.jbuilder
+++ /dev/null
@@ -1 +0,0 @@
-json.partial! 'ecs/shared/user', user: @user
diff --git a/app/views/ecs/reach_evaluations/show.xlsx.axlsx b/app/views/ecs/reach_evaluations/show.xlsx.axlsx
index a62e4f6c2..a79d059a3 100644
--- a/app/views/ecs/reach_evaluations/show.xlsx.axlsx
+++ b/app/views/ecs/reach_evaluations/show.xlsx.axlsx
@@ -10,7 +10,7 @@ wb.styles do |style|
   content_style = style.add_style(sz: 11, height: 16, border: { style: :thin, color: '000000' })
 
   wb.add_worksheet(name: '达成度-毕业要求综合评价报表') do |sheet|
-    sheet.add_row '培养目标及目标分解', style: title_style
+    sheet.add_row ['达成度-毕业要求综合评价报表'], style: title_style
     sheet.merge_cells("A1:D1")
 
     sheet.add_row []
diff --git a/app/views/ecs/requirement_support_objectives/show.json.jbuilder b/app/views/ecs/requirement_support_objectives/show.json.jbuilder
index 1ba783304..642a5f10c 100644
--- a/app/views/ecs/requirement_support_objectives/show.json.jbuilder
+++ b/app/views/ecs/requirement_support_objectives/show.json.jbuilder
@@ -1,4 +1,4 @@
 
 json.graduation_requirements @graduation_requirements, partial: 'ecs/ec_graduation_requirements/shared/ec_graduation_requirement', as: :ec_graduation_requirement
 json.training_subitems @training_subitems, partial: 'ecs/ec_training_subitems/shared/ec_training_subitem', as: :ec_training_subitem
-json.requirement_support_objectives @requirement_support_objectives, partial: 'shared/requirement_support_objective', as: :requirement_support_objective
+json.requirement_support_objectives @requirement_support_objectives, partial: 'ecs/requirement_support_objectives/shared/requirement_support_objective', as: :requirement_support_objective
diff --git a/app/views/ecs/requirement_support_objectives/show.xlsx.axlsx b/app/views/ecs/requirement_support_objectives/show.xlsx.axlsx
index 934ad2941..6534ce36a 100644
--- a/app/views/ecs/requirement_support_objectives/show.xlsx.axlsx
+++ b/app/views/ecs/requirement_support_objectives/show.xlsx.axlsx
@@ -16,7 +16,7 @@ wb.styles do |style|
   content_style = style.add_style(sz: 11, height: 16, border: { style: :thin, color: '000000' })
 
   wb.add_worksheet(:name => '毕业要求对培养目标的支撑') do |sheet|
-    sheet.add_row '毕业要求 vs 培养目标矩阵', style: title_style
+    sheet.add_row ['毕业要求 vs 培养目标矩阵'], style: title_style
 
     sheet.merge_cells wb.rows.first.cells[(1..subitem_size)]
 
diff --git a/app/views/ecs/score_levels/show.json.jbuilder b/app/views/ecs/score_levels/show.json.jbuilder
index 0c8b76d86..dcdf63cdc 100644
--- a/app/views/ecs/score_levels/show.json.jbuilder
+++ b/app/views/ecs/score_levels/show.json.jbuilder
@@ -1 +1 @@
-json.score_levels @score_levels, partial: 'shared/ec_score_level', as: :ec_score_level
+json.score_levels @score_levels, partial: 'ecs/score_levels/shared/ec_score_level', as: :ec_score_level
diff --git a/app/views/ecs/students/show.json.jbuilder b/app/views/ecs/students/show.json.jbuilder
index 352970055..468a1cfe3 100644
--- a/app/views/ecs/students/show.json.jbuilder
+++ b/app/views/ecs/students/show.json.jbuilder
@@ -1,2 +1,2 @@
 json.count @count
-json.students @students, partial: 'shared/ec_year_student', as: :ec_year_student
\ No newline at end of file
+json.students @students, partial: 'ecs/students/shared/ec_year_student', as: :ec_year_student
\ No newline at end of file
diff --git a/app/views/ecs/subitem_support_standards/show.json.jbuilder b/app/views/ecs/subitem_support_standards/show.json.jbuilder
index 94fd6c5a0..a92fe7000 100644
--- a/app/views/ecs/subitem_support_standards/show.json.jbuilder
+++ b/app/views/ecs/subitem_support_standards/show.json.jbuilder
@@ -1,4 +1,4 @@
 
 json.graduation_standards @graduation_standards, partial: 'ecs/shared/ec_graduation_standard', as: :ec_graduation_standard
 json.graduation_subitems @graduation_subitems, partial: 'ecs/shared/ec_graduation_subitem', as: :ec_graduation_subitem
-json.subitem_support_standards @subitem_support_standards, partial: 'shared/subitem_support_standard', as: :subitem_support_standard
+json.subitem_support_standards @subitem_support_standards, partial: 'ecs/subitem_support_standards/shared/subitem_support_standard', as: :subitem_support_standard
diff --git a/app/views/ecs/subitem_support_standards/show.xlsx.axlsx b/app/views/ecs/subitem_support_standards/show.xlsx.axlsx
index e12f517f3..8329a27ee 100644
--- a/app/views/ecs/subitem_support_standards/show.xlsx.axlsx
+++ b/app/views/ecs/subitem_support_standards/show.xlsx.axlsx
@@ -17,7 +17,7 @@ wb.styles do |style|
   content_style = style.add_style(sz: 11, height: 16, border: { style: :thin, color: '000000' })
 
   wb.add_worksheet(:name => '毕业要求对通用标准的支撑') do |sheet|
-    sheet.add_row '毕业要求 vs 通用标准矩阵', style: title_style
+    sheet.add_row ['毕业要求 vs 通用标准矩阵'], style: title_style
 
     sheet.merge_cells wb.rows.first.cells[(1..standards_size)]
 
diff --git a/app/views/ecs/users/index.json.jbuilder b/app/views/ecs/users/index.json.jbuilder
new file mode 100644
index 000000000..0109b9ca0
--- /dev/null
+++ b/app/views/ecs/users/index.json.jbuilder
@@ -0,0 +1,12 @@
+json.count @count
+json.users do
+  json.array! @users.each do |user|
+    json.id user.id
+    json.name user.real_name
+    json.identity user.identity
+    json.school_name user.school_name
+    json.department_name user.department_name
+    json.phone Util.conceal(user.phone, :phone)
+    json.manager @manager_ids.include?(user.id)
+  end
+end
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index e26016ab8..d759ab9bd 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -710,14 +710,15 @@ Rails.application.routes.draw do
 
     # 为避免url过长以及层级过深,路由定义和controller继承都做了处理
     scope module: :ecs do
-      resources :ec_major_schools, only: [] do
+      resources :ec_major_schools, only: [:show] do
+        resources :users, only: [:index]
         resources :major_managers, only: [:create, :destroy]
-        resources :ec_years, only: [:index, :create, :destroy]
+        resources :ec_years, only: [:index, :show, :create, :destroy]
       end
 
       resources :ec_years, only: [] do
         resource :ec_training_objectives, only: [:show, :create]
-        resources :ec_graduation_requirements, only: [:index, :create]
+        resources :ec_graduation_requirements, only: [:index, :create, :update, :destroy]
         resource :requirement_support_objectives, only: [:show, :create, :destroy]
         resource :subitem_support_standards, only: [:show, :create, :destroy]
         resource :students, only: [:show, :destroy] do
diff --git a/db/migrate/20190911080150_change_ec_course_supports.rb b/db/migrate/20190911080150_change_ec_course_supports.rb
new file mode 100644
index 000000000..07c3a536d
--- /dev/null
+++ b/db/migrate/20190911080150_change_ec_course_supports.rb
@@ -0,0 +1,11 @@
+class ChangeEcCourseSupports < ActiveRecord::Migration[5.2]
+  def change
+    add_column :ec_course_supports, :ec_graduation_subitem_id, :integer, index: true
+
+    execute <<-SQL
+      UPDATE ec_course_supports ecs SET ec_graduation_subitem_id = (
+        SELECT ec_graduation_subitem_id FROM ec_graduation_subitem_courses egsc WHERE egsc.ec_course_support_id = ecs.id
+      )
+    SQL
+  end
+end
diff --git a/public/react/config/webpack.config.dev.js b/public/react/config/webpack.config.dev.js
index 8045580e9..a04ec614c 100644
--- a/public/react/config/webpack.config.dev.js
+++ b/public/react/config/webpack.config.dev.js
@@ -32,7 +32,7 @@ module.exports = {
   // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
 	// devtool: "cheap-module-eval-source-map",
   // 开启调试
-  devtool: "eval",  // 开启调试
+  // devtool: "eval",  // 开启调试
   // These are the "entry points" to our application.
   // This means they will be the "root" imports that are included in JS bundle.
   // The first two entry points enable "hot" CSS and auto-refreshes for JS.
@@ -197,6 +197,21 @@ module.exports = {
               },
             ],
           },
+          {
+            test: /\.scss$/,
+            use: [
+              require.resolve("style-loader"),
+              {
+                loader: require.resolve("css-loader"),
+                options: {
+                  importLoaders: 1,
+                },
+              },
+              {
+                loader: require.resolve("sass-loader")
+              }
+            ],
+          },
           // "file" loader makes sure those assets get served by WebpackDevServer.
           // When you `import` an asset, you get its (virtual) filename.
           // In production, they would get copied to the `build` folder.
diff --git a/public/react/config/webpack.config.prod.js b/public/react/config/webpack.config.prod.js
index 27512b1dc..84dbffd3b 100644
--- a/public/react/config/webpack.config.prod.js
+++ b/public/react/config/webpack.config.prod.js
@@ -224,6 +224,23 @@ module.exports = {
             ),
             // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
           },
+          {
+            test: /\.scss$/,
+            use: [
+              require.resolve("style-loader"),
+              {
+                loader: require.resolve("css-loader"),
+                options: {
+                  importLoaders: 1,
+                  minimize: true,
+                  sourceMap: shouldUseSourceMap,
+                },
+              },
+              {
+                loader: require.resolve("sass-loader")
+              }
+            ],
+          },
           // "file" loader makes sure assets end up in the `build` folder.
           // When you `import` an asset, you get its filename.
           // This loader doesn't use a "test" so it will catch all modules
diff --git a/public/react/package.json b/public/react/package.json
index 84dec6d11..e91e61f03 100644
--- a/public/react/package.json
+++ b/public/react/package.json
@@ -5,7 +5,7 @@
   "dependencies": {
     "@icedesign/base": "^0.2.5",
     "@novnc/novnc": "^1.1.0",
-    "antd": "^3.20.1",
+    "antd": "^3.23.2",
     "array-flatten": "^2.1.2",
     "autoprefixer": "7.1.6",
     "axios": "^0.18.0",
@@ -163,6 +163,8 @@
     "babel-plugin-import": "^1.11.0",
     "concat": "^1.0.3",
     "happypack": "^5.0.1",
+    "node-sass": "^4.12.0",
+    "sass-loader": "^7.3.1",
     "webpack-bundle-analyzer": "^3.0.3",
     "webpack-parallel-uglify-plugin": "^1.1.0"
   }
diff --git a/public/react/src/App.js b/public/react/src/App.js
index e243553bb..9b85acfa8 100644
--- a/public/react/src/App.js
+++ b/public/react/src/App.js
@@ -262,6 +262,11 @@ const Help = Loadable({
 	loading: Loading,
 })
 
+const Ecs = Loadable({
+	loader: () => import('./modules/ecs/Ecs'),
+	loading: Loading,
+})
+
 class App extends Component {
 	constructor(props) {
 		super(props)
@@ -475,6 +480,10 @@ class App extends Component {
 										 render={
 											 (props)=>(<Help {...this.props} {...props} {...this.state}></Help>)
 										 }/>
+							<Route path="/ecs"
+										 render={
+											 (props)=>(<Ecs {...this.props} {...props} {...this.state}></Ecs>)
+										 }/>
 							<Route exact path="/" component={ShixunsHome}/>
 							<Route component={Shixunnopage}/>
 
diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js
index 0eb6b50cd..207f1c916 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 {
@@ -48,8 +48,7 @@ export function initAxiosInterceptors(props) {
         proxy="https://test-newweb.educoder.net"
 
     // wy
-        // proxy="http://192.168.2.63:3001"
-
+    //     proxy="http://192.168.2.63:3001"
 
     // 在这里使用requestMap控制,避免用户通过双击等操作发出重复的请求;
     // 如果需要支持重复的请求,考虑config里面自定义一个allowRepeat参考来控制
diff --git a/public/react/src/images/ecs/bg.jpg b/public/react/src/images/ecs/bg.jpg
new file mode 100644
index 000000000..c2abdb6a7
Binary files /dev/null and b/public/react/src/images/ecs/bg.jpg differ
diff --git a/public/react/src/modules/ecs/EcSetting/CourseSupports/ecCourseSupports.css b/public/react/src/modules/ecs/EcSetting/CourseSupports/ecCourseSupports.css
new file mode 100644
index 000000000..3f1dc000a
--- /dev/null
+++ b/public/react/src/modules/ecs/EcSetting/CourseSupports/ecCourseSupports.css
@@ -0,0 +1,352 @@
+.eaSystemp a{
+  color:#05101a;
+}
+.eaSystemp span{
+  color: #05101a !important;
+}
+.eacourse p{
+  height:84px;
+  margin-bottom:0px !important;
+}
+.eacourse #training_objective_contents{
+   height:81px;
+}
+.courseSystem{
+font-size:18px;
+font-family:MicrosoftYaHei;
+font-weight:400;
+line-height:45px;
+color:rgba(5,16,26,1);
+}
+.SystemParameters{
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  line-height:45px;
+  color:rgba(50,50,50,1);
+}
+.Systemnum{
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  color:#FF6800;
+}
+.newSystem{
+  width:1200px;
+  overflow:auto;
+  background: #FFF;
+}
+.newSystem .clearfix .column-1{
+  width: 113px !important;
+  text-align: center;
+}
+.operationColumn{
+  margin: 0px 10%;
+  width:100%;
+  height:100%;
+}
+.operationalter{
+  margin: 20px 16px;
+}
+.SystemModifythelist  .column-1{
+  width: 120px !important;
+  text-align: center;
+}
+
+.SystemModifythelist  .column-3{
+  padding-left: 96px;
+  margin-right: 23px;
+}
+.operationright{
+  float:right !important;
+}
+
+.newSystem p{
+  /*padding: 10px 33px !important;*/
+  margin-bottom: 0em;
+}
+.newSystem li{
+  margin:0 !important;
+}
+.SystemModifythelist{
+  background:#FFF !important;
+}
+
+.SystemModifythelist  .column-1:nth-child(1){
+  margin-left: 7px;
+}
+
+.Systempoint{
+  font-size:12px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  color:rgba(152,152,152,1);
+}
+.editorModify{
+  background:#FFF !important;
+}
+.newSystem .editorModify .column-1{
+  width: 194px !important;
+  text-align: left;
+  margin-left: 30px;
+}
+.newSystem .editorModify .column-1:nth-child(1){
+  margin-right: 510px;
+}
+.editorModify .ant-select{
+  width: 556px  !important;
+  margin-left: 36px;
+}
+.editorModify .ant-select .ant-select-selection{
+  height: 30px !important;
+}
+.editorModify .ant-select .ant-select-selection .ant-select-selection__rendered{
+  height: 30px !important;
+}
+.editorModify .ant-select .ant-select-selection .ant-select-selection__rendered .ant-select-selection-selected-value{
+  line-height: 30px !important;
+}
+.inputWeight{
+ width: 20%;
+ font-size:14px;
+ height:30px;
+ margin-left: 20px;
+ background-color: #F5F5F5;
+}
+.SetTheAssociated{
+  width: 314px;
+  height: 30px;
+  float: right;
+  margin-right: -3.5%;
+}
+.SetTheAssociatedchild{
+  width: 120px;
+  height: 30px;
+  background: rgba(255,255,255,1);
+  border: 1px solid rgba(234,234,234,1);
+  border-radius: 4px;
+  float: left;
+  margin-right: 10px;
+  text-align: center;
+  line-height: 30px;
+  /*margin-left: 34px;*/
+}
+.operatebutton{
+  margin-left: 20px;
+  /* margin-top: 16px; */
+}
+.editbulebutton{
+  width:120px;
+  height:30px;
+  background:rgba(76,172,255,1);
+  border-radius:2px;
+  color:#FFF;
+  text-align: center;
+  line-height: 30px;
+}
+.editglybutton{
+  width:120px;
+  height:30px;
+  border:1px solid rgba(205,205,205,1);
+  border-radius:2px;
+  color:#999;
+  text-align: center;
+  line-height: 30px;
+}
+
+.editglybuttonbox{
+  width: 275px;
+  margin-bottom: 30px;
+  margin-right: 20px;
+  margin-right:7%;
+}
+.editglybuttonboxs{
+  width: 275px;
+  margin-bottom: 30px;
+  margin-right: 20px;
+  margin-right:3%;
+}
+.defalutCancelbtn:hover {
+  border: 1px solid #B2B2B2;
+  color: #B2B2B2!important;
+}
+
+.gouxuanbule{
+  color:#4CACFF;
+}
+.gouxuanwhite{
+  color:#FFF;
+}
+.icon-gouxuan{
+  cursor: pointer;
+}
+/* 谷歌 */
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+    -webkit-appearance: none;
+    appearance: none;
+    margin: 0;
+}
+/* 火狐 */
+input{
+    -moz-appearance:textfield;
+}
+.inputWeight{
+  text-indent:0.625rem;
+}
+
+.columnlocation{
+  height: 40px;
+  line-height: 40px;
+}
+.paddingLF{
+  padding:0 33px;
+}
+.width20{
+  width: 20px;
+  height: 20px;
+  text-align: center;
+}
+.defalutSubmitbtn,.defalutCancelbtn{
+  cursor: pointer;
+}
+.mb290{
+  margin-bottom:290px;
+}
+.Spinlarge{
+  text-align: center;
+  width: 100%;
+  margin-top: 25px;
+  margin-bottom: 25px;
+}
+.DDred{
+  color:#DD1717;
+}
+.color-666{
+  color:#666666 !important;
+}
+.color-05101A{
+  color:#05101A !important;
+}
+.ec_graduation_name{
+  margin-right:20px !important;
+}
+.column-width575{
+  color: transparent !important;
+}
+.column-width130{
+  width: 130px !important;
+  height: 40px;
+}
+
+
+.ListTableLine li>span {
+    max-width: 550px !important;
+}
+
+.graduateRequirement .clearfix .column-1 {
+    width: 76px!important;
+}
+
+.newrightcalculatebutton{
+  width: 50px;
+    height: 25px;
+    border: 1px solid rgba(76,172,255,1);
+    border-radius: 1px;
+    line-height: 25px;
+    text-align: center;
+    margin-top: 7px;
+    cursor: pointer;
+    color: rgba(76,172,255,1);
+}
+.columnbox{
+  height: 53px;
+  overflow: hidden;
+}
+
+.ant-modal-mask {
+  background-color: rgba(5,16,26,0.4);
+}
+.ecmodeldelet{
+  top:300px;
+}
+.ecmodeldelet .ant-modal-header{
+  padding: 0px 24px;
+}
+.ecmodeldelet .ant-modal-title{
+  padding: 0px 15px;
+  text-align: center;
+  box-sizing: border-box;
+  line-height: 70px;
+  height: 70px;
+  border-radius: 10px 10px 0px 0px;
+  font-size: 16px;
+  font-weight: bold;
+}
+.bor-red {
+  border: 1px solid #db0505 !important;
+}
+
+.ml93{
+  margin-left:93px;
+}
+.ml26{
+  margin-left: 26px;
+}
+.finishtarget{
+  width: 69px;
+  /* height: 48px; */
+  line-height: 20px;
+  text-align: center;
+  margin-right: 48px;
+}
+
+.bordereaeaea{
+  border-bottom: 1px solid transparent !important;
+}
+
+.heightimportant{
+  height: 30px !important;
+  background-color: #F5F5F5;
+}
+.heightimportant:focus {
+  background-color: #fff;
+}
+.inputWeight:focus {
+  background-color: #fff;
+ }
+.heightlineimportant{
+  line-height: 30px !important;
+}
+
+.ant-select-selection:hover{
+  border-color: #d9d9d9 !important;
+}
+.ant-input:focus {
+  outline: 0;
+  -webkit-box-shadow: 0 0 0 2px transparent !important;
+  box-shadow: 0 0 0 2px transparent !important;
+ }
+ .ant-input{
+  border-color: #d9d9d9 !important;
+ }
+ .ant-select-selection:focus{
+  -webkit-box-shadow: 0 0 0 2px transparent !important;
+  box-shadow: 0 0 0 2px transparent !important;
+ }
+ .ant-select-selection:active{
+  -webkit-box-shadow: 0 0 0 2px transparent !important;
+  box-shadow: 0 0 0 2px transparent !important;
+ }
+
+ .ant-select-selection:focus{
+  border-color: #d9d9d9 !important;
+ }
+ .ant-select-selection{
+  -webkit-box-shadow: 0 0 0 2px transparent !important;
+  box-shadow: 0 0 0 2px transparent !important;
+ }
+
+.mt60{
+  margin-top:60px;
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcSetting/CourseSupports/index.js b/public/react/src/modules/ecs/EcSetting/CourseSupports/index.js
new file mode 100644
index 000000000..e5d413601
--- /dev/null
+++ b/public/react/src/modules/ecs/EcSetting/CourseSupports/index.js
@@ -0,0 +1,594 @@
+import React, { Component } from 'react';
+
+import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
+
+import axios from 'axios';
+
+import { Select,message,Modal,Input,Spin,Icon,Tooltip  } from 'antd';
+
+import './ecCourseSupports.css';
+
+const $ = window.$;
+class CourseSupports extends Component {
+    constructor(props) {
+        super(props)
+        this.state={
+            data:'',
+            ec_courses_list:[],
+            editcourse:[{"weigths": 0,
+                "ec_course_name":'',
+                "top_relation": false,
+                "ec_course_id":''
+            }],
+            editnum:0,
+            index:0,
+            ec_graduation_subitem_id:0,
+            ec_year_id:0,
+            schooldata:{},
+            spinning:true,
+            ecComponentState:'ecCourseSupports',
+            supportid:null,
+            Editkey:null,
+            titlemessage:"提示",
+            Supportstype:false,
+            Supportslist:'',
+            Supportssum:false,
+            Supportsclass:false
+        }
+    }
+
+    componentWillMount(){
+        this.setState({
+            ec_year_id:this.props.match.params.ec_year_id,
+            major_school_id:this.props.match.params.major_school_id
+        })
+        window.document.title = '课程体系 vs 毕业要求';
+    }
+
+    UpdateClassData=()=>{
+
+        let ec_year_id=this.props.match.params.ec_year_id;
+
+        this.setState({
+            ec_year_id:ec_year_id
+        })
+
+        const url = `/ec_years/${ec_year_id}/graduation_course_supports.json`;
+        axios.get(url)
+				.then((response) => {
+						if(response.status===200){
+								this.setState({
+										data:response.data
+								})
+						}
+						if(response.data.graduation_subitems.length===0){
+								this.setState({
+										Supportstype:true,
+										Supportslist:'数据为空,请去毕业要求——>毕业要求指标点分解列表配置数据'
+								})
+						}
+				})
+				.catch(function (error) {
+						console.log(error);
+				});
+
+    }
+    componentDidMount(){
+        this.setState({
+            ec_year_id:this.props.match.params.ec_year_id,
+            major_school_id:this.props.match.params.major_school_id
+        })
+        this.UpdateClassData();
+
+    }
+    EditSupportCourse=(key,e)=>{
+        $('#school_major_list').scrollLeft(0);
+        let id=e.target.id;
+        id=parseInt(id);
+
+        let subindex =e.target.getAttribute("subindex");
+        const url = `/ec_course_supports/edit_require_vs_course?subitem_id=`+id
+        axios.get(url)
+            .then((response) => {
+
+                if(response.status===200){
+                    var support_data;
+                    if(response.data.edit_support_data.length>0){
+                        support_data=response.data.edit_support_data;
+                    }else if(response.data.edit_support_data.length===0){
+                        support_data=[{weights: 0,top_relation: false,ec_course_name:'',ec_course_id:''}];
+                    }
+
+                    this.setState({
+                        ec_courses_list:response.data.ec_courses_list,
+                        editcourse:support_data,
+                        index:subindex,
+                        ec_graduation_subitem_id:id,
+                        Supportssum:false,
+                        Supportsclass:false,
+                    })
+
+                    let {editcourse} =this.state;
+                    let neweditcourse=editcourse;
+                    let newnum=0;
+                    for(var j=0;j<neweditcourse.length;j++){
+                        if(neweditcourse[j].weigths===undefined){
+                            newnum=0
+                        }else{
+                            newnum=newnum+neweditcourse[j].weigths;
+                        }
+                    }
+                    newnum= Math.round(newnum*100)/100;
+
+                    this.setState({
+                        editnum:newnum
+                    })
+                }
+
+            })
+            .catch(function (error) {
+                console.log(error);
+            });
+
+        this.setState({
+            Editkey:key
+        })
+        // $("#school_ListTableLine").show();
+        // let offsettop=$("#school_ListTableLine").position().top||$("#school_ListTableLine").scrollTop || $("#school_ListTableLine").pageYOffset;
+        // window.scrollTo(0, offsettop)
+    }
+
+    Addcourse=(e)=>{
+        let {editcourse} =this.state;
+        let neweditcourse=editcourse;
+        let newadd = {weigths: 0,top_relation: false,ec_course_name:'',ec_course_id:''};
+        neweditcourse.push(newadd);
+        this.setState({
+            editcourse:neweditcourse
+        })
+    }
+    editcourse=(neweditcourse)=>{
+        this.setState({
+            editcourse:neweditcourse
+        })
+
+    }
+
+    Deletcourse=(e)=>{
+        // 删除
+        // let id =e.target.getAttribute("index");
+        let {editcourse} = this.state;
+        let neweditcourse=editcourse;
+        neweditcourse.splice(e,1);
+        let newnum=0;
+        for(var j=0;j<neweditcourse.length;j++){
+            if(neweditcourse[j].weigths===undefined){
+                newnum=0
+            }else{
+                newnum=newnum+neweditcourse[j].weigths;
+            }
+        }
+        newnum= Math.round(newnum*100)/100;
+        this.setState({
+            Supportstype:false,
+            supportid:null,
+            Supportslist:"",
+            editcourse:neweditcourse,
+            editnum:newnum
+        })
+    }
+
+    enterweight=(e)=>{
+        let {editcourse} = this.state;
+        let neweditcourse=editcourse;
+        var id=e.target.id;
+        var value=parseFloat(e.target.value);
+        if(isNaN(value)){
+            value=""
+        }
+        var x = String(value).indexOf('.') + 1;
+        var y = String(value).length - x;
+        if(y > 2){
+            this.setState({
+                // Supportstype:true,
+                Supportslist:'请精确到2位数',
+                Supportssum:true
+            })
+            return
+        }
+
+
+        const person = new Object ();
+        person.weigths=value;
+        person.ec_course_id= neweditcourse[id].ec_course_id;
+        person.ec_course_name=neweditcourse[id].ec_course_name;
+        person.top_relation=neweditcourse[id].top_relation;
+
+
+        neweditcourse[id]=person;
+
+        let newnum=0;
+        for(var j=0;j<neweditcourse.length;j++){
+
+            if(neweditcourse[j].weigths===undefined){
+                newnum=newnum+0;
+            }else if(neweditcourse[j].weigths===""){
+                newnum=newnum+0;
+            }else{
+                newnum=newnum+neweditcourse[j].weigths;
+            }
+
+        }
+        newnum= Math.round(newnum*100)/100;
+        this.setState({
+            editnum:newnum,
+            editcourse:neweditcourse
+        })
+        if(newnum>1){
+            this.setState({
+                // Supportstype:true,
+                Supportslist:'权重之和不能大于1',
+                Supportssum:true
+            })
+        }
+
+    }
+    handleChange=(e)=> {
+
+        let {editcourse} = this.state;
+        let value=`${e[0]}`;
+        value=parseInt(value)
+        let neweditcourse=editcourse;
+        let num=`${e[1]}`;
+        num=parseInt(num)
+
+        for(var z=0;z<editcourse.length;z++){
+            if(neweditcourse[z].ec_course_name===`${e[2]}`){
+                this.setState({
+                    Supportstype:true,
+                    Supportslist:"请勿选择重复的支持课程"
+                })
+                return
+            }
+        }
+        for(var i=0;i<1;i++){
+            neweditcourse[num].ec_course_id=value;
+            neweditcourse[num].ec_course_name=`${e[2]}`
+        }
+
+        this.editcourse(neweditcourse);
+    }
+
+    relevancetop=(e)=>{
+
+        let {editcourse} = this.state;
+        let neweditcourse=editcourse;
+        let id =e.target.getAttribute("itindex");
+        for(var i=0;i<1;i++){
+            neweditcourse[id].top_relation=false;
+        }
+
+        this.editcourse(neweditcourse);
+    }
+
+    relevancebottom=(e)=>{
+
+        let {editcourse} = this.state;
+        let neweditcourse=editcourse;
+        let id =e.target.getAttribute("itindex");
+        for(var i=0;i<1;i++){
+            neweditcourse[id].top_relation=true;
+        }
+
+        this.editcourse(neweditcourse);
+    }
+    focus() {
+        this.inputNumberRef.focus();
+    }
+
+    blur() {
+        this.inputNumberRef.blur();
+    }
+    CancelSupports=()=>{
+        this.setState({
+            Editkey:null,
+            Supportssum:false,
+            Supportsclass:false,
+        })
+    }
+    SubmitClassData=()=>{
+        let {editcourse,editnum,ec_graduation_subitem_id,ec_year_id} = this.state;
+        if(editcourse.length===0){
+            this.setState({
+                // Supportstype:true,
+                Supportslist:'保存失败,至少保留一个课程',
+                Supportssum:true
+            })
+            return
+        } 
+        if(editnum>1||editnum===0){
+            this.setState({
+                // Supportstype:true,
+                Supportslist:'保存失败,权重大于1或为空',
+                Supportssum:true
+            })
+            return
+        }
+        for(var p=0; p<editcourse.length;p++){
+            if(editcourse[p].weigths===""){
+                editcourse[p].weigths=0;
+            }
+            if(editcourse[p].ec_course_id===""){
+                this.setState({
+                    // Supportstype:true,
+                    Supportslist:'保存失败,课程不能为空',
+                    Supportsclass:true
+                })
+                return
+            }
+        }    
+        var Url = '/ec_course_supports';
+        axios.post(Url, {
+                ec_year_id: ec_year_id,
+                ec_graduation_subitem_id:ec_graduation_subitem_id,
+                course: editcourse
+            },
+            {
+                withCredentials: true
+            }
+        ).then((response) => {
+
+            if(response.data.status===0){
+                this.setState({
+                    Editkey:null,
+                    Supportslist:response.data.messsage,
+                    Supportstype:true,
+                    Supportssum:false,
+                    Supportsclass:false,
+                })
+                this.UpdateClassData();
+            }else if(response.data.status===-1){
+                this.setState({
+                    Supportslist:"参数错误",
+                    Supportstype:true,
+                    Supportssum:false,
+                    Supportsclass:false,
+                })
+            }
+        }).catch((error) => {
+            console.log(error)
+        })
+    }
+    Deletcourses=(key)=>{
+        this.setState({
+            supportid:key,
+            Supportslist:"您确定要删除吗?",
+            Supportstype:true
+        })
+    }
+    hideSupports=()=>{
+        this.setState({
+            Supportstype:false,
+            supportid:null,
+            Supportslist:"",
+        })
+    }
+    render() {
+        const Option = Select.Option;
+        let {data,ec_courses_list,editcourse,editnum,index,ec_year_id,schooldata,ecComponentState,hidesupport,supportid,Editkey,titlemessage,Supportstype,Supportslist,Supportssum,Supportsclass,major_school_id} = this.state;
+        var list = (length) => {
+            var res = [];
+            for(var i = 0; i < length; i++) {
+                res.push( <span key={i} className="column-1 color-666">
+                            <div style={{lineHeight: '20px'}}>支撑课程
+                            <br/> (权值)
+                            </div>
+                          </span>)
+            }
+            return res
+        }
+
+        return (
+            <div className="newMain clearfix">
+                <Modal
+                    title={titlemessage}
+                    // Supportstype
+                    visible={Supportstype}
+                    className={"ecmodeldelet"}
+                    closable={false}
+                    footer={null}
+                >
+                    <div className="task-popup-content">
+                        <div className="task-popup-text-center font-14">{Supportslist}</div>
+                    </div>
+                    <div className="task-popup-submit clearfix">
+                    <a onClick={this.hideSupports} className="task-btn fl">取消</a>
+                        { supportid===null?<a className="task-btn task-btn-orange fr"
+                            onClick={this.hideSupports}
+                        >确定</a>:
+                       <a  className="task-btn task-btn-orange fr"
+                            onClick={()=>this.Deletcourse(supportid)}
+                        >确定</a>}
+                    </div>
+                </Modal>
+
+
+                <div className="educontent mb290">
+
+
+
+                    <div className="edu-back-white eacourse">
+
+                        <div className="clearfix padding20-30 bor-bottom-greyE" style={{position:'relative'}}>
+                            <span className="font-18 courseSystem">课程体系对毕业要求的支撑</span>
+                            {/* <a href="javascript:void(0)" className="fr white-btn edu-blueback-btn mt4">导出培养目标</a> */}
+                            <span className={data.is_manager===false?"none":"Importclassroomdata"} style={{top: '29px'}}>
+                                <a className="white-btn edu-blueback-btn fr mb10 mr10" target="_blank" href={'/ec_major_schools/'+major_school_id+'/academic_years/'+ec_year_id+'/export_course_requirements?format=xls'}>导出课程体系支撑矩阵</a>
+                            </span>
+                            <div className="color-grey-9 mr10">用矩阵图的形式说明本专业课程体系对毕业要求的支撑关系  <a className={"color-blue"} onClick={() => window.elasticLayer(3534)} >查看详情</a></div>
+
+                        </div>
+                        <div className="padding20-30" id="training_objective_contents">
+                            <span className="fl SystemParameters" >毕业要求指标点(<a href={data.subitems_url}><span className="Systemnum">{data.subitems_count}</span></a>)</span>
+                            <span className="fl ml20 SystemParameters">课程体系(<a href={data.course_url}><span className="Systemnum">{data.course_count}</span></a>)</span>
+                        </div>
+
+                    </div>
+
+                    <div className="ListTableLine" id="school_major_list" style={{overflow:'auto'}}>
+
+                        <p className="clearfix" style={{width: 120*data.max_support_count>1200? 140*data.max_support_count : 1200+"px"}}>
+                            <span className="color-666 finishtarget">毕业要求指标点</span>
+                            {list(data.max_support_count<5||data.max_support_count===undefined?5:data.max_support_count)}
+                            <span className="column-1 operationright color-666"
+                            style={{
+                                paddingLeft: '28px'
+                            }}
+                            >合计</span>
+                        </p>
+                        <div className="paddingLF" style={{background:'#fff'}}>
+                            {
+                                data.graduation_subitems===undefined? <Spin  delay={500} className="Spinlarge"  indicator={<Icon type="loading" style={{ fontSize: 30 }} spin />}/>:data.graduation_subitems.map((item,key)=>{
+
+                                    return (
+                                        <li className={data.graduation_subitems.length===key+1?"clearfix mb10":"clearfix"}  key={key} style={{width: 120*data.max_support_count > 1134 ? 136*data.max_support_count : 1134+"px",margin: '0px 0px'}}>
+                                            <Tooltip placement="bottom" title={item.sequence_title}>
+                                                <span className="column-1 columnlocation" style={{display:Editkey!=key?"block":'none',width: '95px', paddingLeft: '23px'}}>{item.sequence_num}</span>
+                                            </Tooltip>
+
+
+                                            {
+                                                item.course_supports.map((t,kes)=>{
+                                                    return(
+                                                        <span key={kes} className="column-1" 
+                                                        style={{
+                                                            display:Editkey!=key?"block":'none',
+                                                            marginRight: '-1px'
+                                                        }}>
+                                                        <div data-tip-down={t.name} className={t.top_relation===true?"DDred columnbox":"columnbox"}
+                                                        style={{textAlign: 'center'}}
+                                                        >{t.name.length>12?t.name.substring(0, 10)+"...":t.name}</div>
+                                                        <div className={t.top_relation===true?"DDred":""}
+                                                         style={{textAlign: 'center'}}
+                                                        >({t.weigths})</div>
+                                                         </span>
+                                                    )
+
+                                                })
+                                            }
+
+                                            <span className="column-1 operationright" style={{display:Editkey!=key?"block":'none',width:'75px'}}>
+                                                  <div className="operationColumn">
+                                                      <div className="left">
+                                                          <div className="width20 columnbox">{item.course_supports.length}</div>
+                                                          <div className="width20">{Math.round(item.weights_total*100)/100===0?0:(Math.round(item.weights_total*100)/100)}</div>
+                                                      </div>
+                                                      <div className="left operationalter">
+                                                         {data.is_manager===false?"":<a className="editSubentry" data-tip-down="编辑">
+                                                            <i className="iconfont icon-bianjidaibeijing color-green" id={item.ec_graduation_subitem_id} subindex={item.sequence_num} onClick={this.EditSupportCourse.bind(this,key)}></i>
+                                                          </a>} 
+                                                    </div>
+                                                  </div>
+
+                                              </span>
+
+                                            <p className="ListTableLine" id="school_ListTableLine" style={{width: '1134px',display:Editkey===key?"block":'none'}} >
+
+                                                <p className="clearfix SystemModifythelist">
+                                                    <span className="ml6" style={{width:'77px'}}>指标点 {index}</span>
+                                                    <span className="column-4">支撑课程</span>
+                                                    <span className="column-2 ml93">
+                                                      <span> 权重(∑=1)</span>
+                                                      <span className="Systempoint">(精确到两位小数)</span>
+                                                    </span>
+                                                    <span className="column-1 ml50">关联度最高</span>
+                                                </p>
+
+                                                <div className="clearfix editorModify">
+
+                                                    {
+                                                        editcourse.map((it,key)=>{
+
+                                                            return(
+                                                                <div className="mb15" key={key}>
+
+                                                                    <Select className={Supportsclass===true?"bor-red heightimportant":"heightimportant"} showSearch value={it.ec_course_name} onChange={this.handleChange}>
+                                                                        {
+                                                                            ec_courses_list.map((qva,qk)=>{
+                                                                                return(
+                                                                                    <Option value={[qva.id,key,qva.name]} key={qk}>{qva.name}</Option>
+                                                                                )
+                                                                            })
+
+                                                                        }
+                                                                    </Select>
+                                                                    <Input
+                                                                        type="number"
+                                                                        size="large"
+                                                                        className={Supportssum===true?"inputWeight bor-red":"inputWeight"}
+                                                                        id={key}
+                                                                        value={it.weigths}
+                                                                        onInput={this.enterweight.bind(this)}
+                                                                    />
+
+                                                                    <div className="SetTheAssociated">
+
+                                                                        <div className="SetTheAssociatedchild">
+
+                                                                            <i className="iconfont icon-gouxuan gouxuanbule" style={{display:it.top_relation===false?'none':'block'}} itindex={key} onClick={this.relevancetop.bind(this)}></i>
+                                                                            <i className="iconfont icon-gouxuan gouxuanwhite" style={{display:it.top_relation===false?'block':'none'}} itindex={key} onClick={this.relevancebottom.bind(this)}></i>
+
+                                                                        </div>
+
+                                                                        <div className="left operatebutton">
+                                                                            <a className="mr15 delSubentry" data-tip-down="删除">
+                                                                                <i className="iconfont icon-shanchu color-grey-c font-15" onClick={()=>this.Deletcourses(key)}></i>
+                                                                            </a>
+                                                                            <a className="newAddSubentry" data-tip-down="添加"
+                                                                               style={{display:key===editcourse.length-1?"inline-block":'none'}}
+                                                                            ><i className="iconfont icon-tianjiafangda color-green" onClick={this.Addcourse}></i></a>
+                                                                        </div>
+
+                                                                    </div>
+
+                                                                </div>
+                                                            )
+                                                        })
+                                                    }
+
+                                                </div>
+                                                <span className="c_red none ml35" id="error_tip" style={{display:Supportssum===true||Supportsclass===true?'inline':'none'}}>{Supportslist}</span>
+                                                <div className="clearfix editorModify">
+                                                    <span className="column-1"
+                                                    style={{
+                                                        width: '580px',
+                                                        paddingLeft: '37px',
+                                                        display: 'inline-block'
+                                                    }}
+                                                    >合计: <span>{editcourse.length}</span></span>
+                                                    <span className="ml30">合计: <span>{editnum}</span></span>
+                                                </div>
+
+                                                <div className="right editglybuttonboxs">
+                                                    <div className="defalutSubmitbtn fr" onClick={this.SubmitClassData}>保存</div>
+                                                    <div className="defalutCancelbtn fr mr20" onClick={this.CancelSupports}>取消</div>
+                                                </div>
+
+                                            </p>
+
+
+                                        </li>
+                                    )
+                                })
+                            }
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        );
+    }
+}
+
+export default  CourseSupports ;
+
diff --git a/public/react/src/modules/ecs/EcSetting/GraduationRequirement/index.js b/public/react/src/modules/ecs/EcSetting/GraduationRequirement/index.js
new file mode 100644
index 000000000..4ee387a73
--- /dev/null
+++ b/public/react/src/modules/ecs/EcSetting/GraduationRequirement/index.js
@@ -0,0 +1,384 @@
+import React from 'react';
+import PropTypes from "prop-types";
+import { Link } from 'react-router-dom';
+import { Spin, Button, Input, Divider, Icon, Tooltip, Form, message, Modal } from 'antd';
+import axios from 'axios';
+import _ from 'lodash'
+
+import './index.scss';
+
+const { confirm } = Modal;
+
+class GraduationRequirement extends React.Component {
+  constructor (props) {
+    super(props);
+
+    this.state = {
+      loading: true,
+      editIndex: null,
+      addState: false,
+      submitState: false,
+      validateState: false,
+
+      currentEditReq: {},
+      newRequirement: {},
+      graduationRequirements: []
+    }
+  }
+
+  componentDidMount() {
+    this.getData();
+  }
+
+  getData = () => {
+    let { yearId } = this.props;
+
+    this.setState({ loading: true });
+    axios.get(`/ec_years/${yearId}/ec_graduation_requirements.json`).then(res => {
+      if(res.status === 200){
+        this.setState({
+          graduationRequirements: res.data.graduation_requirements,
+          loading: false
+        })
+      }
+    }).catch(e => console.log(e))
+  }
+
+  showDeleteConfirm = (id) => {
+    if(this.state.editIndex !== null || this.state.addState){
+      message.error('请先保存其它内容');
+      return
+    }
+    confirm({
+      title: '确认删除该毕业要求?',
+      okText: '确认',
+      cancelText: '取消',
+      onOk: () => {
+        this.deleteRequirement(id);
+      },
+      onCancel() {},
+    });
+  }
+
+  deleteRequirement = (id) => {
+    let { yearId } = this.props;
+    let url = `/ec_years/${yearId}/ec_graduation_requirements/${id}.json`;
+    axios.delete(url).then(res => {
+      if(res){
+        message.success('操作成功');
+        this.getData();
+      }
+    }).catch(e => console.log(e))
+  }
+
+  showEditContent = (index) => {
+    let { editIndex, graduationRequirements } = this.state;
+    if(editIndex !== null){
+      message.error('请先保存其它内容');
+      return
+    }
+
+    this.setState({ editIndex: index, currentEditReq: _.cloneDeep(graduationRequirements[index])})
+  }
+
+  onEditContentChange = (e) => {
+    let { currentEditReq } = this.state;
+    currentEditReq.content = e.target.value;
+    this.setState({ currentEditReq });
+  }
+
+  onEditItemContentChange = (e, index) => {
+    let { currentEditReq } = this.state;
+    currentEditReq.ec_graduation_subitems[index].content = e.target.value;
+    this.setState({ currentEditReq });
+  }
+
+  addEditItem = () => {
+    let { currentEditReq } = this.state;
+    currentEditReq.ec_graduation_subitems.push({id: null, content: ''})
+    this.setState({ currentEditReq });
+  }
+
+  removeEditItem = (index) => {
+    let { currentEditReq } = this.state;
+    currentEditReq.ec_graduation_subitems.splice(index, 1);
+    this.setState({ currentEditReq });
+  }
+
+  saveContentEdit = () => {
+    let { currentEditReq } = this.state;
+
+    let contentExist = currentEditReq.content && currentEditReq.content.length !== 0;
+    let errorItem = currentEditReq.ec_graduation_subitems.find(item => !item.content || item.content.length === 0);
+    this.setState({ validateState: !!errorItem || !contentExist });
+
+    if(errorItem || !contentExist){ return }
+
+    this.setState({ submitState: true }, this.updateRequirement);
+  }
+
+  cancelContentEdit = () => {
+    this.setState({ currentEditReq: {}, editIndex: null, validateState: false });
+  }
+
+  updateRequirement = () => {
+    let { yearId } = this.props;
+    let { currentEditReq } = this.state;
+
+    let url = `/ec_years/${yearId}/ec_graduation_requirements/${currentEditReq.id}.json`;
+
+    axios.put(url, { content: currentEditReq.content, position: currentEditReq.position, graduation_subitems: currentEditReq.ec_graduation_subitems }).then(res => {
+      if(res){
+        message.success('操作成功');
+        this.setState({ submitState: false, editIndex: null });
+        this.getData();
+      }
+    }).catch(e => {
+      console.log(e);
+      this.setState({ submitState: false });
+    })
+  }
+
+  showNewReqContent = () => {
+    let { editIndex, graduationRequirements } = this.state;
+    if(editIndex !== null){
+      message.error('请先保存其它内容');
+      return
+    }
+
+    this.setState({
+      editIndex: -1, addState: true,
+      newRequirement: {
+        content: '', position: graduationRequirements.length + 1,
+        graduation_subitems: [
+          { id: null, content: '' },
+          { id: null, content: '' },
+          { id: null, content: '' },
+        ]
+      }
+    })
+  }
+
+  onNewReqContentChange = (e) => {
+    let { newRequirement } = this.state;
+    newRequirement.content = e.target.value;
+    this.setState({ newRequirement });
+  }
+
+  onNewReqItemContentChange = (e, index) => {
+    let { newRequirement } = this.state;
+    newRequirement.graduation_subitems[index].content = e.target.value;
+    this.setState({ newRequirement });
+  }
+
+  addNewReqItem = () => {
+    let { newRequirement } = this.state;
+    newRequirement.graduation_subitems.push({id: null, content: ''})
+    this.setState({ newRequirement });
+  }
+
+  removeNewReqItem = (index) => {
+    let { newRequirement } = this.state;
+    newRequirement.graduation_subitems.splice(index, 1);
+    this.setState({ newRequirement });
+  }
+
+  saveNewReq = () => {
+    let { newRequirement } = this.state;
+
+    let contentExist = newRequirement.content && newRequirement.content.length !== 0;
+    let errorItem = newRequirement.graduation_subitems.find(item => !item.content || item.content.length === 0);
+    this.setState({ validateState: !!errorItem || !contentExist });
+
+    if(errorItem || !contentExist){ return }
+
+    this.setState({ submitState: true }, this.createRequirement);
+  }
+
+  cancelNewReq = () => {
+    this.setState({ newRequirement: {}, addState: false, editIndex: null, validateState: false });
+  }
+
+  createRequirement = () => {
+    let { yearId } = this.props;
+    let { newRequirement } = this.state;
+
+    let url = `/ec_years/${yearId}/ec_graduation_requirements.json`;
+
+    axios.post(url, newRequirement).then(res => {
+      if(res){
+        message.success('操作成功');
+        this.setState({ submitState: false, editIndex: null, addState: false });
+        this.getData();
+      }
+    }).catch(e => {
+      console.log(e);
+      this.setState({ submitState: false });
+    })
+  }
+
+  render() {
+    let { can_manager } = this.props.year;
+    let { loading, editIndex, addState, submitState, validateState, currentEditReq, graduationRequirements, newRequirement } = this.state;
+
+    return (
+      <div>
+        <Spin spinning={loading} size='large' style={{ marginTop: '15%' }}>
+          <div className="educontent ec-graduation-requirement-page">
+            <div className="ec-head">
+              <div className="ec-head-left">
+                <div className="ec-head-label">毕业要求(及其指标点)</div>
+                <div className="ec-head-tip">
+                  <span>请结合本专业特色修改毕业要求文字描述及指标点,需完全覆盖12项通用标准</span>
+                  <Link to="/forums/3530" target="_blank" className="link ml10">查看详情</Link>
+                </div>
+              </div>
+              <a href={`/api/ec_years/${this.props.yearId}/ec_graduation_requirements.xlsx`} target="_blank" className="ant-btn ant-btn-primary color-white">导出毕业要求</a>
+            </div>
+
+            <Divider/>
+
+            <div className="graduation-requirement-body">
+              <div className="graduation-requirement-items">
+                <div className="graduation-requirement-items-head">
+                  <div className="no-column">指标点</div>
+                  <div className="item-content-column">内容</div>
+                  <div className="operation-column">
+                    {
+                      can_manager && !addState && (
+                        <Tooltip title="添加">
+                          <Icon type="plus-circle" className="edit-action" onClick={this.showNewReqContent} />
+                        </Tooltip>
+                      )
+                    }
+                  </div>
+                </div>
+                <div className="graduation-requirement-items-body">
+                  {
+                    graduationRequirements && graduationRequirements.map((item, index) => {
+                      return can_manager && index === editIndex ? (
+                        <div className="graduation-requirement-items-body-item active" key={index}>
+                          <div className="item-row item-head">
+                            <div className="no-column">{ index + 1 }</div>
+                            <div className="item-content-column">
+                              <Form.Item label={false} validateStatus={validateState && (!currentEditReq.content || currentEditReq.content.length === 0) ? 'error' : ''}>
+                                <Input.TextArea rows={2} value={currentEditReq.content} onChange={this.onEditContentChange} />
+                              </Form.Item>
+                            </div>
+                            <div className="item-column-operation">
+                              <Tooltip title="添加"><Icon type="plus-circle" style={{ color: '#29BD8B' }} onClick={this.addEditItem}/></Tooltip>
+                            </div>
+                          </div>
+                          {
+                            currentEditReq.ec_graduation_subitems.map((subitem, i) => {
+                              return (
+                                <div className="item-row" key={i}>
+                                  <div className="no-column">{ index + 1 }-{ i + 1 }</div>
+                                  <div className="item-content-column">
+                                    <Form.Item label={false} validateStatus={validateState && (!subitem.content || subitem.content.length === 0) ? 'error' : ''}>
+                                      <Input.TextArea rows={2} value={subitem.content} onChange={(e) => this.onEditItemContentChange(e, i)} />
+                                    </Form.Item>
+                                  </div>
+                                  <div className="item-column-operation">
+                                    <Tooltip title="删除"><Icon type="delete" onClick={() => this.removeEditItem(i)}/></Tooltip>
+                                  </div>
+                                </div>
+                              )
+                            })
+                          }
+
+                          <div className="edit-form">
+                            <Button type="primary" loading={submitState} onClick={this.saveContentEdit}>保存</Button>
+                            <Button disabled={submitState} onClick={this.cancelContentEdit}>取消</Button>
+                          </div>
+                        </div>
+                      ) : (
+                        <div className="graduation-requirement-items-body-item" key={index}>
+                          <div className="item-row item-head">
+                            <div className="no-column">{ index + 1 }</div>
+                            <div className="item-content-column">{ item.content }</div>
+                            {
+                              can_manager && (
+                                <div className="item-column-operation">
+                                  <Tooltip title="删除"><Icon type="delete" onClick={() => this.showDeleteConfirm(item.id)} /></Tooltip>
+                                  <Tooltip title="编辑"><Icon type="edit" theme="filled" className="edit-action" onClick={() => this.showEditContent(index)}/></Tooltip>
+                                  {
+                                    index === graduationRequirements.length - 1 && !addState && (
+                                      <Tooltip title="添加"><Icon type="plus-circle" style={{ color: '#29BD8B' }} onClick={this.showNewReqContent}/></Tooltip>
+                                    )
+                                  }
+                                </div>
+                              )
+                            }
+
+                          </div>
+                          {
+                            item.ec_graduation_subitems.map((subitem, i) => {
+                              return (
+                                <div className="item-row" key={i}>
+                                  <div className="no-column">{ index + 1 }-{ i + 1 }</div>
+                                  <div className="item-content-column">{ subitem.content }</div>
+                                </div>
+                              )
+                            })
+                          }
+                        </div>
+                      )
+                    })
+                  }
+
+                  {
+                    can_manager && addState && (
+                      <div className="graduation-requirement-items-body-item active">
+                        <div className="item-row item-head">
+                          <div className="no-column">{ graduationRequirements.length + 1 }</div>
+                          <div className="item-content-column">
+                            <Form.Item label={false} validateStatus={validateState && (!newRequirement.content || newRequirement.content.length === 0) ? 'error' : ''}>
+                              <Input.TextArea rows={2} value={newRequirement.content} onChange={this.onNewReqContentChange} />
+                            </Form.Item>
+                          </div>
+                          <div className="item-column-operation">
+                            <Tooltip title="添加"><Icon type="plus-circle" style={{ color: '#29BD8B' }} onClick={this.addNewReqItem}/></Tooltip>
+                          </div>
+                        </div>
+                        {
+                          newRequirement.graduation_subitems.map((subitem, i) => {
+                            return (
+                              <div className="item-row" key={i}>
+                                <div className="no-column">{ graduationRequirements.length + 1 }-{ i + 1 }</div>
+                                <div className="item-content-column">
+                                  <Form.Item label={false} validateStatus={validateState && (!subitem.content || subitem.content.length === 0) ? 'error' : ''}>
+                                    <Input.TextArea rows={2} value={subitem.content} onChange={(e) => this.onNewReqItemContentChange(e, i)} />
+                                  </Form.Item>
+                                </div>
+                                <div className="item-column-operation">
+                                  <Tooltip title="删除"><Icon type="delete" onClick={() => this.removeNewReqItem(i)}/></Tooltip>
+                                </div>
+                              </div>
+                            )
+                          })
+                        }
+
+                        <div className="edit-form">
+                          <Button type="primary" loading={submitState} onClick={this.saveNewReq}>保存</Button>
+                          <Button disabled={submitState} onClick={this.cancelNewReq}>取消</Button>
+                        </div>
+                      </div>
+                    )
+                  }
+                </div>
+              </div>
+            </div>
+          </div>
+        </Spin>
+      </div>
+    )
+  }
+}
+GraduationRequirement.propTypes = {
+  schoolId: PropTypes.string,
+  majorId: PropTypes.string,
+  yearId: PropTypes.string,
+}
+
+export default GraduationRequirement
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcSetting/GraduationRequirement/index.scss b/public/react/src/modules/ecs/EcSetting/GraduationRequirement/index.scss
new file mode 100644
index 000000000..9d740a970
--- /dev/null
+++ b/public/react/src/modules/ecs/EcSetting/GraduationRequirement/index.scss
@@ -0,0 +1,94 @@
+.ec-graduation-requirement-page {
+  background: #fff;
+
+  .graduation-requirement {
+    &-body {
+      margin-top: -24px;
+    }
+
+    &-items {
+      &-head {
+        padding: 15px 30px;
+        display: flex;
+        background: #F5F5F5;
+      }
+
+      &-body {
+        margin: 0 30px;
+
+        &-item {
+          padding: 10px 0px;
+          border-bottom: 1px solid #eaeaea;
+
+          &.active {
+            .item-row {
+              margin-bottom: 10px;
+              align-items: center;
+            }
+
+            .item-column-operation {
+              width: 40px;
+            }
+          }
+
+          &:last-child {
+            border-bottom: unset;
+          }
+
+          .item-head {
+            margin-bottom: 10px;
+            font-weight: bold;
+          }
+
+          .item-row {
+            display: flex;
+          }
+        }
+      }
+
+
+      .no-column {
+        width: 60px;
+        text-align: center;
+      }
+
+      .item-content-column {
+        flex: 1;
+        padding-left: 10px;
+        display: flex;
+
+        .ant-form-item {
+          flex: 1;
+          margin-bottom: 0;
+        }
+      }
+
+      .item-column-operation {
+        display: flex;
+        justify-content: flex-end;
+        width: 80px;
+
+        & > i {
+          margin: 0 5px;
+          font-size: 16px;
+          cursor: pointer;
+        }
+      }
+    }
+  }
+
+  .edit-form {
+    margin-top: 10px;
+    text-align: right;
+
+    button {
+      margin-left: 10px;
+    }
+  }
+
+  i.edit-action {
+    color: #29BD8B;
+    cursor: pointer;
+    font-size: 16px;
+  }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcSetting/TrainingObjective/index.js b/public/react/src/modules/ecs/EcSetting/TrainingObjective/index.js
new file mode 100644
index 000000000..e48cf2c84
--- /dev/null
+++ b/public/react/src/modules/ecs/EcSetting/TrainingObjective/index.js
@@ -0,0 +1,264 @@
+import React from 'react';
+import PropTypes from "prop-types";
+import { Link } from 'react-router-dom';
+import { Spin, Button, Input, Divider, Icon, Tooltip, Form, message } from 'antd';
+import axios from 'axios';
+
+import './index.scss';
+
+class TrainingObjective extends React.Component {
+  constructor (props) {
+    super(props);
+
+    this.state = {
+      loading: true,
+      contentEditState: false,
+      itemsEditState: false,
+      submitState: false,
+      validateState: false,
+      itemSubmitState: false,
+      itemValidateState: false,
+
+      objective: {},
+      editContent: '',
+      trainingSubitems: []
+    }
+  }
+
+  componentDidMount() {
+    this.getData();
+  }
+
+  getData = () => {
+    let { yearId } = this.props;
+
+    axios.get(`/ec_years/${yearId}/ec_training_objectives.json`).then(res => {
+      if(res.status === 200){
+        this.setState({
+          objective: res.data,
+          editContent: res.data.content,
+          trainingSubitems: res.data.ec_training_items,
+          loading: false
+        })
+      }
+    }).catch(e => console.log(e))
+  }
+
+  saveContentEdit = () => {
+    let { editContent } = this.state;
+    this.setState({ validateState: editContent.length === 0 });
+    if(editContent.length === 0){ return; }
+
+    this.setState(
+      { submitState: true },
+      () => {
+        this.updateTrainingObjective(
+          { content: editContent },
+          () => {
+            this.setState({ submitState: false, contentEditState: false });
+            this.getData();
+          },
+          _e => {
+            this.setState({ submitState: false })
+          }
+        )
+      }
+    );
+  }
+
+  cancelContentEdit = () => {
+    this.setState({ editContent: this.state.objective.content, contentEditState: false });
+  }
+
+  editItemsContent = () => {
+    let { trainingSubitems } = this.state;
+    if(!trainingSubitems || trainingSubitems.length === 0){
+      trainingSubitems = [{ id: null, content: null }]
+    }
+    this.setState({ trainingSubitems: trainingSubitems, itemsEditState: true });
+  }
+
+  addItemColumn = (index) => {
+    let { trainingSubitems } = this.state;
+    trainingSubitems.splice(index, 0, { id: null, content: null });
+    this.setState({ trainingSubitems })
+  }
+
+  removeItemColumn = (index) => {
+    let { trainingSubitems } = this.state;
+    trainingSubitems.splice(index, 1);
+    this.setState({ trainingSubitems })
+  }
+
+  onItemContentChange = (e, index) => {
+    let { trainingSubitems } = this.state;
+    trainingSubitems[index].content = e.target.value;
+
+    this.setState({ trainingSubitems: trainingSubitems });
+  }
+
+  saveItemsContentEdit = () => {
+    let { objective, trainingSubitems } = this.state;
+
+    let errorItem = trainingSubitems.find(item => !item.content || item.content.length === 0);
+    this.setState({ itemValidateState: !!errorItem });
+
+    if(errorItem){ return }
+
+    this.setState(
+      { itemSubmitState: true },
+      () => {
+        this.updateTrainingObjective(
+          { content: objective.content, training_subitems: trainingSubitems },
+          () => {
+            this.setState({ itemSubmitState: false, itemsEditState: false });
+            this.getData();
+          },
+          _e => {
+            this.setState({ itemSubmitState: false })
+          }
+        )
+      }
+    );
+  }
+
+  cancelItemsContentEdit = () => {
+    this.setState({ trainingSubitems: this.state.objective.ec_training_items, itemsEditState: false, itemValidateState: false });
+  }
+
+  updateTrainingObjective = (data, success, fail) => {
+    let { yearId } = this.props;
+    let url = `/ec_years/${yearId}/ec_training_objectives.json`;
+
+    axios.post(url, data).then(res => {
+      if(res){
+        message.success('操作成功');
+        success();
+      }
+    }).catch(e => {
+      console.log(e);
+      fail(e);
+    })
+  }
+
+  render() {
+    let { can_manager } = this.props.year;
+    let { loading, contentEditState, itemsEditState, objective, editContent, trainingSubitems, validateState, itemValidateState, itemSubmitState, submitState } = this.state;
+
+    return (
+      <div>
+        <Spin spinning={loading} size='large' style={{ marginTop: '15%' }}>
+          <div className="educontent ec-training-objective-page">
+            <div className="ec-head">
+              <div className="ec-head-left">
+                <div className="ec-head-label">培养目标</div>
+                <div className="ec-head-tip">
+                  <span>请结合本专业特色修改培养目标文字描述及目标分解查看详情</span>
+                  <Link to="/forums/3529" target="_blank" className="link ml10">查看详情</Link>
+                </div>
+              </div>
+              <a href={`/api/ec_years/${this.props.yearId}/ec_training_objectives.xlsx`} target="_blank" className="ant-btn ant-btn-primary color-white">导出培养目标</a>
+            </div>
+
+            <Divider/>
+
+            <div className="training-objective-body">
+              {
+                can_manager && contentEditState ? (
+                  <div className="training-objective-content block">
+                    <div>
+                      <Form.Item label={false} validateStatus={validateState && (!editContent || editContent.length === 0) ? 'error' : ''}>
+                        <Input.TextArea rows={6} value={editContent} onChange={e => this.setState({ editContent: e.target.value })} />
+                      </Form.Item>
+                    </div>
+                    <div className="training-objective-content-form">
+                      <Button type="primary" loading={submitState} onClick={this.saveContentEdit}>保存</Button>
+                      <Button loading={submitState} onClick={this.cancelContentEdit}>取消</Button>
+                    </div>
+                  </div>
+                ) : (
+                  <div className="training-objective-content">
+                    <div className="training-objective-content-text">{ objective.content }</div>
+                    {
+                      can_manager && (
+                        <div className="training-objective-content-edit">
+                          <Tooltip title="编辑">
+                            <Icon type="edit" theme="filled" className="edit-action" onClick={() => this.setState({ contentEditState: true })} />
+                          </Tooltip>
+                        </div>
+                      )
+                    }
+                  </div>
+                )
+              }
+              
+              <div className="training-objective-items">
+                <div className="training-objective-items-head">
+                  <div className="no-column">分项</div>
+                  <div className="item-content-column">目标分解详情</div>
+                  <div className="operation-column">
+                      {
+                        !can_manager || itemsEditState || (
+                          <Tooltip title="编辑">
+                            <Icon type="edit" theme="filled" className="edit-action" onClick={this.editItemsContent} />
+                          </Tooltip>
+                        )
+                      }
+                  </div>
+                </div>
+                <div className="training-objective-items-body">
+                  {
+                    can_manager && itemsEditState ? (
+                      <div>
+                        {
+                          trainingSubitems && trainingSubitems.map((item, index) => {
+                            return (
+                              <div className="training-objective-items-body-item" key={index}>
+                                <div className="no-column">{index + 1}</div>
+                                <div className="item-content-column">
+                                  <Form.Item label={false} validateStatus={itemValidateState && (!item.content || item.content.length === 0) ? 'error' : ''}>
+                                    <Input.TextArea rows={2} value={item.content} onChange={e => this.onItemContentChange(e, index)} />
+                                  </Form.Item>
+                                  <div className="item-column-operation">
+                                    { index !== 0 && <Icon type="delete" onClick={() => this.removeItemColumn(index)} /> }
+
+                                    <Icon type="plus-circle" onClick={() => this.addItemColumn(index + 1)} style={{ color: '#29BD8B' }} />
+                                  </div>
+                                </div>
+                              </div>
+                            )
+                          })
+                        }
+
+                        <div className="training-objective-content-form">
+                          <Button type="primary" loading={itemSubmitState} onClick={this.saveItemsContentEdit}>保存</Button>
+                          <Button disabled={itemSubmitState} onClick={this.cancelItemsContentEdit}>取消</Button>
+                        </div>
+                      </div>
+                    ) : (
+                      objective.ec_training_items && objective.ec_training_items.map((item, index) => {
+                        return (
+                          <div className="training-objective-items-body-item" key={index}>
+                            <div className="no-column">{ index + 1 }</div>
+                            <div className="item-content-column">{ item.content }</div>
+                          </div>
+                        )
+                      })
+                    )
+                  }
+                </div>
+              </div>
+            </div>
+          </div>
+        </Spin>
+      </div>
+    )
+  }
+}
+TrainingObjective.propTypes = {
+  schoolId: PropTypes.string,
+  majorId: PropTypes.string,
+  yearId: PropTypes.string,
+}
+
+export default TrainingObjective
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcSetting/TrainingObjective/index.scss b/public/react/src/modules/ecs/EcSetting/TrainingObjective/index.scss
new file mode 100644
index 000000000..50b801459
--- /dev/null
+++ b/public/react/src/modules/ecs/EcSetting/TrainingObjective/index.scss
@@ -0,0 +1,99 @@
+.ec-training-objective-page {
+  background: #ffffff;
+
+  .training-objective {
+    &-body {
+      margin-top: -24px;
+      min-height: 600px;
+    }
+
+    &-content {
+      display: flex;
+      padding: 20px 30px;
+      line-height: 2.0;
+
+      &.block {
+        display: block;
+      }
+
+      &-text {
+        flex: 1;
+      }
+
+      &-edit {
+        margin-left: 20px;
+
+        & > i {
+          color: #29BD8B;
+          cursor: pointer;
+          font-size: 18px;
+        }
+      }
+
+      &-form {
+        margin-top: 10px;
+        text-align: right;
+
+        button {
+          margin-left: 10px;
+        }
+      }
+    }
+
+    &-items {
+      &-head {
+        padding: 15px 30px;
+        display: flex;
+        background: #F5F5F5;
+      }
+
+      &-body {
+        margin: 0 30px;
+
+        &-item {
+          display: flex;
+          min-height: 48px;
+          padding: 10px 0px;
+          border-bottom: 1px solid #eaeaea;
+
+          &:last-child {
+            border-bottom: unset;
+          }
+        }
+      }
+
+      .no-column {
+        width: 40px;
+        text-align: center;
+      }
+
+      .item-content-column {
+        flex: 1;
+        padding-left: 10px;
+        display: flex;
+
+        .ant-form-item {
+          flex: 1;
+          margin-bottom: 0;
+        }
+
+        .item-column-operation {
+          display: flex;
+          justify-content: flex-end;
+          width: 80px;
+
+          & > i {
+            margin: 15px 10px;
+            font-size: 18px;
+          }
+        }
+      }
+    }
+  }
+
+  i.edit-action {
+    color: #29BD8B;
+    cursor: pointer;
+    font-size: 18px;
+  }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcSetting/index.js b/public/react/src/modules/ecs/EcSetting/index.js
new file mode 100644
index 000000000..d85d10aec
--- /dev/null
+++ b/public/react/src/modules/ecs/EcSetting/index.js
@@ -0,0 +1,148 @@
+import React from 'react';
+import { Switch, Route, Link } from 'react-router-dom';
+import { Steps, Breadcrumb } from 'antd';
+import axios from 'axios';
+
+import './index.scss';
+
+import CustomLoadable from "../../../CustomLoadable";
+import Loadable from 'react-loadable';
+import Loading from "../../../Loading";
+const { Step } = Steps;
+const steps = ["培养目标", "毕业要求", "培养目标VS毕业要求", "毕业要求VS通用标准", "学生", "课程体系", "课程体系VS毕业要求", "达成度评价结果"];
+const stepTypes = ["training_objectives", "graduation_requirement", "requirement_vs_objective", "requirement_vs_standard", "students", "courses", "requirement_vs_courses", "reach_calculation_info"];
+const EcStudentList=Loadable({
+  loader: () => import('../subroute/ecStudentList/EcStudentList'),
+  loading: Loading,
+});
+const Curriculum=Loadable({
+  loader: () => import('../../../modules/ecs/curriculum/Curriculum'),
+  loading: Loading,
+});
+const TrainingObjective=Loadable({
+  loader: () => import('./TrainingObjective/index'),
+  loading: Loading,
+});
+const GraduationRequirement=Loadable({
+  loader: () => import('./GraduationRequirement/index'),
+  loading: Loading,
+});
+const CourseSupports=Loadable({
+  loader: () => import('./CourseSupports/index'),
+  loading: Loading,
+});
+
+class EcSetting extends React.Component {
+  constructor (props) {
+    super(props);
+
+    this.state = {
+      schoolId: null,
+      majorId: props.match.params.majorId,
+      yearId: props.match.params.yearId,
+      year: null,
+
+      stepIndex: 0,
+    }
+  }
+
+  componentDidMount() {
+    this.setupStep();
+    this.getYearDetail();
+  }
+
+  getYearDetail = () => {
+    let { majorId, yearId } = this.state;
+    axios.get(`/ec_major_schools/${majorId}/ec_years/${yearId}.json`).then(res => {
+      if(res){
+        this.setState({ year: res.data, schoolId: res.data.school_id })
+      }
+    }).catch(e => console.log(e))
+  }
+
+  onStepChange = (stepIndex) => {
+    let { majorId, yearId } = this.state;
+    let type = stepTypes[stepIndex];
+
+    this.setState({ stepIndex: stepIndex });
+    if(type==="courses"){
+      this.props.history.push(`/ecs/major_schools/${majorId}/years/${yearId}/${type}/ec_course_support_setting/1`);
+    }else {
+      this.props.history.push(`/ecs/major_schools/${majorId}/years/${yearId}/${type}`);
+    }
+  }
+
+  setupStep = () => {
+    let type = this.props.match.params.type;
+
+    let stepIndex = stepTypes.indexOf(type);
+    this.setState({ stepIndex: stepIndex });
+  }
+
+  render() {
+    let { year, schoolId, majorId, yearId } = this.state;
+    let { stepIndex } = this.state;
+
+    return (
+      <div>
+        <div className="ec-page">
+          <div className="educontent ec-breadcrumb">
+            <Breadcrumb separator=">">
+              <Breadcrumb.Item key="department">
+                <Link to={`/ecs/department?school_id=${schoolId}`}>{ year && year.school_name }</Link>
+              </Breadcrumb.Item>
+              <Breadcrumb.Item key="major-school">
+                <Link to={`/ecs/major_schools/${majorId}`}>{ year && year.major_name }</Link>
+              </Breadcrumb.Item>
+              <Breadcrumb.Item key="year">{year && year.year}届</Breadcrumb.Item>
+            </Breadcrumb>
+          </div>
+
+          <div className="educontent ec-steps">
+            <Steps type="navigation"
+                   size='small'
+                   className="ec-steps-box"
+                   current={stepIndex}
+                   onChange={this.onStepChange}>
+
+              {
+                steps.map((title, index) => {
+                  return (
+                    <Step subTitle={title} status={index === stepIndex ? 'process' : 'wait'} key={index}/>
+                  )
+                })
+              }
+            </Steps>
+          </div>
+
+          {
+            year && (
+              <Switch>
+                <Route extra path='/ecs/major_schools/:majorId/years/:yearId/training_objectives'
+                       render={ (props) => (<TrainingObjective {...this.props} {...props} {...this.state} />) }></Route>
+								<Route extra path='/ecs/major_schools/:majorId/years/:yearId/graduation_requirement'
+											 render={ (props) => (<GraduationRequirement {...this.props} {...props} {...this.state} />) }></Route>
+
+
+                {/*学生*/}
+                <Route extra path='/ecs/major_schools/:majorId/years/:yearId/students'
+                       render={ (props) => (<EcStudentList {...this.props} {...props} {...this.state} />) }></Route>
+                {/*课程体系*/}
+                <Route extra path='/ecs/major_schools/:majorId/years/:yearId/courses'
+                       render={ (props) => (<Curriculum {...this.props} {...props} {...this.state} />) }></Route>
+                {/*课程体系VS毕业要求*/}
+								<Route extra path='/ecs/major_schools/:major_school_id/years/:ec_year_id/requirement_vs_courses'
+											 render={ (props) => (<CourseSupports {...this.props} {...props} {...this.state} />) }></Route>
+
+
+								
+              </Switch>
+            )
+          }
+        </div>
+      </div>
+    )
+  }
+}
+
+export default EcSetting
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcSetting/index.scss b/public/react/src/modules/ecs/EcSetting/index.scss
new file mode 100644
index 000000000..7fcd80880
--- /dev/null
+++ b/public/react/src/modules/ecs/EcSetting/index.scss
@@ -0,0 +1,62 @@
+.ec-page {
+  margin-bottom: 50px;
+
+  .ec-breadcrumb {
+    margin-top: 10px;
+    margin-bottom: 10px;
+  }
+
+  .ec-steps {
+    &-box {
+      margin-bottom: 10px;
+      padding-left: 20px;
+      padding-right: 20px;
+      justify-content: space-between;
+      background: #fff;
+
+      .ant-steps-item {
+        flex: unset !important;
+
+        &-container {
+          margin-left: 0;
+        }
+
+        &.ant-steps-item-active {
+          .ant-steps-item-subtitle {
+            color: #1890ff;
+          }
+        }
+
+        &-subtitle {
+          margin-left: 0;
+          margin-right: 8px;
+        }
+      }
+    }
+  }
+
+  .ec-head {
+    margin-bottom: -24px;
+    padding: 20px 30px;
+    display: flex;
+    align-items: flex-end;
+    justify-content: space-between;
+
+    &-left {
+      flex: 1;
+    }
+
+    &-label {
+      font-size: 18px;
+    }
+
+    &-tip {
+      font-size: 14px;
+      color: #999999;
+    }
+  }
+
+  .link {
+    color: #007bff;
+  }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcYear/AddYearModal.js b/public/react/src/modules/ecs/EcYear/AddYearModal.js
new file mode 100644
index 000000000..e54ba6b73
--- /dev/null
+++ b/public/react/src/modules/ecs/EcYear/AddYearModal.js
@@ -0,0 +1,108 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Modal, Select, message } from 'antd';
+import axios from 'axios';
+
+import './AddYearModal.scss';
+
+const { Option } = Select;
+
+class AddYearModal extends React.Component {
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      confirmLoading: false,
+      error: '',
+
+      year: '',
+      currentYear: new Date().getFullYear()
+    }
+  }
+
+  handleOk = () => {
+    let { year } = this.state;
+
+    if(!year || year.length === 0){
+      this.setState({ error: '请选择届别' });
+      return;
+    }
+
+    this.submitYear();
+  }
+
+  handleCancel = () => {
+    this.props.onHide(false);
+  }
+
+  onAfterModalClose = () => {
+    this.setState({ year: '' });
+  }
+
+  submitYear = () =>  {
+    let { schoolId, majorId } = this.props;
+    let { year } = this.state;
+
+    this.setState({ confirmLoading: true });
+    axios.post(`/ec_major_schools/${majorId}/ec_years.json`, { school_id: schoolId, year: year }).then(res => {
+      if(res.status === 200){
+        message.success('操作成功');
+        this.setState({ confirmLoading: false });
+        this.props.onHide(true);
+      }
+    }).catch(e => {
+      console.log(e);
+      this.setState({ confirmLoading: false });
+    })
+  }
+
+  render() {
+    let { confirmLoading, year, currentYear } = this.state;
+
+    return (
+      <div>
+        <Modal
+          title="添加届别"
+          wrapClassName="add-year-modal"
+          visible={this.props.visible}
+          confirmLoading={confirmLoading}
+          afterClose={this.onAfterModalClose}
+          onOk={this.handleOk}
+          onCancel={this.handleCancel}>
+          
+          <div className="add-year-container">
+            <div className="add-year-tip">
+              基础数据:除学生列表与成绩录入以外的所有基础数据<br/>
+              将自动复制上届别的数据;数据均可再编辑
+            </div>
+
+            <div className="add-year-content">
+              <div className="add-year-content-label">选择届别:</div>
+              <div className="add-year-content-select">
+                <Select defaultValue="" value={year} onChange={ value => this.setState({ year: value })} style={{width: '100%'}} placeholder="请选择届别">
+                  {
+                    [...Array(10)].map((_, index) => {
+                      let y = currentYear - 5 + index;
+                      return (
+                        <Option value={ y }>{y}届</Option>
+                      )
+                    })
+                  }
+                </Select>
+              </div>
+            </div>
+          </div>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+AddYearModal.propTypes = {
+  schoolId: PropTypes.number,
+  majorId: PropTypes.number,
+  visible: PropTypes.bool,
+  onHide: PropTypes.func
+}
+
+export default AddYearModal
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcYear/AddYearModal.scss b/public/react/src/modules/ecs/EcYear/AddYearModal.scss
new file mode 100644
index 000000000..75218677d
--- /dev/null
+++ b/public/react/src/modules/ecs/EcYear/AddYearModal.scss
@@ -0,0 +1,34 @@
+.add-year-modal {
+  .add-year {
+    &-container {
+      padding: 0 40px;
+    }
+
+    &-tip {
+      margin-bottom: 20px;
+      color: #666666;
+      line-height: 30px;
+      text-align: center;
+    }
+
+    &-content {
+      padding: 0 50px;
+      display: flex;
+      align-items: center;
+
+      &-label {
+
+      }
+
+      &-select {
+        flex: 1;
+      }
+    }
+  }
+
+  .ant-modal-footer {
+    padding-bottom: 20px;
+    text-align: center;
+    border-top: unset;
+  }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcYear/index.js b/public/react/src/modules/ecs/EcYear/index.js
new file mode 100644
index 000000000..e9d3a0296
--- /dev/null
+++ b/public/react/src/modules/ecs/EcYear/index.js
@@ -0,0 +1,218 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+import axios from 'axios';
+import { Spin, Button, Table, Input, Divider, Modal, message, Breadcrumb } from 'antd';
+
+import './index.scss';
+import AddYearModal from "./AddYearModal";
+
+const { Search } = Input;
+const { confirm } = Modal;
+
+const defaultPagination = { current: 1, pageSize: 20, total: 0 };
+
+
+class EcYear extends React.Component {
+  constructor (props) {
+    super(props);
+
+    this.state = {
+      majorId: props.match.params.majorId,
+
+      spin: true,
+      loading: true,
+      keyword: '',
+      pagination: {...defaultPagination},
+
+      major: {},
+      yearData: [],
+      
+      // add year modal vars
+      addYearModalVisible: false
+    }
+  }
+
+  componentDidMount() {
+    this.getMajor();
+  }
+
+  getMajor = () => {
+    axios.get(`/ec_major_schools/${this.state.majorId}.json`).then(res => {
+      if(res.status === 200){
+        window.document.title = res.data.name;
+        this.setState({ spin: false, major: res.data });
+        this.getYearData();
+      }
+    }).catch(e => console.log(e));
+  }
+
+  onSearch = () => {
+    this.setState({ pagination: {...defaultPagination} }, () => {
+      this.getYearData();
+    })
+  }
+
+  getYearData = () => {
+    let { majorId, keyword, pagination } = this.state;
+    axios.get(`/ec_major_schools/${majorId}/ec_years.json`, {
+      params: {
+        search: keyword,
+        page: pagination.current,
+        per_page: pagination.pageSize
+      }
+    }).then(res => {
+      if(res.status === 200){
+        let pagination = { ...this.state.pagination };
+        pagination.total = res.data.count;
+
+        this.setState({
+          loading: false,
+          yearData: res.data.ec_years,
+          pagination
+        })
+      }
+    }).catch((e) => {
+      console.log(e);
+      this.setState({ loading: false });
+    })
+  }
+
+  onPaginationChange = (page, pageSize) => {
+    this.setState({ pagination: { current: page, pageSize: pageSize } }, () => {
+      this.getYearData()
+    });
+  }
+
+  showDeleteYearConfirm = (yearId) => {
+    confirm({
+      title: '确认删除该届别?',
+      okText: '确认',
+      cancelText: '取消',
+      onOk: () => {
+        this.deleteYear(yearId);
+      },
+      onCancel() {},
+    });
+  }
+
+  deleteYear = (yearId) => {
+    let { majorId } = this.state;
+    axios.delete(`/ec_major_schools/${majorId}/ec_years/${yearId}.json`).then(res => {
+      if(res.status === 200){
+        message.success('操作成功');
+        this.getYearData();
+      }
+    }).catch(e => console.log(e))
+  }
+
+  HideAddYearModal = (added) => {
+    this.setState({ AddYearModalVisible: false });
+    if(added){
+      this.setState({ keyword: '', pagination: { ...defaultPagination } }, this.getYearData);
+    }
+  }
+
+  render() {
+    let { majorId, spin, keyword, loading, pagination, major, yearData } = this.state;
+
+    const linkRender = (num, url) => {
+      return <Link to={url}>{ num === 0 ? "立即配置" : num }</Link>;
+    }
+    const contrastRender = (num, other) => {
+      let color = other !== 0 && num === other ? 'color-green' : 'color-orange';
+
+      return other === 0 ? (
+        <div className={color}><span>--</span> / <span>--</span></div>
+      ) : (
+        <div className={color}><span>{num}</span> / <span>{other}</span></div>
+      )
+    }
+    const statusRender = (text, record) => {
+      let zero = record.graduation_subitem_count === 0;
+
+      return zero ? (
+        <span className="color-orange">--</span>
+      ) : (
+        <span className={text === 'achieved' ? 'color-green' : 'color-orange'}>
+      { text === 'achieved' ? '已达成' : '未达成' }
+    </span>
+      )
+    }
+    const operationRender = (_, record) => {
+      return (
+        <div className="operation-box">
+          <Link to={`/ecs/major_schools/${majorId}/years/${record.id}/training_objectives`} className="link">立即配置</Link>
+          <a className="link" onClick={() => this.showDeleteYearConfirm(record.id)}>删除</a>
+        </div>
+      )
+    }
+    const tableColumns = [
+      { title: '届别', dataIndex: 'year', render: text => `${text}届` },
+      { title: '培养目标', dataIndex: 'training_subitem_count', render: (text, record) => linkRender(text, `/ecs/major_schools/${this.state.majorId}/years/${record.id}/training_objectives`), },
+      { title: '毕业要求', dataIndex: 'graduation_requirement_count', render: (text, record) => linkRender(text, `/ecs/major_schools/${this.state.majorId}/years/${record.id}/graduation_requirement`), },
+      { title: '课程体系', dataIndex: 'course_count', render: (text, record) => linkRender(text, `/ecs/major_schools/${this.state.majorId}/years/${record.id}/ec_course_setting`), },
+      { title: '课程目标(达成情况)', key: 'courseTarget', render: (_, record) => { return contrastRender(record.achieved_graduation_course_count, record.course_target_count) } },
+      { title: '毕业要求指标点(达成情况)', key: 'graduation', render: (_, record) => { return contrastRender(record.achieved_graduation_objective_count, record.graduation_subitem_count) } },
+      { title: '评价结果', dataIndex: 'status', render: statusRender },
+      { title: '操作', key: 'operation', render: operationRender }
+    ];
+
+    return (
+      <div className="newMain clearfix">
+        <Spin size="large" spinning={spin} style={{marginTop: '15%'}}>
+          <div className="educontent ec-year-list-page">
+            <div className="educontent ec-breadcrumb">
+              <Breadcrumb separator=">">
+                <Breadcrumb.Item key="department">
+                  <Link to={`/ecs/department?school_id=${major && major.school_id}`}>{ major && major.school_name }</Link>
+                </Breadcrumb.Item>
+                <Breadcrumb.Item key="major-school">{ major && major.name }</Breadcrumb.Item>
+              </Breadcrumb>
+            </div>
+            
+            <div className="ec-year-list-container">
+              <div className="year-list-head">
+                <div className="year-list-head-left">
+                  <div className="year-list-head-label">{ major.name }</div>
+                  <div className="year-list-head-tip">
+                    <span>请选择添加参与认证的学生界别,多个界别分次添加</span>
+                    <Link to="/forums/3528" target="_blank" className="link ml10">查看详情</Link>
+                  </div>
+                </div>
+                <Button type="primary" onClick={() => this.setState({ AddYearModalVisible: true })}>添加届别</Button>
+              </div>
+  
+              <Divider/>
+  
+              <div className="year-list-body">
+                <div className="year-list-search">
+                  <Search
+                    placeholder="届别检索"
+                    onInput={e => this.setState({keyword: e.target.value})}
+                    onSearch={this.onSearch}
+                    value={keyword}
+                    style={{ width: 200 }}/>
+                </div>
+  
+                <div className="year-list-table">
+                  <Table rowKey="id"
+                         loading={loading}
+                         columns={tableColumns}
+                         dataSource={yearData}
+                         pagination={{...pagination, onChange: this.onPaginationChange}}/>
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <AddYearModal schoolId={major && major.school_id}
+                        majorId={majorId}
+                        visible={this.state.AddYearModalVisible}
+                        onHide={this.HideAddYearModal}/>
+        </Spin>
+      </div>
+    )
+  }
+}
+
+export default EcYear;
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/EcYear/index.scss b/public/react/src/modules/ecs/EcYear/index.scss
new file mode 100644
index 000000000..66f49e304
--- /dev/null
+++ b/public/react/src/modules/ecs/EcYear/index.scss
@@ -0,0 +1,62 @@
+.ec-year-list-page {
+  .ec-breadcrumb {
+    margin-top: 10px;
+    margin-bottom: 10px;
+  }
+
+  .ec-year-list-container {
+    background: #fff;
+  }
+
+  .year-list {
+    &-head {
+      margin-bottom: -24px;
+      padding: 20px 30px;
+      display: flex;
+      align-items: flex-end;
+      justify-content: space-between;
+
+      &-left {
+        flex: 1;
+      }
+
+      &-label {
+        font-size: 18px;
+      }
+
+      &-tip {
+        font-size: 14px;
+        color: #999999;
+      }
+    }
+
+
+    &-body {
+      margin-top: -24px;
+    }
+
+    &-search {
+      padding: 20px 30px;
+      display: flex;
+      flex-direction: row-reverse;
+    }
+
+    &-table {
+      min-height: 400px;
+
+      th, td {
+        text-align: center;
+      }
+    }
+  }
+
+  .link {
+    color: #007bff;
+  }
+
+  .operation-box {
+    .link {
+      margin: 0 5px;
+    }
+  }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/Ecs.js b/public/react/src/modules/ecs/Ecs.js
new file mode 100644
index 000000000..dab84e8d5
--- /dev/null
+++ b/public/react/src/modules/ecs/Ecs.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import { Switch, Route } from 'react-router-dom';
+import { SnackbarHOC } from 'educoder';
+
+import CustomLoadable from "../../CustomLoadable";
+import {TPMIndexHOC} from "../tpm/TPMIndexHOC";
+
+const Home = CustomLoadable(() => import('./Home/index'));
+const EcYear = CustomLoadable(() => import('./EcYear/index'));
+const EcSetting = CustomLoadable(() => import('./EcSetting/index'));
+
+class Ecs extends React.Component {
+
+  render() {
+    return (
+      <div className="newMain clearfix">
+        <Switch>
+          <Route extra path='/ecs/department' component={Home}></Route>
+          <Route path='/ecs/major_schools/:majorId/years/:yearId/:type' component={EcSetting}></Route>
+          <Route extra path='/ecs/major_schools/:majorId' component={EcYear}></Route>
+        </Switch>
+      </div>
+    )
+  }
+}
+
+export default SnackbarHOC() (TPMIndexHOC  ( Ecs ));
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/Home/AddMajorModal.js b/public/react/src/modules/ecs/Home/AddMajorModal.js
new file mode 100644
index 000000000..9b58ed7e4
--- /dev/null
+++ b/public/react/src/modules/ecs/Home/AddMajorModal.js
@@ -0,0 +1,179 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Modal, Input, Table, message } from 'antd';
+import axios from 'axios';
+
+import './AddMajorModal.scss';
+
+const { Search } = Input;
+const tableColumns = [
+  { title: '专业代码', dataIndex: 'code', key: 'code', width: 100, },
+  { title: '专业名称', dataIndex: 'name', key: 'name', },
+  { title: '', dataIndex: 'selected', key: 'selected', width: 80, render: selected => selected && <span className="color-orange">已选择</span> },
+];
+const defaultPagination = { current: 1, pageSize: 10, total: 0 };
+
+class AddMajorModal extends React.Component {
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      loading: false,
+      confirmLoading: false,
+      error: '',
+      keyword: '',
+      pagination: {...defaultPagination},
+
+      schoolId: props.schoolId,
+      majorData: [],
+      selectedData: []
+    }
+
+    this.getMajors = this.getMajors.bind(this);
+    this.selectMajor = this.selectMajor.bind(this);
+    this.onAfterModalClose = this.onAfterModalClose.bind(this);
+    this.handleOk = this.handleOk.bind(this);
+    this.handleCancel = this.handleCancel.bind(this);
+    this.onPaginationChange = this.onPaginationChange.bind(this);
+  }
+
+  componentDidUpdate(prevProps) {
+    if(!prevProps.visible && this.props.visible){
+      this.getMajors();
+    }
+  }
+
+  onSearch = () => {
+    this.setState({ pagination: {...defaultPagination} }, () => {
+      this.getMajors();
+    })
+  }
+
+  getMajors(){
+    let { schoolId, keyword, pagination } = this.state;
+
+    this.setState({ loading: true });
+    axios.get(`/schools/${schoolId}/ec_majors.json`, {
+      params: {
+        search: keyword,
+        page: pagination.current,
+        per_page: pagination.pageSize
+      }
+    }).then(res => {
+      if(res.status === 200){
+        let pagination = { ...this.state.pagination };
+        pagination.total = res.data.count;
+
+        this.setState({
+          majorData: res.data.ec_majors,
+          loading: false,
+          pagination,
+        })
+      }
+    }).catch(e => {
+      console.log(e);
+      this.setState({ loading: false })
+    })
+  }
+
+  getCheckboxProps(record){
+    return { ...record, disabled: record.selected }
+  }
+
+  selectMajor(selectedRowKeys){
+    this.setState({ selectedData: selectedRowKeys });
+  }
+
+  onPaginationChange(page, pageSize){
+    this.setState({ pagination: { current: page, pageSize: pageSize } }, () => {
+      this.getMajors()
+    });
+  }
+
+  handleOk(){
+    let { selectedData } = this.state;
+
+    if(selectedData.length === 0){
+      this.setState({ error: '请选择专业' });
+      return;
+    }
+
+    this.submitMajor(selectedData);
+  }
+
+  handleCancel(){
+    this.props.onHide(false);
+  }
+
+  onAfterModalClose(){
+    this.setState({
+      error: '',
+      keyword: '',
+      pagination: {...defaultPagination},
+      majorData: [],
+      selectedData: [],
+    });
+  }
+
+  submitMajor(ids) {
+    let { schoolId } = this.state;
+
+    this.setState({ confirmLoading: true });
+    axios.post(`/schools/${schoolId}/ec_major_schools.json`, { major_ids: ids }).then(res => {
+      if(res.status === 200){
+        message.success('操作成功');
+        this.setState({ confirmLoading: false });
+        this.props.onHide(true);
+      }
+    }).catch(e => {
+      console.log(e);
+      this.setState({ confirmLoading: false });
+    })
+  }
+
+  render() {
+    let { loading, keyword, majorData, selectedData, pagination } = this.state;
+
+    return (
+      <div>
+        <Modal
+          title="添加认证专业"
+          wrapClassName="add-major-modal"
+          visible={this.props.visible}
+          confirmLoading={this.state.confirmLoading}
+          afterClose={this.onAfterModalClose}
+          onOk={this.handleOk}
+          onCancel={this.handleCancel}>
+
+          <div className="add-major-search">
+            <Search
+              placeholder="专业代码/专业名称检索"
+              onInput={e => this.setState({keyword: e.target.value})}
+              onSearch={this.onSearch}
+              value={keyword}/>
+          </div>
+
+          <div className="add-major-body">
+            <Table rowKey="id"
+                   rowSelection={{onChange: this.selectMajor, getCheckboxProps: this.getCheckboxProps, selectedRowKeys: selectedData}}
+                   loading={loading}
+                   columns={tableColumns}
+                   dataSource={majorData}
+                   pagination={{...pagination, onChange: this.onPaginationChange}}
+                   size="small"
+                   scroll={{ y: 200 }}/>
+            <div className="error">{ this.state.error }</div>
+          </div>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+AddMajorModal.propTypes = {
+  schoolId: PropTypes.number,
+  visible: PropTypes.bool,
+  onHide: PropTypes.func
+}
+
+export default AddMajorModal
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/Home/AddMajorModal.scss b/public/react/src/modules/ecs/Home/AddMajorModal.scss
new file mode 100644
index 000000000..bde678bcd
--- /dev/null
+++ b/public/react/src/modules/ecs/Home/AddMajorModal.scss
@@ -0,0 +1,29 @@
+.add-major-modal {
+  .add-major-search {
+    margin-bottom: 20px;
+  }
+  .ant-modal-body {
+    padding-bottom: 0;
+
+    .major-row {
+      padding: 10px;
+    }
+    .ant-table-thead {
+      background: #fafafa;
+    }
+    .ant-table-scroll {
+      min-height: 250px;
+    }
+
+    .error {
+      height: 20px;
+      margin-top: -20px;
+      color: red;
+    }
+  }
+  .ant-modal-footer {
+    padding-bottom: 20px;
+    text-align: center;
+    border-top: unset;
+  }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/Home/AddManagerModal.js b/public/react/src/modules/ecs/Home/AddManagerModal.js
new file mode 100644
index 000000000..7e341ea11
--- /dev/null
+++ b/public/react/src/modules/ecs/Home/AddManagerModal.js
@@ -0,0 +1,226 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Modal, Input, Table, message, Select, Form, Row, Col, Button } from 'antd';
+import axios from 'axios';
+
+import './AddManagerModal.scss';
+
+const { Option } = Select;
+
+const columnRender = (text) => <div style={{ wordWrap: 'break-word', wordBreak: 'break-all' }}> {text} </div>
+const tableColumns = [
+  { title: '姓名', dataIndex: 'name', key: 'name', width: 60, render: columnRender },
+  { title: '职称', dataIndex: 'identity', key: 'identity', width: 60, },
+  { title: '单位', dataIndex: 'school_name', key: 'school_name', render: (_, record) => columnRender(`${record.school_name} ${record.department_name}`) },
+  { title: '手机号', dataIndex: 'phone', key: 'phone', width: 80, },
+];
+const defaultPagination = { current: 1, pageSize: 20, total: 0 };
+
+class AddManagerModal extends React.Component {
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      loading: false,
+      confirmLoading: false,
+      nameValidateStatus: '',
+      error: '',
+      name: '',
+      school: props.schoolName,
+      identity: '',
+      pagination: {...defaultPagination},
+
+      schoolId: props.schoolId,
+      userData: [],
+      selectedData: []
+    }
+
+    this.getUsers = this.getUsers.bind(this);
+    this.selectUser = this.selectUser.bind(this);
+    this.onAfterModalClose = this.onAfterModalClose.bind(this);
+    this.handleOk = this.handleOk.bind(this);
+    this.handleCancel = this.handleCancel.bind(this);
+    this.onPaginationChange = this.onPaginationChange.bind(this);
+  }
+
+  onSearch = () => {
+    this.setState({ pagination: {...defaultPagination} }, () => {
+      this.getUsers();
+    })
+  }
+
+  getUsers(){
+    let { majorId } = this.props;
+    let { name, school, identity, pagination } = this.state;
+
+    if(name.length === 0){
+      this.setState({ nameValidateStatus: 'error' });
+      return;
+    }
+
+    this.setState({ loading: true });
+    axios.get(`/ec_major_schools/${majorId}/users.json`, {
+      params: {
+        name, school, identity,
+        page: pagination.current,
+        per_page: pagination.pageSize
+      }
+    }).then(res => {
+      if(res.status === 200){
+        let pagination = { ...this.state.pagination };
+        pagination.total = res.data.count;
+
+        this.setState({
+          userData: res.data.users,
+          loading: false,
+          pagination,
+        })
+      }
+    }).catch(e => {
+      console.log(e);
+      this.setState({ loading: false })
+    })
+  }
+
+  getCheckboxProps(record){
+    return { ...record, disabled: record.manager }
+  }
+
+  selectUser(selectedRowKeys){
+    this.setState({ selectedData: selectedRowKeys });
+  }
+
+  onPaginationChange(page, pageSize){
+    this.setState({ pagination: { current: page, pageSize: pageSize } }, () => {
+      this.getUsers()
+    });
+  }
+
+  onNameChange = (e) => {
+    let name = e.target.value;
+    let nameValidateStatus = '';
+
+    if(name.length === 0){
+      nameValidateStatus = 'error'
+    }
+
+    this.setState({ nameValidateStatus, name });
+  }
+
+  handleOk(){
+    this.setState({ error: '' });
+    let { selectedData } = this.state;
+
+    if(selectedData.length === 0){
+      this.setState({ error: '请选择至少一个用户' });
+      return;
+    }
+
+    this.submitUsers(selectedData);
+  }
+
+  handleCancel(){
+    this.props.onHide(false);
+  }
+
+  onAfterModalClose(){
+    this.setState({
+      error: '',
+      nameValidateStatus: '',
+      name: '',
+      school: this.props.schoolName,
+      identity: '',
+      pagination: {...defaultPagination},
+      userData: [],
+      selectedData: [],
+    });
+  }
+
+  submitUsers(ids) {
+    let { majorId } = this.props;
+
+    this.setState({ confirmLoading: true });
+    axios.post(`/ec_major_schools/${majorId}/major_managers.json`, { user_ids: ids }).then(res => {
+      if(res.status !== 200){ return }
+
+      message.success('操作成功');
+      this.setState({ confirmLoading: false });
+      this.props.onHide(true);
+    }).catch(e => {
+      console.log(e);
+      this.setState({ confirmLoading: false });
+    })
+  }
+
+  render() {
+    let { loading, name, school, identity, userData, selectedData, pagination, nameValidateStatus } = this.state;
+
+    return (
+      <div>
+        <Modal
+          title="添加管理员"
+          wrapClassName="add-ec-manager-modal"
+          visible={this.props.visible}
+          confirmLoading={this.state.confirmLoading}
+          afterClose={this.onAfterModalClose}
+          onOk={this.handleOk}
+          onCancel={this.handleCancel}>
+
+          <div className="add-ec-manager-search">
+            <Form layout="horizontal">
+              <Row>
+                <Col span={12}>
+                  <Form.Item label="姓名" labelCol={{ span: 6 }} wrapperCol={{span: 16}} validateStatus={nameValidateStatus}>
+                    <Input onChange={this.onNameChange} value={name} placeholder="请输入姓名" />
+                  </Form.Item>
+                </Col>
+                <Col span={12}>
+                  <Form.Item label="职业" labelCol={{ span: 6 }} wrapperCol={{span: 17}} >
+                    <Select value={identity} onChange={value => this.setState({ identity: value }) } placeholder="请选择职业">
+                      <Option value="">全部</Option>
+                      <Option value="teacher">教师</Option>
+                      <Option value="student">学生</Option>
+                      <Option value="professional">专业人士</Option>
+                    </Select>
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row>
+                <Col span={18}>
+                  <Form.Item label="学校" labelCol={{ span: 4 }} wrapperCol={{span: 18}}>
+                    <Input onChange={e => this.setState({ school: e.target.value })} value={school} placeholder="请输入学校名称"/>
+                  </Form.Item>
+                </Col>
+                <Col span={4} offset={2}>
+                  <Button type="primary" className="mt5" onClick={this.onSearch}>搜索</Button>
+                </Col>
+              </Row>
+            </Form>
+          </div>
+
+          <div className="add-ec-manager-body">
+            <Table rowKey="id"
+                   rowSelection={{onChange: this.selectUser, getCheckboxProps: this.getCheckboxProps, selectedRowKeys: selectedData, columnWidth: 40}}
+                   loading={loading}
+                   columns={tableColumns}
+                   dataSource={userData}
+                   pagination={{...pagination, onChange: this.onPaginationChange}}
+                   size="small"
+                   scroll={{ y: 200 }}/>
+            <div className="error">{ this.state.error }</div>
+          </div>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+AddManagerModal.propTypes = {
+  schoolId: PropTypes.string,
+  schoolName: PropTypes.string,
+  majorId: PropTypes.number,
+  visible: PropTypes.bool,
+  onHide: PropTypes.func
+}
+
+export default AddManagerModal
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/Home/AddManagerModal.scss b/public/react/src/modules/ecs/Home/AddManagerModal.scss
new file mode 100644
index 000000000..2b30690fc
--- /dev/null
+++ b/public/react/src/modules/ecs/Home/AddManagerModal.scss
@@ -0,0 +1,35 @@
+.add-ec-manager-modal {
+  .ant-modal-body {
+    padding-bottom: 0;
+
+    .ant-table-thead {
+      background: #fafafa;
+    }
+    .ant-table-scroll {
+      min-height: 250px;
+    }
+
+    .add-ec-manager-search {
+      margin-bottom: 20px;
+
+      .ant-form-item {
+        margin-bottom: 0;
+
+        &-label > label {
+          font-size: 14px !important;
+        }
+      }
+    }
+
+    .error {
+      height: 20px;
+      margin-top: -20px;
+      color: red;
+    }
+  }
+  .ant-modal-footer {
+    padding-bottom: 20px;
+    text-align: center;
+    border-top: unset;
+  }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/Home/MajorManager.js b/public/react/src/modules/ecs/Home/MajorManager.js
new file mode 100644
index 000000000..37b9d6e49
--- /dev/null
+++ b/public/react/src/modules/ecs/Home/MajorManager.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Tag, message } from 'antd';
+import axios from 'axios';
+
+class MajorManager extends React.Component {
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      schoolId: props.schoolId,
+      majorId: props.majorId,
+      canManage: props.canManage,
+      managers: props.managers
+    }
+
+    this.deleteManager = this.deleteManager.bind(this);
+  }
+
+  componentDidUpdate(prevProps) {
+    if(this.props.managers.length !== prevProps.managers.length){
+      this.setState({ managers: this.props.managers });
+    }
+  }
+
+  deleteManager(managerId){
+    axios.delete(`/ec_major_schools/${this.state.majorId}/major_managers/${managerId}.json`).then(result => {
+      if(result.status === 200){
+        message.success('操作成功');
+      }
+    }).catch(e => { console.log(e) })
+  }
+
+  render() {
+    let { canManage, managers } = this.state;
+
+    return (
+      <div className="manager-box-content">
+        {
+          managers && managers.map(manager => {
+            return (
+              <Tag key={manager.id} closable={canManage} onClose={() => { this.deleteManager(manager.id) }} color="blue">
+                { manager.name }
+              </Tag>
+            )
+          })
+        }
+      </div>
+    )
+  }
+}
+
+MajorManager.propTypes = {
+  schoolId: PropTypes.string,
+  majorId: PropTypes.number,
+  canManage: PropTypes.bool,
+  managers: PropTypes.array
+}
+
+export default MajorManager
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/Home/index.js b/public/react/src/modules/ecs/Home/index.js
new file mode 100644
index 000000000..8f66b6572
--- /dev/null
+++ b/public/react/src/modules/ecs/Home/index.js
@@ -0,0 +1,265 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+import { Spin, Avatar, Tooltip, Button, Divider, Input, Row, Col, Icon, Modal } from "antd";
+import { getImageUrl } from 'educoder';
+import axios from 'axios';
+
+import './index.scss';
+import bgImage from '../../../images/ecs/bg.jpg';
+
+import MajorManager from "./MajorManager";
+import AddMajorModal from "./AddMajorModal";
+import AddManagerModal from "./AddManagerModal";
+
+const { Search } = Input;
+const { confirm } = Modal;
+
+class Home extends React.Component {
+  constructor (props) {
+    super(props);
+
+    const searchParams = new URLSearchParams(props.location.search.substring(1));
+    let schoolId = searchParams.get('school_id');
+
+    if(!schoolId){
+      this.props.history.push(`/nopage`);
+      return;
+    }
+
+    this.state = {
+      loading: true,
+      majorLoading: true,
+      AddMajorVisible: false,
+      AddManagerVisible: false,
+      searchKeyword: '',
+
+      schoolId: schoolId,
+      currentMajorId: null,
+      school: null,
+      currentUser: null,
+      managers: null,
+      templateMajor: null,
+      majors: null,
+      majorCount: 0
+    }
+
+    this.getSchoolMajors = this.getSchoolMajors.bind(this);
+    this.HideAddMajorModal = this.HideAddMajorModal.bind(this);
+    this.showDeleteMajorConfirm = this.showDeleteMajorConfirm.bind(this);
+    this.showAddManagerModal = this.showAddManagerModal.bind(this);
+    this.HideAddManagerModal = this.HideAddManagerModal.bind(this);
+  }
+
+  componentDidMount() {
+    this.getSchoolDetail();
+  }
+
+  getSchoolDetail() {
+    axios.get(`/schools/${this.state.schoolId}/detail.json`).then(result => {
+      if(result.status === 200){
+        window.document.title = result.data.school.name;
+        this.setState({
+          school: result.data.school,
+          currentUser: result.data.current_user,
+          managers: result.data.school_managers,
+          loading: false
+        });
+        this.getSchoolMajors();
+      }
+    }).catch(e => {
+      console.log(e);
+      this.setState({ loading: false });
+    });
+  }
+
+  getSchoolMajors(){
+    let that = this;
+    let keyword = this.state.searchKeyword;
+    this.setState({ majorLoading: true });
+
+    axios.get(`/schools/${this.state.schoolId}/ec_major_schools.json?search=${keyword}&per_page=50`).then(result => {
+      if(result.status === 200){
+        that.setState({
+          majorCount: result.data.count,
+          templateMajor: result.data.template_ec_major_school,
+          majors: result.data.ec_major_schools,
+          majorLoading: false
+        });
+      }
+    }).catch(e => {
+      console.log(e);
+      that.setState({ majorLoading: false });
+    });
+  }
+
+  showAddManagerModal(majorId){
+    this.setState({ currentMajorId: majorId, AddManagerVisible: true });
+  }
+
+  HideAddMajorModal(added){
+    this.setState({ AddMajorVisible: false });
+    if(added){
+      this.setState({ searchKeyword: '' }, this.getSchoolMajors)
+    }
+  }
+  HideAddManagerModal(added){
+    this.setState({ AddManagerVisible: false });
+    if(added){
+      this.setState({ searchKeyword: '' }, this.getSchoolMajors)
+    }
+  }
+
+  showDeleteMajorConfirm(majorId){
+    confirm({
+      title: '确认删除该认证专业?',
+      okText: '确认',
+      cancelText: '取消',
+      onOk: () => {
+        this.deleteMajor(majorId);
+      },
+      onCancel() {},
+    });
+  }
+
+  deleteMajor(majorId){
+    let { schoolId, majorCount, majors } = this.state;
+    axios.delete(`/schools/${schoolId}/ec_major_schools/${majorId}.json`).then(res => {
+      if(res.status === 200){
+        this.setState({
+          majorCount: majorCount - 1,
+          majors: majors.filter(major => major.id !== majorId)
+        });
+      }
+    }).catch(e => console.log(e))
+  }
+
+  render() {
+    let { currentUser, school, managers, templateMajor, majors, majorCount } = this.state;
+
+    const manageSchool = !!currentUser && (currentUser.manager || currentUser.admin);
+    const manageMajor = !!currentUser && (manageSchool || currentUser.major_manager);
+
+    const configBtnText = manageMajor ? '配置' : '查看';
+
+    return (
+      <div className="newMain clearfix">
+        <Spin spinning={this.state.loading}  size="large" style={{marginTop:'15%'}}>
+          <div className="ec-home">
+            <div className="pr mb20">
+              <div className="head-image" style={{background: `url(${bgImage}) no-repeat top center`}}>
+                <span className="font-30 color-white font-bd">{ school && school.name }</span>
+              </div>
+            </div>
+
+            <div className="educontent mb20 ec-home-item school-manager-item">
+              <div className="ec-home-item-head">
+                <div className="ec-home-item-label">学校管理员</div>
+                <div className="ec-home-item-tip">温馨提醒:学校管理员有添加专业及设置专业管理员等权限</div>
+              </div>
+              <div className="ec-home-item-body ec-school-manager">
+                {
+                  managers && managers.map((manager) => {
+                    return (
+                      <Link to={`/users/${manager.login}`} key={manager.id} className="ec-school-manager-item">
+                        <Avatar size={48} src={getImageUrl(`images/${manager.image_url}`)} alt="头像"/>
+                        <Tooltip title={manager.name} placement="bottom">
+                          <span className="ec-school-manager-name">{ manager.name }</span>
+                        </Tooltip>
+                      </Link>
+                    )
+                  })
+                }
+              </div>
+            </div>
+
+            <div className="educontent mb50 ec-home-item major-list-item">
+              <div className="ec-home-item-head">
+                <div className="major-list-item-head">
+                  <div className="ec-home-item-label">专业列表</div>
+                  <div className="ec-home-item-tip">
+                    <span>请添加参与认证的专业名称</span>
+                    <Link to="/forums/3527" target="_blank" className="link ml10">查看详情</Link>
+                  </div>
+                </div>
+                <Button type="primary" onClick={() => { this.setState({ AddMajorVisible: true }) }}>添加专业</Button>
+              </div>
+
+              <Divider/>
+
+              <div className="major-list-container">
+                <div className="major-list-head">
+                  <div className="total">{majorCount || 0} 个检索结果({majorCount || 0} 专业)</div>
+                  <Search
+                    placeholder="专业代码/专业名称检索"
+                    onInput={e => this.setState({searchKeyword: e.target.value})}
+                    onSearch={this.getSchoolMajors}
+                    value={this.state.searchKeyword}
+                    style={{ width: 200 }}
+                  />
+                </div>
+                <div className="major-list-body">
+                  <Row className="major-list-row head">
+                    <Col span={2} className="textcenter">序号</Col>
+                    <Col span={4}>专业代码</Col>
+                    <Col span={6}>专业名称</Col>
+                    <Col span={8}>专业管理员</Col>
+                    <Col span={4} className="textcenter">操作</Col>
+                  </Row>
+                  <Spin spinning={this.state.majorLoading}>
+                    {
+                      templateMajor && (
+                        <Row className="major-list-row">
+                          <Col span={2} className="textcenter">0</Col>
+                          <Col span={4}>000000</Col>
+                          <Col span={6}>
+                            <Link to={`/ecs/major_schools/${templateMajor.id}`}>{ templateMajor.name }</Link>
+                          </Col>
+                          <Col span={8}></Col>
+                          <Col span={4} className="textcenter">
+                            <Link to={`/ecs/major_schools/${templateMajor.id}`} className="link">{ configBtnText }</Link>
+                          </Col>
+                        </Row>
+                      )
+                    }
+                    {
+                      majors && majors.map((major, index) => {
+                        return (
+                          <Row className="major-list-row" key={major.id}>
+                            <Col span={2} className="textcenter">{ index + 1 }</Col>
+                            <Col span={4}>{ major.code }</Col>
+                            <Col span={6}>
+                              <Link to={`/ecs/major_schools/${major.id}`}>{ major.name }</Link>
+                            </Col>
+                            <Col span={8}>
+                              <div className="manager-box">
+                                { manageMajor && <a className="link mr10" onClick={() => this.showAddManagerModal(major.id)}><Icon type="plus-circle" /></a> }
+
+                                <MajorManager schoolId={school.id}
+                                              majorId={major.id}
+                                              canManage={manageMajor}
+                                              managers={major.major_managers}></MajorManager>
+                              </div>
+                            </Col>
+                            <Col span={4} className="textcenter operate-box">
+                              <Link to={`/ecs/major_schools/${major.id}`} className="link">{ configBtnText }</Link>
+                              { manageSchool && ( <a className="link" onClick={() => this.showDeleteMajorConfirm(major.id)}>删除</a> ) }
+                            </Col>
+                          </Row>
+                        )
+                      })
+                    }
+                  </Spin>
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <AddMajorModal schoolId={this.state.schoolId} visible={this.state.AddMajorVisible} onHide={this.HideAddMajorModal}/>
+          { this.state.school && <AddManagerModal schoolId={this.state.schoolId} schoolName={this.state.school.name} majorId={this.state.currentMajorId} visible={this.state.AddManagerVisible} onHide={this.HideAddManagerModal}/> }
+        </Spin>
+      </div>
+    )
+  }
+}
+
+export default Home;
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/Home/index.scss b/public/react/src/modules/ecs/Home/index.scss
new file mode 100644
index 000000000..93a5d3f35
--- /dev/null
+++ b/public/react/src/modules/ecs/Home/index.scss
@@ -0,0 +1,127 @@
+.ec-home {
+  .head-image {
+    width: 100%;
+    height: 240px;
+    background-size: 100% 100%;
+    justify-content: center;
+    align-items: center;
+    display: -webkit-flex;
+  }
+
+  .ec-home-item {
+    background: #fff;
+
+    &-head {
+      display: flex;
+      align-items: baseline;
+      margin-bottom: 20px;
+    }
+
+    &-label {
+      margin-right: 20px;
+      font-size: 18px;
+    }
+
+    &-tip {
+      color: #999;
+      font-size: 12px;
+    }
+
+    &.major-list-item {
+      .ec-home-item {
+        &-head {
+          margin-bottom: -24px;
+          padding: 20px 30px;
+          justify-content: space-between;
+          align-items: center;
+        }
+
+        &-tip {
+          font-size: 14px;
+        }
+      }
+    }
+  }
+
+  .school-manager-item {
+    padding: 20px 30px;
+  }
+
+  .ec-school-manager {
+    display: flex;
+    flex-wrap: wrap;
+
+    &-item {
+      margin-right: 20px;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+    }
+
+    &-name {
+      display: block;
+      text-align: center;
+      max-width: 48px;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      color: #666;
+    }
+  }
+
+  .major-list-item {
+    .major-list {
+      &-container {
+
+      }
+
+      &-head {
+        margin-top: -24px;
+        padding: 20px 30px;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+
+        .total { font-size: 12px; }
+      }
+
+      &-body {
+        padding-bottom: 30px;
+      }
+
+      &-row {
+        padding: 10px 15px;
+        border-bottom: 1px solid #eee;
+
+        &:last-child { border-bottom: unset; }
+
+        &.head {
+          background: #F5F5F5;
+        }
+        .ant-btn-link {
+          text-align: center;
+        }
+      }
+    }
+  }
+  .operate-box {
+    .link {
+      margin: 0 5px;
+    }
+  }
+  .manager-box {
+    display: flex;
+    align-items: center;
+
+    &-content {
+      flex: 1;
+      display: flex;
+      flex-wrap: wrap;
+      align-items: center;
+    }
+  }
+
+  .link {
+    color: #007bff;
+  }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/css/ec.css b/public/react/src/modules/ecs/css/ec.css
new file mode 100644
index 000000000..3c62678c9
--- /dev/null
+++ b/public/react/src/modules/ecs/css/ec.css
@@ -0,0 +1,27 @@
+.newedu-class-container{
+  width:1240px;
+  height:84px;
+}
+.ecnewbutton{
+  width:68px;
+  height:30px;
+  background:rgba(76,172,255,1);
+  border-radius:2px;
+  float:right;
+}
+.newedu-title-bottom{
+  width:1240px;
+  height:65px;
+}
+.edu-con-bottom {
+  padding: 10px 0;
+  background: #fff;
+  font-size: 16px;
+}
+
+.TabledataSource .ant-table-wrapper{
+  width: 1240px;
+}
+.ant-table-thead{
+  background:rgba(245,245,245,1);
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/css/ecCourseEvaluations.css b/public/react/src/modules/ecs/css/ecCourseEvaluations.css
new file mode 100644
index 000000000..f27ad7313
--- /dev/null
+++ b/public/react/src/modules/ecs/css/ecCourseEvaluations.css
@@ -0,0 +1,576 @@
+.TrainingLecturer{
+  font-size:18px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  color:#656565;
+}
+.TrainingTheory{
+  font-size:18px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  color:#05101A !important;
+}
+#SystemParameters{
+  height: 81px;
+  line-height: 40px;
+}
+#SystemParameters .SystemParameters:nth-child(1){
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  /* color:#989898 !important; */
+}
+#SystemParameters .SystemParameters:nth-child(2){
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  color:#989898 !important;
+}
+.operationright{
+  float:right !important;
+}
+.ml75{
+  margin-left:75px;
+}
+.mlim30{
+  margin-left:30px !important;
+}
+.RadioGroupbox{
+  display: inline-block;
+  width: 100px;
+  height: 25px;
+  position: relative;
+}
+.RadioGroupboxab{
+  position: absolute;
+  top: -5px;
+  left: 30px;
+}
+.buttoninline{
+  display: inline-block;
+  margin-left: 29px;
+  position: relative;
+  /* width: 100px; */
+  margin-top: 0px;
+  height: 25px;
+}
+.placeholder::-moz-placeholder{font-size:12px;}
+.placeholder::-webkit-input-placeholder{font-size:12px;}
+.placeholder:-ms-input-placeholder{font-size:12px;}
+.mr16{
+  margin-right:16px;
+}
+.defalutSubmitbtn{
+  cursor: pointer;
+}
+.defalutCancelbtn{
+  cursor: pointer;
+}
+.newSystem{
+  background: #fff;
+}
+/* #EvaluationsList{
+  padding:20px 0px;
+} */
+.mt55{
+  margin-top:55px !important;
+}
+.mb100{
+  margin-bottom:100px !important;
+}
+.mt26{
+  margin-top:26px !important;
+}
+.mb80{
+  margin-bottom:80px !important;
+}
+.color99{
+  color:#999999;
+}
+.ant-select-selection__placeholder{
+  width: 100%;
+  font-size:14px;
+  height:58px;
+}
+.mt70{
+  margin-top:70px;
+}
+.mb50{
+  margin-bottom:50px;
+}
+/* 谷歌 */
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+  -webkit-appearance: none;
+  appearance: none;
+  margin: 0;
+  font-size:14px;
+}
+/* 火狐 */
+input{
+  -moz-appearance:textfield;
+  font-size:14px;
+}
+.ColorF68{
+  color:#FF6800;
+}
+.eaSystemp a{
+  color:#05101a;
+}
+.eaSystemp span{
+  color: #05101a !important;
+}
+.editorModify div .ant-input-lg{
+  font-size: 14px;
+}
+#Coursemultiple div div ul .ant-select-selection__choice{
+  margin-left: 0px;
+  height: 20px !important;
+  min-height: 29px;
+  font-size: 14px;
+  line-height: 27px;
+  margin-top: 4px;
+  margin-bottom: 3px;
+}
+
+#Coursemultiple .ant-select-selection--multiple{
+  min-height: 40px !important;
+  line-height: 38px !important;
+}
+#Coursemultiple div div ul .ant-select-search.ant-select-search--inline{
+  margin-left: 0px;
+  height: 20px !important;
+  min-height: 29px;
+  font-size: 14px;
+  line-height: 27px;
+  margin-top: 4px;
+  margin-bottom: 3px;
+}
+.neweditSubentry{
+  position: relative;
+  top: -4px;
+  left: 7px;
+}
+.nulleditSubentry{
+  position: relative;
+  top: -4px;
+  left: 3px;
+}
+.percentage{
+  margin-left: 8px;
+  padding-left: 25px !important;
+}
+.Coursetitle{
+  margin-bottom:0px !important;
+}
+.textaligncenter{
+  padding-left: 30px !important;
+  width: 70px !important;
+}
+.ml72{
+  margin-left:72px;
+}
+
+.bordereaeaea{
+  border-bottom: 1px solid transparent !important;
+}
+.ecnowrap{
+  max-width: 170px;
+  display: inline-block;
+  overflow: hidden;
+  -o-text-overflow: ellipsis;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  color: #40a9ff !important;
+  margin-right: 108px;
+}
+.ecblock{
+  display: inline-block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.Spinlarge{
+  text-align: center;
+  width: 100%;
+  margin-top: 25px;
+  margin-bottom: 25px;
+}
+/* .ant-select-search{
+  display:none;
+}
+.ant-select-search--inline{
+  display:none;
+} */
+.boxinline-block{
+  display: inline-block;
+}
+.boxinline{
+  margin-right: 20px;
+}
+.evaluationdataClass{
+  margin-left: 217px !important;
+  width: 589px !important;
+  display: inline-block;
+}
+.absolute{
+  position:absolute;
+}
+.ml115{
+  margin-left: 115px;
+}
+.ml100{
+  margin-left: 100px;
+}
+.Importclassroomdata{
+  position: absolute;
+  right: 18px;
+  top: 26px;
+}
+.Importclassroomdatas{
+  position: absolute;
+  right: 375px!important;
+  top: 122px !important;
+}
+.Importclassroomdatass {
+  position: absolute;
+  right: 375px !important;
+  top: 248px !important;
+}
+
+#SystemParameters{
+  position: relative;
+}
+
+.newSystem .newtarget_scoreclass{
+  padding: 10px 0px !important;
+  margin: 0px 20px !important;
+}
+
+.newSystem .newtarget_target{
+  padding: 10px 0px !important;
+  margin: 0px 30px !important;
+  border-bottom:1px solid transparent !important;
+}
+
+.nowrap329{
+  max-width: 329px !important;
+  text-align: left;
+  overflow:hidden;
+  text-overflow:ellipsis;
+  white-space:nowrap;
+  color:transparent !important;
+  min-width: 329px !important;
+}
+.ListTableLine li>.column-500{
+  max-width: 360px !important;
+  text-align: left;
+  min-width: 360px !important;
+}
+.color-666{
+  color:#666666 !important;
+}
+.color-05101A{
+  color:#05101A !important;
+}
+#SystemParametersP{
+  position:relative;
+  margin-bottom:0px !important;
+}
+.major_name{
+  cursor:inherit;
+}
+.padding1030{
+  padding: 10px 30px;
+  height: 60px !important;
+}
+.color-red{
+  color:#DD1717;
+}
+.color-redFF{
+  color:#FF6666;
+}
+.margin-left63{
+  margin-left: 63px !important;
+}
+.colorTransparent{
+  color:transparent !important;
+}
+.color999{
+  color: #999999 !important;
+}
+.operationrightbotton{
+  margin-top: 2px!important;
+  margin-right: -25px;
+}
+.mr2{
+  margin-right:2px;
+}
+.colorFF6800{
+  color: #FF6800 !important;
+}
+.lineheight60{
+  line-height: 52px !important;
+}
+.mr13{
+  margin-right: 13px;
+}
+.mr14{
+  margin-right: 14px;
+}
+
+.ecmorelist{
+  margin: 0 auto;
+  width: 100px;
+  /* height: 100px; */
+  display: block;
+}
+
+.padding10im{
+  padding: 10px 0px !important;
+}
+
+.lipadding10im{
+  margin: 0 0px!important;
+}
+
+.lipadding20im{
+  padding: 10px 20px!important;
+}
+
+.marlr19{
+  margin: 0 19px!important;
+}
+.mrj15{
+  margin-right: -15px;
+}
+.margin64px{
+  margin: 0 64px!important;
+}
+.marginright84{
+  margin-right: 84px!important;
+}
+
+.marginright162{
+  margin-right: 162px;
+}
+.width86{
+  width: 86px!important;
+}
+
+.ant-modal-mask {
+  background-color: rgba(5,16,26,0.4);
+}
+.ecmodeldelet{
+  /* 考虑有各种尺寸的屏幕,用比例 */
+  top:36%;
+}
+.ecmodeldelet .ant-modal-header{
+  padding: 0px 24px;
+}
+.ecmodeldelet .ant-modal-title{
+  padding: 0px 15px;
+  text-align: center;
+  box-sizing: border-box;
+  line-height: 70px;
+  height: 70px;
+  border-radius: 10px 10px 0px 0px;
+  font-size: 16px;
+  font-weight: bold;
+}
+a.TrainingLecturer:hover{
+  color:#4CACFF !important;
+}
+
+.newSystem .lipadding10im{
+  margin: 0 0px!important;
+}
+
+.operationleft{
+ float:left !important;
+}
+.color4D4D4D{
+    color:#4D4D4D !important;
+}
+
+/* #SystemParameters .SystemParameters:nth-child(1){
+  color:#4D4D4D !important;
+} */
+
+.color4CACFF{
+  color:#4CACFF !important;
+}
+
+.SystemParameters4CACFF{
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  line-height: 45px;
+}
+
+.detaillist{
+  text-align: center !important;
+  width: 133px  !important;
+  height: 24px ;
+}
+
+.associatedclass{
+    margin-right: 128px !important;
+}
+
+.associatedclasslist{
+  width: 234px;
+  height: 20px;
+  font-size: 14px;
+  font-family: MicrosoftYaHei;
+  font-weight: 400;
+  color: rgba(101,101,101,1);
+  line-height: 22px;
+  margin: 6px auto;
+}
+
+.associatedclasslists{
+  width: 323px;
+  height: 35px;
+  font-size: 14px;
+  font-family: MicrosoftYaHei;
+  font-weight: 400;
+  color: rgba(101,101,101,1);
+  line-height: 22px;
+  margin: 6px auto;
+  margin-bottom: 15px;
+}
+.newecmodeldelet{
+  width:600px !important;
+  top:100px;
+}
+
+.assclasslistsearch{
+  width:454px;
+  height:36px;
+  background:rgba(244,244,244,1);
+  border:1px solid rgba(234,234,234,1);
+  border-radius:4px;
+  position: relative;
+}
+
+.assclassposition{
+    position: absolute;
+    top: 3px;
+    left: 9px;
+}
+
+.assclasslistsearchbtn{
+  width: 64px;
+  height: 35px !important;
+  font-weight: 300 !important;
+  line-height: 35px !important;
+}
+.btnweight{
+  font-weight: 300 !important;
+  color: #fff !important;
+}
+
+.CBCBCB{
+  background:#CBCBCB!important;
+}
+.clear{
+  clear: both;
+}
+.ml120{
+  margin-left: 120px;
+}
+.ml88{
+  margin-left: 88px;
+}
+.assclasslistmid{
+  width: 540px;
+  height: 282px;
+  background: rgba(244,250,255,1);
+  border-radius: 4px;
+  margin-left: 10px;
+  overflow: auto;
+  padding-top: 10px;
+}
+
+.assclasslistsubmit{
+  margin-top: 26px !important;
+  margin-bottom: 8px !important;
+}
+.ant-modal-header{
+  border-top-left-radius:10px;
+  border-top-right-radius:10px;
+}
+.ant-modal-content{
+  border-radius: 10px;
+}
+.assclasslistmidname{
+  width: 160px;
+  overflow: hidden;
+  /* height: 24px; */
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.bordereaeaeas{
+  border-bottom: 1px solid #eaeaea !important;
+}
+.isreloadsbtn{
+  width: 80px !important;
+  font-weight: 400 !important;
+  padding: 0px !important;
+  padding-left: 10px !important;
+}
+
+.f5f5f5{
+  color:rgb(245, 245, 245) !important;
+}
+
+.ant-select-selection{
+  border-radius: 0px !important;
+  background-color: #F5F5F5;
+}
+
+.ant-select-selection:focus{
+  border-radius: 0px !important;
+  background-color: #fff;
+  border-color: #d9d9d9 !important;
+}
+
+.listchildbox{
+  overflow: hidden;
+}
+
+.listchildboxs{
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.ant-input:focus, .ant-input:hover{
+  border-color: transparent;
+}
+.inputWeight{
+  background-color: #F5F5F5;
+}
+.inputWeight:focus {
+  background-color: #fff;
+ }
+ .ant-input:focus {
+  outline: 0;
+  -webkit-box-shadow: 0 0 0 2px transparent !important;
+  box-shadow: 0 0 0 2px transparent !important;
+ }
+
+ .ant-input{
+  border-color: #d9d9d9 !important;
+ }
+
+.mt60{
+  margin-top:60px;
+}
+
+.SystemParameters{
+    height:auto;
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/css/ecCourseSupports.css b/public/react/src/modules/ecs/css/ecCourseSupports.css
new file mode 100644
index 000000000..10b6ebd91
--- /dev/null
+++ b/public/react/src/modules/ecs/css/ecCourseSupports.css
@@ -0,0 +1,368 @@
+.eaSystemp a{
+  color:#05101a;
+}
+.eaSystemp span{
+  color: #05101a !important;
+}
+.eacourse p{
+  height:84px;
+  margin-bottom:0px !important;
+}
+.eacourse #training_objective_contents{
+   height:81px;
+}
+.courseSystem{
+font-size:18px;
+font-family:MicrosoftYaHei;
+font-weight:400;
+line-height:45px;
+color:rgba(5,16,26,1);
+}
+.SystemParameters{
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  line-height:45px;
+  color:rgba(50,50,50,1);
+}
+.SystemParametersysls{
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  color:rgba(50,50,50,1);
+}
+.Systemnum{
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  color:#FF6800;
+}
+.newSystem{
+  width:1200px;
+  overflow:auto;
+  background: #FFF;
+}
+.newSystem .clearfix .column-1{
+  width: 113px !important;
+  text-align: center;
+}
+.operationColumn{
+  margin: 0px 10%;
+  width:100%;
+  height:100%;
+}
+.operationalter{
+  margin: 20px 16px;
+}
+.SystemModifythelist  .column-1{
+  width: 120px !important;
+  text-align: center;
+}
+
+.SystemModifythelist  .column-3{
+  padding-left: 96px;
+  margin-right: 23px;
+}
+.operationright{
+  float:right !important;
+}
+
+.newSystem p{
+  /*padding: 10px 33px !important;*/
+  margin-bottom: 0em;
+}
+.newSystem li{
+  margin:0 !important;
+}
+.SystemModifythelist{
+  background:#FFF !important;
+}
+
+.SystemModifythelist  .column-1:nth-child(1){
+  margin-left: 7px;
+}
+
+.Systempoint{
+  font-size:12px;
+  font-family:MicrosoftYaHei;
+  font-weight:400;
+  color:rgba(152,152,152,1);
+}
+.editorModify{
+  background:#FFF !important;
+}
+.newSystem .editorModify .column-1{
+  width: 194px !important;
+  text-align: left;
+  margin-left: 30px;
+}
+.newSystem .editorModify .column-1:nth-child(1){
+  margin-right: 510px;
+}
+.editorModify .ant-select{
+  width: 556px  !important;
+  margin-left: 36px;
+}
+.editorModify .ant-select .ant-select-selection{
+  height: 30px !important;
+}
+.editorModify .ant-select .ant-select-selection .ant-select-selection__rendered{
+  height: 30px !important;
+}
+.editorModify .ant-select .ant-select-selection .ant-select-selection__rendered .ant-select-selection-selected-value{
+  line-height: 30px !important;
+}
+.inputWeight{
+ width: 20%;
+ font-size:14px;
+ height:30px;
+ margin-left: 20px;
+ background-color: #F5F5F5;
+}
+.SetTheAssociated{
+  width: 314px;
+  height: 30px;
+  float: right;
+  margin-right: -3.5%;
+}
+.SetTheAssociatedchild{
+  width: 120px;
+  height: 30px;
+  background: rgba(255,255,255,1);
+  border: 1px solid rgba(234,234,234,1);
+  border-radius: 4px;
+  float: left;
+  margin-right: 10px;
+  text-align: center;
+  line-height: 30px;
+  /*margin-left: 34px;*/
+}
+.operatebutton{
+  margin-left: 20px;
+  /* margin-top: 16px; */
+}
+.editbulebutton{
+  width:120px;
+  height:30px;
+  background:rgba(76,172,255,1);
+  border-radius:2px;
+  color:#FFF;
+  text-align: center;
+  line-height: 30px;
+}
+.editglybutton{
+  width:120px;
+  height:30px;
+  border:1px solid rgba(205,205,205,1);
+  border-radius:2px;
+  color:#999;
+  text-align: center;
+  line-height: 30px;
+}
+
+.editglybuttonbox{
+  width: 275px;
+  margin-bottom: 30px;
+  margin-right: 20px;
+  margin-right:7%;
+}
+.editglybuttonboxs{
+  width: 275px;
+  margin-bottom: 30px;
+  margin-right: 20px;
+  margin-right:3%;
+}
+.defalutCancelbtn:hover {
+  border: 1px solid #B2B2B2;
+  color: #B2B2B2!important;
+}
+
+.gouxuanbule{
+  color:#4CACFF;
+}
+.gouxuanwhite{
+  color:#FFF;
+}
+.icon-gouxuan{
+  cursor: pointer;
+}
+/* 谷歌 */
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+    -webkit-appearance: none;
+    appearance: none;
+    margin: 0;
+}
+/* 火狐 */
+input{
+    -moz-appearance:textfield;
+}
+.inputWeight{
+  text-indent:0.625rem;
+}
+
+.columnlocation{
+  height: 40px;
+  line-height: 40px;
+}
+.paddingLF{
+  padding:0 33px;
+}
+.width20{
+  width: 20px;
+  height: 20px;
+  text-align: center;
+}
+.defalutSubmitbtn,.defalutCancelbtn{
+  cursor: pointer;
+}
+.mb290{
+  margin-bottom:290px;
+}
+.Spinlarge{
+  text-align: center;
+  width: 100%;
+  margin-top: 25px;
+  margin-bottom: 25px;
+}
+.DDred{
+  color:#DD1717;
+}
+.color-666{
+  color:#666666 !important;
+}
+.color-05101A{
+  color:#05101A !important;
+}
+.ec_graduation_name{
+  margin-right:20px !important;
+}
+.column-width575{
+  color: transparent !important;
+}
+.column-width130{
+  width: 130px !important;
+  height: 40px;
+}
+
+
+.ListTableLine li>span {
+    max-width: 550px !important;
+}
+
+.graduateRequirement .clearfix .column-1 {
+    width: 76px!important;
+}
+.newrightcalculatebutton{
+  width: 50px;
+  height: 25px;
+  border: 1px solid rgba(76,172,255,1);
+  border-radius: 1px;
+  line-height: 25px;
+  text-align: center;
+  margin-top: 7px;
+  cursor: pointer;
+  color: rgba(76,172,255,1);
+}
+.newrightcalculatebuttons{
+   width: 50px;
+   height: 25px;
+   border: 1px solid rgba(76,172,255,1);
+   border-radius: 1px;
+   line-height: 25px;
+   text-align: center;
+   margin-top:9px;
+   cursor: pointer;
+   color: rgba(76,172,255,1);
+ }
+.columnbox{
+  height: 53px;
+  overflow: hidden;
+}
+
+.ant-modal-mask {
+  background-color: rgba(5,16,26,0.4);
+}
+.ecmodeldelet{
+  top:300px;
+}
+.ecmodeldelet .ant-modal-header{
+  padding: 0px 24px;
+}
+.ecmodeldelet .ant-modal-title{
+  padding: 0px 15px;
+  text-align: center;
+  box-sizing: border-box;
+  line-height: 70px;
+  height: 70px;
+  border-radius: 10px 10px 0px 0px;
+  font-size: 16px;
+  font-weight: bold;
+}
+.bor-red {
+  border: 1px solid #db0505 !important;
+}
+
+.ml93{
+  margin-left:93px;
+}
+.ml26{
+  margin-left: 26px;
+}
+.finishtarget{
+  width: 69px;
+  /* height: 48px; */
+  line-height: 20px;
+  text-align: center;
+  margin-right: 48px;
+}
+
+.bordereaeaea{
+  border-bottom: 1px solid transparent !important;
+}
+
+.heightimportant{
+  height: 30px !important;
+  background-color: #F5F5F5;
+}
+.heightimportant:focus {
+  background-color: #fff;
+}
+.inputWeight:focus {
+  background-color: #fff;
+ }
+.heightlineimportant{
+  line-height: 30px !important;
+}
+
+.ant-select-selection:hover{
+  border-color: #d9d9d9 !important;
+}
+.ant-input:focus {
+  outline: 0;
+  -webkit-box-shadow: 0 0 0 2px transparent !important;
+  box-shadow: 0 0 0 2px transparent !important;
+ }
+ .ant-input{
+  border-color: #d9d9d9 !important;
+ }
+ .ant-select-selection:focus{
+  -webkit-box-shadow: 0 0 0 2px transparent !important;
+  box-shadow: 0 0 0 2px transparent !important;
+ }
+ .ant-select-selection:active{
+  -webkit-box-shadow: 0 0 0 2px transparent !important;
+  box-shadow: 0 0 0 2px transparent !important;
+ }
+
+ .ant-select-selection:focus{
+  border-color: #d9d9d9 !important;
+ }
+ .ant-select-selection{
+  -webkit-box-shadow: 0 0 0 2px transparent !important;
+  box-shadow: 0 0 0 2px transparent !important;
+ }
+
+.mt60{
+  margin-top:60px;
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/css/search.svg b/public/react/src/modules/ecs/css/search.svg
new file mode 100644
index 000000000..cf0e16c0c
--- /dev/null
+++ b/public/react/src/modules/ecs/css/search.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="20px" height="20px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M463.9 804.4c-194.7 0-353.1-158.4-353.1-353.1S269.2 98.2 463.9 98.2 817 256.6 817 451.3 658.6 804.4 463.9 804.4z m0-651.9c-164.8 0-298.8 134-298.8 298.8s134 298.8 298.8 298.8 298.8-134 298.8-298.8-134-298.8-298.8-298.8zM884.9 926.6c-7.2 0-14.4-2.9-19.8-8.6l-198-210.6c-10.3-10.9-9.7-28.1 1.2-38.4 10.9-10.3 28.1-9.8 38.4 1.2l198 210.6c10.3 10.9 9.7 28.1-1.2 38.4-5.2 5-11.9 7.4-18.6 7.4z" /></svg>
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/curriculum/Curriculum.js b/public/react/src/modules/ecs/curriculum/Curriculum.js
new file mode 100644
index 000000000..3dae260de
--- /dev/null
+++ b/public/react/src/modules/ecs/curriculum/Curriculum.js
@@ -0,0 +1,255 @@
+import React, { Component } from 'react';
+import classNames from 'classnames'
+
+import axios from 'axios';
+
+import { TPMIndexHOC } from '../../tpm/TPMIndexHOC';
+
+import { SnackbarHOC } from 'educoder'
+
+import { message,Modal,Spin,Icon} from 'antd';
+
+import 'antd/dist/antd.css';
+
+import EcTitleCourseEvaluations from '../ecTitle/ecTitle'
+
+import '../css/ecCourseSupports.css';
+
+import '../css/ecCourseEvaluations.css';
+import {
+	BrowserRouter as Router,
+	Route,
+	Switch
+} from 'react-router-dom';
+import Loadable from 'react-loadable';
+import Loading from "../../../Loading";
+const $ = window.$;
+const Curriculumtwo = Loadable({
+	loader: () => import('./Curriculumtwo'),
+	loading: Loading,
+})
+const EcCourseEvaluationsbottom =Loadable({
+	loader: () => import('../subroute/ecCourseEvaluations/EcCourseEvaluationsbottom'),
+	loading: Loading,
+});
+const EcCompletionCalculation =Loadable({
+	loader: () => import('../subroute/ecCompletion_calculation/EcCompletionCalculation'),
+	loading: Loading,
+});
+
+
+class Curriculum extends Component {
+	//课程体系
+	constructor(props) {
+		super(props)
+		this.state= {
+      classcalue:5,
+			newec_course_idbottom:"",
+			course_name:undefined,
+			course_url:"a",
+			ecmanager:true,
+			titine:1,
+		}
+		}
+
+	componentWillMount(){
+		// window.document.title = '课程达成评价结果';
+	}
+	componentDidMount(){
+		console.log(this.props);
+	}
+	sync_course_data=()=>{
+		// this.setState({listSpin:true})
+		// let ec_course_id=this.props.match.params.ec_course_id;
+		// let Url ='/ec_course_achievement_methods/sync_course_data';
+		// axios.post(Url, {
+		// 		ec_course_id:ec_course_id
+		// 	},
+		// 	{
+		// 		withCredentials: true
+		// 	}
+		// ).then((response) => {
+		// 	if(response.data.status===0){
+		// 		this.setState({
+		// 			// titlemessage: response.data.message+"(支撑关系变更)",
+		// 			Modallist: response.data.message,
+		// 			Modallisttype:true,
+		// 			listSpin:false
+		// 		})
+		// 		this.UpdateEvaluations();
+		// 	}else if(response.data.status===-1){
+		// 		this.setState({
+		// 			// titlemessage: response.data.message+"(支撑关系变更)",
+		// 			Modallist: response.data.message,
+		// 			Modallisttype:true,
+		// 			listSpin:false
+		// 		})
+		//
+		// 	}
+		// }).catch((error) => {
+		// 	console.log(error)
+		// })
+
+	}
+
+	onAclick=(i)=>{
+		console.log("onAclick");
+		console.log(i);
+		if(i===1){
+			this.props.history.push(this.props.match.url+"/ec_course_support_setting/1");
+		}else if(i===2){
+			this.props.history.push(this.props.match.url+"/ec_course_reach_setting/2");
+		}else if(i===3){
+			this.props.history.push(this.props.match.url+"/score_level/3");
+		}else if(i===4){
+			this.props.history.push(this.props.match.url+"/evaluation_methods/4");
+		}else{
+			this.props.history.push(this.props.match.url+"/competition_calculation_info/5");
+		}
+		this.setState({
+			titine:i,
+		})
+
+	};
+	Ontitine=(s)=>{
+		if(s==="ec_course_support_setting"){
+			this.setState({
+				titine:1,
+			})
+		}else if(s==="ec_course_reach_setting"){
+			this.setState({
+				titine:2,
+			})
+		}else if(s==="score_level"){
+			this.setState({
+				titine:3,
+			})
+		}else if(s==="evaluation_methods"){
+			this.setState({
+				titine:4,
+			})
+		}else if(s==="competition_calculation_info"){
+			this.setState({
+				titine:5,
+			})
+		}
+
+	};
+	associatedclass=()=>{
+
+	};
+	deleteassociatedclass=()=>{
+
+	}
+	render() {
+		let {newec_course_idbottom,titine,classcalue,course_name,course_url,ecmanager,Spintype,calculatesetype,ec_course_id,course_total_scoreaverage,ec_course_targets_count,schooldata,ecComponentState,course_total_score,total_rate_data,ec_course_targets,graduation_list,target_list,target_score,evaluate_result,morelisttype,titlemessage,completiontype,completionlist,ismanager} = this.state;
+    // console.log("Curriculum");
+    // console.log(this.props);
+		// console.log(titine);
+		return (
+			<div className="educontent">
+			<div className="newMain clearfix">
+				<div className="edu-back-white eacourse">
+
+					<div className="clearfix padding20-30 bor-bottom-greyE">
+						<a href={schooldata&&schooldata.course_setting_url} className="color-grey-9 TrainingLecturer">课程体系</a> >
+						<a className="TrainingTheory major_name"> {schooldata&&schooldata.ec_course_name} 达成评价详情</a>
+						{/* <a href="javascript:void(0)" className="fr white-btn edu-blueback-btn mt4">导出培养目标</a> */}
+						<div className="color-grey-9 mr10">系统根据课程目标、课程考核方式与课程目标评价方法,一键计算评价课程目标的达成情况  <a className={"color-blue"} onClick={() => window.elasticLayer(3533)}>查看详情</a></div>
+						{
+							titine === 4 ?
+								<span className="Importclassroomdatas" style={{top: '22px'}}>
+                  <a className="white-btn edu-blueback-btn fr mb10 mr10 mt7" target="_blank"
+									href={'/ec_courses/' + newec_course_idbottom + '/export_ec_course_targets?format=xls'}>导出评价方法</a>
+                  </span>
+						  :titine === 1 ?
+								<span className="Importclassroomdatas" style={{top: '22px'}}>
+                  <a className="white-btn edu-blueback-btn fr mb10 mr10 mt7"
+									href={`/ec_courses/${this.props.match.params.ec_course_id}/export_ec_course_targets?format=xls`}
+									>导出课程目标</a>
+                  </span>
+							:titine===2?
+									<div className={"Importclassroomdatas"}>
+                                <span className="" >
+                                <a className="white-btn edu-blueback-btn fr mr10 mt7"    style={{top: '22px',display:ecmanager===false?"none":"block"}} target="_blank" href={'/ec_courses/'+ec_course_id+'/export_ec_course_targets?format=xls'}>导出考核方法</a>
+                                </span>
+										<a className="white-btn edu-blueline-btn fr mr10 mt7 mr20"
+											 onClick={this.associatedclass}
+											 style={{display: course_url === "" && ecmanager === true ? "block" : "none"}}
+										>关联课堂</a>
+										<a className="white-btn edu-blueline-btn fr mr10 mt7 mr20"
+											 onClick={this.deleteassociatedclass}
+											 style={{display:course_url!=""&&ecmanager===true?"block":"none"}}
+										>取消关联</a>
+									</div>
+							:""
+						}
+					</div>
+
+					<div className="padding20-30"style={titine===2||titine===3?{height:"100px"}:{height:"80px"}}
+					>
+						<a className="fl SystemParameters" style={titine===1?{display:schooldata&&schooldata.ec_course_support_setting_url===null?"none":"block",color:'#4CACFF'}:{display:schooldata&&schooldata.ec_course_support_setting_url===null?"none":"block",color:'#4D4D4D'}}
+							  onClick={()=>this.onAclick(1)}>1.课程目标</a>
+						<a className="fl SystemParameters ml40"
+							 style={titine===2?{display:schooldata&&schooldata.ec_course_reach_setting_url===null?"none":"block",color:'#4CACFF'}:{display:schooldata&&schooldata.ec_course_reach_setting_url===null?"none":"block",color:'#4D4D4D'}}
+							 onClick={()=>this.onAclick(2)}>2.课程考核方式与数据来源</a>
+						<a className="fl SystemParameters4CACFF ml40 "
+							 style={titine===3?{color:'#4CACFF'}:{display:"block",color:'#4D4D4D'}}
+							 onClick={()=>this.onAclick(3)}>3.成绩等级设置</a>
+						<a className="fl SystemParameters ml40"
+							 style={titine===4?{display:schooldata&&schooldata.evaluation_methods_url===null?"none":"block",color:'#4CACFF'}:{display:schooldata&&schooldata.evaluation_methods_url===null?"none":"block",color:'#4D4D4D'}}
+							 onClick={()=>this.onAclick(4)}
+						>4.课程目标评价方法</a>
+						<a className="fl SystemParameters ml40 "
+							 style={titine===5?{display:schooldata&&schooldata.competition_calculation_info_url===null?"none":"block",color:'#4CACFF'}:{display:schooldata&&schooldata.competition_calculation_info_url===null?"none":"block",color:'#4D4D4D'}}
+							 onClick={()=>this.onAclick(5)}
+						>5.课程达成评价结果</a>
+						{
+							titine===5?
+						  <span>
+						  <span className={ismanager===false?"none":""} style={{top: "26px"}}>
+							<a className="white-btn edu-blueback-btn fr mb10 mr10 mt9" target="_blank" href={"/ec_courses/"+ec_course_id+"/export_evaluation_result.xls"}>导出评价详情</a>
+							</span>
+						  <span className={ismanager===false?"none":"right newrightcalculatebuttons fr mb10 mr20 "}
+							onClick={this.newrightcalculatebutton}>计算</span>
+							</span>
+						 :titine===4?
+								<span className="fr ml20 SystemParameters" style={{color: '#989898'}}>(各环节平均得分*占比)之和/(各环节总分*占比)之和</span>
+						 :titine===3?
+							<span className="fl SystemParametersysls" style={{display:course_name===null||course_name===undefined?"block":"none",
+							padding: '0px 0px 0px 0px',textAlign: 'left',width: '100%',color:'#989898'}}>(将学生的成绩转换成对应的等级)</span>
+							:titine===2?
+							<span>
+							<span className="fl" style={{display:course_name===null||course_name===undefined?"block":"none",padding: '0px 0px 0px 0px',textAlign: 'left',width: '100%',color: '#989898'}}>(请在完成配置后,使用各项成绩导入模板,将本学年所有参与的学生成绩数据导入系统)</span>
+							<span className="Importclassroomdatass" style={{display:course_url===""||ecmanager===false?"none":"block",}}><a onClick={this.sync_course_data} className="white-btn edu-orangeback-btn  fr mt2 mr10" style={{width:'112px'}}>导入课堂数据</a></span>
+							</span>
+							:""
+						}
+					</div>
+				</div>
+				<Switch>
+					{/*Curriculumtwo 测试用*/}
+					{/*课程目标*/}
+					<Route extra path='/ecs/major_schools/:majorId/years/:yearId/courses/:type/1'
+								 render={ (props) => (<Curriculumtwo {...this.props} {...props} {...this.state} Ontitine={(i)=>this.Ontitine(i)} />) }></Route>
+					{/*课程考核方式与数据来源*/}
+					<Route extra path='/ecs/major_schools/:majorId/years/:yearId/courses/:type/2'
+								 render={ (props) => (<Curriculumtwo {...this.props} {...props} {...this.state} Ontitine={(i)=>this.Ontitine(i)}/>) }></Route>
+					{/*成绩等级设置*/}
+					<Route extra path='/ecs/major_schools/:majorId/years/:yearId/courses/:type/3'
+								 render={ (props) => (<Curriculumtwo {...this.props} {...props} {...this.state} Ontitine={(i)=>this.Ontitine(i)}/>) }></Route>
+					{/*4课程目标评价方法*/}
+					<Route extra path='/ecs/major_schools/:majorId/years/:yearId/courses/:type/4'
+								 render={ (props) => (<EcCourseEvaluationsbottom {...this.props} {...props} {...this.state} Ontitine={(i)=>this.Ontitine(i)}/>) }></Route>
+					{/*5课程达成评价结果*/}
+					<Route extra path='/ecs/major_schools/:majorId/years/:yearId/courses/:type/5'
+								 render={ (props) => (<EcCompletionCalculation {...this.props} {...props} {...this.state} Ontitine={(i)=>this.Ontitine(i)}/>) }></Route>
+				</Switch>
+			</div>
+			</div>
+		)
+	}
+
+
+}
+export default Curriculum;
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/curriculum/Curriculumtwo.js b/public/react/src/modules/ecs/curriculum/Curriculumtwo.js
new file mode 100644
index 000000000..221b2afb5
--- /dev/null
+++ b/public/react/src/modules/ecs/curriculum/Curriculumtwo.js
@@ -0,0 +1,32 @@
+import React, { Component } from 'react';
+
+class Curriculumtwo extends Component {
+	//测试用
+	constructor(props) {
+		super(props)
+		// console.log(props);
+	}
+
+	componentWillMount(){
+	}
+	componentDidMount(){
+		// console.log(this.props);
+		console.log("Curriculumtwo");
+		console.log(this.props.match.params.type);
+   this.props.Ontitine(this.props.match.params.type);
+	}
+
+
+	render() {
+		// console.log("Curriculumtwo");
+		// console.log(this.props);
+		return (
+			<div className="educontent fl">
+				<span>测试</span>
+			</div>
+		)
+	}
+
+
+}
+export default Curriculumtwo;
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/ecTitle/ecTitle.css b/public/react/src/modules/ecs/ecTitle/ecTitle.css
new file mode 100644
index 000000000..3f6796cdd
--- /dev/null
+++ b/public/react/src/modules/ecs/ecTitle/ecTitle.css
@@ -0,0 +1,104 @@
+#traningNav {
+    display: flex 
+}
+ #traningNav>li {
+    float: none !important;
+}
+ /* 最后一个item 占满剩余空间 */
+#traningNav>li:last-child{
+    flex: 1;
+}
+
+#traningNav>li>.ecTitle {
+    width: 24px;
+    height: 24px;
+    border: 1px solid rgba(65, 140, 205, 1);
+    border-radius: 50%;
+    text-align: center;
+    line-height: 22px;
+    display: inline-block;
+    color: rgba(65, 140, 205, 1) !important;
+    margin-right: 10px;
+}
+#traningNav>li>.ecTitles {
+    line-height: 16px !important;
+    height: 18px!important;
+    width: 18px!important;
+}
+
+#traningNav>li>.ecTitlefont:hover{
+    color: rgba(65, 140, 205, 1)  !important;
+}
+
+.ecimgs3{
+    background: url("./img/3.png");
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    -moz-background-size: 100% 100%;
+    height: 90px;
+    line-height: 90px;
+    width: 235px;
+}
+.ecimgs2{
+    background: url("./img/4.png");
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    -moz-background-size: 100% 100%;
+    height: 90px;
+    line-height: 90px;
+    width: 190px;
+}
+.ecimgs11{
+    background: url("./img/3.png");
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    -moz-background-size: 100% 100%;
+    height: 90px;
+    line-height: 90px;
+    width: 146px;
+}
+.ml18{
+    margin-left: 18px;
+}
+.ecimgs{
+    height: 90px;
+    line-height: 90px;
+}
+.ecmarginleft{
+    margin-left: 23px;
+}
+
+#traningNav>li>.ecTitlefontFFF{
+    color:#fff  !important;
+}
+
+#traningNav>li>.ecTitleFFF {
+    width: 24px;
+    height: 24px;
+    border: 1px solid #fff;
+    border-radius: 50%;
+    text-align: center;
+    line-height: 22px;
+    display: inline-block;
+    color: #fff !important;
+    margin-right: 10px;
+}
+.traningNavs{
+    padding: 0px 0px 0px 0px  !important;
+}
+.traningNavs>li{
+    padding: 0px 10px 30px 10px !important;
+}
+
+.mb0{
+    margin-bottom: 0px !important;
+}
+
+.info2{
+  width:232px;
+    text-align: center;
+}
+.info1{
+  width: 206px;
+    text-align: center;
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/ecTitle/ecTitle.js b/public/react/src/modules/ecs/ecTitle/ecTitle.js
new file mode 100644
index 000000000..f24409018
--- /dev/null
+++ b/public/react/src/modules/ecs/ecTitle/ecTitle.js
@@ -0,0 +1,100 @@
+import React, { Component } from 'react';
+import './ecTitle.css';
+
+class EcTitleCourseEvaluations extends Component {
+    constructor(props) {
+        super(props)
+        this.state = {
+            schooldata:{},
+            ecComponentState:"",
+            ecpaths:""
+        }
+    }
+    componentWillReceiveProps(nextProps){
+        const {schooldata,ecComponentState,ecpath}=nextProps;
+        this.setState({
+            schooldata:schooldata,
+            ecComponentState:ecComponentState,
+            ecpaths:ecpath
+        })
+    }
+
+    render() {
+        let{schooldata,ecComponentState,ecpaths}=this.state;
+
+        return (
+            <div>
+                <div className="mb10 mt10 eaSystemp">
+
+                    <a href={schooldata.user_url}>{schooldata.user_name===undefined?"":schooldata.user_name+" > "}</a>
+                    <a href={schooldata.school_url}>{schooldata.school_name===undefined?"":schooldata.school_name+"认证"}</a>
+                    <a href={schooldata.major_url}>{schooldata.school_name===undefined?"":" >  "+schooldata.major_name+" > "}</a>
+                    <span> {schooldata.school_name===undefined?"":schooldata.year+"届"}</span>
+
+                </div>
+
+                <ul className="clearfix mb0 traningNavs " id="traningNav" style={{display:ecpaths==='none'?"none":"flex"}}>
+                    <li className={"ecimgs"}>
+                        <a className={"ecTitle ecTitles"} >1</a>
+                        <a className={"ecTitlefont"} href={schooldata.major_training}>培养目标</a>
+                    </li>
+                    <li className={"ecimgs"}>
+                        <a className={"ecTitle ecTitles"} >2</a>
+                        <a className={"ecTitlefont"} href={schooldata.graduation_requirement_url} >毕业要求</a>
+                    </li>
+                    <li className={"ecimgs"}>
+                        <a className={"ecTitle ecTitles"} >3</a>
+                        <a className={"ecTitlefont"} href={schooldata.requirement_vs_objective_url}>毕业要求 vs 培养目标</a>
+                    </li>
+                    <li className={"ecimgs"}>
+                        <a className={"ecTitle ecTitles"} >4</a>
+                        <a className={"ecTitlefont"} href={schooldata.requirement_vs_standard}>毕业要求 vs 通用标准</a>
+                    </li>
+                    <li className={ecpaths==="ecStudentList"?"ecimgs11":"ecimgs"} style={{width: ecpaths==="ecStudentList"?'126px':'83px'}}>
+                        <a className={ ecpaths==="ecStudentList"?"ml18 ecTitleFFF ecTitles":"ecTitle"} >5</a>
+                        <a  className={ ecpaths==="ecStudentList"?"ecTitlefontFFF":"ecTitlefont"} href={schooldata.students_url}>学生</a>
+                    </li>
+                    <li className={ecpaths==="ec_course_support_setting"||ecpaths==="show"?"ecimgs11":"ecimgs"}>
+                        <a className={ ecpaths==="ec_course_support_setting"||ecpaths==="show"?"ml18 ecTitleFFF ecTitles":"ecTitle ecTitles"} >6</a>
+                        <a  className={ ecpaths==="ec_course_support_setting"||ecpaths==="show"?"ecTitlefontFFF":"ecTitlefont"} href={schooldata.course_setting_url}>课程体系</a>
+                    </li>
+                    <li className={ecpaths==="requirement_vs_courses"?"ecimgs3":"ecimgs"}>
+                        <a className={ ecpaths==="requirement_vs_courses"?"ecmarginleft ecTitleFFF ecTitles":"ecTitle ecTitles"} >7</a>
+                        <a className={ ecpaths==="requirement_vs_courses"?"ecTitlefontFFF":"ecTitlefont"} href={schooldata.requirement_vs_courses}>课程体系 vs 毕业要求</a>
+                    </li>
+                    <li className={ecpaths==="reach_calculation_info"?"ecimgs2 info2":"ecimgs"}>
+                        <a className={ ecpaths==="reach_calculation_info"?"ecTitleFFF ml18 ecTitles":"ecTitle ecTitles"} >8</a>
+                        <a className={ ecpaths==="reach_calculation_info"?"ecTitlefontFFF":"ecTitlefont"} href={schooldata.reach_calculation_info_url}>达成度评价结果</a>
+                    </li>
+                    {/*<li className={ecComponentState==="ecCourseSupports"?"active edu-menu-panel":"edu-menu-panel"}>*/}
+                    {/*<a>毕业要求</a>*/}
+                    {/*<i className="iconfont icon-xiajiantou font-14 ml5" style={{display:ecComponentState==="ecCourseSupports"?"inline-block":"none"}}></i>*/}
+                    {/*<ul className="edu-menu-list" style={{width:'200px',right:'unset',top:'34px'}}>*/}
+                    {/*<li><a href={schooldata.major_training} >专业培养目标</a></li>*/}
+                    {/*<li><a href={schooldata.graduation_requirement_url} >毕业要求指标点</a></li>*/}
+                    {/*<li><a href={schooldata.requirement_vs_objective_url} >毕业要求vs培养目标</a></li>*/}
+                    {/*<li><a href={schooldata.requirement_vs_standard} >毕业要求vs通用要求</a></li>*/}
+                    {/*<li><a href={schooldata.requirement_vs_courses} >毕业要求vs课程体系</a></li>*/}
+                    {/*</ul>*/}
+                    {/*</li>*/}
+
+                    {/*<li className={ecComponentState==="ecCourseEvaluations"?"active edu-menu-panel":"edu-menu-panel"}>*/}
+                    {/*<a href={schooldata.course_setting_url}>课程配置</a>*/}
+                    {/*</li>*/}
+
+                    {/*<li className={ecComponentState==="ecCompletion"?"active edu-menu-panel":"edu-menu-panel"}>*/}
+                    {/*<a>达成度计算</a>*/}
+                    {/*<i className="iconfont icon-xiajiantou font-14 ml5" style={{display:ecComponentState==="ecCompletion"?"inline-block":"none"}}></i>*/}
+                    {/*<ul className="edu-menu-list" style={{width:'200px',right:'unset',top:'34px'}}>*/}
+                    {/*<li><a href={schooldata.completion_calculation_url}>课程达成计算</a></li>*/}
+                    {/*<li><a href={schooldata.reach_calculation_info_url}>毕业要求指标点达成计算</a></li>*/}
+                    {/*</ul>*/}
+                    {/*</li>*/}
+                    {/*<a className="fr color-grey-6 font-16" href={schooldata.go_back_url}>返回</a>*/}
+
+                </ul>
+            </div>
+        )}
+}
+
+export default EcTitleCourseEvaluations;
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/ecTitle/img/1.png b/public/react/src/modules/ecs/ecTitle/img/1.png
new file mode 100644
index 000000000..28325a3ea
Binary files /dev/null and b/public/react/src/modules/ecs/ecTitle/img/1.png differ
diff --git a/public/react/src/modules/ecs/ecTitle/img/2.png b/public/react/src/modules/ecs/ecTitle/img/2.png
new file mode 100644
index 000000000..4a558df21
Binary files /dev/null and b/public/react/src/modules/ecs/ecTitle/img/2.png differ
diff --git a/public/react/src/modules/ecs/ecTitle/img/3.png b/public/react/src/modules/ecs/ecTitle/img/3.png
new file mode 100644
index 000000000..da3d47779
Binary files /dev/null and b/public/react/src/modules/ecs/ecTitle/img/3.png differ
diff --git a/public/react/src/modules/ecs/ecTitle/img/4.png b/public/react/src/modules/ecs/ecTitle/img/4.png
new file mode 100644
index 000000000..37dab8ea0
Binary files /dev/null and b/public/react/src/modules/ecs/ecTitle/img/4.png differ
diff --git a/public/react/src/modules/ecs/subroute/ecCompletion_calculation/EcCompletionCalculation.js b/public/react/src/modules/ecs/subroute/ecCompletion_calculation/EcCompletionCalculation.js
new file mode 100644
index 000000000..4be7c11d3
--- /dev/null
+++ b/public/react/src/modules/ecs/subroute/ecCompletion_calculation/EcCompletionCalculation.js
@@ -0,0 +1,809 @@
+import React, { Component } from 'react';
+import classNames from 'classnames'
+
+import axios from 'axios';
+
+// import { TPMIndexHOC } from '../../../tpm/TPMIndexHOC';
+
+import { SnackbarHOC } from 'educoder'
+
+import { message,Modal,Spin,Icon} from 'antd';
+
+import 'antd/dist/antd.css';
+
+import EcTitleCourseEvaluations from '../../ecTitle/ecTitle'
+
+import '../../css/ecCourseSupports.css';
+
+import '../../css/ecCourseEvaluations.css';
+
+const $ = window.$;
+class EcCompletionCalculation extends Component {
+    constructor(props) {
+        super(props)
+        this.state={
+            schooldata:{},
+            ecComponentState:"ecCompletion",
+            course_total_score:[],
+            ec_course_targets:0,
+            graduation_list:[],
+            target_list:[],
+            target_score:[],
+            evaluate_result:"",
+            ec_course_targets_count:0,
+            new_target_ec_year_id:0,
+            total_rate_data:undefined,
+            calculatetype:false,
+            ec_course_id:0,
+            morelisttype:false,
+            titlemessage:"提示",
+            completiontype:false,
+            completionlist:"",
+            course_total_scoreaverage:0,
+            calculatesetype:false,
+            Spintype:false,
+            ismanager:false
+        }
+    }
+
+    componentWillMount(){
+        window.document.title = '课程达成评价结果';
+    }
+
+    componentDidMount(){
+        let ec_course_id =this.props.match.params.ec_course_id;
+        this.UpdateClassData(true);
+        const Url =`/ec_major_schools/get_navigation_data?ec_course_id=`+ec_course_id;
+        axios.get(Url, {
+            withCredentials: true,
+        })
+            .then((response) => {
+                if(response.status===200){
+                    // if(response.data.allow_visit===false){
+                    //     window.location.href="/403"
+                    //  }
+                    this.setState({
+                        schooldata:response.data,
+                        ec_course_id:ec_course_id
+                    })
+                }
+            })
+            .catch(function (error) {
+                console.log(error);
+            });
+    }
+
+    targetsget_navigation_data=(ec_year_id,ec_course_id)=>{
+        const Url =`/ec_major_schools/get_navigation_data?ec_year_id=`+ec_year_id+"&ec_course_id="+ec_course_id;
+        axios.get(Url, {
+            withCredentials: true,
+        })
+            .then((response) => {
+                if(response.status===200){
+                    // if(response.data.allow_visit===false){
+                    //     window.location.href="/403"
+                    //  }
+                    this.setState({
+                        schooldata:response.data,
+                        ec_course_id:ec_course_id
+                    })
+                }
+            })
+            .catch(function (error) {
+                console.log(error);
+            });
+    }
+    showmorelist=()=>{
+        this.setState({
+            morelisttype:false
+        })
+        this.UpdateClassData(false)
+    }
+    UpdateClassData=(key)=>{
+        let {calculatetype} =this.state;
+        let ec_course_id =this.props.match.params.ec_course_id;
+        this.setState({
+            ec_course_id:ec_course_id
+        })
+        const Arl =`/ec_courses/`+ec_course_id+`/calculation_info_data`;
+        axios.get(Arl, {
+            withCredentials: true,
+        })
+            .then((response) => {
+
+                if(response.status===200){
+                    // var list=[];
+                    // if(key===true){
+                    //     for(var i=0; i<response.data.course_total_score.length;i++){
+                    //         if(i<10){
+                    //             list.push(response.data.course_total_score[i])
+                    //         }
+                    //     }
+                    // }else{
+                    //     list=response.data.course_total_score
+                    // }
+                    // let newgraduation_list= response.data.graduation_list.reverse();
+                    let newmorelisttype=false;
+                    if(response.data.course_total_score>10){
+                        newmorelisttype=true
+
+                    }
+
+                    let course_total_scoreaverage;
+                    let newlist=response.data.course_total_score[response.data.course_total_score.length-1].total_rate;
+                    for(var i=0; i<newlist.length;i++){
+                            if(i===newlist.length-1){
+                                course_total_scoreaverage=newlist[i].total_score
+                            }
+                    }
+
+                    this.setState({
+                        evaluate_result:response.data.evaluate_result,
+                        course_total_score:response.data.course_total_score[response.data.course_total_score.length-1].total_rate,
+                        total_rate_data:response.data.course_total_score[response.data.course_total_score.length-1].total_rate.length,
+                        graduation_list:response.data.graduation_list,
+                        target_list:response.data.target_list,
+                        target_score:response.data.target_score,
+                        ec_course_targets_count:response.data.ec_course_targets_count,
+                        morelisttype:newmorelisttype,
+                        course_total_scoreaverage:course_total_scoreaverage,
+                        ismanager:response.data.is_manager
+                    })
+                    
+            
+                    // ec_course_targets:response.data.ec_course_targets,
+                    this.targetsget_navigation_data(response.data.ec_year_id,ec_course_id)
+                    if(calculatetype===true){
+                        this.setState({
+                            calculatetype:false,
+                            completiontype:true,
+                            completionlist:'刷新列表数据成功',
+                            calculatesetype:true
+                        })
+                    }
+
+                }
+            })
+            .catch(function (error) {
+                console.log(error);
+            });
+
+        //
+        // let newcourse_total_score=[
+        //     {
+        //         student_scores:{
+        //             name: "黎子豪",
+        //             student_number: "13408100113",
+        //             target_info: [
+        //                 {position: 1, score: 73.3},
+        //                 {position: 2, score: 71.8},
+        //                 {position: 3, score: 92.2},
+        //                 {position: 4, score: 82.1},
+        //                 {position: 5, score: 87.7}
+        //             ],
+        //             total_score: 81.4
+        //         }
+        //     },{
+        //         total_rate:[
+        //             {position: 1, score: 65.35, rate: 0.1},
+        //             {position: 2, score: 68.81, rate: 0.1},
+        //             {position: 3, score: 68.34, rate: 0.1},
+        //             {position: 4, score: 78.09, rate: 0.35},
+        //             {position: 5, score: 77, rate: 0.35},
+        //             {total_score: 74.5},
+        //         ]
+        //     }
+        // ]
+        //
+        // var list=[];
+        // if(key===true){
+        //     for(var i=0; i<newcourse_total_score.length;i++){
+        //         if(i<10){
+        //             list.push(newcourse_total_score[i])
+        //         }
+        //     }
+        // }else{
+        //     list=newcourse_total_score
+        // }
+        // let graduation_list=[
+        //     {
+        //         ec_graduation_name: "5-1",
+        //         ec_subitem_content: "能够针对计算机系统的设计、开发、部署、运行和维护等方面的复杂工程问题,开发、选择与使用恰当的技术、资源、现代工程工具和信息技术工具,进行科学合理的预测与模拟,并充分认识到问题的复杂性与解决手段的局限性。",
+        //         reach_real_target: 0.078,
+        //         reach_target: 0.07,
+        //         result: "达成",
+        //         target_position: [0, 0, 0, 1, 0],
+        //         weight: 0.1
+        //     }
+        // ]
+        // let newgraduation_list= graduation_list.reverse();
+        // this.setState({
+        //     course_total_score:list,
+        //     total_rate_data:newcourse_total_score[newcourse_total_score.length-1].total_rate.length,
+        //     graduation_list:newgraduation_list,
+        //     evaluate_result:false,
+        //     target_list:[
+        //         {
+        //             content: "理解数据管理技术和数据库技术的发展,区分不同数据模型的作用和特点,描述数据库系统的类型、结构、数据独立性。",
+        //             real_grade: 65.35,
+        //             result: "达成",
+        //             standard_grade: 65,
+        //             weigths: 0.1
+        //         }
+        //     ],
+        //     target_score:[
+        //         {average_score: 65.35,
+        //         ec_course_targets_count: 5,
+        //         from50: [9, 20.45],
+        //         from60: [13, 29.55],
+        //         from70: [14, 31.82],
+        //         from80: [3, 6.82],
+        //         from90: [1, 2.27],
+        //         from_down: [4, 0.09],
+        //         graduation_list: [],
+        //         low_score: 40,
+        //         top_score: 93.4}
+        //     ],
+        //     ec_course_targets_count:5
+        //
+        // })
+        // if(calculatetype===true){
+        //     message.success('刷新列表数据成功!');
+        //     this.setState({
+        //         calculatetype:false,
+        //         completiontype:true,
+        //         completionlist:'刷新列表数据成功!'
+        //     })
+        // }
+
+
+
+
+
+    }
+
+    newrightcalculatebutton=()=>{
+        this.setState({
+            Spintype:true
+        })
+        let {ec_course_id}=this.state;
+        const Orl =`/ec_courses/`+ec_course_id+`/sync_data`;
+        axios.get(Orl, {
+            withCredentials:true,
+        })
+            .then((response) => {
+                if(response.data.status===1){
+                    this.setState({
+                        calculatetype:true,
+                        completiontype:true,
+                        completionlist:'计算成功',
+                        calculatesetype:true,
+                        Spintype:false
+                    })
+                    this.UpdateClassData(true);
+                }
+            })
+            .catch(function (error) {
+                    console.log(error)
+            });
+    }
+    hidecompletion=()=>{
+        this.setState({
+            completiontype:false,
+            completionlist:"",
+            calculatesetype:false
+        })
+    }
+    render() {
+        let {Spintype,calculatesetype,ec_course_id,course_total_scoreaverage,ec_course_targets_count,schooldata,ecComponentState,course_total_score,total_rate_data,ec_course_targets,graduation_list,target_list,target_score,evaluate_result,morelisttype,titlemessage,completiontype,completionlist,ismanager} = this.state;
+
+        let TargetresList = (length) => {
+            let target_listres = [];
+            for(let i = 0; i < length; i++) {
+                // target_listres.push(<span className="column-1 operationleft color-666"  key={i}>目标{length-i}</span>)
+                // target_listres.push(<span className="column-2 operationleft color-666"  key={i}>目标{i+1}</span>)
+                target_listres.push(<span className="column-1 operationright color-666"  key={i}>目标{length-i}</span>)
+            }
+            return target_listres
+        }
+
+        let TargetresLists = (length) => {
+            let target_listress = [];
+            for(let i = 0; i < length; i++) {
+                // target_listres.push(<span className="column-1 operationleft color-666"  key={i}>目标{length-i}</span>)
+                target_listress.push(<span className="column-2 operationleft color-666"  key={i}>目标{i+1}</span>)
+                // target_listres.push(<span className="column-1 operationright color-666"  key={i}>目标{length-i}</span>)
+            }
+            return target_listress
+        }
+
+        let TargetresContentList = (length,value) => {
+            let target_listres = [];
+            if(value!=undefined){
+                for(let i = 0; i < length; i++) {
+
+                    if(value[i]===1){
+                        target_listres.push(<span className="column-1 operationright color-green"  key={i}><i class="iconfont icon-gouxuan color-green font-16 mr5"></i></span>)
+                    }else{
+                        target_listres.push(<span className="column-1 operationright color-666"  key={i}><i class="iconfont icon-guanbi font-14 mr5"></i></span>)
+                    }
+
+                }
+                target_listres.reverse()
+                return target_listres
+            }
+        }
+
+
+
+        let Total_rate_dataList = (value) => {
+
+            let target_listres = [];
+            if(value!=undefined){
+                for(let i = 0; i < value.length; i++) {
+
+                    if(i===value.length-1){
+                        target_listres.push(<span className="column-1 operationright" key={i}>
+                            {/*<div className="color-red">{value[i].total_score}</div>*/}
+                            <div className="color-red">100%</div>
+                        </span>)
+                    }else{
+                            target_listres.push(<span className={i===0?"  column-2 operationleft":"column-2 operationleft"} key={i}>
+                    {/*<div>{value[i].score}</div>*/}
+                    {/*<div className="color-redFF">占比{(value[i].rate*100).toFixed(2)}%</div>*/}
+                    <div>
+                        {(value[i].rate*100).toFixed(2)}%
+                    </div>
+                    </span>)
+                        }
+
+                }
+                return target_listres
+            }else{
+                target_listres.push(<span className="column-1 operationright">
+                {/*<div className="color-red">{value[i].total_score}</div>*/}
+                    <div className="">--</div>
+                </span>)
+             return target_listres
+            }
+        }
+
+        let newTotal_rate_dataList = (length,value) => {
+
+            let target_listres = [];
+            if(value!=undefined){
+                for(let i = 0; i < value.length; i++) {
+
+                    // if(i===0){
+                    //     target_listres.push(<span className="column-2  color-05101A" key={i}>
+                    //         <div>{value[i].score.toFixed(2)}</div>
+                    // </span>)
+                    // }else{
+                    //     target_listres.push(<span className="column-2 color-05101A" key={i}>
+                    //     <div>{value[i].score.toFixed(2)}</div>
+                    // </span>)
+                    // }
+
+                    if(i<value.length-1){
+                        target_listres.push(<span className="column-2  color-05101A" key={i}>
+                             <div>{value[i].score.toFixed(2)}</div>
+                        </span>)
+                    }
+
+                }
+                return target_listres
+            }
+        }
+        return (
+            <div className="newMain clearfix">
+                <Modal
+                    title={titlemessage}
+                    visible={completiontype}
+                    className={"ecmodeldelet"}
+                    closable={false}
+                    footer={null}
+                >
+                    <div className="task-popup-content">
+                        <div className="task-popup-text-center font-14">{completionlist}</div>
+                    </div>
+                    {
+                        calculatesetype===true?
+                        <div className="task-popup-submit clearfix"
+                        style={{width:'69px'}}
+                        >
+                            <a  className="task-btn task-btn-orange fr"
+                                style={{fontWeight: '400'}}
+                                onClick={this.hidecompletion}
+                            >知道啦</a>
+                        </div>
+                        :
+                        <div className="task-popup-submit clearfix">
+                            <a onClick={this.hidecompletion} className="task-btn fl">取消</a>
+                            <a  className="task-btn task-btn-orange fr"
+                                onClick={this.hidecompletion}
+                            >确定</a>
+                        </div>
+                    }
+
+
+
+                </Modal>
+
+                <div className="educontent mb290">
+
+                    {/*<EcTitleCourseEvaluations*/}
+                    {/*    {...this.props}*/}
+                    {/*    schooldata={schooldata}*/}
+                    {/*    ecComponentState={'ecCompletion'}*/}
+                    {/*    ecpath={"show"}*/}
+                    {/*/>*/}
+
+                    {/*<div className="edu-back-white eacourse">*/}
+                    {/*    <div className="clearfix padding20-30 bor-bottom-greyE">*/}
+                    {/*        <a href={schooldata.course_setting_url} className="color-grey-9 TrainingLecturer">课程体系</a> >*/}
+                    {/*        <a className="TrainingTheory major_name"> {schooldata.ec_course_name} 达成评价详情</a>*/}
+                    {/*        /!* <a href="javascript:void(0)" className="fr white-btn edu-blueback-btn mt4">导出培养目标</a> *!/*/}
+                    {/*        <div className="color-grey-9 mr10">系统根据课程目标、课程考核方式与课程目标评价方法,一键计算评价课程目标的达成情况  <a className={"color-blue"} onClick={() => window.elasticLayer(3533)}>查看详情</a></div>*/}
+                    {/*    </div>*/}
+                    {/* <div className="padding20-30" id="training_objective_contents"*/}
+                    {/*        style={{*/}
+                    {/*            position: 'relative'*/}
+                    {/*          }}*/}
+                    {/* >*/}
+                    {/*        <a className="fl SystemParameters" style={{display:schooldata.ec_course_support_setting_url===null?"none":"block"}}*/}
+                    {/*           href={schooldata.ec_course_support_setting_url}>1.课程目标</a>*/}
+                    {/*        <a className="fl SystemParameters ml40"*/}
+                    {/*           style={{display:schooldata.ec_course_reach_setting_url===null?"none":"block"}}*/}
+                    {/*           href={schooldata.ec_course_reach_setting_url}>2.课程考核方式与数据来源</a>*/}
+                    {/*        <a className="fl SystemParameters4CACFF ml40 color4D4D4D"*/}
+                    {/*          href={schooldata.score_level_setting_url}*/}
+                    {/*        >3.成绩等级设置</a>*/}
+                    {/*        <a className="fl SystemParameters ml40"*/}
+                    {/*           style={{display:schooldata.evaluation_methods_url===null?"none":"block"}}*/}
+                    {/*           href={schooldata.evaluation_methods_url}>4.课程目标评价方法</a>*/}
+                    {/*        <a className="fl SystemParameters ml40"*/}
+                    {/*           style={{display:schooldata.competition_calculation_info_url===null?"none":"block",color:'#4CACFF'}}*/}
+                    {/*           href={schooldata.competition_calculation_info_url}>5.课程达成评价结果</a>*/}
+                    {/*        /!* <span className="right ml20 SystemParameters">课程体系:*/}
+                    {/*  {*/}
+                    {/*    evaluate_result===false?<span className="Systemnum">未达成</span>:<span className="Systemnum color-green">达成</span>*/}
+                    {/*  }*/}
+                    {/*  </span> *!/*/}
+                    {/*        <span className={ismanager===false?"none":"right newrightcalculatebutton"}  */}
+                    {/*        style={{*/}
+                    {/*            marginLeft: '26px',*/}
+                    {/*            position: 'absolute',*/}
+                    {/*            right: '157px'*/}
+                    {/*        }}*/}
+                    {/*        onClick={this.newrightcalculatebutton}>计算</span>*/}
+                    {/*        <span className={ismanager===false?"none":"Importclassroomdata"} style={{top: "26px"}}>*/}
+                    {/*             <a className="white-btn edu-blueback-btn fr mb10 mr10" target="_blank" href={"/ec_courses/"+ec_course_id+"/export_evaluation_result.xls"}>导出评价详情</a>*/}
+                    {/*        </span>*/}
+                    {/*    </div>*/}
+                    {/*</div>*/}
+
+                    <div className="ListTableLine newSystem mb20" id="school_major_list">
+
+                        <p className="clearfix padding10im" >
+                            <span className="column-1 color-666">课程目标</span>
+                            <span className="column-1 operationright color-666">达成结果</span>
+                            <span className="column-1 operationright color-666">达成标准(分)</span>
+                            <span className="column-1 operationright color-666">实际达成</span>
+                            <span className="column-1 operationright color-666">权重</span>
+                        </p>
+                        
+                        { Spintype===true?<Spin className="Spinlarge"  indicator={<Icon type="loading" style={{ fontSize: 30 }} spin />}/>:"" }
+
+                            { target_list.length===0&&Spintype===false?
+                            <li className={ "clearfix newtarget_scoreclass lipadding10im"}>
+                                <span className="column-1 color-05101A">--</span>
+                                <span className="column-575 color-05101A">--</span>
+                                <span className={"column-1 operationright Systemnum"}>--</span>
+                                <span className="column-1 operationright color-05101A">--</span>
+                                <span className="column-1 operationright">--</span>
+                                <span className="column-1 operationright">--</span>
+                            </li>:""}
+                        
+                        
+                            {Spintype===false?target_list.map((item,key)=>{
+
+                                return(
+                                    <li className={key+1===target_list.length?"clearfix newtarget_target lipadding10im":"clearfix newtarget_scoreclass lipadding10im"} key={key}>
+                                        <span className="column-1 color-05101A">{key+1}</span>
+                                        <span className="column-575 color-05101A">{item.content}</span>
+                                        <span className={item.result==="未达成"?"column-1 operationright Systemnum":"column-1 operationright color-green"}>{item.result}</span>
+                                        <span className="column-1 operationright color-05101A">{item.standard_grade}</span>
+                                        <span className="column-1 operationright">{item.real_grade}</span>
+                                        <span className="column-1 op erationright">{item.weigths}</span>
+                                    </li>
+                                )
+
+                            }):""
+                        }
+
+                   
+                    </div>
+
+                    <div className="edu-back-white eacourse">
+
+                        <div className="padding1030" id="training_objective_contents">
+                            <span className="fl SystemParameters lineheight60" style={{height:'46px'}}>   毕业要求指标点达成评价结果</span>
+                            <span className="right ml20 SystemParameters" style={{height:'46px'}}>注:<span className="color-green"><i class="iconfont icon-gouxuan color-green font-16 mr5"></i></span> 代表支持指标点;<i class="iconfont icon-guanbi font-14 mr5"></i>代表不支持指标点</span>
+                        </div>
+
+                    </div>
+
+                    <div className="ListTableLine newSystem mb20 graduateRequirement " id="school_major_list">
+
+                    {
+                        graduation_list.length===0?
+                        <p className="clearfix lipadding20im" style={{minWidth:'1200px'}}>
+                        <span className="column-1 color-666 mr16">毕业要求</span>
+                        <span className="nowrap329">{5}</span>
+                        <span className="column-1 operationright color-666">达成结果</span>
+                        <span className="column-1 operationright color-666">达成目标值</span>
+                        <span className="column-1 operationright color-666">达成实际值</span>
+                        <span className="column-1 operationright color-666">课程权重</span>
+                        {TargetresList(5)}
+                    </p>
+                    :""
+                    }
+
+                   { Spintype===true?<Spin className="Spinlarge"  indicator={<Icon type="loading" style={{ fontSize: 30 }} spin />}/>:"" }
+
+                    {
+                        graduation_list.length===0&&Spintype===false?
+                        <li className={'clearfix newtarget_scoreclass marlr19'}  style={{minWidth:'1137px'}}>
+                        {/* <span className="column-1 color-05101A ec_graduation_name">{item.ec_graduation_name}</span> */}
+                        <span className="column-1 color-05101A ec_graduation_name">{1}</span>
+                        <span className="column-500 color-05101A">{"--"}</span>
+                        <span className={"column-1 operationright Systemnum mrj15"}>{"--"}</span>
+                        <span className="column-1 operationright color-05101A">{"--"}</span>
+                        <span className="column-1 operationright">{"--"}</span>
+                        <span className="column-1 operationright"> <a href={schooldata.requirement_vs_courses} style={{color:'rgb(76, 172, 255)'}}>立即配置</a></span>
+                        {TargetresContentList(5,[2,2,2,2,2])}
+                    </li>
+                    :""
+                    }
+                    {
+                        Spintype===false?graduation_list.map((item,key)=>{
+
+                            if(key===0){
+                                return(
+                                    <p key={key} className="clearfix lipadding20im" style={{minWidth: ec_course_targets_count > 5 ? (76*(ec_course_targets_count+4)+380+15):1200+"px"}}>
+                                        <span className="column-1 color-666 mr16">毕业要求</span>
+                                        <span className="nowrap329">{item.ec_subitem_content}</span>
+                                        <span className="column-1 operationright color-666">达成结果</span>
+                                        <span className="column-1 operationright color-666">达成目标值</span>
+                                        <span className="column-1 operationright color-666">达成实际值</span>
+                                        <span className="column-1 operationright color-666">课程权重</span>
+                                        {TargetresList(ec_course_targets_count)}
+                                    </p>
+                                )
+                            }
+
+                        }):""
+                    }
+
+                    
+                        {
+                            Spintype===false?graduation_list.map((item,key)=>{
+
+                                return(
+                                    <li className={key+1===target_list.length?"clearfix newtarget_target marlr19":"clearfix newtarget_scoreclass marlr19"} key={key} style={{minWidth: ec_course_targets_count > 5 ? (76*(ec_course_targets_count+4)+380):1200+"px"}}>
+                                        {/* <span className="column-1 color-05101A ec_graduation_name">{item.ec_graduation_name}</span> */}
+                                        <span className="column-1 color-05101A ec_graduation_name">{key+1}</span>
+                                        <span className="column-500 color-05101A" data-tip-down={item.content}>{item.ec_subitem_content}</span>
+                                        <span className={item.result==="未达成"?"column-1 operationright Systemnum mrj15":"column-1 operationright color-green mrj15"}>{item.result}</span>
+                                        <span className="column-1 operationright color-05101A">{item.reach_target===null?0:item.reach_target}</span>
+                                        <span className="column-1 operationright">{item.reach_real_target===null?0:item.reach_real_target}</span>
+                                        {item.weight===null||item.weight===0?<span className="column-1 operationright" ><a href={schooldata.requirement_vs_courses} style={{color:'rgb(76, 172, 255)'}}>立即配置</a></span>:<span className="column-1 operationright">{item.weight}</span>}
+                                        {TargetresContentList(ec_course_targets_count,item.target_position)}
+                                    </li>
+                                )
+
+                            }):""
+                        }
+                    </div>
+
+                    <div className="edu-back-white eacourse">
+
+                        <div className="padding1030" id="training_objective_contents">
+                            <span className="fl SystemParameters lineheight60" style={{height:'46px'}}>课程总评成绩表</span>
+                        </div>
+
+                    </div>
+
+                    <div className="ListTableLine newSystem mb20" id="school_major_list">
+
+                        <p  className="clearfix padding10im" style={{width: total_rate_data > 5 ? (180 * total_rate_data+226+16) : 1200+"px"}}>
+                            {/*<span className="column-1 color-666 mr16 width86">序号</span>*/}
+                            <span className="column-1 color-666 mr16 width86">课程目标</span>
+                            {/*<span className="column-1 color-666 mr16">姓名</span>*/}
+                            {/*<span className="column-1 color-666 mr16">学号</span>*/}
+                            {TargetresLists(total_rate_data-1)}
+                            <span className="column-1 operationright color-666">总评成绩</span>
+                        </p>
+                        {/*style={{width: 113*(total_rate_data+4)>1136?113*(total_rate_data+4.5):1136+"px"}}*/}
+                        {
+                            // course_total_score.map((i,k)=>{
+
+                            //     if(k===course_total_score.length-1){
+
+                            //         return(
+                            //             <li className={"clearfix newtarget_scoreclass lipadding10im margin64px"} key={k} style={{width: 113*(total_rate_data+4)>1200?(113*(total_rate_data+4.5))+63:1200+"px"}}>
+                            //                 <span className="column-1 color-05101A mr16 width86">占比</span>
+                                            // {/*colorTransparent*/}
+                                            // {/*<span className="column-1 color-05101A ec_graduation_name mr16 colorTransparent"> 平均数 </span>*/}
+                                            // {/*<span className="column-1 color-05101A ec_graduation_name mr16 colorTransparent  "> 平均数 </span>*/}
+                                            // {/* {Total_rate_dataList(total_rate_data-1,i.total_rate)}
+                            //             </li>
+                            //         )
+
+                            //     }
+
+                            // }) */}
+                        }
+                          { Spintype===true?<Spin className="Spinlarge"  indicator={<Icon type="loading" style={{ fontSize: 30 }} spin />}/>:"" }
+                       {
+                            Spintype===false? <li className={"clearfix newtarget_scoreclass lipadding10im margin64px"} style={{width: total_rate_data > 5 ? (180 * total_rate_data+226+16) : 1200 + "px"}}>
+                            <span className="column-1 color-05101A mr16 width86">占比</span>
+                            {/*colorTransparent*/}
+                            {/*<span className="column-1 color-05101A ec_graduation_name mr16 colorTransparent"> 平均数 </span>*/}
+                            {/*<span className="column-1 color-05101A ec_graduation_name mr16 colorTransparent  "> 平均数 </span>*/}
+                            {Total_rate_dataList(course_total_score)}
+                            {
+                                course_total_score.length===0? <span className="column-1 operationright">--</span>:""
+                            }
+                            </li>:""
+                       }
+                        {/*style={{width: 113*(total_rate_data+4)>1136?113*(total_rate_data+4):1136+"px"}}*/}
+                        {
+                            // course_total_score.map((i,k)=>{
+
+                            //     if(k!=course_total_score.length-1){
+
+                            //         return(
+                            //             <li className={"clearfix newtarget_scoreclass lipadding10im"} style={{width: 113*(total_rate_data+4)>1200?(113*(total_rate_data+4.5))+63:1200+"px"}}>
+                            //                 {/*<span className="column-1 color-05101A mr16 width86">{k+1}</span>*/}
+                            //                 <span className="column-1 color-05101A mr16 width86">平均分</span>
+                            //                 {/*<span className="column-1 color-05101A ec_graduation_name mr16">{i.student_scores.name}</span>*/}
+                            //                 {/*<span className="column-1 color999 ec_graduation_name mr16  ">{i.student_scores.student_number}</span>*/}
+                            //                 {newTotal_rate_dataList(total_rate_data-1,i.student_scores.target_info)}
+                            //                 <span className="column-1 color-red operationright">{i.student_scores.total_score.toFixed(2)}</span>
+                            //             </li>
+                            //         )
+
+                            //     }
+
+                            // })
+                        }
+                        {
+                             Spintype===false?<li className={"clearfix newtarget_scoreclass lipadding10im bordereaeaea"} style={{width: 113*(total_rate_data+4)>1200?(113*(total_rate_data+4.5))+63:1200+"px"}}>
+                             {/*<span className="column-1 color-05101A mr16 width86">{k+1}</span>*/}
+                             <span className="column-1 color-05101A mr16 width86">平均分</span>
+                             {/*<span className="column-1 color-05101A ec_graduation_name mr16">{i.student_scores.name}</span>*/}
+                             {/*<span className="column-1 color999 ec_graduation_name mr16  ">{i.student_scores.student_number}</span>*/}
+                             {newTotal_rate_dataList(course_total_score-1,course_total_score)}
+                             {/* <span className="column-1 color-red operationright">{course_total_score.length===0?"":course_total_score[course_total_score-1].total_score}</span> */}
+                             {
+                                 course_total_score.length===0? <span className="column-1 operationright">--</span>:<span className="column-1 color-red operationright">{course_total_scoreaverage}</span>
+                             }
+                              </li>:""
+                        }
+
+
+                        <li class="clearfix newtarget_scoreclass" style={{width: 113*(total_rate_data+4)>1136?113*(total_rate_data+4):1136+"px",display:morelisttype===true?"block":"none"}}>
+                            <a className={"ecmorelist"} onClick={()=>this.showmorelist()}>加载更多</a>
+                        </li>
+                    </div>
+
+
+
+                    <div className="edu-back-white eacourse">
+
+                        <div className="padding1030" id="training_objective_contents">
+                            <span className="fl SystemParameters lineheight60" style={{height:'46px'}}>课程目标成绩分析</span>
+                        </div>
+
+                    </div>
+
+
+                    <div className="ListTableLine newSystem mb20" id="school_major_list">
+
+                        <p  className="clearfix padding10im">
+                            <span className="column-1 color-666">课程目标</span>
+                            <span className="column-1 color-666">平均分</span>
+                            <span className="column-1 color-666">最高分数</span>
+                            <span className="column-1 color-666">最低分数</span>
+                            <span className="column-1 color-666">90分以上</span>
+                            <span className="column-1 color-666">80-89分</span>
+                            <span className="column-1 color-666">70-79分</span>
+                            <span className="column-1 color-666">60-69分</span>
+                            <span className="column-1 color-666">50-59分</span>
+                            <span className="column-1 color-666">低于50分</span>
+                        </p>
+
+                        {
+                            Spintype===false?target_score.map((i,k)=>{
+
+                                return(
+                                    <li className={"clearfix newtarget_scoreclass lipadding10im"} key={k}>
+                                        <span className="column-1 color-05101A">{k+1}</span>
+                                        <span className="column-1 color-05101A">{i.average_score}</span>
+                                        <span className="column-1 colorFF6800">{i.top_score}</span>
+                                        <span className="column-1 color-green">{i.low_score}</span>
+                                        <span className="column-1 color-05101A">
+                                              <div>{i.from90[0]}人</div>
+                                              <div className="color999">{(i.from90[1]).toFixed(2)}%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>{i.from80[0]}人</div>
+                                              <div className="color999">{(i.from80[1]).toFixed(2)}%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>{i.from70[0]}人</div>
+                                              <div className="color999">{(i.from70[1]).toFixed(2)}%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>{i.from60[0]}人</div>
+                                              <div className="color999">{(i.from60[1]).toFixed(2)}%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>{i.from50[0]}人</div>
+                                              <div className="color999">{(i.from50[1]).toFixed(2)}%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>{i.from_down[0]}人</div>
+                                              <div className="color999">{(i.from_down[1]).toFixed(2)}%</div>
+                                        </span>
+                                    </li>
+                                )
+
+                            }):""
+                        }
+
+                            { Spintype===true?<Spin className="Spinlarge"  indicator={<Icon type="loading" style={{ fontSize: 30 }} spin />}/>:"" }
+                   
+                            {target_score.length===0&&Spintype===false?
+                                    <li className={"clearfix newtarget_scoreclass lipadding10im"}>
+                                        <span className="column-1 color-05101A">--</span>
+                                        <span className="column-1 color-05101A">--</span>
+                                        <span className="column-1 colorFF6800">--</span>
+                                        <span className="column-1 color-green">--</span>
+                                        <span className="column-1 color-05101A">
+                                              <div>--人</div>
+                                              <div className="color999">--%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>--人</div>
+                                              <div className="color999">--%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>--人</div>
+                                              <div className="color999">--%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>--人</div>
+                                              <div className="color999">--%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>--人</div>
+                                              <div className="color999">--%</div>
+                                        </span>
+                                        <span className="column-1 color-05101A">
+                                              <div>--人</div>
+                                              <div className="color999">--%</div>
+                                        </span>
+                                    </li>:""}
+               
+                    </div>
+
+                </div>
+            </div>
+        );
+    }
+}
+
+export default SnackbarHOC() (EcCompletionCalculation);
+
diff --git a/public/react/src/modules/ecs/subroute/ecCourseEvaluations/EcCourseEvaluationsbottom.js b/public/react/src/modules/ecs/subroute/ecCourseEvaluations/EcCourseEvaluationsbottom.js
new file mode 100644
index 000000000..6e27711b2
--- /dev/null
+++ b/public/react/src/modules/ecs/subroute/ecCourseEvaluations/EcCourseEvaluationsbottom.js
@@ -0,0 +1,1039 @@
+import React, { Component } from 'react';
+
+import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
+
+import classNames from 'classnames'
+
+import axios from 'axios';
+
+// import { TPMIndexHOC } from '../../../tpm/TPMIndexHOC';
+
+import { SnackbarHOC } from 'educoder'
+
+import { Select,InputNumber,message,Modal,Input,Radio,Spin,Icon,Tooltip } from 'antd';
+
+import 'antd/dist/antd.css';
+
+import '../../css/ecCourseEvaluations.css';
+import EcTitleCourseEvaluations from "../../ecTitle/ecTitle";
+
+const $ = window.$;
+
+// 课程目标评价方法
+class EcCourseEvaluationsbottom extends Component {
+    constructor(props) {
+      super(props)
+      this.state={
+        totalevaluations_list:[],
+        ec_course_target_id:0,
+        achievement_list:[],
+        evaluations_listSelec:[],
+        evaluations_lists: [],
+        evaluation_subitems_lists: [],
+        evaluations_list:[],
+        evaluation_subitems_list:{},
+        achievement_methods:[],
+        ec_course_target_name:"",
+        buttomSaveCourseEvaluationsbottom:this.SaveCourseEvaluationsbottom,
+        spinningstate:true,
+        schooldata:{},
+        sequenceid:0,
+        target_id:null,
+        titlemessages:"提示",
+        Modallists:"",
+        eacoursetype:false,
+        eacoursesavetypes:false,
+        newec_course_idbottom:undefined,
+        methodologytype:false,
+        meweacoursetype:false,
+        newshowredvalue:false,
+        percentagetype:false,
+        ismanager:false
+      }
+    }
+    getec_course_achievement_methods=()=>{
+      const {newec_course_idbottom}=this.state;
+      if(newec_course_idbottom!=undefined){
+          const url = `/ec_course_achievement_methods?ec_course_id=`+newec_course_idbottom;
+          axios.get(url, {
+                withCredentials: true,
+              })
+            .then((response)=>{
+              this.setState({
+                achievement_list:response.data.achievement_list,
+                spinningstate:false,
+                ismanager:response.data.is_manager
+              })
+          }).catch(function (error) {
+                console.log(error);
+            });
+      }
+        // this.setState({
+        //     achievement_list:[
+        //         {target_evaluate_data: [
+        //                 {
+        //                     evaluate_id: 24,
+        //                     evaluate_name: "期末考试",
+        //                     evaluation_relates_data: [
+        //                         {evaluation_relates_id: 31, evaluation_relates_name: "期末考试1目标1考题"},
+        //                         {evaluation_relates_id: 32, evaluation_relates_name: "期末考试1目标2考题"}
+        //                     ],
+        //                     percentage: 100,
+        //                     score: 15
+        //                 }
+        //             ],
+        //             target_id: 5
+        //         },
+        //     ],
+        //     spinningstate:false
+        // })
+
+
+    }
+
+    getNavigationData=(ec_course_id)=>{
+        // const jol =`/ec_major_schools/get_navigation_data?ec_year_id=`+ec_year_id+"&ec_course_id="+ec_course_id;
+        const jol =`/ec_major_schools/get_navigation_data?ec_course_id=`+ec_course_id;
+        axios.get(jol, {
+            withCredentials: true,
+        })
+            .then((response) => {
+                if(response.status===200){
+                //   if(response.data.allow_visit===false){
+                //     window.location.href="/403"
+                //  }
+                    this.setState({
+                        schooldata:response.data
+                    })
+                }
+
+            })
+            .catch(function (error) {
+                console.log(error);
+            });
+    }
+    componentDidMount(){
+        let ec_course_id=this.props.match.params.ec_course_id;
+          const url = `/ec_course_achievement_methods?ec_course_id=`+ec_course_id;
+          axios.get(url, {
+                withCredentials: true,
+              })
+            .then((response)=>{
+              this.setState({
+                achievement_list:response.data.achievement_list,
+                spinningstate:false,
+                ismanager:response.data.is_manager
+              })
+          }).catch(function (error) {
+                console.log(error);
+            });
+    
+         this.getNavigationData(ec_course_id);
+         this.setState({
+             newec_course_idbottom:ec_course_id
+         })
+    }
+    editecCourseEvaluationslist=(e)=>{
+        let id =e.target.getAttribute("target_id");
+        let newid =e.target.name;
+
+      this.setState({
+          buttomSaveCourseEvaluationsbottom:this.SaveCourseEvaluationsbottom,
+          target_id:id,
+          percentagetype:false
+       })
+      // $("#ecCourseEvaluationsbottomsubmit").show();
+      // $("#SystemParametersbottom").show();
+      // let offsettop=$("#ecCourseEvaluationsbottomsubmit").position().top||$("#ecCourseEvaluationsbottomsubmit").scrollTop || $("#ecCourseEvaluationsbottomsubmit").pageYOffset;
+      // window.scrollTo(0, offsettop)
+
+      let {evaluations_list,evaluation_subitems_list,achievement_methods} = this.state;
+      this.setState({
+        achievement_methods:undefined,
+        selectevaluation_phase:[],
+        course_select_value:'',
+        evaluations_lists:[],
+        sequenceid:newid,
+        methodologytype:false,
+        Modallists:' ',
+        meweacoursetype:false,
+        eacoursesavetypes:false,
+        newshowredvalue:false
+      })
+
+      let newevaluations_list=[];
+      let newevaluation_subitems_list=new Object ();
+      let newachievement_methods=[];
+      const url = `/ec_course_achievement_methods/edit_course_target?ec_course_target_id=`+id;
+      axios.get(url, {
+            withCredentials: true,
+          })
+        .then((response)=>{
+          if(response.status===200){
+          if(response.data.evaluation_phase_list.length===0){
+            this.setState({
+              achievement_methods:undefined
+            })
+               let newObject=new Object ();
+               newachievement_methods.push(newObject)
+          }
+
+          if(response.data.evaluation_phase_list.length>0){
+            let evaluation_phase_list=response.data.evaluation_phase_list;
+            let evaluations_list=response.data.evaluations_list;
+            for(var i=0; i<evaluation_phase_list.length;i++){
+              let course_select_value=null;
+              let newevaluation_phase=evaluation_phase_list[i].evaluation_phase;
+              let selectevaluation_phase=[]
+              for(var j=0;j<response.data.evaluations_list.length;j++){
+                    if(evaluation_phase_list[i].evaluation_id===evaluations_list[j].id){
+                       course_select_value=evaluations_list[j].name
+                    }
+              }
+              for(var z=0;z<newevaluation_phase.length;z++){
+                selectevaluation_phase.push(newevaluation_phase[z].name)
+              }
+              let newObject={
+                course_evaluation_id:evaluation_phase_list[i].evaluation_id,
+                score:evaluation_phase_list[i].score,
+                percentage: evaluation_phase_list[i].percentage,
+                evaluation_subitems:evaluation_phase_list[i].evaluation_phase,
+                course_select_value:course_select_value,
+                selectevaluation_phase:selectevaluation_phase
+              }
+              newachievement_methods.push(newObject)
+            }
+
+          }
+          for(var i=0; i<response.data.evaluations_list.length;i++){
+                newevaluations_list.push(response.data.evaluations_list[i].name);
+                newevaluation_subitems_list[response.data.evaluations_list[i].name]=[];
+                for(var j=0; j<response.data.evaluations_list[i].evaluation_subitems_list.length;j++){
+                  newevaluation_subitems_list[response.data.evaluations_list[i].name].push(response.data.evaluations_list[i].evaluation_subitems_list[j].name)
+                }
+            }
+          // let newec_course_target_name="";
+          // let newec_course_target_namelist=response.data.evaluations_list;
+          //     for(var o=0; o<newec_course_target_namelist.length;o++){
+          //       newec_course_target_name=newec_course_target_namelist[o].ec_course_target_name
+          //     }
+            this.setState({
+              achievement_methods:newachievement_methods,
+              totalevaluations_list:response.data,
+              // ec_course_target_name:newec_course_target_name,
+              evaluations_list:newevaluations_list,
+              evaluation_subitems_list:newevaluation_subitems_list,
+              newec_course_target_id:id,
+              methodologytype:true,
+              ec_course_target_name:response.data.ec_course_target_name,
+              ismanager:response.data.is_manager
+            })
+
+            // this.setState({
+            //   // evaluations_lists: evaluation_subitems_list[evaluations_list[0]],
+            //   evaluation_subitems_lists: evaluation_subitems_list[evaluations_list[0]][0]
+            // })
+          }
+       }).catch(function (error) {
+            console.log(error);
+        });
+    }
+
+    handleevaluations_list=(value,keythis)=>{
+
+      let {evaluation_subitems_list,totalevaluations_list,achievement_methods} = this.state;
+      let newachievement_methods=achievement_methods;
+      let newlist=new Object ();
+      let location=keythis.key;
+      let list=totalevaluations_list.evaluations_list;
+      // 点击切换清空
+        for(var z=0; z<newachievement_methods.length;z++){
+            if(z===location){
+                newachievement_methods[z].evaluation_subitems=[]
+            }
+        }
+      this.setState({
+        evaluations_lists: evaluation_subitems_list[value],
+        evaluation_subitems_lists: evaluation_subitems_list[value][0],
+         achievement_methods:newachievement_methods
+      });
+
+
+
+      if(newachievement_methods.length===0){
+          for(var i=0; i<list.length;i++){
+            if(list[i].name===value){
+              newlist.course_evaluation_id=list[i].id
+            }
+          }
+          newachievement_methods.push(newlist)
+      }else if(newachievement_methods.length>0){
+          if(newachievement_methods[location]===undefined){
+              newachievement_methods.push(newlist)
+          }
+          for(var i=0; i<list.length;i++){
+            if(list[i].name===value){
+              newachievement_methods[location].course_evaluation_id=list[i].id
+              newachievement_methods[location].course_select_value=value
+              newachievement_methods[location].selectevaluation_phase=[]
+            }
+          }
+      }
+
+      this.setState({
+        achievement_methods: newachievement_methods
+      });
+
+    }
+    handevaluation_subitems_list=(value,keynum)=>{
+      let{totalevaluations_list,achievement_methods}=this.state;
+      let newachievement_methods=[];
+      let id;
+      if(value.length>0){
+
+        newachievement_methods=achievement_methods
+        for(var j=0; j<value.length;j++){
+          if(!isNaN(keynum[j].key)){
+            id=keynum[j].key
+          }
+        }
+
+        let list=[];
+
+        for(var k=0; k<value.length;k++){
+
+          for(var i=0; i<totalevaluations_list.evaluations_list.length;i++){
+            let newlist=totalevaluations_list.evaluations_list[i].evaluation_subitems_list;
+            for(var z=0; z<newlist.length; z++){
+                  if(value[k]===newlist[z].name){
+                    let Objectlist=new Object ();
+                    Objectlist.id=newlist[z].id;
+                    // Objectlist.name=newlist[z].name;
+                    Objectlist.position=newlist[z].position;
+                    list.push(Objectlist)
+                  }
+            }
+          }
+         }
+      newachievement_methods[id].evaluation_subitems=list;
+      newachievement_methods[id].selectevaluation_phase=value;
+       this.setState({
+        evaluation_subitems_lists: value,
+        achievement_methods:newachievement_methods
+      });
+
+      }
+    }
+
+    handevaluation_Addlist=(value,keynum)=>{
+      let id=parseInt(keynum.key);
+      let{achievement_methods}=this.state;
+      let newachievement_methods=achievement_methods;
+      for(var i=0; i<newachievement_methods.length;i++){
+          if(isNaN(id)){
+              for(var j=0; j< newachievement_methods[i].evaluation_subitems.length; j++){
+                  if(newachievement_methods[i].evaluation_subitems[j].name===value){
+                      newachievement_methods[i].evaluation_subitems.splice(j,1);
+                      newachievement_methods[i].selectevaluation_phase.splice(j,1);
+                  }
+              }
+          }else{
+              if(id===i){
+                  newachievement_methods[i].evaluation_subitems.splice(i,1);
+                  newachievement_methods[i].selectevaluation_phase.splice(i,1);
+              }
+          }
+      }
+      this.setState({
+        achievement_methods:newachievement_methods
+      })
+    }
+
+
+    handevaluation_CourseScore=(e)=>{
+      let {achievement_methods} = this.state;
+      let newachievement_methods=achievement_methods;
+      let id=e.target.id;
+      var value=parseFloat(e.target.value);
+      for(var i=0; i<newachievement_methods.length;i++){
+        newachievement_methods[id].score=value
+      }
+      this.setState({
+        achievement_methods:newachievement_methods
+      })
+    }
+    handevaluation_CoursePercentag=(e)=>{
+      let {achievement_methods} = this.state;
+      let newachievement_methods=achievement_methods;
+      let id=e.target.id;
+      let value=parseFloat(e.target.value);
+
+        if(value>100){
+        // message.warning('占比请输入0~100的数');
+        this.setState({
+            Modallists:'占比请输入0~100的数',
+            meweacoursetype:true,
+            newshowredvalue:true
+        })
+        value=100
+      }
+
+        if(value<0){
+            // message.warning('占比请输入0~100的数');
+            this.setState({
+                Modallists:'占比不能小于0',
+                meweacoursetype:true,
+                newshowredvalue:true
+            })
+            value=0
+        }
+
+        if(value===""||value===null||value===undefined){
+            // message.warning('占比请输入0~100的数');
+            this.setState({
+                Modallists:'占比不能为空',
+                meweacoursetype:true,
+                newshowredvalue:true
+            })
+            value=0
+        }
+
+      for(var i=0; i<newachievement_methods.length;i++){
+        newachievement_methods[id].percentage=value
+      }
+      this.setState({
+        achievement_methods:newachievement_methods
+      })
+    }
+
+    Addhandevaluation=(e)=>{
+      let {achievement_methods} = this.state;
+      let newachievement_methods=achievement_methods;
+      let newlist=new Object ();
+      newachievement_methods.push(newlist);
+      this.setState({
+        achievement_methods:newachievement_methods
+     });
+    }
+    Delethandevaluation=(e)=>{
+      let {achievement_methods} = this.state;
+      let id =e.target.getAttribute("index");
+      let newachievement_methods=achievement_methods;
+      newachievement_methods.splice(id,1);
+      this.setState({
+        achievement_methods:newachievement_methods
+     });
+    }
+
+
+    EvaluationsSaveonloadgetdata=(id)=>{
+      const url = `/ec_course_achievement_methods?ec_course_id=`+id
+      axios.get(url, {
+            withCredentials: true,
+          })
+        .then((response)=>{
+          this.setState({
+            achievement_list:response.data.achievement_list,
+            spinningstate:false,
+            ismanager:response.data.is_manager
+          })
+
+       }).catch(function (error) {
+            console.log(error);
+            this.setState({
+              spinningstate:false
+            })
+        });
+
+
+     }
+     ecrestoration=()=>{
+      this.setState({
+        buttomSaveCourseEvaluationsbottom:this.SaveCourseEvaluationsbottom
+       })
+     }
+
+    SaveCourseEvaluationsbottom=()=>{
+      let ec_course_id=this.props.match.params.ec_course_id;
+        this.setState({
+          buttomSaveCourseEvaluationsbottom:'',
+          percentagetype:true
+        })
+      let {newec_course_target_id,achievement_methods} = this.state;
+
+
+      for(var j=0; j<achievement_methods.length;j++){
+        if(achievement_methods[j].course_evaluation_id===undefined){
+          // message.error('提交失败!请选择该目标评价环节');
+            this.setState({
+                Modallists:'提交失败,评价环节不能为空',
+                meweacoursetype:true,
+                eacoursesavetypes:true
+            })
+          this.ecrestoration();
+          return;
+        }
+
+        if(achievement_methods[j].evaluation_subitems===undefined){
+          // message.error('提交失败!请选择支撑项');
+            this.setState({
+                Modallists:'提交失败,支撑项内容不能为空',
+                meweacoursetype:true,
+                eacoursesavetypes:true
+            })
+          this.ecrestoration();
+          return;
+        }
+        if(achievement_methods[j].score===undefined||achievement_methods[j].score===NaN||achievement_methods[j].score===null){
+          // message.error('提交失败!请填写支撑分数!');
+            this.setState({
+                Modallists:'提交失败,支撑分数不能为空',
+                meweacoursetype:true,
+                eacoursesavetypes:true
+            })
+          this.ecrestoration();
+          return;
+        }
+
+        if(achievement_methods[j].percentage===undefined||achievement_methods[j].percentage===NaN||achievement_methods[j].percentage===null){
+          // message.error('提交失败!请填写占比!');
+            this.setState({
+                Modallists:'提交失败,占比不能为空',
+                meweacoursetype:true,
+                eacoursesavetypes:true,
+                newshowredvalue:true
+            })
+          this.ecrestoration();
+          return;
+        }
+
+
+      }
+
+      let percentagenum=0;
+      for(var o=0;o<achievement_methods.length;o++){
+        percentagenum=percentagenum+achievement_methods[o].percentage;
+      }
+      if(percentagenum>100){
+        // message.error('提交失败!支撑占比不能超过总和100%');
+          this.setState({
+              Modallists:'提交失败,支撑占比不能超过总和100%',
+              meweacoursetype:true,
+              newshowredvalue:true,
+              percentagetype:true
+          })
+        this.setState({
+          buttomSaveCourseEvaluationsbottom:this.SaveCourseEvaluationsbottom
+         })
+        return
+      }
+      if(percentagenum<100){
+        // message.error('提交失败!支撑占比不能超过总和100%');
+          this.setState({
+              Modallists:'提交失败,支撑占比总和要等于100%',
+              meweacoursetype:true,
+              newshowredvalue:true,
+              percentagetype:true
+          })
+        this.setState({
+          buttomSaveCourseEvaluationsbottom:this.SaveCourseEvaluationsbottom
+         })
+        return
+      }
+      for(var i=0;i<achievement_methods.length;i++){
+        if(JSON.stringify(achievement_methods[i])==="{}"){
+          achievement_methods.splice(i,1);
+        }else{
+          delete achievement_methods[i].course_select_value;
+          delete achievement_methods[i].selectevaluation_phase;
+          for(var j=0; j< achievement_methods[i].evaluation_subitems.length;j++){
+            delete achievement_methods[i].evaluation_subitems[j].evaluation_subitem_id;
+            delete achievement_methods[i].evaluation_subitems[j].name;
+          }
+        }
+      }
+
+
+      var Url = '/ec_course_achievement_methods/create_evaluation_methods';
+      axios.post(Url, {
+        ec_course_target_id: newec_course_target_id,
+        achievement_methods:achievement_methods
+      },
+      {
+        withCredentials: true
+      }
+      ).then((response) => {
+        if(response.data.status===0){
+            this.setState({
+              target_id:null,
+              newec_course_idbottom:response.data.ec_course_id,
+              buttomSaveCourseEvaluationsbottom:this.SaveCourseEvaluationsbottom,
+              // Modallists:response.data.message,
+              // eacoursetype:true,
+              Modallists:' ',
+              meweacoursetype:false,
+              achievement_methods:undefined,
+              eacoursesavetypes:false,
+              newshowredvalue:false,
+              ismanager:response.data.is_manager
+            })
+            // $("#ecCourseEvaluationsbottomsubmit").hide();
+            // $("#SystemParametersbottom").hide();
+            this.EvaluationsSaveonloadgetdata(response.data.ec_course_id);
+            this.getNavigationData(ec_course_id);
+
+        }else if(response.data.status===-1){
+           this.setState({
+            buttomSaveCourseEvaluationsbottom:this.SaveCourseEvaluationsbottom,
+            Modallists:response.data.message,
+            eacoursetype:true,
+           })
+        }
+      }).catch((error) => {
+        console.log(error)
+      })
+    }
+    CancelecCourseEvaluationsbottom=()=>{
+      this.setState({
+        achievement_methods:undefined,
+        target_id:null,
+        methodologytype:false,
+        Modallists:' ',
+        meweacoursetype:false,
+        eacoursesavetypes:false,
+        newshowredvalue:false,
+        percentagetype:false
+      })
+      // $("#ecCourseEvaluationsbottomsubmit").hide();
+      // $("#SystemParametersbottom").hide();
+      this.getec_course_achievement_methods();
+    }
+
+    selectsonFocuslist=(e,key)=>{
+       let value =e.course_select_value;
+       let {evaluation_subitems_list,totalevaluations_list,achievement_methods} = this.state;
+       let newachievement_methods=achievement_methods;
+       let newlist=new Object ();
+       let location=key;
+       let list=totalevaluations_list.evaluations_list;
+       this.setState({
+         evaluations_lists: evaluation_subitems_list[value],
+         evaluation_subitems_lists: evaluation_subitems_list[value][0]
+       });
+
+       if(newachievement_methods.length===0){
+           for(var i=0; i<list.length;i++){
+             if(list[i].name===value){
+               newlist.course_evaluation_id=list[i].id
+             }
+           }
+           newachievement_methods.push(newlist)
+       }else if(newachievement_methods.length>0){
+           if(newachievement_methods[location]===undefined){
+               newachievement_methods.push(newlist)
+           }
+           for(var i=0; i<list.length;i++){
+             if(list[i].name===value){
+               newachievement_methods[location].course_evaluation_id=list[i].id
+             }
+           }
+       }
+
+       this.setState({
+         achievement_methods: newachievement_methods
+       });
+    }
+
+    hidemodeleacourse=()=>{
+        this.setState({
+            eacoursetype:false
+        })
+    }
+  	render() {
+      const Option = Select.Option;
+      let {schooldata,achievement_list,spinningstate,evaluations_list,evaluations_lists,newec_course_target_id,achievement_methods,ec_course_target_name,buttomSaveCourseEvaluationsbottom,sequenceid,target_id,
+          titlemessages,
+          Modallists,
+          eacoursetype,
+          eacoursesavetypes,
+          methodologytype,
+          newec_course_idbottom,
+          meweacoursetype,
+          percentagetype,
+          ismanager
+      } = this.state;
+	    return (
+        <div className="newMain clearfix">
+          <div className="educontent mb50">
+              <Modal
+                  title={titlemessages}
+                  // visible={modeldelet===true&&listid===list.id?true:false}
+                  visible={eacoursetype}
+                  className={"ecmodeldelet"}
+                  closable={false}
+                  footer={null}
+              >
+                  <div className="task-popup-content"  >
+                      <div className="task-popup-text-center font-14">{Modallists}</div>
+                  </div>
+                  <div className="task-popup-submit clearfix">
+                      <a onClick={this.hidemodeleacourse} className="task-btn fl">取消</a>
+                      <a  className="task-btn task-btn-orange fr"
+                          onClick={this.hidemodeleacourse}
+                      >确定</a>
+                  </div>
+              </Modal>
+
+              {/*导航*/}
+              {/*<div className="edu-back-white eacourse">*/}
+
+                  {/*<p className="clearfix padding20-30 bor-bottom-greyE" id="SystemParametersP">*/}
+                      {/*<a href={schooldata.course_setting_url} className="TrainingLecturer color-grey-9">课程列表 > </a>*/}
+                      {/*<a className="TrainingTheory major_name"> {schooldata.ec_course_name} 课程考核方式与数据来源</a>*/}
+                      {/*/!* <span className="fl font-18 courseSystem"></span> *!/*/}
+                      {/*/!* <a href="javascript:void(0)" className="fr white-btn edu-blueback-btn mt4">导出培养目标</a> *!/*/}
+                      {/*<span className="Importclassroomdata" style={{top: '22px'}}><a className="white-btn edu-blueback-btn fr mb10 mr10">导出策略</a></span>*/}
+                  {/*</p>*/}
+
+                  {/*<div className="padding20-30" id="SystemParameters">*/}
+                      {/*<span className="fl SystemParameters">课程考核标准</span>*/}
+                      {/*<span className="fl ml20 SystemParameters">(请在完成配置后,使用各项成绩导入模板,将本学年所有参与的学生成绩数据导入系统)</span>*/}
+                      {/*<span className="fr ml20 SystemParameters" style={{display:course_name===null||course_name===undefined?"none":"block",height:'37px'}}><span className="ecblock">在线课堂:</span><a href={course_url} target="_blank" className="ecnowrap" data-tip-down={course_name}>{course_name}</a></span>*/}
+                      {/*<span className="Importclassroomdata" style={{display:course_name===null||course_name===undefined?"none":"block"}}><a onClick={this.sync_course_data} className="white-btn edu-orangeback-btn  fr mt2 mr10">导入课堂数据</a></span>*/}
+                  {/*</div>*/}
+
+              {/*</div>*/}
+              {/*<EcTitleCourseEvaluations*/}
+              {/*    {...this.props}*/}
+              {/*    schooldata={schooldata}*/}
+              {/*    ecpath={"show"}*/}
+              {/*/>*/}
+
+                {/*<div className="edu-back-white eacourse">*/}
+
+                {/*    <p className="clearfix padding20-30 bor-bottom-greyE" id="SystemParametersP">*/}
+                {/*        <a href={schooldata.course_setting_url} className="TrainingLecturer color-grey-9">课程体系 </a> >*/}
+                {/*        <a className="TrainingTheory major_name"> {schooldata.ec_course_name} </a>*/}
+                {/*        <div className="color-grey-9 mr10">请结合本课程的教学情况,修改说明每个课程目标的评价环节和评估方式  <a className={"color-blue"} onClick={() => window.elasticLayer(3533)}>查看详情</a></div>*/}
+
+                {/*      /!*课程考核方式与数据来源*!/*/}
+                {/*        /!* <span className="fl font-18 courseSystem"></span> *!/*/}
+                {/*        /!* <a href="javascript:void(0)" className="fr white-btn edu-blueback-btn mt4">导出培养目标</a> *!/*/}
+                {/*        <span className="Importclassroomdata" style={{top: '22px'}}>*/}
+                {/*           <a className="white-btn edu-blueback-btn fr mb10 mr10" target="_blank" href={'/ec_courses/'+newec_course_idbottom+'/export_ec_course_targets?format=xls'}>导出评价方法</a>*/}
+                {/*        </span>*/}
+                {/*    </p>*/}
+
+                {/*    <div className="padding20-30" id="SystemParameters">*/}
+                {/*      /!*<span className="fl SystemParameters">课程目标达成方法</span>*!/*/}
+                {/*        <a className="fl SystemParameters color4D4D4D" style={{display:schooldata.ec_course_support_setting_url===null?"none":"block",marginLeft: '9px' }}*/}
+                {/*           href={schooldata.ec_course_support_setting_url}>1.课程目标</a>*/}
+                {/*        <a className="fl ml40 SystemParameters4CACFF color4D4D4D"*/}
+                {/*           style={{display:schooldata.ec_course_reach_setting_url===null?"none":"block"}}*/}
+                {/*           href={schooldata.ec_course_reach_setting_url}>2.课程考核方式与数据来源</a>*/}
+                {/*        <a className="fl SystemParameters4CACFF ml40 color4D4D4D"*/}
+                {/*          href={schooldata.score_level_setting_url}*/}
+                {/*        >3.成绩等级设置</a>*/}
+                {/*        <a className="fl ml40 SystemParameters4CACFF color4CACFF"*/}
+                {/*           style={{display:schooldata.evaluation_methods_url===null?"none":"block"}}*/}
+                {/*           href={schooldata.evaluation_methods_url}>4.课程目标评价方法</a>*/}
+                {/*        <a className="fl SystemParameters ml40 color4D4D4D"*/}
+                {/*           style={{display:schooldata.competition_calculation_info_url===null?"none":"block"}}*/}
+                {/*           href={schooldata.competition_calculation_info_url}>5.课程达成评价结果</a>*/}
+                {/*      <span className="fr ml20 SystemParameters" style={{color: '#989898'}}>(各环节平均得分*占比)之和/(各环节总分*占比)之和</span>*/}
+                {/*    </div>*/}
+
+                {/*</div>*/}
+
+                <div className="ListTableLine newSystem" id="school_major_list">
+
+                        <p className="clearfix Coursetitle" style={{width:"1200px"}}>
+                          <span className="column-1 color-666">课程目标</span>
+                          <span className="column-1 color-666">评价环节</span>
+                          <span className="column-1 ml15 color-666">数据内容</span>
+                          <span className="column-1 operationright color-666 f5f5f5"
+                          >
+                             操作 
+                          </span>
+                          <span className="column-1 ml30 operationright color-666">评价占比</span>
+                          <span className="column-1 ml15 operationright color-666">支撑总分值</span>
+                        </p>
+
+                        {
+                          achievement_list.length===0?<Spin spinning={spinningstate} className="Spinlarge"  indicator={<Icon type="loading" style={{ fontSize: 30 }} spin />}/>:achievement_list.map((item,key)=>{
+                            return(
+                                    <div key={key} >
+                                    {
+                                      item.target_evaluate_data.length===0?
+                                      <li key={key} className="clearfix" style={{width:"1140px"}}>
+                                          <div  style={{ width:'99.8%'}}  style={{display:parseInt(target_id)===item.target_id?"none":"block"}}>
+                                              <span className="column-1 mt4 textaligncenter"><span>{key+1}</span></span>
+                                          <span>
+                                          <span className="column-1 ml80 mt4">
+                                                <span></span>
+                                          </span>
+                                          <span className="column-1 ml80 color99 mt4 newtextaligncenter">
+                                                          <span></span>
+                                          </span>
+                                          <span className="column-1 operationright mt4">
+                                              <div className="operationColumn">
+                                                  <div className="right operationalter nulleditSubentry" style={{display:ismanager===false?'none':'block'}}>
+                                                      <a className="mr16 editSubentry" data-tip-down="编辑" ><i target_id={item.target_id}  name={key} onClick={this.editecCourseEvaluationslist.bind(this)} className="iconfont icon-bianjidaibeijing color-green" ></i></a>
+                                                </div>
+                                              </div>
+                                          </span>
+
+
+                                          <span className="column-1 ml15 operationright mt4 percentage">
+                                              <div></div>
+                                          </span>
+
+                                          <span className="column-1 ml15 operationright mt4">
+                                              <div className="ColorF68"></div>
+                                          </span>
+
+                                          </span>
+                                          </div>
+
+                                          {/* 修改start*/}
+                                          <div className="ListTableLine newSystem" id="EvaluationsList">
+                                              <div style={{display:parseInt(target_id)===item.target_id?"block":"none"}} >
+                                                  {/* <div className="edu-back-white eacourse" id="SystemParametersbottom" style={{display:parseInt(sequenceid)===key?"block":"none"}}> */}
+                                                  <div className="edu-back-white eacourse" id="SystemParametersbottom" style={{display:parseInt(target_id)===item.target_id?"block":"none"}}>
+                                                      <div className="padding20-30" id="SystemParameters" style={{paddingLeft:'0px'}}>
+                                                          {/* <span className="fl SystemParameters">课程目标{sequenceid}:{ec_course_target_name}</span> */}
+                                                          <span className="fl SystemParameters">课程目标{key+1}:{ec_course_target_name}</span>
+                                                      </div>
+                                                  </div>
+                                                  {
+                                                      achievement_methods===undefined?" ":achievement_methods.map((item,itemkey)=>{
+                                                          return(
+                                                              <div key={itemkey} className="clearfix editorModify"  >
+                                                                  <div className="">
+                                                                      <span className="column-1 mr12" style={{paddingLeft:'0px'}}>评价环节</span>
+                                                                      <Select
+                                                                          // className={item.course_select_value===undefined&&eacoursesavetypes===true? "inputWeight  bor-red": "inputWeight"}
+                                                                          className={item.course_select_value===undefined&&eacoursesavetypes===true?Modallists==='提交失败,评价环节不能为空'?"inputWeight  bor-red":"inputWeight": "inputWeight"}
+
+                                                                          placeholder="请选择该目标的评价环节"
+                                                                          size="large"
+                                                                          style={{ width: '20%' }}
+                                                                          value={item.course_select_value}
+                                                                          onChange={this.handleevaluations_list.bind(this)}
+                                                                      >
+                                                                          {evaluations_list.map(province => <Option value={province} key={itemkey}>{province}</Option>)}
+
+                                                                      </Select>
+
+                                                                      <span className="column-1 mr13"></span>
+
+                                                                      <Select
+                                                                          mode="multiple"
+                                                                          // className={item.selectevaluation_phase===undefined&&eacoursesavetypes===true? "inputWeight  bor-red": "inputWeight"}
+                                                                          className={item.selectevaluation_phase===undefined&&eacoursesavetypes===true?Modallists==='提交失败,支撑项内容不能为空'?"inputWeight bor-red":"inputWeight": "inputWeight"}
+
+                                                                          placeholder="请选择具体数据内容"
+                                                                          size="large"
+                                                                          id="Coursemultiple"
+                                                                          style={{ width: '37%' }}
+                                                                          onChange={this.handevaluation_subitems_list.bind(this)}
+                                                                          onDeselect={this.handevaluation_Addlist.bind(this)}
+                                                                          value={item.selectevaluation_phase}
+                                                                          onFocus={()=>this.selectsonFocuslist(item,itemkey)}
+                                                                      >
+                                                                          {evaluations_lists.map(city => <Option value={city} key={itemkey}>{city}</Option>)}
+                                                                      </Select>
+
+                                                                      <span className="column-1 mr14"></span>
+                                                                      <Input size="large"  type="number" value={item.score}
+                                                                             className={item.score===undefined&&eacoursesavetypes===true?Modallists==='提交失败,支撑分数不能为空'?"bor-red": "": ""}
+                                                                             onInput={this.handevaluation_CourseScore.bind(this)} id={itemkey} style={{ width: '11%' }} placeholder="请输入支撑分数"/>
+                                                                      <span className="column-1 ml5 mr10">分</span>
+                                                                      <Input size="large" type="number"   value={item.percentage}
+                                                                             className={item.percentage===undefined&&eacoursesavetypes===true||item.percentage>100&&eacoursesavetypes===true||percentagetype===true?"bor-red": ""}
+                                                                             onInput={this.handevaluation_CoursePercentag.bind(this)}  id={itemkey} style={{ width: '11%' }}  placeholder="请输入占比"/>
+                                                                      <span className="column-1 ml5 mr10">%</span>
+                                                                      <span className="buttoninline SetTheAssociated"  style={{marginLeft:'10px'}}>
+                                                                                    <div className="left operatebutton" style={{display:ismanager===false?'none':'block'}}>
+                                                                                        <a className="mr15 delSubentry" style={{display:itemkey===0?'none':'inline-block'}}>
+                                                                                            <Tooltip placement="bottom" title="删除">
+                                                                                                <i className="iconfont icon-shanchu color-grey-c  font-17" index={itemkey} onClick={this.Delethandevaluation.bind(this)}></i>
+                                                                                            </Tooltip>
+                                                                                        </a>
+                                                                                        <a className="newAddSubentry" data-tip-down="添加"
+                                                                                          style={{ display:itemkey===achievement_methods.length-1?'inline-block':'none'}}
+                                                                                        ><i className="iconfont icon-tianjiafangda color-green" index={itemkey} onClick={this.Addhandevaluation.bind(this)}></i></a>
+                                                                                    </div>
+                                                                            </span>
+                                                                  </div>
+                                                                  <br />
+                                                              </div>
+                                                          )
+                                                      })
+                                                  }
+                                                  <span className="c_red none ml30" id="error_tip" style={{display:meweacoursetype===true?'inline-block':'none'}}>{Modallists}</span>
+                                                  <div className="right editglybuttonbox mb10" id="ecCourseEvaluationsbottomsubmit"  style={{display:parseInt(target_id)===item.target_id?"block":"none"}} >
+                                                      <div className="defalutSubmitbtn fr" onClick={buttomSaveCourseEvaluationsbottom}>保存</div>
+                                                      <div className="defalutCancelbtn fr mr20" onClick={this.CancelecCourseEvaluationsbottom}>取消</div>
+                                                  </div>
+                                              </div>
+                                          </div>
+                                          {/* 修改end*/}
+
+
+                                      
+                                      </li>
+                                      :item.target_evaluate_data.map((i,k)=>{
+                                            return(
+                                              <li key={key} className={achievement_list.length-1===key?item.target_evaluate_data.length-1===k?"clearfix":"bordereaeaea clearfix":item.target_evaluate_data.length-1===k?"bordereaeaeas clearfix":" bordereaeaea clearfix" } style={{width:"1140px",display:parseInt(target_id)===item.target_id&&methodologytype===true?item.target_evaluate_data.length-1===k?'block':"none":"block"}}>
+                                              <div  style={{ width:'99.8%'}}  style={{display:parseInt(target_id)===item.target_id&&methodologytype===true?"none":"block"}} >
+                                                  <span className="column-1 mt4 textaligncenter absolute"><span>{key-k===key?key+1:""}</span></span>
+                                              <span>
+                                              <span className="column-1 ml100 mt4 absolute">
+                                                    <span>{i.evaluate_name}</span>
+                                              </span>
+                                              <span className="column-1 ml80 color99 mt4 newtextaligncenter  evaluationdataClass" style={{marginLeft: '72px'}}>
+                                                  {
+                                                    i.evaluation_relates_data.map((y,e)=>{
+                                                      return(
+                                                              <div key={y} className="boxinline">{y.evaluation_relates_name+"  "} </div>
+                                                      )
+                                                    })
+                                                  }
+                                              </span>
+                                              {
+                                                key-k===key?<span className="column-1 operationright mt4">
+                                                  <div className="operationColumn">
+                                                      <div className="right operationalter neweditSubentry" style={{display:ismanager===false?'none':'block'}}>
+                                                          <a className="mr20 editSubentry" data-tip-down="编辑" ><i target_id={item.target_id} name={key} onClick={this.editecCourseEvaluationslist.bind(this)} className="iconfont icon-bianjidaibeijing color-green" ></i></a>
+                                                      </div>
+                                                  </div>
+                                              </span>:
+                                                <span className="column-1 operationright mt4">
+                                                    <div className="operationColumn">
+                                                        <div className="left operationalter neweditSubentry">
+                                                            <a className="mr20 editSubentry"></a>
+                                                      </div>
+                                                    </div>
+                                                </span>
+                                              }
+
+
+                                              <span className="column-1 ml15 operationright mt4 percentage">
+                                                  <div>{i.percentage+"%"}</div>
+                                              </span>
+
+                                              <span className="column-1 ml15 operationright mt4">
+                                                  <div className="ColorF68">{i.score}</div>
+                                              </span>
+
+                                              </span>
+                                              </div>
+                                                  {/* 修改start*/}
+                                                  <div className="ListTableLine newSystem" id="EvaluationsList">
+                                                      <div style={{display:parseInt(target_id)===item.target_id&&item.target_evaluate_data.length-1===k?"block":"none"}} >
+                                                          <div className="edu-back-white eacourse" id="SystemParametersbottom" style={{display:parseInt(target_id)===item.target_id&&item.target_evaluate_data.length-1===k?"block":"none"}}>
+                                                              <div className="padding20-30" id="SystemParameters" style={{paddingLeft:'0px'}}>
+                                                                  {/* <span className="fl SystemParameters">课程目标{sequenceid}:{ec_course_target_name}</span> */}
+                                                                  <span className="fl SystemParameters">课程目标{key+1}:{ec_course_target_name}</span>
+                                                              </div>
+                                                          </div>
+                                                          {
+                                                              achievement_methods===undefined?" ":achievement_methods.map((item,itemkey)=>{
+                                                        
+                                                                  return(
+                                                                      <div key={itemkey} className="clearfix editorModify"  >
+                                                                          <div className="">
+                                                                              <span className="column-1 mr12" style={{
+                                                                                    paddingLeft: '0px'
+                                                                              }}>评价环节</span>
+                                                                              <Select
+                                                                                  className={item.course_select_value===undefined&&eacoursesavetypes===true?Modallists==='提交失败,评价环节不能为空'?"inputWeight  bor-red":"inputWeight": "inputWeight"}
+
+                                                                                  placeholder="请选择该目标的评价环节"
+                                                                                  size="large"
+                                                                                  style={{ width: '20%' }}
+                                                                                  value={item.course_select_value}
+                                                                                  onChange={this.handleevaluations_list.bind(this)}
+                                                                              >
+                                                                                  {evaluations_list.map(province => <Option value={province} key={itemkey}>{province}</Option>)}
+
+                                                                              </Select>
+
+                                                                              <span className="column-1 mr13"></span>
+
+                                                                              <Select
+                                                                                  mode="multiple"
+                                                                                  className={item.selectevaluation_phase===undefined&&eacoursesavetypes===true?Modallists==='提交失败,支撑项内容不能为空'?"inputWeight bor-red":"inputWeight": "inputWeight"}
+
+                                                                                  placeholder="请选择具体支撑项"
+                                                                                  size="large"
+                                                                                  id="Coursemultiple"
+                                                                                  style={{ width: '37%' }}
+                                                                                  onChange={this.handevaluation_subitems_list.bind(this)}
+                                                                                  onDeselect={this.handevaluation_Addlist.bind(this)}
+                                                                                  value={item.selectevaluation_phase}
+                                                                                  onFocus={()=>this.selectsonFocuslist(item,itemkey)}
+                                                                              >
+                                                                                  {evaluations_lists.map(city => <Option value={city} key={itemkey}>{city}</Option>)}
+                                                                              </Select>
+
+                                                                              <span className="column-1 mr14"></span>
+                                                                              <Input size="large"  type="number"
+                                                                                     value={item.score}
+                                                                                     className={item.score===undefined&&eacoursesavetypes===true?Modallists==='提交失败,支撑分数不能为空'?"bor-red": "": ""}
+                                                                                     onInput={this.handevaluation_CourseScore.bind(this)} id={itemkey} style={{ width: '11%' }} placeholder="请输入支撑分数"/>
+                                                                              <span className="column-1 ml5 mr10">分</span>
+                                                                              <Input size="large" type="number"
+                                                                                     value={item.percentage}
+                                                                                     className={item.percentage===undefined&&eacoursesavetypes===true||item.percentage>100&&eacoursesavetypes===true||percentagetype===true?"bor-red": ""}
+                                                                                     onInput={this.handevaluation_CoursePercentag.bind(this)}
+                                                                                     id={itemkey} style={{ width: '11%' }}
+                                                                                     placeholder="请输入占比"/>
+                                                                              <span className="column-1 ml5 mr10">%</span>
+                                                                              <span className="buttoninline SetTheAssociated" style={{marginLeft:'10px'}}>
+                                                                                    <div className="left operatebutton" style={{display:ismanager===false?'none':'block'}}>
+                                                                                        <a className="mr15 delSubentry" style={{display:achievement_methods.length===1?'none':'inline-block'}}>
+                                                                                            <Tooltip placement="bottom" title="删除">
+                                                                                                <i className="iconfont icon-shanchu color-grey-c  font-17" index={itemkey} onClick={this.Delethandevaluation.bind(this)}></i>
+                                                                                            </Tooltip>
+                                                                                        </a>
+                                                                                        <a className="newAddSubentry" data-tip-down="添加"
+                                                                                           style={{ display:itemkey===achievement_methods.length-1?'inline-block':'none'}}
+                                                                                        ><i className="iconfont icon-tianjiafangda color-green" index={itemkey} onClick={this.Addhandevaluation.bind(this)}></i></a>
+                                                                                    </div>
+                                                                            </span>
+                                                                          </div>
+                                                                          <br />
+                                                                      </div>
+                                                                  )
+                                                              })
+                                                          }
+                                                          <span className="c_red none ml30" id="error_tip" style={{display:meweacoursetype===true?'inline-block':'none'}}>{Modallists}</span>
+                                                          <div className="right editglybuttonbox mb10" id="ecCourseEvaluationsbottomsubmit"  style={{display:parseInt(target_id)===item.target_id?"block":"none"}}>
+                                                              <div className="defalutSubmitbtn fr" onClick={buttomSaveCourseEvaluationsbottom}>保存</div>
+                                                              <div className="defalutCancelbtn fr mr20" onClick={this.CancelecCourseEvaluationsbottom}>取消</div>
+                                                          </div>
+                                                      </div>
+                                                  </div>
+                                                  {/* 修改end*/}
+
+                                              </li>
+
+                                            )
+
+                                      })
+                                    }
+                            </div>
+                              )
+                            })
+                          }
+              </div>
+
+             </div>
+         </div>
+	    );
+  	}
+}
+
+export default SnackbarHOC() (EcCourseEvaluationsbottom);
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/subroute/ecStudentList/EcStudentList.js b/public/react/src/modules/ecs/subroute/ecStudentList/EcStudentList.js
new file mode 100644
index 000000000..312bfeecf
--- /dev/null
+++ b/public/react/src/modules/ecs/subroute/ecStudentList/EcStudentList.js
@@ -0,0 +1,405 @@
+import React, { Component } from 'react';
+
+import axios from 'axios';
+import { Spin } from 'antd';
+
+import { TPMIndexHOC } from '../../../tpm/TPMIndexHOC';
+
+import { SnackbarHOC,getImageUrl } from 'educoder'
+
+import { Pagination,Upload,Modal,Checkbox } from 'antd';
+
+import EcTitleCourseEvaluations from '../../ecTitle/ecTitle'
+
+import 'antd/dist/antd.css';
+
+import './ecStudentList.css';
+
+const $ = window.$;
+
+class EcStudentList extends Component {
+    constructor(props) {
+        super(props)
+        this.state={
+            majorschoollist:undefined,
+            titlemessage:"提示",
+            // ecComponentState:"ecStudentList",
+            visible:false,
+            Modallist:'',
+            Modallisttypes:0,
+            studentall:false,
+            student_id:undefined,
+            Modallisttypess:0,
+            ismanager:false,
+            isSpin:false
+        }
+    }
+    componentDidMount(){
+        window.document.title = '学生列表';
+        let major_id=this.props.match.params.major_id;
+        let year_id=this.props.match.params.year_id;
+
+        const url ='/ec_major_schools/'+major_id+'/academic_years/'+year_id+'/student_lists_data';
+            axios.get(url, {
+                withCredentials: true,
+            }).then((response) => {
+                if(response.status===200){
+                  this.setState({
+                      majorschoollist:response.data,
+                      ismanager:response.data.ismanager,
+                  })
+                }
+            })
+            .catch(function (error) {
+                console.log(error);
+            });
+            // let  majorschoollist={
+            //         ec_students: [{index: 1, student_name: "同意", student_id: "s20111458"},
+            //                         {index: 1, student_name: "同意", student_id: "s20111458"},
+            //                         {index: 2, student_name: "涛哥", student_id: "2011554f4"},
+            //                         {index: 3, student_name: "例如", student_id: "20154787b"},
+            //                         {index: 4, student_name: "问问", student_id: "201548580014"},
+            //                         {index: 5, student_name: "嗯嗯", student_id: "2015748912321234"},
+            //                         {index: 6, student_name: "让人", student_id: "20157456"},
+            //                         {index: 7, student_name: "方法", student_id: "20159658"},
+            //                         {index: 8, student_name: "全球", student_id: "20159632"},
+            //                         {index: 9, student_name: "是说", student_id: "20154512"},
+            //                         {index: 10, student_name: "谷歌", student_id: "20157932"},
+            //                         {index: 11, student_name: "版本", student_id: "20159635"},
+            //                         {index: 12, student_name: "捏捏", student_id: "20153451"},
+            //                         ],
+            //         import_url: "/ec_major_schools/3/academic_years/10/import_students",
+            //         show_name: true,
+            //         template_url: "/attachments/download/227528/01_学生列表导入模板.xls",
+            //         total_page: 1
+            //     }
+            // this.setState({
+            //     majorschoollist:majorschoollist
+            // })
+    }
+    uploadcomponentDidMount(){
+        let major_id=this.props.match.params.major_id;
+        let year_id=this.props.match.params.year_id;
+        const url ='/ec_major_schools/'+major_id+'/academic_years/'+year_id+'/student_lists_data';
+        axios.get(url, {
+            withCredentials: true,
+        }).then((response) => {
+            if(response.status===200){
+              this.setState({
+                  majorschoollist:response.data,
+                  ismanager:response.data.ismanager,
+              })
+            }
+        })
+        .catch(function (error) {
+            console.log(error);
+        });
+    }
+        
+
+    windowsgoblack=()=>{
+        window.history.go(-1)
+    }
+
+
+    uploadfile=(file)=>{
+        this.setState({isSpin:true})
+        let {majorschoollist}=this.state;
+        let Url =majorschoollist.import_url;
+        const form = new FormData();
+        form.append('file', file.file);
+        axios.post(Url,form
+        ).then((response) => {
+            if(response.data.status===1){
+                // message.success('已成功导入'+response.data.count+"条数据!");
+                this.setState({
+                    // titlemessage: response.data.message+"(支撑关系变更)",
+                    Modallist: '已成功导入'+response.data.count+"条数据!",
+                    Modallisttype:true,
+                    Modallisttypes:1,
+                    isSpin:false
+                })
+            }else if(response.data.status===0){
+                // message.warning(response.data.message);
+                this.setState({
+                    // titlemessage: response.data.message+"(支撑关系变更)",
+                    Modallist:response.data.message,
+                    Modallisttype:true,
+                    Modallisttypes:0,
+                    isSpin:false
+                })
+            }
+        }).catch((error) => {
+            console.log(error)
+        })
+    }
+    hidemodeldelete=()=>{
+        let {Modallisttypes}=this.state;
+        this.setState({
+            Modallisttype:false,
+            Modallist:'',
+            Modallisttypess:0
+        })
+        if(Modallisttypes===1){
+            // window.location.reload();
+            this.uploadcomponentDidMount();
+        }
+    }
+
+    showecStudentList=(page)=>{
+        let major_id=this.props.match.params.major_id;
+        let year_id=this.props.match.params.year_id;
+        const url ='/ec_major_schools/'+major_id+'/academic_years/'+year_id+'/student_lists_data?page='+page;
+        axios.get(url, {
+            withCredentials: true,
+        }).then((response) => {
+            if(response.status===200){
+                this.setState({
+                    majorschoollist:response.data,
+                    ismanager:response.data.ismanager,
+                })
+            }
+        }).catch(function (error) {
+                console.log(error);
+            });
+    }
+
+    onChangestudentall=(e)=>{
+        let {majorschoollist}=this.state;
+        let mewmajorschoollist=majorschoollist
+        for(var i=0; i<mewmajorschoollist.ec_students.length; i++){
+                mewmajorschoollist.ec_students[i].istrue=e.target.checked
+        }
+        this.setState({
+            studentall:e.target.checked,
+            majorschoollist:mewmajorschoollist
+           })
+    }
+
+    onChangestudent=(e)=>{
+        let {majorschoollist,studentall}=this.state;
+        let mewmajorschoollist=majorschoollist;
+        let newstudentall=studentall;
+        if(e.target.checked===false){
+            newstudentall=false
+        }
+        for(var i=0; i<mewmajorschoollist.ec_students.length; i++){
+            if(i===e.target.index&&e.target.id===mewmajorschoollist.ec_students[i].student_id){
+                mewmajorschoollist.ec_students[i].istrue=e.target.checked
+            }
+        }
+       this.setState({
+         student_id:e.target.id,
+         majorschoollist:mewmajorschoollist,
+         studentall:newstudentall
+       })
+    }
+
+    deletelistbth=()=>{
+        let {majorschoollist,studentall} =this.state;
+        let studentalltype=0
+        for(var i=0; i<majorschoollist.ec_students.length; i++){
+            if(majorschoollist.ec_students[i].istrue===true){
+                studentalltype=1
+            }
+        }
+        if(studentall===true||studentalltype===1){
+            this.setState({
+                Modallist: '确定删除这些学生吗?',
+                Modallisttype:true,
+                Modallisttypess:1
+            })    
+        }else{
+            this.setState({
+                Modallist: '请选择学生!',
+                Modallisttype:true
+            })     
+        }
+    }
+    deletelistbthenters=()=>{
+        let {majorschoollist,studentall} =this.state;
+        let major_id=this.props.match.params.major_id;
+        let year_id=this.props.match.params.year_id;
+        let newstudent_id=[];
+        if(studentall===false){
+            for(var i=0; i<majorschoollist.ec_students.length; i++){
+                if(majorschoollist.ec_students[i].istrue===true){
+                    newstudent_id.push(majorschoollist.ec_students[i].student_id)
+                }
+            }
+        }
+        let url ='/ec_major_schools/'+major_id+'/academic_years/'+year_id+'/destroy_students'
+        axios.delete(url,{data:{
+                all:studentall,
+                student_ids:newstudent_id,
+            }}).then((response) => {
+            if(response.data.status===1){
+               this.setState({
+                    // Modallist: "删除成功!",
+                    // Modallisttype:true,
+                    Modallisttypes:1,
+                    Modallisttypess:0
+               })
+               this.hidemodeldelete();
+            }
+        }).catch((error) => {
+            console.log(error)
+        })
+    }
+
+    render() {
+        let {
+            majorschoollist,
+            Modallisttype,
+            titlemessage,
+            Modallist,
+            studentall,
+            student_id,
+            Modallisttypess,
+            ismanager
+        }=this.state;
+        // ec_students: []
+        // import_url: "/ec_major_schools/:1/academic_years/:1/import_students"
+        // template_url: "javascript:void(0);"
+        // total_page: 0
+        const uploadProps = {
+            name: 'file',
+
+            onPreview(file) {
+                // dispatch({ type: `${nameSpace}/updateState`, payload: { uploadPreviewVisible: true, uploadPreviewImage: file.url || file.thumbUrl } });
+            },
+            onChange(file) {
+                // dispatch({ type: `${nameSpace}/updateState`, payload: { fileList: fileList } });
+            },
+            onRemove(option) {
+            },
+            customRequest: file => {
+                this.uploadfile(file)
+            }
+        }
+        return (
+           <div className="newMain clearfix">
+                <Modal
+                    title={titlemessage}
+                    // visible={modeldelet===true&&listid===list.id?true:false}
+                    visible={Modallisttype}
+                    className={"ecmodeldelet"}
+                    closable={false}
+                    footer={null}
+                >
+                    <div className="task-popup-content">
+                        <div className="task-popup-text-center font-14">{Modallist}</div>
+                    </div>
+                    <div className="task-popup-submit clearfix">
+                        <a onClick={this.hidemodeldelete} className="task-btn fl">取消</a>
+                        {
+                            Modallisttypess===0?<a className="task-btn task-btn-orange fr"
+                            onClick={this.hidemodeldelete}
+                            >确定</a>:<a className="task-btn task-btn-orange fr"
+                                onClick={this.deletelistbthenters}
+                            >确定</a>
+                        }
+
+                    </div>
+                </Modal>
+                <div className="educontent mb290">
+                   <div className="clearfix padding20-30 bor-bottom-greyE mb10 edu-back-white">
+                        <span className="fl font-18 courseSystem ">学生列表</span>
+                        <a className="fr font-15 courseSystem" onClick={this.windowsgoblack}>返回</a>
+                    </div>
+
+                    <div className="edu-back-white eacourse">
+
+                        <div className="clearfix padding20-30 bor-bottom-greyE"><span
+                            className=" font-18 courseSystem">学生列表(
+                            {majorschoollist===undefined?"":majorschoollist.total_student}
+                            )</span>
+                            <div className="color-grey-9 mr10">提供模板支持导入学生信息(请先下载模板)  <a className={"color-blue"} onClick={() => window.elasticLayer(3533)}>查看详情</a></div>
+                        </div>
+
+                        <div className="padding20-30 padbottom" id="training_objective_contents">
+                        {ismanager===false?"":
+                        <span className="mr30">请使用导入模板(<a href={majorschoollist===undefined?"":majorschoollist.template_url} className="color-green"><i className="iconfont icon-fujian mr5 color-green font-16"></i>点击下载</a>),将本学年所有参与的学生导入系统,以便录入教学活动相关数据</span>
+                        }
+                            <a className="white-btn edu-orangeback-btn fr mr10" >
+                            {ismanager===false?"":<Upload
+                                {...uploadProps}
+                                showUploadList={false}
+                                style={{color:'#fff'}}
+                            >
+                                导入 
+                            </Upload>}
+                            </a>
+                        </div>
+
+                        <div  id="training_objective_contents" className='deletelist' >
+                            {ismanager===false?"":<div className="white-btn deletebth ml30 mr10" onClick={this.deletelistbth}>
+                                删除
+                            </div>}
+                        </div>
+                        <Spin spinning={this.state.isSpin}>
+                            <div className="ListTableLine minH-560 edu-back-white mb80" id="listContent">
+                            <p className="clearfix">
+                                <span className="column-No column-2 relative">
+                                <Checkbox 
+                                    className={'mr20 changestudent'}
+                                    checked={studentall===true?true:false}
+                                    onChange={this.onChangestudentall}></Checkbox>
+                                序号
+                                </span>
+                                <span className="column-2" style={{display:majorschoollist===undefined?"":majorschoollist.show_name===false?"none":'inline-block'}}>姓名</span>
+                                <span className="column-2">学号</span>
+                            </p>
+
+
+                            <ul>
+                                {
+                                    majorschoollist===undefined?
+                                    <div className="edu-txt-center color-grey-9 pt50">
+                                        <p className="mb20"><img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")} /></p>
+                                        <p>学生数据为空,请导入数据</p>
+                                    </div>
+                                    :majorschoollist.ec_students.length===0?
+                                    <div className="edu-txt-center color-grey-9 pt50">
+                                        <p className="mb20"><img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/></p>
+                                        <p>学生数据为空,请导入数据</p>
+                                    </div>:majorschoollist.ec_students.map((item,key)=>{
+                                        // console.log(item)
+                                            return(
+                                                <li className="clearfix" key={key}>
+                                                    <span className="column-No column-2 relative">
+                                                    <Checkbox 
+                                                    className={'mr20 changestudents'}
+                                                    checked={item.istrue===true?true:false}
+                                                    key={key}
+                                                    index={key}
+                                                    onChange={this.onChangestudent} id={item.student_id}></Checkbox>
+                                                    {item.index}
+                                                    </span>
+                                                    <span className="column-2"  style={{display:majorschoollist===undefined?"none":majorschoollist.show_name===false?"none":'inline-block'}}>{item.student_name}</span>
+                                                    <span className="column-2">{item.student_id}</span>
+                                                </li>
+                                            )
+                                    })
+                                }
+
+                            </ul>
+
+                            <div style={{width:'100%',position: 'relative'}}>
+                            {
+                                majorschoollist===undefined?"":majorschoollist.total_page===0||majorschoollist.total_student<51?"": <Pagination size="small" className={"pagelistStudentList mt30"} pageSize={50} showQuickJumper defaultCurrent={1} total={majorschoollist.total_student} onChange={this.showecStudentList} />
+                            }     
+                            </div>
+                        </div>
+                        </Spin>    
+                    </div>
+                </div>
+
+            </div>
+
+        )
+
+    }
+}
+
+export default SnackbarHOC() (EcStudentList);
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/subroute/ecStudentList/ecStudentList.css b/public/react/src/modules/ecs/subroute/ecStudentList/ecStudentList.css
new file mode 100644
index 000000000..0dfc22b99
--- /dev/null
+++ b/public/react/src/modules/ecs/subroute/ecStudentList/ecStudentList.css
@@ -0,0 +1,44 @@
+.pagelistStudentList{
+    position: absolute;
+    padding-left: 40%;
+}
+
+.relative{
+    position: relative;
+}
+.changestudent{
+    position: absolute;
+    top: 13px;
+    left: 50px;
+}
+.changestudents{
+    position: absolute;
+    top: -1px;
+    left: 50px;
+}
+.padbottom{
+    padding-bottom: 0px;
+}
+
+.deletelist{
+    margin-top: 10px;
+    margin-bottom: 10px;
+}
+
+.deletelist:hover{
+    color:#afafaf !important;
+}
+
+.deletebth{
+    width:64px;
+    height:24px;
+    border:1px solid #afafaf;
+    border-radius:2px;
+    color:#afafaf;
+    background:#fff;
+    line-height:24px;
+}
+
+.mt60{
+    margin-top:60px;
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/subroute/ecStudentList/nodata.png b/public/react/src/modules/ecs/subroute/ecStudentList/nodata.png
new file mode 100644
index 000000000..15a9e522f
Binary files /dev/null and b/public/react/src/modules/ecs/subroute/ecStudentList/nodata.png differ
diff --git a/public/react/src/modules/help/Help.js b/public/react/src/modules/help/Help.js
index f04079bcc..f148dd373 100644
--- a/public/react/src/modules/help/Help.js
+++ b/public/react/src/modules/help/Help.js
@@ -26,7 +26,6 @@ class Help extends React.Component {
   }
 
   componentDidUpdate(prevProps) {
-    console.log('update', prevProps, this.props);
     if(prevProps.match.params.type !== this.props.match.params.type){
       this.setState({ type: this.props.match.params.type });
     }