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/graduation_course_supports_controller.rb b/app/controllers/ecs/graduation_course_supports_controller.rb index 2a6d59024..c70121a0d 100644 --- a/app/controllers/ecs/graduation_course_supports_controller.rb +++ b/app/controllers/ecs/graduation_course_supports_controller.rb @@ -3,6 +3,7 @@ class Ecs::GraduationCourseSupportsController < Ecs::BaseController def show @graduation_subitems = current_year.ec_graduation_subitems + .reorder('ec_graduation_requirements.position ASC, ec_graduation_subitems.position ASC') .includes(:ec_graduation_requirement, ec_course_supports: :ec_course) @course_count = current_year.ec_courses.count diff --git a/app/controllers/ecs/graduation_subitems_controller.rb b/app/controllers/ecs/graduation_subitems_controller.rb new file mode 100644 index 000000000..03cf379bb --- /dev/null +++ b/app/controllers/ecs/graduation_subitems_controller.rb @@ -0,0 +1,6 @@ +class Ecs::GraduationSubitemsController < Ecs::BaseController + def index + subitems = current_year.ec_graduation_subitems.reorder('ec_graduation_requirements.position ASC, ec_graduation_subitems.position ASC') + @graduation_subitems = subitems.includes(:ec_graduation_requirement) + end +end \ No newline at end of file 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/student_works_controller.rb b/app/controllers/student_works_controller.rb index ab62cbd45..2612510c5 100644 --- a/app/controllers/student_works_controller.rb +++ b/app/controllers/student_works_controller.rb @@ -321,11 +321,12 @@ class StudentWorksController < ApplicationController ActiveRecord::Base.transaction do begin - revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last - if revise_attachment.present? && @work.student_works_scores.where("created_at > '#{revise_attachment.created_on}' - and score is not null").count == 0 - revise_attachment.destroy - end + # 补交作业附件不覆盖之前上传的附件 + # revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last + # if revise_attachment.present? && @work.student_works_scores.where("created_at > '#{revise_attachment.created_on}' + # and score is not null").count == 0 + # revise_attachment.destroy + # end Attachment.associate_container(params[:attachment_ids], @work.id, @work.class, 7) revise_attachment = Attachment.where(attachtype: 7, container_id: @work.id, container_type: "StudentWork").last revise_attachment.update_attributes(description: params[:description]) if revise_attachment.present? 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/jobs/apply_teacher_role_join_course_notify_job.rb b/app/jobs/apply_teacher_role_join_course_notify_job.rb index 3ae5e32db..ab5a9e354 100644 --- a/app/jobs/apply_teacher_role_join_course_notify_job.rb +++ b/app/jobs/apply_teacher_role_join_course_notify_job.rb @@ -8,7 +8,7 @@ class ApplyTeacherRoleJoinCourseNotifyJob < ApplicationJob return if user.blank? || course.blank? attrs = %i[user_id trigger_user_id container_id container_type belong_container_id - belong_container_type tiding_type extra created_at updated_at] + belong_container_type tiding_type status extra created_at updated_at] same_attrs = { trigger_user_id: user.id, container_id: course.id, container_type: 'JoinCourse', status: 0, 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/course_message.rb b/app/models/course_message.rb index 7774dbf0c..a3578d500 100644 --- a/app/models/course_message.rb +++ b/app/models/course_message.rb @@ -32,6 +32,6 @@ class CourseMessage < ApplicationRecord belong_container: course, extra: content.to_i == 2 ? '9' : '7', tiding_type: 'System', status: deal_status ) # 将申请消息置为已处理 - Tiding.where(trigger_user_id: user_id, container_id: course_id, container_type: 'JoinCourse', status: 0).update_all(status: 1) + Tiding.where(trigger_user_id: course_message_id, container_id: course_id, container_type: 'JoinCourse', status: 0).update_all(status: 1) end end \ No newline at end of file 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/models/student_graduation_topic.rb b/app/models/student_graduation_topic.rb index 50f150f92..b8f4dfbbb 100644 --- a/app/models/student_graduation_topic.rb +++ b/app/models/student_graduation_topic.rb @@ -21,7 +21,7 @@ class StudentGraduationTopic < ApplicationRecord def send_tiding self.tidings << Tiding.new(:user_id => self.graduation_topic.tea_id, :trigger_user_id => self.user_id, :parent_container_id => self.graduation_topic_id, :parent_container_type => "GraduationTopic", - :belong_container_id => self.graduation_topic.course_id, :belong_container_type => "Course", :viewed => 0, :status => 0, :tiding_type => "GraduationTopic") + :belong_container_id => self.graduation_topic.course_id, :belong_container_type => "Course", :viewed => 0, :status => 0, :tiding_type => "Apply") 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..ced8a5c72 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 @@ -2,4 +2,5 @@ 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.course_supports ec_graduation_subitem.ec_course_supports, partial: 'ecs/graduation_course_supports/shared/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/graduation_subitems/index.json.jbuilder b/app/views/ecs/graduation_subitems/index.json.jbuilder new file mode 100644 index 000000000..0a1235b1d --- /dev/null +++ b/app/views/ecs/graduation_subitems/index.json.jbuilder @@ -0,0 +1,8 @@ +json.graduation_subitems do + json.array! @graduation_subitems do |graduation_subitem| + json.extract! graduation_subitem, :id, :position, :content + json.graduation_requirement_position graduation_subitem.ec_graduation_requirement.position + end +end + +json.count @graduation_subitems.size \ No newline at end of file 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..1647101ea 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 @@ -736,6 +737,7 @@ Rails.application.routes.draw do resource :graduation_course_supports, only: [:show, :create] resource :reach_evaluation, only: [:show, :create] resource :reach_criteria, only: [:create] + resources :graduation_subitems, only: [:index] end resources :ec_courses, only: [] 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)=>() }/> + () + }/> diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index 0eb6b50cd..025db7f5c 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 { @@ -38,18 +38,13 @@ export function initAxiosInterceptors(props) { // https://github.com/axios/axios/issues/1497 // TODO 读取到package.json中的配置? - var proxy = "http://localhost:3000"; - // proxy = "http://testbdweb.trustie.net" - // proxy = "http://testbdweb.educoder.net" - // proxy = "https://testeduplus2.educoder.net" - proxy="http://47.96.87.25:48080"; - // wy - proxy="https://pre-newweb.educoder.net"; - proxy="https://test-newweb.educoder.net" - - // wy - // proxy="http://192.168.2.63:3001" - + var proxy = "http://localhost:3000" + // proxy = "http://testbdweb.trustie.net" + // proxy = "http://testbdweb.educoder.net" + // proxy = "https://testeduplus2.educoder.net" + //proxy="http://47.96.87.25:48080" + proxy="https://pre-newweb.educoder.net" + proxy="https://test-newweb.educoder.net" // 在这里使用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/courses/busyWork/CommonWorkAppraise.js b/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js index dc82de540..f41528657 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js @@ -248,7 +248,9 @@ class CommonWorkAppraise extends Component{ } - + {is_evaluation != true && project_info && project_info.name &&
diff --git a/public/react/src/modules/courses/busyWork/CommonWorkAppraiseReviseAttachments.js b/public/react/src/modules/courses/busyWork/CommonWorkAppraiseReviseAttachments.js index d12099d38..b487af487 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkAppraiseReviseAttachments.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkAppraiseReviseAttachments.js @@ -33,7 +33,7 @@ function CommonWorkAppraiseReviseAttachments(props) { {item.title} {item.filesize} - {item.delete===true?:""} + {item.delete===true?:""}
) })} diff --git a/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js b/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js index 60065f43e..6fdde6aeb 100644 --- a/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js +++ b/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js @@ -22,7 +22,7 @@ import 'moment/locale/zh-cn'; import './yslexercisetable.css'; import {getImageUrl, toPath} from 'educoder'; import CheckBoxGroup from "../../page/component/CheckBoxGroup"; - +import NoneData from '../../../modules/courses/coursesPublic/NoneData' const Search = Input.Search; const RadioGroup = Radio.Group; const CheckboxGroup = Checkbox.Group; @@ -1217,6 +1217,7 @@ class Studentshavecompletedthelist extends Component { ) }, ], + exercise_status:0, } // console.log("Studentshavecompletedthelist"); // console.log(props.current_status); @@ -1277,6 +1278,20 @@ class Studentshavecompletedthelist extends Component { }catch (e) { } + try { + if(this.props.Commonheadofthetestpaper.exercise_status !== undefined){ + this.setState({ + exercise_status:this.props.Commonheadofthetestpaper.exercise_status, + }) + }else{ + this.setState({ + exercise_status:0, + }) + } + }catch (e) { + + } + } componentWillReceiveProps = (nextProps) => { @@ -2065,11 +2080,11 @@ class Studentshavecompletedthelist extends Component { this.setState({ loadingstate: false, }) - console.log(response); - console.log(1997); + // console.log(response); + // console.log(1997); this.Generatenewdatasy(response.data.exercise_users, response); }).catch((error) => { - console.log(error) + // console.log(error) this.setState({ loadingstate: false, }) @@ -2472,7 +2487,7 @@ class Studentshavecompletedthelist extends Component { render() { const isAdmin = this.props.isAdmin(); - let {data, datas, page, columns, course_groupyslsthree, columnstwo, styletable, course_groupyslstwodatas, limit, course_groupysls, course_groupyslstwodata, course_groupyslstwo, teacherlists, Teacherliststudentlist, order, columnss, course_groupsdatas, course_groups, Evaluationarray, unlimited, unlimiteds, unlimitedtwo, teacherlist, searchtext, loadingstate, review, nocomment, commented, unsubmitted, submitted, columnsys, exercise_users,mylistansum} = this.state; + let {data, datas, page, columns, course_groupyslsthree, columnstwo, styletable,exercise_status, course_groupyslstwodatas, limit, course_groupysls, course_groupyslstwodata, course_groupyslstwo, teacherlists, Teacherliststudentlist, order, columnss, course_groupsdatas, course_groups, Evaluationarray, unlimited, unlimiteds, unlimitedtwo, teacherlist, searchtext, loadingstate, review, nocomment, commented, unsubmitted, submitted, columnsys, exercise_users,mylistansum} = this.state; // console.log("Studentshavecompletedthelist"); // console.log(this.props.current_status); return ( @@ -2483,202 +2498,211 @@ class Studentshavecompletedthelist extends Component { " min-width": " 1200px", }}> {/*老师*/} -
-
    + { + exercise_status===0 || exercise_status===1 ? +
    + +
    + : +
    +
    +
      - {/*你的评阅:*/} - { - Teacherliststudentlist === undefined || Teacherliststudentlist.exercise_types.subjective === 0 ? -
    • - 作品状态: - this.notlimiteds()}>不限 - this.checkeboxstwo(e, course_groupyslstwodata && course_groupyslstwodata)}> - { - course_groupyslstwodata.map((item, key) => { - return ( - {item.tu}({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unanswer_users : Teacherliststudentlist.exercise_types.answer_users}) - ) - }) - } - -
      - this.onSearchKeywordKeyUp(e)} - onInput={this.inputSearchValues} - onSearch={this.searchValues} - > -
      -
    • - : -
      -
    • - 你的评阅: - this.notlimited()}>不限 - - this.checkeboxs(e, course_groupyslstwodata && course_groupyslstwodata)}> - { - course_groupyslstwodatas.map((item, key) => { - return ( - {item.tu}({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unreview_counts : Teacherliststudentlist.exercise_types.review_counts}) - ) - }) - } - -
      - this.onSearchKeywordKeyUp(e)} - onInput={this.inputSearchValues} - onSearch={this.searchValues} - > -
      -
    • - {/*作品状态*/} -
    • - 作品状态: - this.notlimiteds()}>不限 - this.checkeboxstwo(e, course_groupyslstwodata && course_groupyslstwodata)}> - { - course_groupyslstwodata.map((item, key) => { - return ( - {item.tu}({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unanswer_users : Teacherliststudentlist.exercise_types.answer_users}) - ) - }) - } - -
    • -
      + {/*你的评阅:*/} + { + Teacherliststudentlist === undefined || Teacherliststudentlist.exercise_types.subjective === 0 ? +
    • + 作品状态: + this.notlimiteds()}>不限 + this.checkeboxstwo(e, course_groupyslstwodata && course_groupyslstwodata)}> + { + course_groupyslstwodata.map((item, key) => { + return ( + {item.tu}({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unanswer_users : Teacherliststudentlist.exercise_types.answer_users}) + ) + }) + } + +
      + this.onSearchKeywordKeyUp(e)} + onInput={this.inputSearchValues} + onSearch={this.searchValues} + > +
      +
    • + : +
      +
    • + 你的评阅: + this.notlimited()}>不限 + + this.checkeboxs(e, course_groupyslstwodata && course_groupyslstwodata)}> + { + course_groupyslstwodatas.map((item, key) => { + return ( + {item.tu}({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unreview_counts : Teacherliststudentlist.exercise_types.review_counts}) + ) + }) + } + +
      + this.onSearchKeywordKeyUp(e)} + onInput={this.inputSearchValues} + onSearch={this.searchValues} + > +
      +
    • + {/*作品状态*/} +
    • + 作品状态: + this.notlimiteds()}>不限 + this.checkeboxstwo(e, course_groupyslstwodata && course_groupyslstwodata)}> + { + course_groupyslstwodata.map((item, key) => { + return ( + {item.tu}({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unanswer_users : Teacherliststudentlist.exercise_types.answer_users}) + ) + }) + } + +
    • +
      - } - {/*分班情况*/} - {course_groups === undefined ? "" : course_groups === null ? "" : course_groups.length < 2 ? "" : JSON.stringify(course_groups) === "[]" ? "" : -
    • - - 分班情况: - this.funtaskstatustwos()}>不限 - - - this.funtaskstatustwo(e, course_groups && course_groups)} - style={{paddingTop: '4px', display: "inline"}}> - { - course_groups.map((item, key) => { - return ( - {item.exercise_group_name}({item.exercise_group_students}) - ) - }) - } - + } + {/*分班情况*/} + {course_groups === undefined ? "" : course_groups === null ? "" : course_groups.length < 2 ? "" : JSON.stringify(course_groups) === "[]" ? "" : +
    • + + 分班情况: + this.funtaskstatustwos()}>不限 + + + this.funtaskstatustwo(e, course_groups && course_groups)} + style={{paddingTop: '4px', display: "inline"}}> + { + course_groups.map((item, key) => { + return ( + {item.exercise_group_name}({item.exercise_group_students}) + ) + }) + } + - - + + -
    • - } + + } -
    +
- - {JSON.stringify(data) !== "[]" ? -
- -
- {data === undefined ? "" : } - - +
+ {data === undefined ? "" :
} + + - : -
-
-
- -

暂时还没有相关数据哦!

-
-
+ : +
+
+
+ +

暂时还没有相关数据哦!

+
+
-
- } +
+ } - - { - Teacherliststudentlist && Teacherliststudentlist.exercise_types.total_users && Teacherliststudentlist.exercise_types.total_users > limit ? -
- +
+ { + Teacherliststudentlist && Teacherliststudentlist.exercise_types.total_users && Teacherliststudentlist.exercise_types.total_users > limit ? +
+ +
+ : "" + } - : "" } @@ -2691,16 +2715,22 @@ class Studentshavecompletedthelist extends Component {
-
+ { + exercise_status === 0 || exercise_status === 1 ? +
+ +
+ : +
-
+
-
+
{Teacherliststudentlist === undefined ? "0" : Teacherliststudentlist.exercise_types.answer_users}} -
+
-
+
- {JSON.stringify(datas) === "[]" ? -
-
-
- -

暂时还没有相关数据哦!

-
-
+ {JSON.stringify(datas) === "[]" ? +
+
+
+ +

暂时还没有相关数据哦!

+
+
-
- : -
- -
- {datas === undefined ? "" :
} - - - } - +
+ {datas === undefined ? "" :
} + + + } - + + } @@ -2766,10 +2796,17 @@ class Studentshavecompletedthelist extends Component { "padding-bottom": "100px", " min-width": " 1200px" }}> -
- -
- {data === undefined ? "" :
} - - {JSON.stringify(datas) === "[]" ? - -
-
-
- -

暂时还没有相关数据哦!

+ } + +
+ {data === undefined ? "" :
} - + {JSON.stringify(datas) === "[]" ? - - : -
- < div id="graduation_work_list" style={{ - padding: '0px 30px 10px 30px', - "margin-top": "20px", - "margin-bottom": "10px" - }}> +
+
+
+ +

暂时还没有相关数据哦!

+
+
-
+
+ : +
+ < div id="graduation_work_list" style={{ + padding: '0px 30px 10px 30px', + "margin-top": "20px", + "margin-bottom": "10px" + }}> + + - -
-
- -
- {datas === undefined ? "" :
} - +
+ {datas === undefined ? "" :
} + - + - } - + } + - { - mylistansum && mylistansum > limit ? -
- + { + mylistansum && mylistansum > limit ? +
+ +
+ : "" + }
- : "" } diff --git a/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js b/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js index 5775bd240..ba3cee3d3 100644 --- a/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js +++ b/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js @@ -436,7 +436,7 @@ class Testpapersettinghomepage extends Component{ /> { // 教师列表 - parseInt(tab[0])==0 && this.setcourse_groupysls(value)} current_status = {this.state.current_status}> + parseInt(tab[0])==0 && this.setcourse_groupysls(value)} current_status = {this.state.current_status} Commonheadofthetestpaper={this.state.Commonheadofthetestpaper}> } {/*统计结果*/} diff --git a/public/react/src/modules/courses/gradinforms/Eduinforms.js b/public/react/src/modules/courses/gradinforms/Eduinforms.js index f52471094..38190afaf 100644 --- a/public/react/src/modules/courses/gradinforms/Eduinforms.js +++ b/public/react/src/modules/courses/gradinforms/Eduinforms.js @@ -45,12 +45,12 @@ class Eduinforms extends Component{ this.setState({ dataquerys:{}, }); - return + }else { + this.setState({ + dataquerys:foqus, + }); + dataqueryss=foqus; } - this.setState({ - dataquerys:foqus, - }); - dataqueryss=foqus; }catch (e) { this.setState({ dataquerys:{}, diff --git a/public/react/src/modules/courses/graduation/tasks/GraduationTasksSubmitedit.js b/public/react/src/modules/courses/graduation/tasks/GraduationTasksSubmitedit.js index 35d9cdad2..41768333a 100644 --- a/public/react/src/modules/courses/graduation/tasks/GraduationTasksSubmitedit.js +++ b/public/react/src/modules/courses/graduation/tasks/GraduationTasksSubmitedit.js @@ -389,7 +389,7 @@ class GraduationTasksSubmitedit extends Component{ let listid=[]; for(var list of fileList){ - listid.push(list.response.id) + listid.push(list.response == undefined ? list.id : list.response.id) } this.props.form.validateFields((err, values) => { diff --git a/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js b/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js index 7aac55b20..a5423b6e9 100644 --- a/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js +++ b/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js @@ -33,6 +33,8 @@ import Startshixuntask from "../coursesPublic/Startshixuntask"; import ModulationModal from "../coursesPublic/ModulationModal"; import HomeworkModal from "../coursesPublic/HomeworkModal"; import ShixunWorkModal from "./Shixunworkdetails/ShixunWorkModal"; +import NoneData from '../../../modules/courses/coursesPublic/NoneData' + const Search = Input.Search; const RadioGroup = Radio.Group; const CheckboxGroup = Checkbox.Group; @@ -1451,13 +1453,14 @@ class Listofworksstudentone extends Component { ], yslpros:false, datajs:[], + homework_status:[], } } componentDidCatch(error, info){ - console.log("-----------------------------905错误信息"); - console.log(error); - console.log(info); + // console.log("-----------------------------905错误信息"); + // console.log(error); + // console.log(info); } // componentWillReceiveProps(nextProps) { @@ -1569,7 +1572,8 @@ class Listofworksstudentone extends Component { allow_late:result.data.allow_late, loadingstate: false, computeTimetype:true, - }) + homework_status:result.data.homework_status, + }); this.seacthdatat(result.data,result.data.student_works,result.data.work_efficiency,result.data.course_group_info,1); if (result.data.student_works === undefined || result.data.student_works === null || JSON.stringify(result.data.student_works) === "[]") { @@ -1626,7 +1630,8 @@ class Listofworksstudentone extends Component { code_review: result.data.code_review, challenges_count:result.data.challenges_count, view_report:result.data.view_report, - }) + homework_status:result.data.homework_status, + }); if (result.data.student_works === undefined || result.data.student_works === null || JSON.stringify(result.data.student_works) === "[]") { this.seacthdata(result.data); } else { @@ -2129,7 +2134,8 @@ class Listofworksstudentone extends Component { code_review: result.data.code_review, challenges_count:result.data.challenges_count, view_report:result.data.view_report, - }) + homework_status:result.data.homework_status, + }); this.seacthdata(result.data); this.props.Getdataback(result,result.data); } @@ -2242,7 +2248,8 @@ class Listofworksstudentone extends Component { end_immediately: result.data.end_immediately, code_review: result.data.code_review, challenges_count:result.data.challenges_count, - }) + homework_status:result.data.homework_status, + }); this.seacthdatat(result.data,result.data.student_works,result.data.work_efficiency,result.data.course_group_info,page); this.props.Getdataback(result,result.data); // } @@ -3037,7 +3044,7 @@ class Listofworksstudentone extends Component { }) } render() { - let {columns,course_groupysls,datajs,isAdmin, course_groupyslstwo, unlimited, unlimitedtwo, course_group_info, orders, task_status, checkedValuesine, searchtext, teacherlist, visible,visibles, game_list,columnsstu,columnsstu2, limit,experience, boolgalist,viewtrainingdata, teacherdata, page, data, jobsettingsdata, styletable, datas, order, loadingstate,computeTimetype} = this.state; + let {columns,course_groupysls,datajs,isAdmin,homework_status, course_groupyslstwo, unlimited, unlimitedtwo, course_group_info, orders, task_status, checkedValuesine, searchtext, teacherlist, visible,visibles, game_list,columnsstu,columnsstu2, limit,experience, boolgalist,viewtrainingdata, teacherdata, page, data, jobsettingsdata, styletable, datas, order, loadingstate,computeTimetype} = this.state; const antIcon = ; // console.log(this.state.student_works); @@ -3068,89 +3075,100 @@ class Listofworksstudentone extends Component { } return ( + this.props.isAdmin() === true ? - ( -
- {visible === true ? this.saveModulationModal(value, num)} - /> : ""} - - {this.state.showmodel === true ? this.hideshowmodel()} - updatas={() => this.isupdatas()} - /> : ""} - - - {visibles === true ? -
- - this.cancelModulationModels()} - /> - -
- : "" - } - - {/*立即发布*/} - this.getcourse_groupslist(id)} - starttimes={this.state.starttimes} - typs={this.state.typs} - /> -
- - -
- - - + this.cancelModulationModels()} + /> + +
+ : "" + } + + {/*立即发布*/} + this.getcourse_groupslist(id)} + starttimes={this.state.starttimes} + typs={this.state.typs} + /> + { + homework_status.length===0? +
+ +
+ : + homework_status.length>0 && homework_status[0]==="未发布"? +
+ +
+ : +
+ + +
+ + + - {computeTimetype===false?
  • - - + + {computeTimetype===false?
  • + + 正在执行成绩计算,完成后将为您自动刷新结果。温馨提示:执行时间因作品数量而异 -
  • :""} + :""} - {/*作品状态GraduationTaskssettinglist*/} -
      -
    • - 计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')} + {/*作品状态GraduationTaskssettinglist*/} +
        +
      • + 计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')} -
        - {course_is_end===true?"": +
        + {course_is_end===true?"": {teacherdata&&teacherdata.publish_immediately===false&&computeTimetype===true? (this.props.isNotMember()===false?
        查看最新成绩 @@ -3223,7 +3241,7 @@ class Listofworksstudentone extends Component {
        :"") }
        } - + -
        -
      • - -
      • - - 作品状态: - this.notlimiteds()}>不限 - this.funtaskstatust(e, task_status && task_status)} - style={{paddingTop: '4px'}}> - - {task_status === undefined ? "" : task_status.map((item, key) => { - return ( - +
    + + +
  • + + 作品状态: + this.notlimiteds()}>不限 + this.funtaskstatust(e, task_status && task_status)} + style={{paddingTop: '4px'}}> + + {task_status === undefined ? "" : task_status.map((item, key) => { + return ( + {item.name} @@ -3257,96 +3275,96 @@ class Listofworksstudentone extends Component { - ) - })} - - {/*请输入姓名或学号搜索*/} - - -
  • - - - {/*分班情况*/} - -
  • - {JSON.stringify(course_group_info) === "[]" ? "" : course_group_info === undefined ? "" : course_group_info.length < 2 ? "" : -
    - 分班情况: - this.notlimitedst()}>不限 - this.funtaskstatustwot(e, course_group_info && course_group_info)} - style={{paddingTop: '4px',width:'1017px'}}> - {course_group_info === undefined ? "" : - course_group_info.map((item, key) => { - return ( - + ) + })} + + {/*请输入姓名或学号搜索*/} + + +
  • + + + {/*分班情况*/} + +
  • + {JSON.stringify(course_group_info) === "[]" ? "" : course_group_info === undefined ? "" : course_group_info.length < 2 ? "" : +
    + 分班情况: + this.notlimitedst()}>不限 + this.funtaskstatustwot(e, course_group_info && course_group_info)} + style={{paddingTop: '4px',width:'1017px'}}> + {course_group_info === undefined ? "" : + course_group_info.map((item, key) => { + return ( + {item.group_group_name} ({item.count}) - ) - }) - } - -
    } -
  • + ) + }) + } + +
    } + - + -
    + + { + JSON.stringify(datajs) === "[]" ? + +
    +
    +
    + +

    暂时还没有相关数据哦!

    +
    +
    + +
    + : + +
    + -
    - {datajs === undefined ? "" :
    } - - - } - - - - { - teacherdata && teacherdata.work_count && teacherdata.work_count > limit ? -
    - -
    - : "" - } - - - - ) +
    + {datajs === undefined ? "" :
    } + + + } + + + + { + teacherdata && teacherdata.work_count && teacherdata.work_count > limit ? +
    + +
    + : "" + } + + } + : - ( -
    - { - teacherdata === undefined || teacherdata.student_works === undefined || teacherdata.student_works === null || JSON.stringify(teacherdata.student_works) === "[]" ? - // 学生不能查看别人的 -
    - - {visibles === true ? -
    - - + {visibles === true ? +
    + + - this.cancelModulationModels()} - /> -
    - : "" - } + } + + this.cancelModulationModels()} + /> +
    + : "" + } + + { + homework_status.length===0? +
    + +
    + : + homework_status.length>0 && homework_status[0]==="未发布"? +
    + +
    + : -
    -
    - - {computeTimetype===false?
  • - - + + {computeTimetype===false?
  • + + 正在执行成绩计算,完成后将为您自动刷新结果。温馨提示:执行时间因作品数量而异 -
  • :""} + :""} - {JSON.stringify(data) !== "[]" ? -
    -
    + {JSON.stringify(data) !== "[]" ? +
    +
    -
    +
    -
    +
    - 计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')} - { course_is_end===true?"":teacherdata&&teacherdata.task_operation[0]==="开启挑战"?"": + 计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')} + { course_is_end===true?"":teacherdata&&teacherdata.task_operation[0]==="开启挑战"?"": {computeTimetype===true? (this.props.isNotMember()===false?
    @@ -3539,14 +3569,14 @@ class Listofworksstudentone extends Component { } } -
    +
    -
    +
    -
    -
    - -
    - {data === undefined ? "" :
    } - - - +
    + {data === undefined ? "" :
    } + + + - : -
    -
    -
    - -

    暂时还没有相关数据哦!

    -
    -
    + : +
    +
    +
    + +

    暂时还没有相关数据哦!

    +
    +
    -
    - } +
    + } - + - + + } + + : + // 学生能查看别人的 +
    + {/*双层*/} + + + {visibles === true ? + this.cancelModulationModels()} + /> : "" + } -
    - : - // 学生能查看别人的 -
    - {/*双层*/} - - - {visibles === true ? - this.cancelModulationModels()} - /> : "" - } -
    + { + homework_status.length===0? +
    + +
    + : + homework_status.length>0 && homework_status[0]==="未发布"? +
    + +
    + : +
    -
    - + - {computeTimetype===false?
  • - - + {computeTimetype===false?
  • + + 正在执行成绩计算,完成后将为您自动刷新结果。温馨提示:执行时间因作品数量而异 -
  • :""} + :""} - -
    - {data === undefined ? "" :
    } - - {JSON.stringify(datas) !== "[]" ? -
    -
    -
    + } + +
    + {data === undefined ? "" :
    } + + {JSON.stringify(datas) !== "[]" ? +
    +
    +
    {teacherdata === undefined ? "0" : teacherdata.commit_count === undefined ? "0" : teacherdata.commit_count} @@ -3692,8 +3734,8 @@ class Listofworksstudentone extends Component { style={{color: '#FF6800'}}>{teacherdata.left_time.time}} - -
    + +
    - 计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')} - { course_is_end===true?"":teacherdata&&teacherdata.task_operation&&teacherdata.task_operation[0]==="开启挑战"?"": + 计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')} + { course_is_end===true?"":teacherdata&&teacherdata.task_operation&&teacherdata.task_operation[0]==="开启挑战"?"": {computeTimetype===true? (this.props.isNotMember()===false?
    查看最新成绩 @@ -3750,12 +3792,12 @@ class Listofworksstudentone extends Component {
    :"") }
    } -
    -
    -
    -
    - -
    - {datas === undefined ? "" :
    } +
    + {datas === undefined ? "" :
    } + + + { + teacherdata && teacherdata.work_count && teacherdata.work_count > limit ? +
    + +
    + : "" + } + + : +
    +
    +
    + +

    暂时还没有相关数据哦!

    +
    +
    +
    + } - { - teacherdata && teacherdata.work_count && teacherdata.work_count > limit ? -
    - -
    - : "" } - : -
    -
    -
    - -

    暂时还没有相关数据哦!

    -
    -
    -
    - } - - - + } - ) + ) } 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..7f497b28e --- /dev/null +++ b/public/react/src/modules/ecs/EcSetting/CourseSupports/ecCourseSupports.css @@ -0,0 +1,358 @@ +.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; +} + + +.editlybuttonbox{ + margin-bottom: 30px; + margin-right: 3%; +} \ 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..2164669f3 --- /dev/null +++ b/public/react/src/modules/ecs/EcSetting/CourseSupports/index.js @@ -0,0 +1,658 @@ +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:[{"weights": 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, + Supportsclasskey:undefined + } + } + + 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 + }) + console.log(response.data.graduation_subitems.length) + if(response.data.graduation_subitems.length===0){ + this.setState({ + Supportstype:true, + Supportslist:'数据为空,请去毕业要求——>毕业要求指标点分解列表配置数据' + }) + } + } + + }) + .catch(function (error) { + console.log(error); + }); + + const zrl = `/ec_years/${ec_year_id}/ec_courses/search.json`; + axios.get(zrl,{params:{ + per_page:10000, + } + }) + .then((response) => { + + if(response.status===200){ + this.setState({ + ec_courses_list:response.data.ec_courses + }) + } + + }) + .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=(keys,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){ + + // + // 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{ + if(keys===key){ + + if(item.course_supports.length>0){ + this.setState({ + editcourse:item.course_supports, + Editkey:key, + index:subindex, + }) + }else if(item.course_supports.length===0){ + this.setState({ + editcourse:[{weights: 0,top_relation: false,ec_course_name:'',ec_course_id:''}], + Editkey:key, + index:subindex, + }) + } + + } + }) + + // $("#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 = {weights: 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{ + 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.weights=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;j1){ + 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{ + + 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{ + if(item.weights===""){ + item.weights=0; + } + if(item.ec_course_id===""){ + this.setState({ + // Supportstype:true, + Supportslist:'保存失败,课程不能为空', + Supportsclass:true, + Supportsclasskey:key + }) + 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, + Supportsclasskey:undefined, + }) + this.UpdateClassData(); + }else if(response.data.status===-1){ + this.setState({ + Supportslist:"参数错误", + Supportstype:true, + Supportssum:false, + Supportsclass:false, + Supportsclasskey:undefined, + }) + } + }).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,Supportsclasskey,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( +
    支撑课程 +
    (权值) +
    +
    ) + } + return res + } + + return ( +
    + +
    +
    {Supportslist}
    +
    + +
    + + +
    + + + +
    + +
    + 课程体系对毕业要求的支撑 + {/* 导出培养目标 */} + + 导出课程体系支撑矩阵 + +
    用矩阵图的形式说明本专业课程体系对毕业要求的支撑关系 window.elasticLayer(3534)} >查看详情
    + +
    +
    + 毕业要求指标点({data.count} + 课程体系({data.course_count} +
    + +
    + +
    + +

    1200? 140*data.max_support_count : 1200+"px"}}> + 毕业要求指标点 + {list(data.max_support_count<5||data.max_support_count===undefined?5:data.max_support_count)} + 合计 +

    +
    + { + data.graduation_subitems===undefined? }/>:data.graduation_subitems.map((item,key)=>{ + + return ( +
  • 1134 ? 136*data.max_support_count : 1134+"px",margin: '0px 0px'}}> + + {item.graduation_requirement_position+"-"+item.position} + + + + { + item.course_supports.map((t,kes)=>{ + + return( + +
    {t.ec_course_name.length>12?t.ec_course_name.substring(0, 10)+"...":t.ec_course_name}
    +
    ({t.weights})
    +
    + ) + + }) + } + + +
    +
    +
    {item.course_supports.length}
    +
    {Math.round(item.weights_total*100)/100===0?0:(Math.round(item.weights_total*100)/100)}
    +
    +
    + {data.is_manager===false?"": + + } +
    +
    + +
    + +

    + +

    + 指标点 {index} + 支撑课程 + + 权重(∑=1) + (精确到两位小数) + + 关联度最高 +

    + +
    + {Supportsclass===true?:""} + { + editcourse.map((it,key)=>{ + + return( +
    + + + + +
    + +
    + + + + +
    + + + +
    + +
    + ) + }) + } + +
    + {Supportslist} +
    + 合计: {editcourse.length} + 合计: {editnum} +
    + +
    +
    保存
    +
    取消
    +
    + +

    + + +
  • + ) + }) + } +
    +
    + +
    +
    + ); + } +} + +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 ( +
    + +
    +
    +
    +
    毕业要求(及其指标点)
    +
    + 请结合本专业特色修改毕业要求文字描述及指标点,需完全覆盖12项通用标准 + 查看详情 +
    +
    + 导出毕业要求 +
    + + + +
    +
    +
    +
    指标点
    +
    内容
    +
    + { + can_manager && !addState && ( + + + + ) + } +
    +
    +
    + { + graduationRequirements && graduationRequirements.map((item, index) => { + return can_manager && index === editIndex ? ( +
    +
    +
    { index + 1 }
    +
    + + + +
    +
    + +
    +
    + { + currentEditReq.ec_graduation_subitems.map((subitem, i) => { + return ( +
    +
    { index + 1 }-{ i + 1 }
    +
    + + this.onEditItemContentChange(e, i)} /> + +
    +
    + this.removeEditItem(i)}/> +
    +
    + ) + }) + } + +
    + + +
    +
    + ) : ( +
    +
    +
    { index + 1 }
    +
    { item.content }
    + { + can_manager && ( +
    + this.showDeleteConfirm(item.id)} /> + this.showEditContent(index)}/> + { + index === graduationRequirements.length - 1 && !addState && ( + + ) + } +
    + ) + } + +
    + { + item.ec_graduation_subitems.map((subitem, i) => { + return ( +
    +
    { index + 1 }-{ i + 1 }
    +
    { subitem.content }
    +
    + ) + }) + } +
    + ) + }) + } + + { + can_manager && addState && ( +
    +
    +
    { graduationRequirements.length + 1 }
    +
    + + + +
    +
    + +
    +
    + { + newRequirement.graduation_subitems.map((subitem, i) => { + return ( +
    +
    { graduationRequirements.length + 1 }-{ i + 1 }
    +
    + + this.onNewReqItemContentChange(e, i)} /> + +
    +
    + this.removeNewReqItem(i)}/> +
    +
    + ) + }) + } + +
    + + +
    +
    + ) + } +
    +
    +
    +
    +
    +
    + ) + } +} +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 ( +
    + +
    +
    +
    +
    培养目标
    +
    + 请结合本专业特色修改培养目标文字描述及目标分解查看详情 + 查看详情 +
    +
    + 导出培养目标 +
    + + + +
    + { + can_manager && contentEditState ? ( +
    +
    + + this.setState({ editContent: e.target.value })} /> + +
    +
    + + +
    +
    + ) : ( +
    +
    { objective.content }
    + { + can_manager && ( +
    + + this.setState({ contentEditState: true })} /> + +
    + ) + } +
    + ) + } + +
    +
    +
    分项
    +
    目标分解详情
    +
    + { + !can_manager || itemsEditState || ( + + + + ) + } +
    +
    +
    + { + can_manager && itemsEditState ? ( +
    + { + trainingSubitems && trainingSubitems.map((item, index) => { + return ( +
    +
    {index + 1}
    +
    + + this.onItemContentChange(e, index)} /> + +
    + { index !== 0 && this.removeItemColumn(index)} /> } + + this.addItemColumn(index + 1)} style={{ color: '#29BD8B' }} /> +
    +
    +
    + ) + }) + } + +
    + + +
    +
    + ) : ( + objective.ec_training_items && objective.ec_training_items.map((item, index) => { + return ( +
    +
    { index + 1 }
    +
    { item.content }
    +
    + ) + }) + ) + } +
    +
    +
    +
    +
    +
    + ) + } +} +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 ( +
    +
    +
    + + + { year && year.school_name } + + + { year && year.major_name } + + {year && year.year}届 + +
    + +
    + + + { + steps.map((title, index) => { + return ( + + ) + }) + } + +
    + + { + year && ( + + () }> + () }> + + + {/*学生*/} + () }> + {/*课程体系*/} + () }> + {/*课程体系VS毕业要求*/} + () }> + + + + + ) + } +
    +
    + ) + } +} + +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 ( +
    + + +
    +
    + 基础数据:除学生列表与成绩录入以外的所有基础数据
    + 将自动复制上届别的数据;数据均可再编辑 +
    + +
    +
    选择届别:
    +
    + +
    +
    +
    +
    +
    + ) + } +} + +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 { num === 0 ? "立即配置" : num }; + } + const contrastRender = (num, other) => { + let color = other !== 0 && num === other ? 'color-green' : 'color-orange'; + + return other === 0 ? ( +
    -- / --
    + ) : ( +
    {num} / {other}
    + ) + } + const statusRender = (text, record) => { + let zero = record.graduation_subitem_count === 0; + + return zero ? ( + -- + ) : ( + + { text === 'achieved' ? '已达成' : '未达成' } + + ) + } + const operationRender = (_, record) => { + return ( + + ) + } + 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 ( +
    + +
    +
    + + + { major && major.school_name } + + { major && major.name } + +
    + +
    +
    +
    +
    { major.name }
    +
    + 请选择添加参与认证的学生界别,多个界别分次添加 + 查看详情 +
    +
    + +
    + + + +
    +
    + this.setState({keyword: e.target.value})} + onSearch={this.onSearch} + value={keyword} + style={{ width: 200 }}/> +
    + +
    +
    + + + + + + + + + ) + } +} + +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 ( +
    + + + + + +
    + ) + } +} + +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 && 已选择 }, +]; +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 ( +
    + + +
    + this.setState({keyword: e.target.value})} + onSearch={this.onSearch} + value={keyword}/> +
    + +
    +
    +
    { this.state.error }
    + + + + ) + } +} + +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) =>
    {text}
    +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 ( +
    + + +
    +
    + +
    + + + + + + + + + + + + + + this.setState({ school: e.target.value })} value={school} placeholder="请输入学校名称"/> + + + + + + + + + +
    +
    +
    { this.state.error }
    + + + + ) + } +} + +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 ( +
    + { + managers && managers.map(manager => { + return ( + { this.deleteManager(manager.id) }} color="blue"> + { manager.name } + + ) + }) + } +
    + ) + } +} + +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 ( +
    + +
    +
    +
    + { school && school.name } +
    +
    + +
    +
    +
    学校管理员
    +
    温馨提醒:学校管理员有添加专业及设置专业管理员等权限
    +
    +
    + { + managers && managers.map((manager) => { + return ( + + + + { manager.name } + + + ) + }) + } +
    +
    + +
    +
    +
    +
    专业列表
    +
    + 请添加参与认证的专业名称 + 查看详情 +
    +
    + +
    + + + +
    +
    +
    {majorCount || 0} 个检索结果({majorCount || 0} 专业)
    + this.setState({searchKeyword: e.target.value})} + onSearch={this.getSchoolMajors} + value={this.state.searchKeyword} + style={{ width: 200 }} + /> +
    +
    + +
    序号 + 专业代码 + 专业名称 + 专业管理员 + 操作 + + + { + templateMajor && ( + + 0 + 000000 + + { templateMajor.name } + + + + { configBtnText } + + + ) + } + { + majors && majors.map((major, index) => { + return ( + + { index + 1 } + { major.code } + + { major.name } + + +
    + { manageMajor && this.showAddManagerModal(major.id)}> } + + +
    + + + { configBtnText } + { manageSchool && ( this.showDeleteMajorConfirm(major.id)}>删除 ) } + + + ) + }) + } + + + + + + + + { this.state.school && } + + + ) + } +} + +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 @@ + \ 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 ( +
    +
    +
    + +
    + 课程体系 > + {schooldata&&schooldata.ec_course_name} 达成评价详情 + {/* 导出培养目标 */} +
    系统根据课程目标、课程考核方式与课程目标评价方法,一键计算评价课程目标的达成情况 window.elasticLayer(3533)}>查看详情
    + { + titine === 4 ? + + 导出评价方法 + + :titine === 1 ? + + 导出课程目标 + + :titine===2? + + :"" + } +
    + +
    + this.onAclick(1)}>1.课程目标 + this.onAclick(2)}>2.课程考核方式与数据来源 + this.onAclick(3)}>3.成绩等级设置 + this.onAclick(4)} + >4.课程目标评价方法 + this.onAclick(5)} + >5.课程达成评价结果 + { + titine===5? + + + 导出评价详情 + + 计算 + + :titine===4? + (各环节平均得分*占比)之和/(各环节总分*占比)之和 + :titine===3? + (将学生的成绩转换成对应的等级) + :titine===2? + + (请在完成配置后,使用各项成绩导入模板,将本学年所有参与的学生成绩数据导入系统) + 导入课堂数据 + + :"" + } +
    +
    + + {/*Curriculumtwo 测试用*/} + {/*课程目标*/} + (this.Ontitine(i)} />) }> + {/*课程考核方式与数据来源*/} + (this.Ontitine(i)}/>) }> + {/*成绩等级设置*/} + (this.Ontitine(i)}/>) }> + {/*4课程目标评价方法*/} + (this.Ontitine(i)}/>) }> + {/*5课程达成评价结果*/} + (this.Ontitine(i)}/>) }> + +
    +
    + ) + } + + +} +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 ( +
    + 测试 +
    + ) + } + + +} +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 ( +
    + + + +
    + )} +} + +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; i10){ + 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{ + 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(目标{length-i}) + // target_listres.push(目标{i+1}) + target_listres.push(目标{length-i}) + } + return target_listres + } + + let TargetresLists = (length) => { + let target_listress = []; + for(let i = 0; i < length; i++) { + // target_listres.push(目标{length-i}) + target_listress.push(目标{i+1}) + // target_listres.push(目标{length-i}) + } + 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() + }else{ + target_listres.push() + } + + } + 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( + {/*
    {value[i].total_score}
    */} +
    100%
    +
    ) + }else{ + target_listres.push( + {/*
    {value[i].score}
    */} + {/*
    占比{(value[i].rate*100).toFixed(2)}%
    */} +
    + {(value[i].rate*100).toFixed(2)}% +
    +
    ) + } + + } + return target_listres + }else{ + target_listres.push( + {/*
    {value[i].total_score}
    */} +
    --
    +
    ) + 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( + //
    {value[i].score.toFixed(2)}
    + //
    ) + // }else{ + // target_listres.push( + //
    {value[i].score.toFixed(2)}
    + //
    ) + // } + + if(i +
    {value[i].score.toFixed(2)}
    + ) + } + + } + return target_listres + } + } + return ( +
    + +
    +
    {completionlist}
    +
    + { + calculatesetype===true? +
    + 知道啦 +
    + : +
    + 取消 + 确定 +
    + } + + + +
    + +
    + + {/**/} + + {/*
    */} + {/*
    */} + {/* 课程体系 >*/} + {/* {schooldata.ec_course_name} 达成评价详情*/} + {/* /!* 导出培养目标 *!/*/} + {/*
    系统根据课程目标、课程考核方式与课程目标评价方法,一键计算评价课程目标的达成情况 window.elasticLayer(3533)}>查看详情
    */} + {/*
    */} + {/*
    */} + {/* 1.课程目标*/} + {/* 2.课程考核方式与数据来源*/} + {/* 3.成绩等级设置*/} + {/* 4.课程目标评价方法*/} + {/* 5.课程达成评价结果*/} + {/* /!* 课程体系:*/} + {/* {*/} + {/* evaluate_result===false?未达成:达成*/} + {/* }*/} + {/* *!/*/} + {/* 计算*/} + {/* */} + {/* 导出评价详情*/} + {/* */} + {/*
    */} + {/*
    */} + +
    + +

    + 课程目标 + 达成结果 + 达成标准(分) + 实际达成 + 权重 +

    + + { Spintype===true?}/>:"" } + + { target_list.length===0&&Spintype===false? +
  • + -- + -- + -- + -- + -- + -- +
  • :""} + + + {Spintype===false?target_list.map((item,key)=>{ + + return( +
  • + {key+1} + {item.content} + {item.result} + {item.standard_grade} + {item.real_grade} + {item.weigths} +
  • + ) + + }):"" + } + + +
    + +
    + +
    + 毕业要求指标点达成评价结果 + 注: 代表支持指标点;代表不支持指标点 +
    + +
    + +
    + + { + graduation_list.length===0? +

    + 毕业要求 + {5} + 达成结果 + 达成目标值 + 达成实际值 + 课程权重 + {TargetresList(5)} +

    + :"" + } + + { Spintype===true?}/>:"" } + + { + graduation_list.length===0&&Spintype===false? +
  • + {/* {item.ec_graduation_name} */} + {1} + {"--"} + {"--"} + {"--"} + {"--"} + 立即配置 + {TargetresContentList(5,[2,2,2,2,2])} +
  • + :"" + } + { + Spintype===false?graduation_list.map((item,key)=>{ + + if(key===0){ + return( +

    5 ? (76*(ec_course_targets_count+4)+380+15):1200+"px"}}> + 毕业要求 + {item.ec_subitem_content} + 达成结果 + 达成目标值 + 达成实际值 + 课程权重 + {TargetresList(ec_course_targets_count)} +

    + ) + } + + }):"" + } + + + { + Spintype===false?graduation_list.map((item,key)=>{ + + return( +
  • 5 ? (76*(ec_course_targets_count+4)+380):1200+"px"}}> + {/* {item.ec_graduation_name} */} + {key+1} + {item.ec_subitem_content} + {item.result} + {item.reach_target===null?0:item.reach_target} + {item.reach_real_target===null?0:item.reach_real_target} + {item.weight===null||item.weight===0?立即配置:{item.weight}} + {TargetresContentList(ec_course_targets_count,item.target_position)} +
  • + ) + + }):"" + } +
    + +
    + +
    + 课程总评成绩表 +
    + +
    + +
    + +

    5 ? (180 * total_rate_data+226+16) : 1200+"px"}}> + {/*序号*/} + 课程目标 + {/*姓名*/} + {/*学号*/} + {TargetresLists(total_rate_data-1)} + 总评成绩 +

    + {/*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( + //
  • 1200?(113*(total_rate_data+4.5))+63:1200+"px"}}> + // 占比 + // {/*colorTransparent*/} + // {/* 平均数 */} + // {/* 平均数 */} + // {/* {Total_rate_dataList(total_rate_data-1,i.total_rate)} + //
  • + // ) + + // } + + // }) */} + } + { Spintype===true?}/>:"" } + { + Spintype===false?
  • 5 ? (180 * total_rate_data+226+16) : 1200 + "px"}}> + 占比 + {/*colorTransparent*/} + {/* 平均数 */} + {/* 平均数 */} + {Total_rate_dataList(course_total_score)} + { + course_total_score.length===0? --:"" + } +
  • :"" + } + {/*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( + //
  • 1200?(113*(total_rate_data+4.5))+63:1200+"px"}}> + // {/*{k+1}*/} + // 平均分 + // {/*{i.student_scores.name}*/} + // {/*{i.student_scores.student_number}*/} + // {newTotal_rate_dataList(total_rate_data-1,i.student_scores.target_info)} + // {i.student_scores.total_score.toFixed(2)} + //
  • + // ) + + // } + + // }) + } + { + Spintype===false?
  • 1200?(113*(total_rate_data+4.5))+63:1200+"px"}}> + {/*{k+1}*/} + 平均分 + {/*{i.student_scores.name}*/} + {/*{i.student_scores.student_number}*/} + {newTotal_rate_dataList(course_total_score-1,course_total_score)} + {/* {course_total_score.length===0?"":course_total_score[course_total_score-1].total_score} */} + { + course_total_score.length===0? --:{course_total_scoreaverage} + } +
  • :"" + } + + +
  • 1136?113*(total_rate_data+4):1136+"px",display:morelisttype===true?"block":"none"}}> + this.showmorelist()}>加载更多 +
  • +
    + + + +
    + +
    + 课程目标成绩分析 +
    + +
    + + +
    + +

    + 课程目标 + 平均分 + 最高分数 + 最低分数 + 90分以上 + 80-89分 + 70-79分 + 60-69分 + 50-59分 + 低于50分 +

    + + { + Spintype===false?target_score.map((i,k)=>{ + + return( +
  • + {k+1} + {i.average_score} + {i.top_score} + {i.low_score} + +
    {i.from90[0]}人
    +
    {(i.from90[1]).toFixed(2)}%
    +
    + +
    {i.from80[0]}人
    +
    {(i.from80[1]).toFixed(2)}%
    +
    + +
    {i.from70[0]}人
    +
    {(i.from70[1]).toFixed(2)}%
    +
    + +
    {i.from60[0]}人
    +
    {(i.from60[1]).toFixed(2)}%
    +
    + +
    {i.from50[0]}人
    +
    {(i.from50[1]).toFixed(2)}%
    +
    + +
    {i.from_down[0]}人
    +
    {(i.from_down[1]).toFixed(2)}%
    +
    +
  • + ) + + }):"" + } + + { Spintype===true?}/>:"" } + + {target_score.length===0&&Spintype===false? +
  • + -- + -- + -- + -- + +
    --人
    +
    --%
    +
    + +
    --人
    +
    --%
    +
    + +
    --人
    +
    --%
    +
    + +
    --人
    +
    --%
    +
    + +
    --人
    +
    --%
    +
    + +
    --人
    +
    --%
    +
    +
  • :""} + +
    + +
    +
    + ); + } +} + +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{ + + 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; z0){ + if(newachievement_methods[location]===undefined){ + newachievement_methods.push(newlist) + } + for(var i=0; i{ + 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{ + let id=parseInt(keynum.key); + let{achievement_methods}=this.state; + let newachievement_methods=achievement_methods; + for(var i=0; i{ + 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{ + 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{ + 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; j100){ + // 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 { + 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; i0){ + if(newachievement_methods[location]===undefined){ + newachievement_methods.push(newlist) + } + for(var i=0; i{ + 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 ( +
    +
    + +
    +
    {Modallists}
    +
    +
    + 取消 + 确定 +
    +
    + + {/*导航*/} + {/*
    */} + + {/*

    */} + {/*课程列表 > */} + {/* {schooldata.ec_course_name} 课程考核方式与数据来源*/} + {/*/!* *!/*/} + {/*/!* 导出培养目标 *!/*/} + {/*导出策略*/} + {/*

    */} + + {/*
    */} + {/*课程考核标准*/} + {/*(请在完成配置后,使用各项成绩导入模板,将本学年所有参与的学生成绩数据导入系统)*/} + {/*在线课堂:{course_name}*/} + {/*导入课堂数据*/} + {/*
    */} + + {/*
    */} + {/**/} + + {/*
    */} + + {/*

    */} + {/* 课程体系 >*/} + {/* {schooldata.ec_course_name} */} + {/*

    请结合本课程的教学情况,修改说明每个课程目标的评价环节和评估方式 window.elasticLayer(3533)}>查看详情
    */} + + {/* /!*课程考核方式与数据来源*!/*/} + {/* /!* *!/*/} + {/* /!* 导出培养目标 *!/*/} + {/* */} + {/* 导出评价方法*/} + {/* */} + {/*

    */} + + {/*
    */} + {/* /!*课程目标达成方法*!/*/} + {/* 1.课程目标*/} + {/* 2.课程考核方式与数据来源*/} + {/* 3.成绩等级设置*/} + {/* 4.课程目标评价方法*/} + {/* 5.课程达成评价结果*/} + {/* (各环节平均得分*占比)之和/(各环节总分*占比)之和*/} + {/*
    */} + + {/*
    */} + +
    + +

    + 课程目标 + 评价环节 + 数据内容 + + 操作 + + 评价占比 + 支撑总分值 +

    + + { + achievement_list.length===0?}/>:achievement_list.map((item,key)=>{ + return( +
    + { + item.target_evaluate_data.length===0? +
  • +
    + {key+1} + + + + + + + + +
    +
    + +
    +
    +
    + + + +
    +
    + + +
    +
    + +
    +
    + + {/* 修改start*/} +
    +
    + {/*
    */} +
    +
    + {/* 课程目标{sequenceid}:{ec_course_target_name} */} + 课程目标{key+1}:{ec_course_target_name} +
    +
    + { + achievement_methods===undefined?" ":achievement_methods.map((item,itemkey)=>{ + return( +
    +
    + 评价环节 + + + + + + + + + + 100&&eacoursesavetypes===true||percentagetype===true?"bor-red": ""} + onInput={this.handevaluation_CoursePercentag.bind(this)} id={itemkey} style={{ width: '11%' }} placeholder="请输入占比"/> + % + +
    + + + + + + +
    +
    +
    +
    +
    + ) + }) + } + {Modallists} +
    +
    保存
    +
    取消
    +
    +
    +
    + {/* 修改end*/} + + + +
  • + :item.target_evaluate_data.map((i,k)=>{ + return( +
  • +
    + {key-k===key?key+1:""} + + + {i.evaluate_name} + + + { + i.evaluation_relates_data.map((y,e)=>{ + return( +
    {y.evaluation_relates_name+" "}
    + ) + }) + } +
    + { + key-k===key? +
    +
    + +
    +
    +
    : + +
    +
    + +
    +
    +
    + } + + + +
    {i.percentage+"%"}
    +
    + + +
    {i.score}
    +
    + +
    +
    + {/* 修改start*/} +
    +
    +
    +
    + {/* 课程目标{sequenceid}:{ec_course_target_name} */} + 课程目标{key+1}:{ec_course_target_name} +
    +
    + { + achievement_methods===undefined?" ":achievement_methods.map((item,itemkey)=>{ + + return( +
    +
    + 评价环节 + + + + + + + + + + 100&&eacoursesavetypes===true||percentagetype===true?"bor-red": ""} + onInput={this.handevaluation_CoursePercentag.bind(this)} + id={itemkey} style={{ width: '11%' }} + placeholder="请输入占比"/> + % + +
    + + + + + + +
    +
    +
    +
    +
    + ) + }) + } + {Modallists} +
    +
    保存
    +
    取消
    +
    +
    +
    + {/* 修改end*/} + +
  • + + ) + + }) + } +
    + ) + }) + } +
    + +
    +
    + ); + } +} + +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..ead6e4c29 --- /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{ + let {majorschoollist,studentall}=this.state; + let mewmajorschoollist=majorschoollist; + let newstudentall=studentall; + if(e.target.checked===false){ + newstudentall=false + } + for(var i=0; i{ + let {majorschoollist,studentall} =this.state; + let studentalltype=0 + for(var i=0; i{ + 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 { + 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 ( +
    + +
    +
    {Modallist}
    +
    +
    + 取消 + { + Modallisttypess===0?确定:确定 + } + +
    +
    +
    +
    + 学生列表 + 返回 +
    + +
    + +
    学生列表( + {majorschoollist===undefined?"":majorschoollist.total_student} + ) +
    提供模板支持导入学生信息(请先下载模板) window.elasticLayer(3533)}>查看详情
    +
    + +
    + {ismanager===false?"": + 请使用导入模板(点击下载),将本学年所有参与的学生导入系统,以便录入教学活动相关数据 + } + + {ismanager===false?"": + 导入 + } + +
    + +
    + {ismanager===false?"":
    + 删除 +
    } +
    + +
    +

    + + + 序号 + + 姓名 + 学号 +

    + + +
      + { + majorschoollist===undefined? +
      +

      +

      学生数据为空,请导入数据

      +
      + :majorschoollist.ec_students.length===0? +
      +

      +

      学生数据为空,请导入数据

      +
      :majorschoollist.ec_students.map((item,key)=>{ + // console.log(item) + return( +
    • + + + {item.index} + + {item.student_name} + {item.student_id} +
    • + ) + }) + } + +
    + +
    + { + majorschoollist===undefined?"":majorschoollist.total_page===0||majorschoollist.total_student<51?"": + } +
    +
    +
    +
    +
    + +
    + + ) + + } +} + +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 }); } diff --git a/public/react/src/modules/page/component/monaco/TPIMonaco.js b/public/react/src/modules/page/component/monaco/TPIMonaco.js index a9820ad27..0d5eb2d34 100644 --- a/public/react/src/modules/page/component/monaco/TPIMonaco.js +++ b/public/react/src/modules/page/component/monaco/TPIMonaco.js @@ -290,6 +290,7 @@ class TPIMonaco extends Component { // theme: "vs-dark", theme: "myCoolTheme", + insertSpaces: false, fontSize: this.state.cmFontSize }); diff --git a/public/react/src/modules/paths/PathDetail/PathDetailIndex.js b/public/react/src/modules/paths/PathDetail/PathDetailIndex.js index c04c74e87..883ed6875 100644 --- a/public/react/src/modules/paths/PathDetail/PathDetailIndex.js +++ b/public/react/src/modules/paths/PathDetail/PathDetailIndex.js @@ -83,7 +83,8 @@ class PathDetailIndex extends Component{ loadtype:false, courses:undefined, items: getItems(10), - pathtopskey:1 + pathtopskey:1, + dataquerys:{}, } this.onDragEnd = this.onDragEnd.bind(this); @@ -146,6 +147,7 @@ class PathDetailIndex extends Component{ } componentDidMount(){ + const query = this.props.location.search; // const type = query.split('?chinaoocTimestamp='); // console.log("Eduinforms12345"); @@ -158,18 +160,19 @@ class PathDetailIndex extends Component{ this.setState({ dataquerys:{}, }); - return + }else{ + this.setState({ + dataquerys:foqus, + }); + dataqueryss=foqus; } - this.setState({ - dataquerys:foqus, - }); - dataqueryss=foqus; }catch (e) { this.setState({ dataquerys:{}, }) } - this.getdatasindexs(undefined,dataqueryss) + + this.getdatasindexs(undefined,dataqueryss); } //截取url 数据的 foo=(url)=> { @@ -252,11 +255,13 @@ class PathDetailIndex extends Component{ }) }; - getdatasindex=(key,yslwebobject)=>{ + getdatasindex=(key)=>{ // yslwebobject 后端需要的接口 let pathid=this.props.match.params.pathId; let url="/paths/"+pathid+".json"; - axios.get(url).then((result)=>{ + axios.get(url, + {params:this.state.dataquerys} + ).then((result)=>{ if (result.data.status === 407 || result.data.status === 401) { debugger return; diff --git a/public/react/src/modules/paths/SchoolStatistics/SecondTab.js b/public/react/src/modules/paths/SchoolStatistics/SecondTab.js index 5fefef219..8716a14d5 100644 --- a/public/react/src/modules/paths/SchoolStatistics/SecondTab.js +++ b/public/react/src/modules/paths/SchoolStatistics/SecondTab.js @@ -237,7 +237,7 @@ class SecondTab extends Component{
    -

    实训使用详情

    +
    实训使用详情
    @@ -268,7 +268,17 @@ class SecondTab extends Component{
    -

    实训学习统计

    + +
    实训学习统计
    {shixunList===undefined?
    :""} {shixunList===undefined?"":
    { - return item.name - }) -// [{name: "湖南科技大学潇湘学院", 已通关: 0, 未通关: 4, sum: 4},{name: "长沙理工大学", 已通关: 0, 未通关: 7, sum: 7},{name: "安徽大学", 已通关: 1, 未通关: 8, sum: 9},{name: "湘潭大学兴湘学院", 已通关: 12, 未通关: 0, sum: 12}, -// {name: "湖南师范大学", 已通关: 10, 未通关: 2, sum: 12},{name: "湖南软件职业学院", 已通关: 11, 未通关: 1, sum: 12},{name: "湖南科技大学", 已通关: 91, 未通关: 34, sum: 125},{name: "湘潭大学", 已通关: 110, 未通关: 45, sum: 155}, -// {name: "湖南工业大学", 已通关: 133, 未通关: 41, sum: 174},{name: "国防科技大学", 已通关: 853, 未通关: 23, sum: 876}]; - // <% @schools.each do |s| %> - // data.push({name: "<%= s['name'] %>", '已通关': <%= s['pass_count'] %>, '未通关': <%= s['unpass_count'] %>}); - // <% end %> - - // =================右边要放的字段名及颜色=========== - var items = [{ - key: '学习人数', color: "#29BD8B" - }, { - key: '已通关', color: "#FF954C" - }, { - key: '未通关', color: "#CBCBCB" - }] - - data.forEach((d) => { - var sum = 0 - items.forEach((i) => { - sum += (d[i.key] || 0) - }) - d.sum = sum; - }) - - // =========================排序================ - data.sort((a, b) => a.sum - b.sum) - - var yData = _yData.reverse(); - // ["湖南科技大学潇湘学院", "长沙理工大学", "安徽大学", "湖南软件职业学院", "湖南师范大学", "湘潭大学兴湘学院", "湖南科技大学", "湘潭大学", "湖南工业大学", "国防科技大学"] - - var itemSeries = items.map((d, i) => { - var values = data.map((p) => p[d.key]) - return { - type: 'bar', - name: d.key, - data: values, - stack: 'all', - xAxisIndex: 1, - yAxisIndex: 1, - label: { - normal: { - color:'#FFF', - // show: ( i == 1 ? true :false), - show: true, - position: 'inside' - } - }, - itemStyle: { - normal: { - color: d.color - } - } - } - }) - - var option = { - backgroundColor: '#fff', // 背景 - tooltip : { - trigger: 'axis', - axisPointer : { - type : '' - } - }, - legend: { - data: ['学习人数','已通关','未通关'], - textStyle: { - color: '#05101A' - }, - right:"20px", - selectedMode:false - }, - grid: [{ - right: '56%', - top: '20', - containLabel: true - }, { - left: '45%', - width:'100%', - top: '20', - containLabel: true - }], - xAxis: [{ - type: 'value', - inverse: true, - splitLine: { - show: false - }, - axisLine: { - show: false - }, - axisLabel: { - show: false - }, - axisTick: { - show: false - } - }, { - type: 'value', - gridIndex: 1, - splitLine: { - show: false - }, - axisLine: { - show: false - }, - axisLabel: { - show: false - }, - axisTick: { - show: false - } - }], - yAxis: [{ - type: 'category', - data: yData, - max:10, - axisLine: { - show: false - }, - axisLabel: { - show: false - }, - axisTick: { - show: false - } - }, { - type: 'category', - data: yData, - max:10, - gridIndex: 1, - axisLine: { - show: false - }, - axisTick: { - show: false - } - }], - series: [...itemSeries, - { - name: '总计', - type: 'bar', - data: data.map((d) => d.sum), - xAxisIndex: 1, - yAxisIndex: 1, - barCategoryGap:'40%', - stack: 'all', - label: { - normal: { - show: true, - position: 'inside', - color: '#666' - } - }, - itemStyle: { - normal: { - color: '#fff' - } - } - }, - // ===================左边=================== - { - type: 'bar', - data: data.map((d) => d.sum), - barCategoryGap:'40%', - label: { - normal: { - show: true, - position: 'left', - color: '#29BD8B' - } - }, - itemStyle: { - normal: { - color: '#29BD8B' - } - } - }] - } - myChart.setOption(option); -} -class ThirdTab extends Component{ - constructor(props){ - super(props); - } - - componentDidMount(){ - var pathId = this.props.match.params.pathId; - - var myChart = echarts.init(document.getElementById('collegeStatistic')); - myChart.showLoading({ - text: "数据获取中", - effect: 'whirling' - }) - - const url = `/paths/${pathId}/school_report.json` - axios.get(url, { - }) - .then((response) => { - // TODO 没用,404返回的error - if (response.data.status == 404) { - this.props.showSnackbar('未找到对应数据,请查看地址是否正确。') - return - } - this.setState({ ...response.data }) - // name: "湖南科技大学潇湘学院", 已通关: 0, 未通关: 4, sum: 4 - /** - "name": "国防科技大学", - "student_count": 9269, - "pass_count": 6061, - "unpass_count": 3208 - */ - const _data = response.data.schools.map( (item, index) => { - return { - name: item.name, - sum: item.student_count, - 已通关: item.pass_count, - 未通关: item.unpass_count, - } - }) - InitCollegeStatistic(_data, myChart); - myChart.hideLoading() - }) - .catch(function (error) { - console.log(error); - }); - } - - render(){ - return( -
    -

    院校学习情况

    -
    -
    - ) - } -} +import React,{ Component } from "react"; +import axios from 'axios'; + +const $ = window.$ +const echarts = require('echarts'); +function InitCollegeStatistic(_data, myChart){ + var data = _data + var _yData = data.map( item => { + return item.name + }) +// [{name: "湖南科技大学潇湘学院", 已通关: 0, 未通关: 4, sum: 4},{name: "长沙理工大学", 已通关: 0, 未通关: 7, sum: 7},{name: "安徽大学", 已通关: 1, 未通关: 8, sum: 9},{name: "湘潭大学兴湘学院", 已通关: 12, 未通关: 0, sum: 12}, +// {name: "湖南师范大学", 已通关: 10, 未通关: 2, sum: 12},{name: "湖南软件职业学院", 已通关: 11, 未通关: 1, sum: 12},{name: "湖南科技大学", 已通关: 91, 未通关: 34, sum: 125},{name: "湘潭大学", 已通关: 110, 未通关: 45, sum: 155}, +// {name: "湖南工业大学", 已通关: 133, 未通关: 41, sum: 174},{name: "国防科技大学", 已通关: 853, 未通关: 23, sum: 876}]; + // <% @schools.each do |s| %> + // data.push({name: "<%= s['name'] %>", '已通关': <%= s['pass_count'] %>, '未通关': <%= s['unpass_count'] %>}); + // <% end %> + + // =================右边要放的字段名及颜色=========== + var items = [{ + key: '学习人数', color: "#29BD8B" + }, { + key: '已通关', color: "#FF954C" + }, { + key: '未通关', color: "#CBCBCB" + }] + + data.forEach((d) => { + var sum = 0 + items.forEach((i) => { + sum += (d[i.key] || 0) + }) + d.sum = sum; + }) + + // =========================排序================ + data.sort((a, b) => a.sum - b.sum) + + var yData = _yData.reverse(); + // ["湖南科技大学潇湘学院", "长沙理工大学", "安徽大学", "湖南软件职业学院", "湖南师范大学", "湘潭大学兴湘学院", "湖南科技大学", "湘潭大学", "湖南工业大学", "国防科技大学"] + + var itemSeries = items.map((d, i) => { + var values = data.map((p) => p[d.key]) + return { + type: 'bar', + name: d.key, + data: values, + stack: 'all', + xAxisIndex: 1, + yAxisIndex: 1, + label: { + normal: { + color:'#FFF', + // show: ( i == 1 ? true :false), + show: true, + position: 'inside' + } + }, + itemStyle: { + normal: { + color: d.color + } + } + } + }) + + var option = { + backgroundColor: '#fff', // 背景 + tooltip : { + trigger: 'axis', + axisPointer : { + type : '' + } + }, + legend: { + data: ['学习人数','已通关','未通关'], + textStyle: { + color: '#05101A' + }, + right:"20px", + selectedMode:false + }, + grid: [{ + right: '56%', + top: '20', + containLabel: true + }, { + left: '45%', + width:'100%', + top: '20', + containLabel: true + }], + xAxis: [{ + type: 'value', + inverse: true, + splitLine: { + show: false + }, + axisLine: { + show: false + }, + axisLabel: { + show: false + }, + axisTick: { + show: false + } + }, { + type: 'value', + gridIndex: 1, + splitLine: { + show: false + }, + axisLine: { + show: false + }, + axisLabel: { + show: false + }, + axisTick: { + show: false + } + }], + yAxis: [{ + type: 'category', + data: yData, + max:10, + axisLine: { + show: false + }, + axisLabel: { + show: false + }, + axisTick: { + show: false + } + }, { + type: 'category', + data: yData, + max:10, + gridIndex: 1, + axisLine: { + show: false + }, + axisTick: { + show: false + } + }], + series: [...itemSeries, + { + name: '总计', + type: 'bar', + data: data.map((d) => d.sum), + xAxisIndex: 1, + yAxisIndex: 1, + barCategoryGap:'40%', + stack: 'all', + label: { + normal: { + show: true, + position: 'inside', + color: '#666' + } + }, + itemStyle: { + normal: { + color: '#fff' + } + } + }, + // ===================左边=================== + { + type: 'bar', + data: data.map((d) => d.sum), + barCategoryGap:'40%', + label: { + normal: { + show: true, + position: 'left', + color: '#29BD8B' + } + }, + itemStyle: { + normal: { + color: '#29BD8B' + } + } + }] + } + myChart.setOption(option); +} +class ThirdTab extends Component{ + constructor(props){ + super(props); + } + + componentDidMount(){ + var pathId = this.props.match.params.pathId; + + var myChart = echarts.init(document.getElementById('collegeStatistic')); + myChart.showLoading({ + text: "数据获取中", + effect: 'whirling' + }) + + const url = `/paths/${pathId}/school_report.json` + axios.get(url, { + }) + .then((response) => { + // TODO 没用,404返回的error + if (response.data.status == 404) { + this.props.showSnackbar('未找到对应数据,请查看地址是否正确。') + return + } + this.setState({ ...response.data }) + // name: "湖南科技大学潇湘学院", 已通关: 0, 未通关: 4, sum: 4 + /** + "name": "国防科技大学", + "student_count": 9269, + "pass_count": 6061, + "unpass_count": 3208 + */ + const _data = response.data.schools.map( (item, index) => { + return { + name: item.name, + sum: item.student_count, + 已通关: item.pass_count, + 未通关: item.unpass_count, + } + }) + InitCollegeStatistic(_data, myChart); + myChart.hideLoading() + }) + .catch(function (error) { + console.log(error); + }); + } + + render(){ + return( +
    +
    院校学习情况
    +
    +
    + ) + } +} export default ThirdTab; \ No newline at end of file diff --git a/public/react/src/modules/tpm/TPMIndexHOC.js b/public/react/src/modules/tpm/TPMIndexHOC.js index c366b21a3..0f753b96c 100644 --- a/public/react/src/modules/tpm/TPMIndexHOC.js +++ b/public/react/src/modules/tpm/TPMIndexHOC.js @@ -81,7 +81,8 @@ export function TPMIndexHOC(WrappedComponent) { isRender: false, AccountProfiletype: false, - globalLoading: false + globalLoading: false, + dataquerys:{}, } } @@ -165,7 +166,32 @@ export function TPMIndexHOC(WrappedComponent) { $.ajaxSetup({ cache: true }); - this.fetchUser(); + + //帮助后台传参数 + const query = this.props.location.search; + // const type = query.split('?chinaoocTimestamp='); + // console.log("Eduinforms12345"); + // console.log(this.foo(query)); + // console.log(JSON.stringify(this.foo(query))); + var dataqueryss={} + try { + var foqus=this.foo(query); + if(JSON.stringify(foqus) ==="{}"){ + this.setState({ + dataquerys:{}, + }); + }else{ + this.setState({ + dataquerys:foqus, + }); + dataqueryss=foqus; + } + }catch (e) { + this.setState({ + dataquerys:{}, + }) + } + this.fetchUsers(dataqueryss); let url=`/users/get_navigation_info.json`; axios.get(url, { @@ -260,10 +286,23 @@ export function TPMIndexHOC(WrappedComponent) { courseId = parseInt(type[2]) // url += `?course_id=${courseId}` } - axios.get(url,{params:{ - course_id:isNaN(courseId)?undefined:courseId, - school:1 - } + var datay={}; + if(JSON.stringify(this.state.dataquerys) ==="{}"){ + datay={ + course_id:isNaN(courseId)?undefined:courseId, + school:1 + } + }else{ + datay={ + course_id:isNaN(courseId)?undefined:courseId, + school:1, + chinaoocTimestamp:this.state.dataquerys.chinaoocTimestamp, + websiteName:this.state.dataquerys.websiteName, + chinaoocKey:this.state.dataquerys.chinaoocKey, + } + } + axios.get(url,{params: + datay }, { // withCredentials: true @@ -301,7 +340,93 @@ export function TPMIndexHOC(WrappedComponent) { }).catch((error) => { console.log(error) }) - } + }; + fetchUsers = (yslurlobject) => { + let url = `/users/get_user_info.json` + let courseId; + let query = this.props.location.pathname; + const type = query.split('/'); + if (type[1] == 'courses' && type[2]) { + courseId = parseInt(type[2]) + // url += `?course_id=${courseId}` + } + var datay={}; + if(JSON.stringify(yslurlobject) ==="{}"){ + datay={ + course_id:isNaN(courseId)?undefined:courseId, + school:1 + } + }else{ + datay={ + course_id:isNaN(courseId)?undefined:courseId, + school:1, + chinaoocTimestamp:yslurlobject.chinaoocTimestamp, + websiteName:yslurlobject.websiteName, + chinaoocKey:yslurlobject.chinaoocKey, + } + } + axios.get(url,{params: + datay + }, + { + // withCredentials: true + } + ).then((response) => { + /* + { + "username": "黄井泉", + "login": "Hjqreturn", + "user_id": 12, + "image_url": "avatar/User/12", + "admin": true, + "is_teacher": false, + "tidding_count": 0 + } + */ + if(response=== undefined){ + return + } + if (response.data) { + this.initCommonState(response.data) + this.setState({ + tpmLoading: false, + coursedata: { + course_identity: response.data.course_identity >= 0 ? response.data.course_identity : undefined, + course_public: response.data.course_public, + name: response.data.course_name, + userid:response.data.user_id + }, + + }) + + } + + }).catch((error) => { + console.log(error) + }) + }; + //截取url 数据的 + foo=(url)=> { + var json = {}; + var regExp = /[\?\&](\w+)(=?)(\w*)/g; + var arr; + do { + arr = regExp.exec(url); + // console.log(arr); // arr = [完整的字符串, key, 等号或'', value或''] + + if (arr) { + var key = arr[1]; + var value = arr[3]; + // arr[2] === ''时, value = undefined + if (!arr[2]) + value = undefined; + + json[key] = value; + } + } while (arr); + + return json; + }; hideLoginDialog = () => { this.setState({ isRender: false