Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

competitions
SylorHuang 6 years ago
commit 0d3e1b610d

@ -1,5 +1,6 @@
# README # README
https://www.trustie.net/issues/24719
[云上实验室] Logo、导航、底部备案信息定制化
This README would normally document whatever steps are necessary to get the This README would normally document whatever steps are necessary to get the
application up and running. application up and running.

@ -0,0 +1,20 @@
class Admins::CompetitionSettingsController < Admins::BaseController
def show
@competition = current_competition
end
def update
Admins::SaveLaboratorySettingService.call(current_competition, form_params)
render_ok
end
private
def current_competition
@_current_competition ||= Competition.find(params[:competition_id])
end
def form_params
params.permit(:identifier, :name, :nav_logo, :login_logo, :tab_logo, :footer, navbar: %i[name link hidden])
end
end

@ -0,0 +1,46 @@
class Admins::CompetitionsController < Admins::BaseController
include CustomSortable
before_action :find_competition, except: [:index]
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
@competitions = custom_sort Competition.all, params[:sort_by], params[:sort_direction]
@params_page = params[:page] || 1
@competitions = paginate @competitions
ids = @competitions.map(&:id)
@member_count_map = TeamMember.where(competition_id: ids).group(:competition_id).count
respond_to do |format|
format.js
format.html
end
end
def publish
@competition.update_attributes!(:published_at, Time.now)
end
def unpublish
@competition.update_attributes!(:published_at, nil)
end
def online_switch
if @competition.status
@competition.update_attributes!(status: false)
else
@competition.update_attributes!(status: true, online_time: Time.now)
end
end
def enroll_list
end
private
def find_competition
@competition = Competition.find_by(id: params[:id])
end
end

@ -17,6 +17,6 @@ class BindUsersController < ApplicationController
private private
def create_params def create_params
params.permit(:login, :password, :type, :not_bind) params.permit(:username, :password, :type, :not_bind)
end end
end end

@ -2,7 +2,7 @@ class BoardsController < ApplicationController
before_action :require_login, :check_auth before_action :require_login, :check_auth
before_action :find_course, only: [:create] before_action :find_course, only: [:create]
before_action :set_board, except: [:create] before_action :set_board, except: [:create]
before_action :teacher_or_admin_allowed before_action :teacher_allowed
def index def index
@boards = @course.boards.includes(messages: [:last_reply, :author]) @boards = @course.boards.includes(messages: [:last_reply, :author])

@ -2,7 +2,7 @@ class CourseGroupsController < ApplicationController
before_action :require_login, :check_auth before_action :require_login, :check_auth
before_action :set_group, except: [:create] before_action :set_group, except: [:create]
before_action :find_course, only: [:create] before_action :find_course, only: [:create]
before_action :teacher_or_admin_allowed before_action :teacher_allowed
def create def create
tip_exception("分班名称不能为空") if params[:name].blank? tip_exception("分班名称不能为空") if params[:name].blank?

@ -2,7 +2,8 @@ class CourseModulesController < ApplicationController
before_action :require_login, :check_auth before_action :require_login, :check_auth
before_action :set_module, except: [:unhidden_modules] before_action :set_module, except: [:unhidden_modules]
before_action :find_course, only: [:unhidden_modules] before_action :find_course, only: [:unhidden_modules]
before_action :teacher_or_admin_allowed before_action :teacher_or_admin_allowed, except: [:add_second_category]
before_action :teacher_allowed, only: [:add_second_category]
# 模块置顶 # 模块置顶
def sticky_module def sticky_module
@ -48,9 +49,9 @@ class CourseModulesController < ApplicationController
tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip) tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip)
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@course_module.course_second_categories.create!(name: params[:name].strip, category_type: @course_module.module_type, category = @course_module.course_second_categories.create!(name: params[:name].strip, category_type: @course_module.module_type,
course_id: @course.id, position: @course_module.course_second_categories.count + 1) course_id: @course.id, position: @course_module.course_second_categories.count + 1)
normal_status(0, "添加成功") render :json => {category_id: category.id, status: 0, message: "添加成功"}
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("添加子目录失败") tip_exception("添加子目录失败")

@ -1,7 +1,7 @@
class CourseSecondCategoriesController < ApplicationController class CourseSecondCategoriesController < ApplicationController
before_action :require_login, :check_auth before_action :require_login, :check_auth
before_action :set_category before_action :set_category
before_action :teacher_or_admin_allowed before_action :teacher_allowed
# 目录重命名 # 目录重命名
def rename_category def rename_category

@ -35,7 +35,7 @@ class CoursesController < ApplicationController
:transfer_to_course_group, :delete_from_course, :export_member_scores_excel, :transfer_to_course_group, :delete_from_course, :export_member_scores_excel,
:search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup, :search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup,
:add_teacher, :export_couser_info, :export_member_act_score, :add_teacher, :export_couser_info, :export_member_act_score,
:update_informs, :new_informs, :delete_informs] :update_informs, :new_informs, :delete_informs, :switch_to_student]
before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin, before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin,
:set_course_group, :create_group_by_importing_file, :set_course_group, :create_group_by_importing_file,
:update_task_position, :tasks_list] :update_task_position, :tasks_list]
@ -681,13 +681,19 @@ class CoursesController < ApplicationController
course_member = @course.course_members.find_by!(user_id: current_user.id, is_active: 1) course_member = @course.course_members.find_by!(user_id: current_user.id, is_active: 1)
tip_exception("切换失败") if course_member.STUDENT? tip_exception("切换失败") if course_member.STUDENT?
course_student = CourseMember.find_by!(user_id: current_user.id, role: %i[STUDENT], course_id: @course.id) course_student = CourseMember.find_by(user_id: current_user.id, role: %i[STUDENT], course_id: @course.id)
course_member.update_attributes(is_active: 0) course_member.update_attributes!(is_active: 0)
course_student.update_attributes(is_active: 1) if course_student
course_student.update_attributes!(is_active: 1)
else
# 学生身份不存在则创建
CourseMember.create!(user_id: current_user.id, role: 4, course_id: @course.id)
CourseAddStudentCreateWorksJob.perform_later(@course.id, [current_user.id])
end
normal_status(0, "切换成功") normal_status(0, "切换成功")
rescue => e rescue => e
uid_logger_error("switch_to_student error: #{e.message}") uid_logger_error("switch_to_student error: #{e.message}")
tip_exception("切换失败") tip_exception(e.message)
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end
@ -1127,7 +1133,7 @@ class CoursesController < ApplicationController
def top_banner def top_banner
@user = current_user @user = current_user
@is_teacher = @user_course_identity < Course::STUDENT @switch_student = Course::BUSINESS < @user_course_identity && @user_course_identity < Course::STUDENT
@is_student = @user_course_identity == Course::STUDENT @is_student = @user_course_identity == Course::STUDENT
@course.increment!(:visits) @course.increment!(:visits)
end end

@ -518,13 +518,13 @@ class ExercisesController < ApplicationController
common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的 common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的
new_group_ids = course_id - common_group #新传入的班级id new_group_ids = course_id - common_group #新传入的班级id
if common_group.count > 0 #判断试卷的分班设置是否存在,存在则更新,负责则新建 if common_group.count > 0 #判断试卷的分班设置是否存在,存在则更新,负责则新建
exercise_group_sets = exercise_groups.find_in_exercise_group("course_group_id",common_group)
exercise_group_sets.each do |the_group_setting|
ex_group_params = { ex_group_params = {
:publish_time => exercise_publish_time, :publish_time => exercise_publish_time,
:end_time => exercise_end_time :end_time => exercise_end_time
} }
exercise_group_sets = exercise_groups.find_in_exercise_group("course_group_id",common_group)
the_group_setting = exercise_group_sets.first
if the_group_setting.present?
the_group_setting_status = set_exercise_status(the_group_setting.publish_time,the_group_setting.end_time) the_group_setting_status = set_exercise_status(the_group_setting.publish_time,the_group_setting.end_time)
if the_group_setting_status == 2 if the_group_setting_status == 2
ex_group_params = { ex_group_params = {
@ -537,8 +537,8 @@ class ExercisesController < ApplicationController
:end_time => the_group_setting.end_time :end_time => the_group_setting.end_time
} }
end end
the_group_setting.update_attributes!(ex_group_params)
end end
exercise_group_sets.update_all(ex_group_params)
end end
if new_group_ids.size > 0 if new_group_ids.size > 0
new_group_ids.each do |c| new_group_ids.each do |c|
@ -560,8 +560,9 @@ class ExercisesController < ApplicationController
error_count == 0 error_count == 0
normal_status(-1,"已发布/已截止的试卷不允许修改时间") normal_status(-1,"已发布/已截止的试卷不允许修改时间")
else else
# 未发布的分班设置才能删除
if old_exercise_groups.size > 0 if old_exercise_groups.size > 0
old_all_ex_groups = exercise_groups.find_in_exercise_group("course_group_id",old_exercise_groups) old_all_ex_groups = exercise_groups.find_in_exercise_group("course_group_id",old_exercise_groups).exercise_group_not_published
old_all_ex_groups.destroy_all old_all_ex_groups.destroy_all
end end
#试卷更新为exercise_group_setting的发布时间最小截止时间最大 #试卷更新为exercise_group_setting的发布时间最小截止时间最大
@ -720,8 +721,8 @@ class ExercisesController < ApplicationController
if exercise.unified_setting if exercise.unified_setting
ex_status = exercise.exercise_status #则为试卷的状态 ex_status = exercise.exercise_status #则为试卷的状态
else else
ex_status = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",params[:group_ids]) ex_status = @course.course_groups.where(id: params[:group_ids]).size !=
.exercise_group_not_published.present? ? 1 : 0 exercise.exercise_group_settings.where("course_group_id", params[:group_ids]).exercise_group_published.size ? 1 : 0
end end
if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过 if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过
g_course = group_ids #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改 g_course = group_ids #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改
@ -739,8 +740,8 @@ class ExercisesController < ApplicationController
g_course.each_with_index do |i, index| g_course.each_with_index do |i, index|
exercise_group_setting = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",i).first #根据课堂分班的id寻找试卷所在的班级 exercise_group_setting = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",i).first #根据课堂分班的id寻找试卷所在的班级
group_end_time = params[:detail] ? group_end_times[index] : ex_end_time group_end_time = params[:detail] ? group_end_times[index] : ex_end_time
if exercise_group_setting #如果该试卷分组存在,则更新,否则新建 if exercise_group_setting.present? #如果该试卷分组存在,则更新,否则新建
exercise_group_setting.update_attributes(publish_time: Time.now, end_time: group_end_time) exercise_group_setting.update_attributes!(publish_time: Time.now, end_time: group_end_time)
else else
p_course_group = { p_course_group = {
:exercise_id => exercise.id, :exercise_id => exercise.id,
@ -1152,7 +1153,7 @@ class ExercisesController < ApplicationController
# 1 老师权限0 学生权限 # 1 老师权限0 学生权限
@is_teacher_or = (@user_course_identity < Course::STUDENT) ? 1 : 0 @is_teacher_or = (@user_course_identity < Course::STUDENT) ? 1 : 0
@student_status = 2 @student_status = 2
@exercise_questions = @exercise.exercise_questions.includes(:exercise_shixun_challenges,:exercise_standard_answers,:exercise_answers,:exercise_shixun_answers).order("question_number ASC") @exercise_questions = @exercise.exercise_questions.includes(:exercise_shixun_challenges,:exercise_standard_answers,:exercise_answers,:exercise_shixun_answers,:exercise_answer_comments).order("question_number ASC")
@question_status = [] @question_status = []
get_exercise_status = @exercise.get_exercise_status(current_user) #当前用户的试卷状态 get_exercise_status = @exercise.get_exercise_status(current_user) #当前用户的试卷状态
@ex_answer_status = @exercise.get_exercise_status(@ex_user&.user) #当前试卷用户的试卷状态 @ex_answer_status = @exercise.get_exercise_status(@ex_user&.user) #当前试卷用户的试卷状态
@ -1715,9 +1716,9 @@ class ExercisesController < ApplicationController
ques_number = q.question_number ques_number = q.question_number
end end
if q.question_type != Exercise::PRACTICAL if q.question_type != Exercise::PRACTICAL
ques_vote = q.exercise_answers.search_exercise_answer("user_id",user_id) ques_vote = q.exercise_answers.select{|answer| answer.user_id == user_id}
else else
ques_vote = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id) ques_vote = q.exercise_shixun_answers.select{|answer| answer.user_id == user_id}
end end
ques_status = 0 ques_status = 0
if ques_vote.present? if ques_vote.present?

@ -9,19 +9,20 @@ class FilesController < ApplicationController
before_action :set_pagination, only: %i[index public_with_course_and_project mine_with_course_and_project] before_action :set_pagination, only: %i[index public_with_course_and_project mine_with_course_and_project]
before_action :validate_upload_params, only: %i[upload import] before_action :validate_upload_params, only: %i[upload import]
before_action :find_file, only: %i[show setting update] before_action :find_file, only: %i[show setting update]
before_action :publish_params, only: %i[upload import update]
SORT_TYPE = %w[created_on downloads quotes] SORT_TYPE = %w[created_on downloads quotes]
def index def index
sort = params[:sort] || 0 # 0: 降序1: 升序 sort = params[:sort] || 0 # 0: 降序1: 升序
sort_type = params[:sort_type] || 'created_on' # created_on时间排序 downloads下载次数排序; quotes: 引用次数排序 sort_type = params[:sort_type] || 'created_on' # created_on时间排序 downloads下载次数排序; quotes: 引用次数排序
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id @course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
@user = current_user @user = current_user
@attachments = course_second_category_id.to_i == 0 ? @course.attachments : @course.attachments.by_course_second_category_id(course_second_category_id) @attachments = @course_second_category_id.to_i == 0 ? @course.attachments.includes(:course_second_category) : @course.attachments.by_course_second_category_id(@course_second_category_id)
@attachments = @attachments.includes(attachment_group_settings: :course_group, author: [:user_extension, :course_members]) @attachments = @attachments.includes(author: [:user_extension, :course_members])
.ordered(sort: sort.to_i, sort_type: sort_type.strip) .ordered(sort: sort.to_i, sort_type: sort_type.strip)
get_category(@course, course_second_category_id) get_category(@course, @course_second_category_id)
@total_count = @attachments.size @total_count = @attachments.size
@publish_count = @attachments.published.size @publish_count = @attachments.published.size
@unpublish_count = @total_count - @publish_count @unpublish_count = @total_count - @publish_count
@ -137,9 +138,9 @@ class FilesController < ApplicationController
def upload def upload
attachment_ids = params[:attachment_ids] attachment_ids = params[:attachment_ids]
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
is_unified_setting = params.has_key?(:is_unified_setting) ? params[:is_unified_setting] : true # is_unified_setting = params.has_key?(:is_unified_setting) ? params[:is_unified_setting] : true
publish_time = params[:publish_time] # publish_time = params[:publish_time]
course_group_publish_times = params[:course_group_publish_times] || [] # course_group_publish_times = params[:course_group_publish_times] || []
begin begin
attachment_ids.each do |attchment_id| attachment_ids.each do |attchment_id|
@ -148,9 +149,12 @@ class FilesController < ApplicationController
attachment.container = @course attachment.container = @course
attachment.course_second_category_id = course_second_category_id attachment.course_second_category_id = course_second_category_id
attachment.description = params[:description] attachment.description = params[:description]
attachment.is_public = params[:is_public] ? 1 : 0 attachment.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0
attachment.set_publish_time(publish_time) if is_unified_setting attachment.is_publish = @atta_is_publish
attachment.set_course_group_publish_time(@course, course_group_publish_times) if @course.course_groups.size > 0 && !is_unified_setting && publish_time.blank? attachment.delay_publish = @atta_delay_publish
attachment.publish_time = @atta_publish_time
# attachment.set_publish_time(publish_time) if is_unified_setting
# attachment.set_course_group_publish_time(@course, course_group_publish_times) if @course.course_groups.size > 0 && !is_unified_setting && publish_time.blank?
attachment.save! attachment.save!
end end
end end
@ -188,8 +192,9 @@ class FilesController < ApplicationController
attach_copied_obj.created_on = Time.now attach_copied_obj.created_on = Time.now
attach_copied_obj.author = current_user attach_copied_obj.author = current_user
attach_copied_obj.is_public = 0 attach_copied_obj.is_public = 0
attach_copied_obj.is_publish = 1 attach_copied_obj.is_publish = @atta_is_publish
attach_copied_obj.publish_time = Time.now attach_copied_obj.delay_publish = @atta_delay_publish
attach_copied_obj.publish_time = @atta_publish_time
attach_copied_obj.course_second_category_id = course_second_category_id attach_copied_obj.course_second_category_id = course_second_category_id
attach_copied_obj.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from attach_copied_obj.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from
if attach_copied_obj.attachtype == nil if attach_copied_obj.attachtype == nil
@ -209,11 +214,7 @@ class FilesController < ApplicationController
def update def update
return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@course) >= 5 && @file.author != current_user return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@course) >= 5 && @file.author != current_user
is_unified_setting = params[:is_unified_setting]
publish_time = params[:publish_time]
publish_time = format_time(Time.parse(publish_time)) unless publish_time.blank?
is_public = params[:is_public] is_public = params[:is_public]
course_group_publish_times = params[:course_group_publish_times] || []
@old_attachment = @file @old_attachment = @file
@new_attachment = Attachment.find_by_id params[:new_attachment_id] @new_attachment = Attachment.find_by_id params[:new_attachment_id]
@ -225,25 +226,29 @@ class FilesController < ApplicationController
old_course_second_category_id = @old_attachment.course_second_category_id old_course_second_category_id = @old_attachment.course_second_category_id
@old_attachment.copy_attributes_from_new_attachment(@new_attachment) @old_attachment.copy_attributes_from_new_attachment(@new_attachment)
@old_attachment.is_public = is_public == true ? 1 : 0 if is_public
@old_attachment.course_second_category_id = old_course_second_category_id @old_attachment.course_second_category_id = old_course_second_category_id
@old_attachment.save! @old_attachment.save!
@new_attachment.delete @new_attachment.delete
end end
@old_attachment.is_public = is_public == true && @course.is_public == 1 ? 1 : 0
@old_attachment.is_publish = @atta_is_publish
@old_attachment.delay_publish = @atta_delay_publish
@old_attachment.publish_time = @atta_publish_time
if params[:description] && !params[:description].strip.blank? && params[:description] != @old_attachment.description if params[:description] && !params[:description].strip.blank? && params[:description] != @old_attachment.description
@old_attachment.description = params[:description] @old_attachment.description = params[:description]
end end
@old_attachment.set_public(is_public) # @old_attachment.set_public(is_public)
if is_unified_setting # if is_unified_setting
@old_attachment.set_publish_time(publish_time) # @old_attachment.set_publish_time(publish_time)
@old_attachment.attachment_group_settings.destroy_all # @old_attachment.attachment_group_settings.destroy_all
end # end
if publish_time.blank? && @course.course_groups.size > 0 && !is_unified_setting # if publish_time.blank? && @course.course_groups.size > 0 && !is_unified_setting
@old_attachment.set_course_group_publish_time(@course, course_group_publish_times) # @old_attachment.set_course_group_publish_time(@course, course_group_publish_times)
end # end
@old_attachment.save! @old_attachment.save!
rescue Exception => e rescue Exception => e
@ -304,11 +309,19 @@ class FilesController < ApplicationController
end end
def file_validate_sort_type def file_validate_sort_type
normal_status(-2, "参数sort_tyope暂时只支持 'created_on', 'quotes', 'downloads'") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip) normal_status(-2, "参数sort_type暂时只支持 'created_on', 'quotes', 'downloads'") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
end end
def validate_upload_params def validate_upload_params
find_attachment_ids find_attachment_ids
find_course_second_category_id find_course_second_category_id
end end
def publish_params
tip_exception("缺少发布参数") if params[:delay_publish].blank?
tip_exception("缺少延期发布的时间参数") if params[:delay_publish].to_i == 1 && params[:publish_time].blank?
@atta_is_publish = params[:delay_publish].to_i == 1 && params[:publish_time].to_time > Time.now ? 0 : 1
@atta_delay_publish = params[:delay_publish].to_i
@atta_publish_time = params[:delay_publish].to_i == 1 && params[:publish_time] ? params[:publish_time] : Time.now
end
end end

@ -160,7 +160,8 @@ class HomeworkCommonsController < ApplicationController
# 作品状态 0 未提交, 1 按时提交, 2 延迟提交 # 作品状态 0 未提交, 1 按时提交, 2 延迟提交
if params[:work_status].present? if params[:work_status].present?
work_status = params[:work_status].map{|status| status.to_i} params_work_status = request.get? ? params[:work_status].split(",") : params[:work_status]
work_status = params_work_status.map{|status| status.to_i}
all_student_works = @student_works.left_joins(:myshixun) all_student_works = @student_works.left_joins(:myshixun)
@student_works = all_student_works.where(work_status: work_status) @student_works = all_student_works.where(work_status: work_status)
@ -170,7 +171,8 @@ class HomeworkCommonsController < ApplicationController
# 分班情况 # 分班情况
unless params[:course_group].blank? unless params[:course_group].blank?
group_user_ids = @course.students.where(course_group_id: params[:course_group]).pluck(:user_id) group_ids = request.get? ? params[:course_group].split(",") : params[:course_group]
group_user_ids = @course.students.where(course_group_id: group_ids).pluck(:user_id)
# 有分组只可能是老师身份查看列表 # 有分组只可能是老师身份查看列表
@student_works = @student_works.where(user_id: group_user_ids) @student_works = @student_works.where(user_id: group_user_ids)
end end
@ -482,7 +484,7 @@ class HomeworkCommonsController < ApplicationController
publish_time = setting[:publish_time] == "" ? Time.now : setting[:publish_time] publish_time = setting[:publish_time] == "" ? Time.now : setting[:publish_time]
# 截止时间为空时取发布时间后一个月 # 截止时间为空时取发布时间后一个月
end_time = setting[:end_time] == "" ? Time.at(publish_time.to_time.to_i+30*24*3600) : setting[:end_time] end_time = setting[:end_time]
HomeworkGroupSetting.where(homework_common_id: @homework.id, course_group_id: setting[:group_id]). HomeworkGroupSetting.where(homework_common_id: @homework.id, course_group_id: setting[:group_id]).
update_all(publish_time: publish_time, end_time: end_time) update_all(publish_time: publish_time, end_time: end_time)
setting_group_ids << setting[:group_id] setting_group_ids << setting[:group_id]
@ -1170,7 +1172,7 @@ class HomeworkCommonsController < ApplicationController
# 可立即截止的分班:统一设置则是用户管理的所有分班,否则是当前用户管理的分班中已发布且未截止的 # 可立即截止的分班:统一设置则是用户管理的所有分班,否则是当前用户管理的分班中已发布且未截止的
charge_group_ids = @course.charge_group_ids(@current_user) # 当前用户管理的分班 charge_group_ids = @course.charge_group_ids(@current_user) # 当前用户管理的分班
group_ids = @homework.unified_setting ? charge_group_ids : group_ids = @homework.unified_setting ? charge_group_ids :
@homework.homework_group_settings.where(course_group_id: charge_group_ids).none_end.pluck(:course_group_id) @homework.homework_group_settings.where(course_group_id: charge_group_ids).published_no_end.pluck(:course_group_id)
@course_groups = @course.course_groups.where(id: group_ids) @course_groups = @course.course_groups.where(id: group_ids)
else else
tip_exception("没有可截止的分班") tip_exception("没有可截止的分班")

@ -279,7 +279,8 @@ class PollsController < ApplicationController
if poll.unified_setting if poll.unified_setting
pl_status = poll.polls_status #则为试卷的状态 pl_status = poll.polls_status #则为试卷的状态
else else
pl_status = poll.poll_group_settings.find_in_poll_group("course_group_id",params[:group_ids]).poll_group_not_published.present? ? 1 : 0 #立即发布针对分组设置的全部未发布的班级才生效 pl_status = @course.course_groups.where(id: params[:group_ids]).size !=
poll.poll_group_settings.where("course_group_id",params[:group_ids]).poll_group_published.size ? 1 : 0 #立即发布针对分组设置的全部未发布的班级才生效
end end
if pl_status == 1 #如果问卷存在已发布的,或者是已截止的,那么则直接跳过 if pl_status == 1 #如果问卷存在已发布的,或者是已截止的,那么则直接跳过
g_course = group_ids #表示是否传入分班参数,如果传入分班的参数那么poll的统一设置需修改 g_course = group_ids #表示是否传入分班参数,如果传入分班的参数那么poll的统一设置需修改
@ -782,13 +783,13 @@ class PollsController < ApplicationController
common_group = poll_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的 common_group = poll_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的
new_group_ids = course_id - common_group #新传入的班级id new_group_ids = course_id - common_group #新传入的班级id
if common_group.size > 0 #传入的参数存在已发布的分班 if common_group.size > 0 #传入的参数存在已发布的分班
poll_group = poll_groups.find_in_poll_group("course_group_id",common_group)
poll_group.each do |the_group_setting|
poll_group_params = { poll_group_params = {
:publish_time => poll_publish_time, :publish_time => poll_publish_time,
:end_time => poll_end_time :end_time => poll_end_time
} }
poll_group = poll_groups.find_in_poll_group("course_group_id",common_group)
the_group_setting = poll_group.first
if the_group_setting.present?
the_group_setting_status = set_poll_status(the_group_setting.publish_time,the_group_setting.end_time) the_group_setting_status = set_poll_status(the_group_setting.publish_time,the_group_setting.end_time)
if the_group_setting_status == 2 if the_group_setting_status == 2
poll_group_params = { poll_group_params = {
@ -801,8 +802,8 @@ class PollsController < ApplicationController
:end_time => the_group_setting.end_time :end_time => the_group_setting.end_time
} }
end end
the_group_setting.update_attributes(poll_group_params)
end end
poll_group.update_all(poll_group_params)
end end
if new_group_ids.size > 0 if new_group_ids.size > 0
new_group_ids.each do |c| new_group_ids.each do |c|
@ -824,8 +825,9 @@ class PollsController < ApplicationController
error_count == 0 error_count == 0
normal_status(-1,"已发布/已截止的问卷不允许修改时间") normal_status(-1,"已发布/已截止的问卷不允许修改时间")
else else
# 未发布的分班设置才能删除
if old_poll_groups.size > 0 if old_poll_groups.size > 0
old_all_poll_groups = poll_groups.find_in_poll_group("course_group_id",old_poll_groups) old_all_poll_groups = poll_groups.find_in_poll_group("course_group_id",old_poll_groups).poll_group_not_published
old_all_poll_groups.destroy_all old_all_poll_groups.destroy_all
end end
#问卷更新为poll_group_setting的发布时间最小截止时间最大 #问卷更新为poll_group_setting的发布时间最小截止时间最大

@ -0,0 +1,34 @@
class Weapps::BaseController < ApplicationController
private
def require_wechat_login!
return if session_unionid.present?
render_error('请先进行微信授权')
end
def weapp_session_key
Wechat::Weapp.session_key(session_openid)
end
def set_weapp_session_key(session_key)
Wechat::Weapp.write_session_key(session_openid, session_key)
end
def session_openid
session[:openid]
end
def set_session_openid(openid)
session[:openid] = openid
end
def session_unionid
session[:unionid]
end
def set_session_unionid(unionid)
session[:unionid] = unionid
end
end

@ -0,0 +1,24 @@
class Weapps::CodeSessionsController < Weapps::BaseController
def create
return render_error('code不能为空') if params[:code].blank?
result = Wechat::Weapp.jscode2session(params[:code])
set_session_openid(result['openid'])
set_weapp_session_key(result['session_key']) # weapp session_key写入缓存 后续解密需要
# 已授权,绑定过账号
open_user = OpenUser::Wechat.find_by(uid: result['unionid'])
if open_user.present? && open_user.user
set_session_unionid(result['unionid'])
successful_authentication(open_user.user)
else
# 新用户
user_info = Wechat::Weapp.decrypt(result['session_key'], params[:encrypted_data], params[:iv])
set_session_unionid(user_info['unionId'])
end
render_ok(openid: result['openid'])
end
end

@ -0,0 +1,12 @@
class Weapps::HomesController < Weapps::BaseController
def show
# banner图
@images = PortalImage.where(status: true).order(position: :asc)
# 热门实训
@shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(4)
# 热门实践课程
@subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(4)
end
end

@ -0,0 +1,63 @@
class Weapps::RegistersController < Weapps::BaseController
before_action :require_wechat_login!
def create
# 查询验证码是否正确;type只可能是1或者8
type = phone_mail_type(params[:login].strip)
code = params[:code].strip
if type == 1
uid_logger("start register by phone: type is #{type}")
pre = 'p'
email = nil
phone = params[:login]
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
else
uid_logger("start register by email: type is #{type}")
pre = 'm'
email = params[:login]
phone = nil
verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
end
uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
# todo 上线前请删除万能验证码"513231"
unless code == "513231" && request.subdomain == "test-newweb"
return render_error('验证码不正确') if verifi_code.try(:code) != code.strip
return render_error('验证码已失效') if !verifi_code&.effective?
end
login = User.generate_login(pre)
@user = User.new(admin: false, login: login, mail: email, phone: phone, type: 'User')
@user.password = params[:password]
# 现在因为是验证码,所以在注册的时候就可以激活
@user.activate
# 必须要用save操作密码的保存是在users中
ActiveRecord::Base.transaction do
@user.save!
UserExtension.create!(user_id: @user.id)
# 绑定微信号
OpenUsers::Wechat.create!(user: @user, uid: session_unionid)
# 注册完成手机号或邮箱想可以奖励500金币
RewardGradeService.call(
@user,
container_id: @user.id,
container_type: pre == 'p' ? 'Phone' : 'Mail',
score: 500
)
end
successful_authentication(@user)
session[:user_id] = @user.id
render_ok
end
private
# 1 手机类型0 邮箱类型
# 注意新版的login是自动名生成的
def phone_mail_type value
value =~ /^1\d{10}$/ ? 1 : 0
end
end

@ -0,0 +1,24 @@
class Weapps::SessionsController < Weapps::BaseController
before_action :require_wechat_login!
def create
return render_error('重复登录') if current_user.present? && current_user.logged?
user = User.try_to_login(params[:login], params[:password])
return render_error('错误的账号或密码') if user.blank?
return render_error('违反平台使用规范,账号已被锁定') if user.locked?
return render_error('错误的账号或密码') unless user.check_password?(params[:password].to_s)
if user.wechat_open_user && user.wechat_open_user.uid != session_unionid
render_error('该账号已被其它微信号绑定')
return
end
# 绑定微信号
OpenUsers::Wechat.create!(user: user, uid: session_unionid) if user.wechat_open_user.blank?
successful_authentication(user)
render_ok
end
end

@ -0,0 +1,8 @@
class Weapps::VerifiesController < Weapps::BaseController
before_action :require_wechat_login!
def create
valid = Wechat::Weapp.verify?(session_openid, params[:verify_string], params[:signature])
render_ok(valid: valid)
end
end

@ -4,5 +4,4 @@ class Users::UpdatePasswordForm
attr_accessor :password, :old_password attr_accessor :password, :old_password
validates :password, presence: true validates :password, presence: true
validates :old_password, presence: true
end end

@ -62,7 +62,7 @@ module CoursesHelper
course_board = course.course_board course_board = course.course_board
"/courses/#{course.id}/boards/#{course_board.id}" "/courses/#{course.id}/boards/#{course_board.id}"
when "course_group" when "course_group"
"/courses/#{course.id}/students" "/courses/#{course.id}/course_groups"
end end
end end

@ -10,9 +10,9 @@ module ExercisesHelper
exercise_obj_status.each do |q| exercise_obj_status.each do |q|
q_type = q.question_type q_type = q.question_type
if q_type == Exercise::PRACTICAL if q_type == Exercise::PRACTICAL
answers_content = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id) answers_content = q.exercise_shixun_answers.select{|answer| answer.user_id == user_id}
else else
answers_content = q.exercise_answers.search_answer_users("user_id",user_id) answers_content = q.exercise_answers.select{|answer| answer.user_id == user_id}
end end
if q_type <= Exercise::JUDGMENT if q_type <= Exercise::JUDGMENT
@ -40,7 +40,7 @@ module ExercisesHelper
ques_score = 0.0 ques_score = 0.0
end end
else else
ques_score = answers_content.score_reviewed.select(:score).pluck(:score).sum ques_score = answers_content.select{|answer| answer.score >= 0.0}.pluck(:score).sum
end end
if ques_score >= q.question_score #满分作答为正确 if ques_score >= q.question_score #满分作答为正确
@ -64,7 +64,7 @@ module ExercisesHelper
exercise_sub_status = exercise_questions.find_by_custom("question_type",Exercise::SUBJECTIVE) #主观题 exercise_sub_status = exercise_questions.find_by_custom("question_type",Exercise::SUBJECTIVE) #主观题
@ex_sub_array = [] #主观题的已答/未答 @ex_sub_array = [] #主观题的已答/未答
exercise_sub_status.each do |s| exercise_sub_status.each do |s|
sub_answer = s.exercise_answers.search_answer_users("user_id",user_id) #主观题只有一个回答 sub_answer = s.exercise_answers.select{|answer| answer.user_id == user_id} #主观题只有一个回答
if sub_answer.present? && sub_answer.first.score >= 0.0 if sub_answer.present? && sub_answer.first.score >= 0.0
if s.question_score <= sub_answer.first.score if s.question_score <= sub_answer.first.score
stand_status = 1 stand_status = 1
@ -772,12 +772,12 @@ module ExercisesHelper
question_comment = [] question_comment = []
# user_score_pre = nil # user_score_pre = nil
if ques_type == 5 if ques_type == 5
exercise_answers = q.exercise_shixun_answers.search_shixun_answers("user_id",ex_answerer_id) exercise_answers = q.exercise_shixun_answers.select{|answer| answer.user_id == ex_answerer_id}
else else
exercise_answers = q.exercise_answers.search_exercise_answer("user_id",ex_answerer_id) #试卷用户的回答 exercise_answers = q.exercise_answers.select{|answer| answer.user_id == ex_answerer_id} #试卷用户的回答
end end
if student_status == 2 #当前为老师,或为学生且已提交 if student_status == 2 #当前为老师,或为学生且已提交
user_score_pre = exercise_answers.score_reviewed user_score_pre = exercise_answers.select{|answer| answer.score >= 0.0}
if ques_type == 4 #主观题时且没有大于0的分数时为空 if ques_type == 4 #主观题时且没有大于0的分数时为空
user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : nil user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : nil
elsif ques_type == 5 || ques_type == 3 elsif ques_type == 5 || ques_type == 3
@ -829,7 +829,7 @@ module ExercisesHelper
if ex_type == 4 #填空题/主观题/实训题有评论的 if ex_type == 4 #填空题/主观题/实训题有评论的
q_answer_id = exercise_answers.present? ? exercise_answers.first.id : nil q_answer_id = exercise_answers.present? ? exercise_answers.first.id : nil
question_comment = q.exercise_answer_comments.search_answer_comments("exercise_answer_id",q_answer_id) question_comment = q.exercise_answer_comments.select{|comment| comment.exercise_answer_id == q_answer_id}
end end
{ {
"user_score": (user_score.present? ? user_score.round(1).to_s : nil), "user_score": (user_score.present? ? user_score.round(1).to_s : nil),

@ -452,7 +452,7 @@ module ExportHelper
end end
end end
out_file_name = "作品附件_#{homework_common&.course&.name}_#{homework_common.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.zip" out_file_name = "作品附件_#{homework_common.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.zip"
out_file_name.gsub!(" ", "-") out_file_name.gsub!(" ", "-")
out_file_name.gsub!("/", "_") out_file_name.gsub!("/", "_")
out_file = find_or_pack(homework_common, homework_common.user_id, digests.sort){ out_file = find_or_pack(homework_common, homework_common.user_id, digests.sort){

@ -0,0 +1,22 @@
class HotSearchKeyword
class << self
def add(keyword)
return if keyword.blank?
Rails.cache.data.zincrby(redis_key, 1, keyword)
end
def hot(limit = 5)
Rails.cache.data.zrevrange(redis_key, 0, limit - 1)
end
def available?
Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
end
private
def redis_key
'educoder:es:hot_keyword'
end
end
end

@ -1,11 +0,0 @@
class Wechat::App
class << self
attr_accessor :appid, :secret
delegate :access_token, :jscode2session, to: :client
def client
@_client ||= Wechat::Client.new(appid, secret)
end
end
end

@ -0,0 +1,47 @@
class Wechat::Weapp
class << self
attr_accessor :appid, :secret
delegate :access_token, :jscode2session, to: :client
def client
@_client ||= Wechat::Client.new(appid, secret)
end
def session_key(openid)
Rails.cache.read(session_key_cache_key(openid))
end
def write_session_key(openid, session_key)
Rails.cache.write(session_key_cache_key(openid), session_key)
end
def verify?(openid, str, signature)
session_key = session_key(openid)
Digest::SHA1.hexdigest("#{str}#{session_key}") == signature
end
def decrypt(session_key, encrypted_data, iv)
session_key = Base64.decode64(session_key)
encrypted_data = Base64.decode64(encrypted_data)
iv = Base64.decode64(iv)
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher.decrypt
cipher.padding = 0
cipher.key = session_key
cipher.iv = iv
data = cipher.update(encrypted_data) << cipher.final
result = JSON.parse(data[0...-data.last.ord])
raise Wechat::Error, '解密错误' if result.dig('watermark', 'appid') != appid
result
end
private
def session_key_cache_key(openid)
"weapp:#{appid}:#{openid}:session_key"
end
end
end

@ -9,6 +9,8 @@ class Attachment < ApplicationRecord
belongs_to :course, foreign_key: :container_id, optional: true belongs_to :course, foreign_key: :container_id, optional: true
has_many :attachment_group_settings, :dependent => :destroy has_many :attachment_group_settings, :dependent => :destroy
has_many :attachment_histories, -> { order(version: :desc) }, :dependent => :destroy has_many :attachment_histories, -> { order(version: :desc) }, :dependent => :destroy
# 二级目录
belongs_to :course_second_category, optional: true
scope :by_filename_or_user_name, -> (keywords) { joins(:author).where("filename like :search or LOWER(concat(users.lastname, users.firstname)) LIKE :search", scope :by_filename_or_user_name, -> (keywords) { joins(:author).where("filename like :search or LOWER(concat(users.lastname, users.firstname)) LIKE :search",
:search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank? } :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank? }
@ -96,7 +98,7 @@ class Attachment < ApplicationRecord
def become_history def become_history
history = self.attachment_histories.first history = self.attachment_histories.first
new_attachment_history = AttachmentHistory.new(self.attributes.except("id", "resource_bank_id", "unified_setting", "course_second_category_id").merge( new_attachment_history = AttachmentHistory.new(self.attributes.except("id", "resource_bank_id", "unified_setting", "course_second_category_id", "delay_publish").merge(
attachment_id: self.id, attachment_id: self.id,
version: history.nil? ? 1 : history.version + 1, version: history.nil? ? 1 : history.version + 1,
)) ))
@ -104,7 +106,7 @@ class Attachment < ApplicationRecord
end end
def copy_attributes_from_new_attachment(new_attachment) def copy_attributes_from_new_attachment(new_attachment)
self.attributes = new_attachment.attributes.dup.except("id","container_id","container_type","is_public","downloads", "quotes",'is_publish','publish_time') self.attributes = new_attachment.attributes.dup.except("id","container_id","container_type","is_public","downloads", "quotes",'is_publish','publish_time', "delay_publish")
end end
def set_public(is_public) def set_public(is_public)

@ -18,6 +18,29 @@ class Competition < ApplicationRecord
after_create :create_competition_modules after_create :create_competition_modules
def mode_type
case mode
when 1
"课堂"
when 2
"实训"
when 3
"教学"
when 4
"托管"
else
"--"
end
end
def teacher_staff_num
teacher_staff ? "#{teacher_staff.minimum}~#{teacher_staff.maximum}" : "--"
end
def member_staff_num
member_staff ? "#{member_staff.minimum}~#{member_staff.maximum}" : "--"
end
# 是否上架 # 是否上架
def published? def published?
status? status?

@ -0,0 +1,3 @@
class CompetitionModeSetting < ApplicationRecord
belongs_to :course
end

@ -6,6 +6,6 @@ class HomeworkGroupSetting < ApplicationRecord
scope :none_published, -> {where("homework_group_settings.publish_time IS NULL OR homework_group_settings.publish_time > ?", Time.now)} scope :none_published, -> {where("homework_group_settings.publish_time IS NULL OR homework_group_settings.publish_time > ?", Time.now)}
scope :published_no_end, -> {where("homework_group_settings.publish_time IS NOT NULL AND homework_group_settings.publish_time < ? scope :published_no_end, -> {where("homework_group_settings.publish_time IS NOT NULL AND homework_group_settings.publish_time < ?
and homework_group_settings.end_time > ?", Time.now, Time.now)} and homework_group_settings.end_time > ?", Time.now, Time.now)}
scope :none_end, -> {where("homework_group_settings.end_time IS NOT NULL AND homework_group_settings.end_time > ?", Time.now)} scope :none_end, -> {where("homework_group_settings.end_time IS NULL or homework_group_settings.end_time > ?", Time.now)}
end end

@ -19,7 +19,7 @@ class Laboratory < ApplicationRecord
return if subdomain.blank? return if subdomain.blank?
rails_env = EduSetting.get('rails_env') rails_env = EduSetting.get('rails_env')
subdomain = subdomain.slice(0, subdomain.size - rails_env.size - 1) if subdomain.end_with?(rails_env) # winse.dev => winse subdomain = subdomain.slice(0, subdomain.size - rails_env.size - 1) if rails_env && subdomain.end_with?(rails_env) # winse.dev => winse
find_by_identifier(subdomain) find_by_identifier(subdomain)
end end

@ -43,7 +43,7 @@ class User < ApplicationRecord
has_many :myshixuns, :dependent => :destroy has_many :myshixuns, :dependent => :destroy
has_many :study_shixuns, through: :myshixuns, source: :shixun # 已学习的实训 has_many :study_shixuns, through: :myshixuns, source: :shixun # 已学习的实训
has_many :course_messages has_many :course_messages
has_many :courses, dependent: :destroy has_many :courses, foreign_key: 'tea_id', dependent: :destroy
#试卷 #试卷
has_many :exercise_banks, :dependent => :destroy has_many :exercise_banks, :dependent => :destroy
@ -274,7 +274,7 @@ class User < ApplicationRecord
# 课堂的学生 # 课堂的学生
def student_of_course?(course) def student_of_course?(course)
course.course_members.exists?(user_id: id, role: %i[STUDENT]) course.course_members.exists?(user_id: id, role: %i[STUDENT], is_active: 1)
end end
# 课堂成员 # 课堂成员
@ -642,6 +642,14 @@ class User < ApplicationRecord
login login
end end
def bind_open_user?(type)
case type
when 'wechat' then wechat_open_user.present?
when 'qq' then qq_open_user.present?
else false
end
end
protected protected
def validate_password_length def validate_password_length
# 管理员的初始密码是5位 # 管理员的初始密码是5位

@ -15,7 +15,7 @@ class Admins::LaboratoryQuery < ApplicationQuery
keyword = strip_param(:keyword) keyword = strip_param(:keyword)
if keyword.present? if keyword.present?
like_sql = 'schools.name LIKE :keyword OR laboratories.identifier LIKE :keyword' like_sql = 'schools.name LIKE :keyword OR laboratories.identifier LIKE :keyword'
laboratories = laboratories.joins(:school).where(like_sql, keyword: "%#{keyword}%") laboratories = laboratories.left_joins(:school).where(like_sql, keyword: "%#{keyword}%")
end end
custom_sort laboratories, params[:sort_by], params[:sort_direction] custom_sort laboratories, params[:sort_by], params[:sort_direction]

@ -30,7 +30,7 @@ class Admins::SaveLaboratorySettingService < ApplicationService
hash = {} hash = {}
hash[:name] = strip nav[:name] hash[:name] = strip nav[:name]
hash[:link] = strip nav[:link] hash[:link] = strip nav[:link]
hash[:hidden] = nav[:hidden].to_s == 0 hash[:hidden] = nav[:hidden].to_s != '0'
hash hash
end end
end end

@ -15,14 +15,16 @@ class CreateBindUserService < ApplicationService
return user return user
end end
bind_user = User.try_to_login(params[:login], params[:password]) bind_user = User.try_to_login(params[:username], params[:password])
raise Error, '用户名或者密码错误' if bind_user.blank? raise Error, '用户名或者密码错误' if bind_user.blank?
raise Error, '该账号已被其他微信号绑定,请更换其他账号进行绑定' if bind_user.bind_open_user?(params[:type].to_s)
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
open_user.user_id = bind_user.id open_user.user_id = bind_user.id
open_user.save! open_user.save!
user.destroy! user.user_extension.delete
user.delete
end end
clear_can_bind_user_flag clear_can_bind_user_flag

@ -17,7 +17,7 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService
new_user = true new_user = true
# 新用户 # 新用户
login = User.generate_login('q') login = User.generate_login('q')
@user = User.new(login: login, nickname: params.dig('info', 'nickname')) @user = User.new(login: login, nickname: params.dig('info', 'nickname'), type: 'User', status: User::STATUS_ACTIVE)
end end
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do

@ -24,7 +24,7 @@ class Oauth::CreateOrFindWechatAccountService < ApplicationService
new_user = true new_user = true
# 新用户 # 新用户
login = User.generate_login('w') login = User.generate_login('w')
@user = User.new(login: login, nickname: result['nickname']) @user = User.new(login: login, nickname: result['nickname'], type: 'User', status: User::STATUS_ACTIVE)
end end
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do

@ -0,0 +1,9 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('竞赛列表', admins_competitions_path) %>
<% end %>
<div class="box competitions-list-container">
<%= render partial: 'admins/competitions/shared/list', locals: { competitions: @competitions } %>
</div>
<%= render partial: 'admins/shared/modal/upload_file_modal', locals: { title: '上传图片' } %>

@ -0,0 +1,30 @@
<table class="table text-center shixun-settings-list-table">
<thead class="thead-light">
<th width="6%">序号</th>
<th width="14%" class="text-left">竞赛主标题</th>
<th width="10%">竞赛副标题</th>
<th width="8%">模式</th>
<th width="8%">报名人数</th>
<th width="8%">指导老师</th>
<th width="8%">参赛者</th>
<th width="14%">主题图片796*397</th>
<th width="8%">创建时间</th>
<th>
操作
</th>
</thead>
<tbody>
<% if competitions.present? %>
<% competitions.each_with_index do |competition, index| %>
<tr id="competition-item-<%= competition.id %>">
<% page_no = list_index_no(@params_page.to_i, index) %>
<%= render partial: "admins/competitions/shared/td",locals: {competition: competition, page_no: page_no} %>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: competitions } %>

@ -0,0 +1,27 @@
<td><%= page_no %></td>
<td class="text-left">
<span><%= link_to competition.name, enroll_list_admins_competition_path(competition), :target => "_blank", :title => competition.name %></span>
</td>
<td><%= competition.sub_title %></td>
<td><%= competition.mode_type %></td>
<td><%= @member_count_map&.fetch(competition.id, 0) || competition.team_members.count %></td>
<td><%= competition.teacher_staff_num %></td>
<td><%= competition.member_staff_num %></td>
<td class="shixun-setting-image">
<% imageExists = File.exist?(disk_filename("Competition", competition.id)) %>
<% imageUrl = imageExists ? '/' + url_to_avatar(competition) + "?#{Time.now.to_i}" : '' %>
<%= image_tag(imageUrl, width: 60, height: 40, class: "preview-image competition-image-#{competition.id}", data: { toggle: 'tooltip', title: '点击预览' }, style: imageExists ? '' : 'display:none') %>
<%= javascript_void_link imageExists ? '重新上传' : '上传图片', class: 'action upload-competition-image-action', data: { source_id: competition.id, source_type: 'Competition', toggle: 'modal', target: '.admin-upload-file-modal' } %>
</td>
<td><%= competition.created_at.strftime('%Y-%m-%d %H:%M') %></td>
<td class="action-container">
<%= link_to '配置', admins_competition_competition_setting_path(competition), class: 'action edit-action' %>
<% if !competition.status? && competition.published_at.blank? %>
<%= link_to '发布', publish_admins_competition_path(competition), class: 'action publish-action', method: :post, remote: true %>
<% else %>
<%= link_to '取消发布', unpublish_admins_competition_path(competition), class: 'action unpublish-action', method: :post, remote: true %>
<% end %>
<%= link_to competition.published? ? "下架" : "上架", online_switch_admins_competition_path(competition), class: 'action online-action', method: :post, remote: true %>
</td>

@ -66,6 +66,8 @@
<% end %> <% end %>
</li> </li>
<li><%= sidebar_item(admins_competitions_path, '竞赛', icon: 'trophy', controller: 'admins-competitions') %></li>
<li> <li>
<%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %> <%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
<li><%= sidebar_item(admins_carousels_path, '轮播图', icon: 'image', controller: 'admins-carousels') %></li> <li><%= sidebar_item(admins_carousels_path, '轮播图', icon: 'image', controller: 'admins-carousels') %></li>

@ -4,10 +4,11 @@ json.is_public attachment.publiced?
# json.is_lock attachment.locked?(@is_member) # json.is_lock attachment.locked?(@is_member)
json.is_lock !attachment.publiced? json.is_lock !attachment.publiced?
json.is_publish attachment.published? json.is_publish attachment.published?
json.delay_publish attachment.delay_publish
json.publish_time attachment.publish_time json.publish_time attachment.publish_time
json.unified_setting attachment.unified_setting json.unified_setting attachment.unified_setting
json.filesize number_to_human_size(attachment.filesize) json.filesize number_to_human_size(attachment.filesize)
json.quotes attachment.quotes_count # json.quotes attachment.quotes_count
json.description attachment.description json.description attachment.description
json.downloads_count attachment.downloads_count json.downloads_count attachment.downloads_count
json.created_on attachment.created_on json.created_on attachment.created_on

@ -20,7 +20,7 @@ json.competitions do
if section if section
json.current_stage do json.current_stage do
json.name = section.competition_stage.name json.name section.competition_stage.name
json.start_time section.display_start_time json.start_time section.display_start_time
json.end_time section.display_end_time json.end_time section.display_end_time
end end

@ -11,7 +11,7 @@ json.course_modules @course_modules.each do |mod|
case mod.module_type case mod.module_type
when "course_group" when "course_group"
# json.none_group_count @course.none_group_count # json.none_group_count @course.none_group_count
json.second_category left_group_info @course # json.second_category left_group_info @course
when "board" when "board"
course_board = @course.course_board course_board = @course.course_board
if course_board.present? if course_board.present?

@ -1,5 +1,6 @@
json.partial! "commons/success" json.partial! "commons/success"
json.data do json.data @courses do |course|
json.array! @courses, :id, :name, :updated_at json.(course, :id, :name, :updated_at, :end_date)
json.created_at course.created_at.strftime("%Y-%m-%d")
end end

@ -1,7 +1,7 @@
json.students do json.students do
json.array! @students do |student| json.array! @students do |student|
json.user_id student.user_id json.user_id student.user_id
# json.login student.user.try(:login) json.login student.user.try(:login)
json.name student.user.try(:real_name) json.name student.user.try(:real_name)
json.name_link user_path(student.user) json.name_link user_path(student.user)
json.student_id student.user.try(:student_id) json.student_id student.user.try(:student_id)

@ -15,7 +15,7 @@ json.is_admin @user_course_identity < Course::PROFESSOR
json.is_public @course.is_public == 1 json.is_public @course.is_public == 1
json.code_halt @course.invite_code_halt == 1 json.code_halt @course.invite_code_halt == 1
json.invite_code @course.invite_code_halt == 0 ? @course.generate_invite_code : "" json.invite_code @course.invite_code_halt == 0 ? @course.generate_invite_code : ""
json.switch_to_student switch_student_role(@is_teacher, @course, @user) json.switch_to_student @switch_student
json.switch_to_teacher switch_teacher_role(@is_student, @course, @user) json.switch_to_teacher switch_teacher_role(@is_student, @course, @user)
json.switch_to_assistant switch_assistant_role(@is_student, @course, @user) json.switch_to_assistant switch_assistant_role(@is_student, @course, @user)
#json.join_course !@user.member_of_course?(@course) #json.join_course !@user.member_of_course?(@course)

@ -65,7 +65,7 @@ json.exercise_questions do
shixun_type: user_ques_answers[:shixun_type], shixun_type: user_ques_answers[:shixun_type],
ques_position: nil, ques_position: nil,
edit_type:nil edit_type:nil
if user_ques_comments.count > 0 if user_ques_comments.size > 0
json.question_comments do json.question_comments do
json.partial! "exercises/exercise_comments", question_comment:user_ques_answers[:question_comment].first json.partial! "exercises/exercise_comments", question_comment:user_ques_answers[:question_comment].first
end end

@ -13,7 +13,10 @@ json.data do
json.author do json.author do
json.partial! "users/user_simple", user: attachment.author json.partial! "users/user_simple", user: attachment.author
end end
json.partial! "files/course_groups", attachment_group_settings: attachment.attachment_group_settings # json.partial! "files/course_groups", attachment_group_settings: attachment.attachment_group_settings
if @course_second_category_id.to_i == 0
json.category_name attachment.course_second_category&.name
end
end end
end end
end end

@ -1,3 +1,3 @@
json.partial! 'attachments/attachment', attachment: @file json.partial! 'attachments/attachment', attachment: @file
json.partial! "files/course_groups", attachment_group_settings: @file.attachment_group_settings # json.partial! "files/course_groups", attachment_group_settings: @file.attachment_group_settings
json.partial! "attachment_histories/list", attachment_histories: @attachment_histories json.partial! "attachment_histories/list", attachment_histories: @attachment_histories

@ -5,10 +5,11 @@ json.partial! "homework_btn_check", locals: {identity: @user_course_identity, ho
json.partial! "student_btn_check", locals: {identity: @user_course_identity, homework: @homework, work: @work} json.partial! "student_btn_check", locals: {identity: @user_course_identity, homework: @homework, work: @work}
json.description @homework.description json.description @homework.description
# 实训作业才有说明 # 实训作业才有说明
if @homework.homework_type == "practice" if @homework.homework_type == "practice"
json.explanation @homework.explanation json.explanation @homework.explanation
# else
# json.description @homework.description
end end
# 附件 # 附件

@ -2,9 +2,9 @@ json.setting do
setting = @laboratory.laboratory_setting setting = @laboratory.laboratory_setting
json.name setting.name || default_setting.name json.name setting.name || default_setting.name
json.nav_logo_url setting.nav_logo_url || default_setting.nav_logo_url json.nav_logo_url (setting.nav_logo_url || default_setting.nav_logo_url)&.[](1..-1)
json.login_logo_url setting.login_logo_url || default_setting.login_logo_url json.login_logo_url (setting.login_logo_url || default_setting.login_logo_url)&.[](1..-1)
json.tab_logo_url setting.tab_logo_url || default_setting.tab_logo_url json.tab_logo_url (setting.tab_logo_url || default_setting.tab_logo_url)&.[](1..-1)
json.navbar setting.navbar || default_setting.navbar json.navbar setting.navbar || default_setting.navbar

@ -0,0 +1,14 @@
json.images do
json.array! @images do |image|
json.path image.link
json.image_url Util::FileManage.source_disk_file_url(image)
end
end
json.shixuns do
json.partial! 'shixuns/shixun', locals: { shixuns: @shixuns }
end
json.subjects do
json.partial! 'subjects/subject', locals: { subjects: @subjects }
end

@ -18,6 +18,9 @@ defaults: &defaults
wechat: wechat:
appid: 'test' appid: 'test'
secret: 'test' secret: 'test'
weapp:
appid: 'test'
secret: 'test'
development: development:
<<: *defaults <<: *defaults

@ -1,9 +1,12 @@
wechat_config = {} wechat_config = {}
weapp_config = {}
begin begin
config = Rails.application.config_for(:configuration) config = Rails.application.config_for(:configuration)
wechat_config = config['wechat'] wechat_config = config['wechat']
weapp_config = config['weapp']
raise 'wechat config missing' if wechat_config.blank? raise 'wechat config missing' if wechat_config.blank?
raise 'weapp config missing' if weapp_config.blank?
rescue => ex rescue => ex
raise ex if Rails.env.production? raise ex if Rails.env.production?
@ -12,5 +15,10 @@ rescue => ex
wechat_config = {} wechat_config = {}
end end
# 网站应用
Wechat::OfficialAccount.appid = wechat_config['appid'] Wechat::OfficialAccount.appid = wechat_config['appid']
Wechat::OfficialAccount.secret = wechat_config['secret'] Wechat::OfficialAccount.secret = wechat_config['secret']
# 小程序
Wechat::Weapp.appid = weapp_config['appid']
Wechat::Weapp.secret = weapp_config['secret']

@ -829,6 +829,14 @@ Rails.application.routes.draw do
get '/auth/qq/callback', to: 'oauth/qq#create' get '/auth/qq/callback', to: 'oauth/qq#create'
get '/auth/wechat/callback', to: 'oauth/wechat#create' get '/auth/wechat/callback', to: 'oauth/wechat#create'
resource :bind_user, only: [:create] resource :bind_user, only: [:create]
namespace :weapps do
resource :home, only: [:show]
resource :session, only: [:create]
resource :register, only: [:create]
resource :code_session, only: [:create]
resource :verify, only: [:create]
end
end end
namespace :admins do namespace :admins do
@ -980,6 +988,16 @@ Rails.application.routes.draw do
resource :laboratory_setting, only: [:show, :update] resource :laboratory_setting, only: [:show, :update]
resource :laboratory_user, only: [:create, :destroy] resource :laboratory_user, only: [:create, :destroy]
end end
resources :competitions, only: [:index, :destroy] do
member do
post :publish
post :unpublish
post :online_switch
get :enroll_list
end
resource :competition_setting, only: [:show, :update]
end
end end
resources :colleges, only: [] do resources :colleges, only: [] do

@ -0,0 +1,7 @@
class MigrateCourseAtta < ActiveRecord::Migration[5.2]
def change
add_column :attachments, :delay_publish, :boolean, default: 0
Attachment.where(container_type: "Course").where(is_publish: 0).where("publish_time > '#{(Time.now).strftime("%Y-%m-%d %H:%M:%S")}'").update_all(delay_publish: 1)
end
end

@ -0,0 +1,6 @@
class AddNewColumnToCompetitions < ActiveRecord::Migration[5.2]
def change
add_column :competitions, :bonus, :integer, default: 0
add_column :competitions, :mode, :integer, default: 0
end
end

@ -0,0 +1,11 @@
class CreateCompetitionModeSettings < ActiveRecord::Migration[5.2]
def change
create_table :competition_mode_settings do |t|
t.references :course
t.datetime :start_time
t.datetime :end_time
t.timestamps
end
end
end

@ -32,7 +32,7 @@ module.exports = {
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
// devtool: "cheap-module-eval-source-map", // devtool: "cheap-module-eval-source-map",
// 开启调试 // 开启调试
devtool: "source-map", // 开启调试 //devtool: "source-map", // 开启调试
// These are the "entry points" to our application. // These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle. // 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. // The first two entry points enable "hot" CSS and auto-refreshes for JS.

@ -8,10 +8,12 @@
<!-- width=device-width, initial-scale=1 , shrink-to-fit=no --> <!-- width=device-width, initial-scale=1 , shrink-to-fit=no -->
<!-- <meta name="viewport" content=""> --> <!-- <meta name="viewport" content=""> -->
<meta name="theme-color" content="#000000"> <meta name="theme-color" content="#000000">
<meta http-equiv="cache-control" content="no-cache,no-store, must-revalidate" />
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"> <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> <!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">-->
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build. It will be replaced with the URL of the `public` folder during the build.
@ -21,7 +23,8 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>EduCoder</title> <!-- <title>EduCoder</title>-->
<!--react-ssr-head-->
<script type="text/javascript"> <script type="text/javascript">
window.__isR = true; window.__isR = true;

@ -10,7 +10,7 @@
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/ homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
--> -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"> <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> <!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">-->
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build. It will be replaced with the URL of the `public` folder during the build.
@ -20,7 +20,8 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>Educoder</title> <!-- <title>Educoder</title>-->
<!--react-ssr-head-->
<script type="text/javascript"> <script type="text/javascript">
window.__isR = true; window.__isR = true;
</script> </script>

@ -9,7 +9,7 @@ import {
Route, Route,
Switch Switch
} from 'react-router-dom'; } from 'react-router-dom';
import axios from 'axios';
import '@icedesign/base/dist/ICEDesignBase.css'; import '@icedesign/base/dist/ICEDesignBase.css';
import '@icedesign/base/index.scss'; import '@icedesign/base/index.scss';
@ -64,6 +64,18 @@ const EducoderLogin = Loadable({
loader: () => import('./modules/login/EducoderLogin'), loader: () => import('./modules/login/EducoderLogin'),
loading: Loading, loading: Loading,
}) })
//微信登录
const Otherlogin=Loadable({
loader: () => import('./modules/login/Otherlogin'),
loading: Loading,
})
const Otherloginstart=Loadable({
loader: () => import('./modules/login/Otherloginstart'),
loading: Loading,
})
const TestIndex = Loadable({ const TestIndex = Loadable({
loader: () => import('./modules/test'), loader: () => import('./modules/test'),
loading: Loading, loading: Loading,
@ -275,6 +287,7 @@ class App extends Component {
Addcoursestypes:false, Addcoursestypes:false,
mydisplay:false, mydisplay:false,
occupation:0, occupation:0,
mygetHelmetapi:undefined,
} }
} }
@ -315,7 +328,6 @@ class App extends Component {
} }
componentDidMount() { componentDidMount() {
this.disableVideoContextMenu(); this.disableVideoContextMenu();
// force an update if the URL changes // force an update if the URL changes
history.listen(() => { history.listen(() => {
this.forceUpdate() this.forceUpdate()
@ -324,7 +336,8 @@ class App extends Component {
$("html").animate({ scrollTop: $('html').scrollTop() - 0 }) $("html").animate({ scrollTop: $('html').scrollTop() - 0 })
}); });
initAxiosInterceptors(this.props) initAxiosInterceptors(this.props);
this.getAppdata();
// //
// axios.interceptors.response.use((response) => { // axios.interceptors.response.use((response) => {
// // console.log("response"+response); // // console.log("response"+response);
@ -350,15 +363,78 @@ class App extends Component {
this.setState({ this.setState({
isRender:false, isRender:false,
}) })
};
//获取当前定制信息
getAppdata=()=>{
let url = "/setting.json";
axios.get(url).then((response) => {
// console.log("app.js开始请求/setting.json");
// console.log("获取当前定制信息");
if(response){
if(response.data){
this.setState({
mygetHelmetapi:response.data.setting
});
document.title = response.data.setting.name;
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = '/'+response.data.setting.tab_logo_url;
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
}else {
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
} }
render() { }else{
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
}
}).catch((error) => {
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
});
};
render() {
let{mygetHelmetapi}=this.state;
// console.log("appappapp");
// console.log(mygetHelmetapi);
return ( return (
<LocaleProvider locale={zhCN}> <LocaleProvider locale={zhCN}>
<MuiThemeProvider theme={theme}> <MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={()=>this.Modifyloginvalue()}></LoginDialog> <LoginDialog {...this.props} {...this.state} Modifyloginvalue={()=>this.Modifyloginvalue()}></LoginDialog>
<Notcompletedysl {...this.props} {...this.state}></Notcompletedysl> <Notcompletedysl {...this.props} {...this.state}></Notcompletedysl>
@ -401,10 +477,28 @@ class App extends Component {
<Route path="/compatibility" component={CompatibilityPageLoadable}/> <Route path="/compatibility" component={CompatibilityPageLoadable}/>
<Route <Route
path="/login" component={EducoderLogin} path="/login"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
/>
<Route
path="/register"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
/>
<Route
path="/otherloginstart" component={Otherloginstart}
/> />
<Route <Route
path="/register" component={EducoderLogin} path="/otherlogin" component={Otherlogin}
/> />
<Route path="/users/:username" <Route path="/users/:username"
render={ render={
@ -422,7 +516,13 @@ class App extends Component {
}></Route> }></Route>
<Route <Route
path="/changepassword" component={EducoderLogin} path="/changepassword"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
/> />
<Route <Route
path="/interesse" component={Interestpage} path="/interesse" component={Interestpage}
@ -450,7 +550,7 @@ class App extends Component {
></Route> ></Route>
{/*课堂*/} {/*课堂*/}
<Route path="/courses" component={CoursesIndex} {...this.props}></Route> <Route path="/courses" component={CoursesIndex} {...this.props} {...this.state}></Route>
{/* <Route path="/forums" component={ForumsIndexComponent}> {/* <Route path="/forums" component={ForumsIndexComponent}>
</Route> */} </Route> */}
@ -484,7 +584,12 @@ class App extends Component {
render={ render={
(props)=>(<Ecs {...this.props} {...props} {...this.state}></Ecs>) (props)=>(<Ecs {...this.props} {...props} {...this.state}></Ecs>)
}/> }/>
<Route exact path="/" component={ShixunsHome}/> <Route exact path="/"
// component={ShixunsHome}
render={
(props)=>(<ShixunsHome {...this.props} {...props} {...this.state}></ShixunsHome>)
}
/>
<Route component={Shixunnopage}/> <Route component={Shixunnopage}/>
@ -607,4 +712,4 @@ moment.defineLocale('zh-cn', {
doy: 4 // The week that contains Jan 4th is the first week of the year. doy: 4 // The week that contains Jan 4th is the first week of the year.
} }
}); });
export default SnackbarHOC()(App); export default SnackbarHOC()(App) ;

@ -94,9 +94,15 @@ export function initAxiosInterceptors(props) {
} }
} }
if (requestMap[config.url] === true) { // 避免重复的请求 if (config.method === "post") {
if (requestMap[config.url] === true) { // 避免重复的请求 导致页面f5刷新 也会被阻止 显示这个方法会影响到定制信息定制信息是get 请求
// console.log(config);
// console.log(JSON.parse(config));
// console.log(config.url);
// console.log("被阻止了是重复请求=================================");
return false; return false;
} }
}
// 非file_update请求 // 非file_update请求
if (config.url.indexOf('update_file') === -1) { if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true; requestMap[config.url] = true;

@ -8,20 +8,20 @@ class WordsBtn extends Component {
} }
render() { render() {
let{to, href,targets, style2 }=this.props let{to, href,targets, style2, style, className, ...others }=this.props
return( return(
<React.Fragment> <React.Fragment>
{ {
to==undefined&&targets==undefined ? to==undefined&&targets==undefined ?
<a href={href || "javascript:void(0)"} onClick={this.props.onClick} className={"btn "+`${map[this.props.style]} ${this.props.className}`} <a href={href || "javascript:void(0)"} onClick={this.props.onClick} className={"btn "+`${map[this.props.style]} ${this.props.className}`}
style={style2} style={style2} {...others}
>{this.props.children}</a>: >{this.props.children}</a>:
targets!=undefined? <a href={to} target="_blank" className={"btn "+`${map[this.props.style]} ${this.props.className}`} targets!=undefined? <a href={to} target="_blank" className={"btn "+`${map[this.props.style]} ${this.props.className}`}
style={style2} style={style2} {...others}
>{this.props.children}</a> >{this.props.children}</a>
: :
<Link to={to} className={"btn "+`${map[this.props.style]} ${this.props.className}`} <Link to={to} className={"btn "+`${map[this.props.style]} ${this.props.className}`}
style={style2} style={style2} {...others}
>{this.props.children}</Link> >{this.props.children}</Link>
} }
</React.Fragment> </React.Fragment>

@ -33,6 +33,12 @@ const StudentsList= Loadable({
loader: () => import('./members/studentsList'), loader: () => import('./members/studentsList'),
loading: Loading, loading: Loading,
}); });
//分班列表
const CourseGroupList= Loadable({
loader: () => import('./members/CourseGroupList'),
loading: Loading,
});
const Eduinforms= Loadable({ const Eduinforms= Loadable({
loader: () => import('./gradinforms/Eduinforms.js'), loader: () => import('./gradinforms/Eduinforms.js'),
loading: Loading, loading: Loading,
@ -234,7 +240,7 @@ class ListPageIndex extends Component{
></Route> ></Route>
<Route path="/courses/:coursesId/course_groups" <Route path="/courses/:coursesId/course_groups"
render={ render={
(props) => (<StudentsList {...this.props} {...props} {...this.state} />) (props) => (<CourseGroupList {...this.props} {...props} {...this.state} />)
} }
></Route> ></Route>

@ -209,6 +209,9 @@ class Fileslistitem extends Component{
text-overflow:ellipsis; text-overflow:ellipsis;
white-space:nowrap white-space:nowrap
} }
.mt2{
margin-top:2px;
}
`}</style> `}</style>
<div className="clearfix ds pr contentSection" style={{cursor : this.props.isAdmin ? "pointer" : "default"}} onClick={() => window.$(`.sourceitem${index} input`).click() }> <div className="clearfix ds pr contentSection" style={{cursor : this.props.isAdmin ? "pointer" : "default"}} onClick={() => window.$(`.sourceitem${index} input`).click() }>
<h6 onClick={(event)=>this.eventStop(event)}> <h6 onClick={(event)=>this.eventStop(event)}>
@ -248,6 +251,29 @@ class Fileslistitem extends Component{
:"" :""
} }
{discussMessage.is_publish===false?<CoursesListType typelist={["未发布"]} typesylename={""}/>:""} {discussMessage.is_publish===false?<CoursesListType typelist={["未发布"]} typesylename={""}/>:""}
{this.props.isAdmin?
<span className={"fr mr10 mt2"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
</span>:""}
{this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login?
<span className={"fr mr10 mt2"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.onDelete(discussMessage.id)}>删除</a>
</WordsBtn>
</span>:""}
</h6> </h6>
<style> <style>
{ {
@ -275,25 +301,26 @@ class Fileslistitem extends Component{
` `
} }
</style> </style>
{discussMessage.course_groups.length===0?"": {/*资源分班*/}
<p className="color-grey panel-lightgrey mt8 fl lightgreybox ml30" style={{width:'100%'}}> {/*{discussMessage.course_groups.length===0?"":*/}
{discussMessage.course_groups.map((item,key)=>{ {/*<p className="color-grey panel-lightgrey mt8 fl lightgreybox ml30" style={{width:'100%'}}>*/}
return( {/*{discussMessage.course_groups.map((item,key)=>{*/}
<div className="mr50"> {/*return(*/}
<span className="mr15 color-dark">{item.course_group_name}</span> {/*<div className="mr50">*/}
<span className="mr15 color-grey9 ">将发布于 { moment(item.course_group_publish_time).format('YYYY-MM-DD HH:mm')}</span> {/*<span className="mr15 color-dark">{item.course_group_name}</span>*/}
</div> {/*<span className="mr15 color-grey9 ">将发布于 { moment(item.course_group_publish_time).format('YYYY-MM-DD HH:mm')}</span>*/}
) {/*</div>*/}
})} {/*)*/}
{/*})}*/}
</p>}
{/*</p>}*/}
<p className={this.props.isAdmin===true?"color-grey panel-lightgrey mt8 fl ml30":"color-grey panel-lightgrey mt8 fl ml13"} style={{width:'100%'}}> <p className={this.props.isAdmin===true?"color-grey panel-lightgrey mt8 fl ml30":"color-grey panel-lightgrey mt8 fl ml13"} style={{width:'100%'}}>
<span className="mr50"> <span className="mr50">
<span className="mr15 color-dark">{discussMessage.author.name}</span> <span className="mr15 color-dark">{discussMessage.author.name}</span>
<span className="mr15 color-grey9">大小 {discussMessage.filesize}</span> <span className="mr15 color-grey9">大小 {discussMessage.filesize}</span>
<span className="mr15 color-grey9">下载 {discussMessage.downloads_count}</span> <span className="mr15 color-grey9">下载 {discussMessage.downloads_count}</span>
<span className="mr15 color-grey9">引用 {discussMessage.quotes}</span> {/*<span className="mr15 color-grey9">引用 {discussMessage.quotes}</span>*/}
<span className="mr15 color-grey-c"> <span className="mr15 color-grey-c">
{/*{moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm:ss')}*/} {/*{moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm:ss')}*/}
{/*{moment(discussMessage.publish_time).fromNow()}*/} {/*{moment(discussMessage.publish_time).fromNow()}*/}
@ -302,33 +329,14 @@ class Fileslistitem extends Component{
{ discussMessage.publish_time===null?"":discussMessage.is_publish===true?moment(discussMessage.publish_time).fromNow():moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm')} { discussMessage.publish_time===null?"":discussMessage.is_publish===true?moment(discussMessage.publish_time).fromNow():moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm')}
</span> </span>
</span> </span>
{this.props.isAdmin? {discussMessage&&discussMessage.category_name===null?"":this.props.child===false?<div className="color-grey9 task-hide fr mr60" title={discussMessage&&discussMessage.category_name}
<span className={"fr mrf2 mr10"} onClick={(event)=>this.eventStop(event)}> style={{"max-width":"268px"}}>所属目录{discussMessage&&discussMessage.category_name}
<WordsBtn style="blue" className="colorblue font-16 mr20 fr"> </div>:""}
<a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
</span>:""}
{this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login?
<span className={"fr mrf2 mr10"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.onDelete(discussMessage.id)}>删除</a>
</WordsBtn>
</span>:""}
</p> </p>
<p className={this.props.isAdmin===true?"color-grey panel-lightgrey mt8 fl ml30":"color-grey panel-lightgrey mt8 fl ml13"} style={{width:'100%'}}> <p className={this.props.isAdmin===true?"color-grey panel-lightgrey mt8 fl ml30":"color-grey panel-lightgrey mt8 fl ml13"} style={{width:'94%'}}>
<style> <style>
{ {
` `

@ -28,7 +28,7 @@ class Fileslists extends Component{
pagesize: 15, pagesize: 15,
tagname:undefined, tagname:undefined,
search:undefined, search:undefined,
sort:undefined, sort:"desc",
sorttype:"created_on", sorttype:"created_on",
coursesecondcategoryid:undefined, coursesecondcategoryid:undefined,
filesId:undefined, filesId:undefined,
@ -49,10 +49,19 @@ class Fileslists extends Component{
checkBoxValues:[], checkBoxValues:[],
checkAllValue:false checkAllValue:false
}) })
if(this.props.match.params.main_id){ if(this.props.match.params.main_id){
this.seactall(); this.setState({
child:false,
sort:"desc"
})
this.seactall(undefined,"desc");
}else if(this.props.match.params.Id){ }else if(this.props.match.params.Id){
this.seactall(parseInt(this.props.match.params.Id),1) this.setState({
child:true,
sort:"desc"
})
this.seactall(parseInt(this.props.match.params.Id),"desc")
} }
this.updadatalist(); this.updadatalist();
on('updateNavSuccess', this.updateNavSuccess) on('updateNavSuccess', this.updateNavSuccess)
@ -60,13 +69,14 @@ class Fileslists extends Component{
} }
updateNavSuccess=()=>{ updateNavSuccess=()=>{
let{sort}=this.state;
this.setState({ this.setState({
isSpin:true isSpin:true
}) })
if(this.props.match.params.main_id){ if(this.props.match.params.main_id){
this.seactall(); this.seactall(undefined,sort);
}else if(this.props.match.params.Id){ }else if(this.props.match.params.Id){
this.seactall(parseInt(this.props.match.params.Id),1) this.seactall(parseInt(this.props.match.params.Id),sort)
} }
} }
componentDidUpdate = (prevProps) => { componentDidUpdate = (prevProps) => {
@ -74,41 +84,30 @@ class Fileslists extends Component{
this.setState({ this.setState({
isSpin:true, isSpin:true,
checkBoxValues:[], checkBoxValues:[],
checkAllValue:false checkAllValue:false,
}) })
if(this.props.match.params.main_id!=undefined){ if(this.props.match.params.main_id!=undefined){
this.seactall(); this.setState({
child:false,
sort:"desc"
})
this.seactall(undefined,"desc");
} }
} }
if(prevProps.match.params.Id != this.props.match.params.Id){ if(prevProps.match.params.Id != this.props.match.params.Id){
this.setState({ this.setState({
isSpin:true, isSpin:true,
checkBoxValues:[], checkBoxValues:[],
checkAllValue:false checkAllValue:false,
}) })
if(this.props.match.params.Id!=undefined){ if(this.props.match.params.Id!=undefined){
this.seactall(parseInt(this.props.match.params.Id),1) this.setState({
} child:true,
} sort:"desc"
// if ( prevProps.match.params.Id != this.props.match.params.Id ||prevProps.isaloadtype!= this.props.isaloadtype) { })
// let lists=this.props.course_modules; this.seactall(parseInt(this.props.match.params.Id),"desc")
// if(lists!=undefined){ }
// debugger }
// let url=this.props.location.pathname;
// lists.forEach((item,index)=>{
// if(url===item.category_url){
// this.seactall();
// }
// if(item.second_category!=undefined&&item.second_category.length!=0){
// item.second_category.forEach((iem,key)=>{
// if(url===iem.second_category_url){
// this.seactall(parseInt(this.props.match.params.Id),2);
// }
// })
// }
// })
// }
// }
} }
updadatalist=(id)=>{ updadatalist=(id)=>{
@ -145,29 +144,42 @@ class Fileslists extends Component{
} }
updatafiled=()=>{ updatafiled=()=>{
let{sort}=this.state;
if(this.props.match.params.main_id){ if(this.props.match.params.main_id){
this.seactall(); this.seactall(undefined,sort);
}else if(this.props.match.params.Id){ }else if(this.props.match.params.Id){
this.seactall(parseInt(this.props.match.params.Id),1) this.seactall(parseInt(this.props.match.params.Id),sort)
} }
} }
seactall=(coursesecondcategoryid,type)=>{ seactall=(coursesecondcategoryid,sort)=>{
this.setState({ this.setState({
coursesecondcategoryid:coursesecondcategoryid, coursesecondcategoryid:coursesecondcategoryid,
isSpin:true isSpin:true
}) })
let{pagesize,page,tagname,searchValue,sort,sorttype}=this.state; let{pagesize,page,tagname,searchValue,sorttype}=this.state;
this.getfileslist(pagesize,page,tagname,searchValue,sort,sorttype,coursesecondcategoryid); this.getfileslist(pagesize,page,tagname,searchValue,sort,sorttype,coursesecondcategoryid);
} }
onSortTypeChange=(sorttype)=>{ onSortTypeChange=(sorttype)=>{
let{pagesize,page,tagname,searchValue,sort,coursesecondcategoryid}=this.state; let{pagesize,page,tagname,searchValue,sort,coursesecondcategoryid,}=this.state;
let newsort="desc";
if(sort==="desc"){
this.setState({ this.setState({
sorttype:sorttype sorttype:sorttype,
sort:"asc"
}) })
this.getfileslist(pagesize,page,tagname,searchValue,sort,sorttype,coursesecondcategoryid); newsort="asc"
}else{
this.setState({
sorttype:sorttype,
sort:"desc"
})
newsort="desc"
}
this.getfileslist(pagesize,page,tagname,searchValue,newsort,sorttype,coursesecondcategoryid);
} }
getfileslist=(pagesize,page,tagname,searchValue,sort,sorttype,coursesecondcategoryid)=>{ getfileslist=(pagesize,page,tagname,searchValue,sort,sorttype,coursesecondcategoryid)=>{
@ -183,13 +195,12 @@ class Fileslists extends Component{
page:page, page:page,
tag_name:tagname, tag_name:tagname,
search:searchValue, search:searchValue,
sort:sort, sort:sort==="desc"?0:1,
sort_type:sorttype, sort_type:sorttype,
course_second_category_id:id course_second_category_id:id
} }
}).then((result)=>{ }).then((result)=>{
// console.log(result) if(result!=undefined){
if(result.status===200){ if(result.status===200){
if(result.data.status===0){ if(result.data.status===0){
let list=result.data.data; let list=result.data.data;
@ -205,6 +216,11 @@ class Fileslists extends Component{
}) })
} }
} }
}else{
this.setState({
isSpin:false
})
}
}).catch((error)=>{ }).catch((error)=>{
console.log(error) console.log(error)
this.setState({ this.setState({
@ -356,7 +372,7 @@ class Fileslists extends Component{
Modalstype:false, Modalstype:false,
}) })
let {checkBoxValues} = this.state; let {checkBoxValues,sort} = this.state;
const cid = this.props.match.params.coursesId; const cid = this.props.match.params.coursesId;
let url="/files/bulk_public.json"; let url="/files/bulk_public.json";
@ -366,7 +382,7 @@ class Fileslists extends Component{
}) })
.then((response) => { .then((response) => {
if (response.data.status == 0) { if (response.data.status == 0) {
this.seactall(); this.updatafiled()
//:response.data.message //:response.data.message
this.props.showNotification("更新成功"); this.props.showNotification("更新成功");
this.setState({ this.setState({
@ -399,13 +415,18 @@ class Fileslists extends Component{
} }
addDir = () => { addDir = () => {
let {filesId}=this.state; let {filesId,course_modules}=this.state;
this.setState({ this.setState({
checkBoxValues:[] checkBoxValues:[]
}) })
if(parseInt(this.props.match.params.main_id)!=parseInt(this.props.coursesids)){
trigger('attachmentAddlog', parseInt( course_modules&&course_modules.course_modules[0].id))
}else{
trigger('attachmentAddlog', parseInt(filesId)) trigger('attachmentAddlog', parseInt(filesId))
} }
}
editDir = (name) => { editDir = (name) => {
let {filesId}=this.state; let {filesId}=this.state;
this.setState({ this.setState({
@ -677,11 +698,14 @@ class Fileslists extends Component{
course_modules, course_modules,
shixunmodal, shixunmodal,
course_is_public, course_is_public,
filesId filesId,
child,
sort
} = this.state; } = this.state;
let category_id= this.props.match.params.category_id; let category_id= this.props.match.params.category_id;
return( return(
<React.Fragment > <React.Fragment >
@ -741,6 +765,7 @@ class Fileslists extends Component{
{/*选择资源*/} {/*选择资源*/}
{shixunmodal&&shixunmodal===true?<Selectresource {shixunmodal&&shixunmodal===true?<Selectresource
{...this.props} {...this.props}
{...this.state}
visible={this.state.shixunmodal} visible={this.state.shixunmodal}
shixunmodallist={this.state.shixunmodallist} shixunmodallist={this.state.shixunmodallist}
newshixunmodallist={this.state.newshixunmodallist} newshixunmodallist={this.state.newshixunmodallist}
@ -748,7 +773,7 @@ class Fileslists extends Component{
patheditarry={this.state.patheditarry} patheditarry={this.state.patheditarry}
coursesecondcategoryid={this.state.coursesecondcategoryid} coursesecondcategoryid={this.state.coursesecondcategoryid}
hidecouseShixunModal={this.hidecouseShixunModal} hidecouseShixunModal={this.hidecouseShixunModal}
setupdate={(id)=>this.seactall(id)} setupdate={(id)=>this.seactall(id,sort)}
attachmentId={this.state.coursesecondcategoryid} attachmentId={this.state.coursesecondcategoryid}
/>:""} />:""}
@ -756,36 +781,50 @@ class Fileslists extends Component{
{/*上传资源*/} {/*上传资源*/}
{Accessoryvisible&&Accessoryvisible===true?<Sendresource {Accessoryvisible&&Accessoryvisible===true?<Sendresource
{...this.props} {...this.props}
{...this.state}
modalname={"上传资源"} modalname={"上传资源"}
visible={Accessoryvisible} visible={Accessoryvisible}
Cancelname={"取消"} Cancelname={"取消"}
Savesname={"确认"} Savesname={"确认"}
Cancel={this.Cancelvisible} Cancel={this.Cancelvisible}
categoryid={category_id} categoryid={category_id}
setupdate={(id)=>this.seactall(id)} setupdate={(id)=>this.seactall(id,sort)}
has_course_groups={this.state.has_course_groups} has_course_groups={this.state.has_course_groups}
attachmentId={this.state.coursesecondcategoryid} attachmentId={this.state.coursesecondcategoryid}
/>:""} />:""}
{/*设置资源*/}
{Settingtype&&Settingtype===true?<Selectsetting {Settingtype&&Settingtype===true?<Selectsetting
{...this.props} {...this.props}
{...this.state}
Settingtype={Settingtype} Settingtype={Settingtype}
discussMessageid={discussMessageid} discussMessageid={discussMessageid}
course_id={this.props.match.params.coursesId} course_id={this.props.match.params.coursesId}
setupdate={(id)=>this.seactall(id)} setupdate={(id)=>this.seactall(id,sort)}
Cancel={this.Cancelvisible} Cancel={this.Cancelvisible}
has_course_groups={this.state.has_course_groups} has_course_groups={this.state.has_course_groups}
attachmentId={this.state.coursesecondcategoryid} attachmentId={this.state.coursesecondcategoryid}
/>:""} />:""}
{child===false?"":<style>
{
`
.filesnameslist{
max-width: 486px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
`
}
</style>}
<Titlesearchsection <Titlesearchsection
title={name} title={child===false?"全部资源":name}
searchValue={ searchValue } searchValue={ searchValue }
// searchtype={this.props.isAdmin||this.props.isStudent ?true:false} // searchtype={this.props.isAdmin||this.props.isStudent ?true:false}
onInputSearchChange={this.onInputSearchChange} onInputSearchChange={this.onInputSearchChange}
firstRowRight={ firstRowRight={
<React.Fragment> <React.Fragment>
{this.props.isAdmin()?parseInt(this.props.match.params.main_id)===parseInt(this.props.coursesids)?<WordsBtn style="blue" onClick={()=>this.addDir()} className={"mr30 font-16"}>添加目录</WordsBtn>:"":""} {/*{this.props.isAdmin()?parseInt(this.props.match.params.main_id)===parseInt(this.props.coursesids)?<WordsBtn style="blue" onClick={()=>this.addDir()} className={"mr30 font-16"}>新建目录</WordsBtn>:"":""}*/}
{this.props.isAdmin()?<WordsBtn style="blue" onClick={()=>this.addDir()} className={"mr30 font-16"}>新建目录</WordsBtn>:""}
{this.props.isAdmin()?parseInt(this.props.match.params.main_id)!=parseInt(this.props.coursesids)?<WordsBtn style="blue" onClick={()=>this.editDir(name)} className={"mr30 font-16"}>目录重命名</WordsBtn>:"":""} {this.props.isAdmin()?parseInt(this.props.match.params.main_id)!=parseInt(this.props.coursesids)?<WordsBtn style="blue" onClick={()=>this.editDir(name)} className={"mr30 font-16"}>目录重命名</WordsBtn>:"":""}
{this.props.isAdmin()||this.props.isStudent() ? <WordsBtn style="blue" className="mr30 font-16" onClick={()=>this.addResource()}>选用资源</WordsBtn>:""} {this.props.isAdmin()||this.props.isStudent() ? <WordsBtn style="blue" className="mr30 font-16" onClick={()=>this.addResource()}>选用资源</WordsBtn>:""}
@ -869,7 +908,7 @@ class Fileslists extends Component{
{/*})}*/} {/*})}*/}
{this.props.isAdmin()?parseInt(this.props.match.params.main_id)===filesId&&filesId? {this.props.isAdmin()?parseInt(this.props.match.params.main_id)===filesId&&filesId?
<p className="drop_down_btn"> <p className="drop_down_btn">
<a className="color-grey-6" onClick={()=>this.addDir()}>添加目录</a> <a className="color-grey-6" onClick={()=>this.addDir()}>新建目录</a>
</p> </p>
:"":""} :"":""}
</ul> </ul>
@ -877,16 +916,24 @@ class Fileslists extends Component{
</li>:""} </li>:""}
<style>
{this.props.isAdmin()||this.props.isStudent()? <li className="drop_down"> {
{sorttype === 'created_on' ? '更新时间排序':sorttype === 'downloads' ?'下载次数排序':'引用次数排序'} `
<i className="iconfont icon-xiajiantou font-12 ml2"></i> .fiilssort{
<ul className="drop_down_normal" style={{width:'130px'}}> position: absolute;
{/*className={sorttype === 'created_on'?"none":""} className={sorttype === 'quotes'?"none":""} className={sorttype === 'downloads'?"none":""} */} top: -10px;
<li style={{width:'130px'}} onClick={() => this.onSortTypeChange('created_on')}>更新时间排序</li> }
<li style={{width:'130px'}} onClick={() => this.onSortTypeChange('downloads')}>下载次数排序</li> `
<li style={{width:'130px'}} onClick={() => this.onSortTypeChange('quotes')}>引用次数排序</li> }
</ul> </style>
{this.props.isAdmin()||this.props.isStudent()? <li className="drop_down" onClick={() => this.onSortTypeChange('created_on')}>
更新时间
<sapn className="relativef ml5"style={{"top":"2px"}} >
<i className={sort==="asc"?
"iconfont icon-sanjiaoxing-up font-12 color-blue fiilssort" :"iconfont icon-sanjiaoxing-up font-12 fiilssort"}></i>
<i className={sort==="desc"?
"iconfont icon-sanjiaoxing-down font-12 yslbottomsj color-blue":"iconfont icon-sanjiaoxing-down font-12 yslbottomsj"}></i>
</sapn>
</li>:""} </li>:""}
</div> </div>
</div> </div>
@ -918,6 +965,7 @@ class Fileslists extends Component{
<div key={index}> <div key={index}>
<Fileslistitem <Fileslistitem
{...this.props} {...this.props}
{...this.state}
discussMessage={item} discussMessage={item}
isAdmin={this.props.isAdmin()} isAdmin={this.props.isAdmin()}
isStudent={this.props.isStudent()} isStudent={this.props.isStudent()}

@ -287,11 +287,12 @@ class BoardsNew extends Component{
const isAdmin = this.props.isAdmin() const isAdmin = this.props.isAdmin()
const courseId=this.props.match.params.coursesId; const courseId=this.props.match.params.coursesId;
const boardId = this.props.match.params.boardId const boardId = this.props.match.params.boardId
const isCourseEnd = this.props.isCourseEnd() const isCourseEnd = this.props.isCourseEnd();
document.title=this.props.coursedata&&this.props.coursedata.name;
return( return(
<div className="newMain "> <div className="newMain ">
<AddDirModal {...this.props} <AddDirModal {...this.props}
title="添加目录" title="新建目录"
label="目录名称" label="目录名称"
ref="addDirModal" ref="addDirModal"
addSuccess={this.addSuccess} addSuccess={this.addSuccess}
@ -385,7 +386,7 @@ class BoardsNew extends Component{
<React.Fragment> <React.Fragment>
<Divider style={{ margin: '4px 0' }} /> <Divider style={{ margin: '4px 0' }} />
<div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}> <div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}>
<Icon type="plus" /> 添加目录 <Icon type="plus" /> 新建目录
</div> </div>
</React.Fragment> </React.Fragment>
} }

@ -526,8 +526,10 @@ class TopicDetail extends Component {
const isAdmin = this.props.isAdmin() const isAdmin = this.props.isAdmin()
// TODO 图片上传地址 // TODO 图片上传地址
const courseId=this.props.match.params.coursesId; const courseId=this.props.match.params.coursesId;
const boardId = this.props.match.params.boardId const boardId = this.props.match.params.boardId;
const isCourseEnd = this.props.isCourseEnd() const isCourseEnd = this.props.isCourseEnd();
document.title=this.props.coursedata&&this.props.coursedata.name;
return ( return (
<div className="edu-back-white edu-class-container edu-position course-message topicDetail" id="yslforum_index_list"> {/* fl with100 */} <div className="edu-back-white edu-class-container edu-position course-message topicDetail" id="yslforum_index_list"> {/* fl with100 */}
<style>{` <style>{`

@ -349,7 +349,7 @@ class Boards extends Component{
searchPlaceholder={ '请输入帖子名称进行搜索' } searchPlaceholder={ '请输入帖子名称进行搜索' }
firstRowRight={ firstRowRight={
<React.Fragment> <React.Fragment>
{ !isCourseEnd && isAdmin && !parent_id && <WordsBtn style="blue" className="mr30" onClick={()=>this.addDir()}>添加目录</WordsBtn> } { !isCourseEnd && isAdmin && !parent_id && <WordsBtn style="blue" className="mr30" onClick={()=>this.addDir()}>新建目录</WordsBtn> }
{ isAdmin && !!parent_id && <WordsBtn style="blue" className="mr30" onClick={()=>this.renameDir()}>目录重命名</WordsBtn> } { isAdmin && !!parent_id && <WordsBtn style="blue" className="mr30" onClick={()=>this.renameDir()}>目录重命名</WordsBtn> }
{ !isCourseEnd && isAdminOrStudent && <WordsBtn style="blue" className="" onClick={()=>this.onToBoardsNew()}>我要发贴</WordsBtn> } { !isCourseEnd && isAdminOrStudent && <WordsBtn style="blue" className="" onClick={()=>this.onToBoardsNew()}>我要发贴</WordsBtn> }
</React.Fragment> </React.Fragment>
@ -393,7 +393,7 @@ class Boards extends Component{
<p className="drop_down_btn"> <p className="drop_down_btn">
<a href="javascript:void(0)" className="color-grey-6" <a href="javascript:void(0)" className="color-grey-6"
onClick={()=>this.addDir()} onClick={()=>this.addDir()}
>添加目录...</a> >新建目录...</a>
</p> </p>
} }
{/* <p className="drop_down_btn"><a href="javascript:void(0)" className="color-grey-6">添加分班...</a></p> */} {/* <p className="drop_down_btn"><a href="javascript:void(0)" className="color-grey-6">添加分班...</a></p> */}

@ -171,6 +171,8 @@ class CommonWorkAppraise extends Component{
let category_id=this.props.match.params.category_id; let category_id=this.props.match.params.category_id;
let studentWorkId=this.props.match.params.studentWorkId; let studentWorkId=this.props.match.params.studentWorkId;
const isAdmin = this.props.isAdmin() const isAdmin = this.props.isAdmin()
document.title=course_name&&course_name;
return( return(
<WorkDetailPageHeader <WorkDetailPageHeader
{...this.props} {...this.state} {...this.props} {...this.state}

@ -225,6 +225,7 @@ class CommonWorkDetailIndex extends Component{
// console.log(params); // console.log(params);
let exportUrl = `/homework_commons/${workId}/works_list.zip?${queryString.stringify(params)}` let exportUrl = `/homework_commons/${workId}/works_list.zip?${queryString.stringify(params)}`
let exportResultUrl = `/homework_commons/${workId}/works_list.xlsx?${queryString.stringify(params)}` let exportResultUrl = `/homework_commons/${workId}/works_list.xlsx?${queryString.stringify(params)}`
document.title=course_name === undefined ? "" : course_name;
return ( return (
<div> <div>
<PublishRightnow ref={this.publishModal} showActionButton={false} {...this.props} checkBoxValues={[workId]} <PublishRightnow ref={this.publishModal} showActionButton={false} {...this.props} checkBoxValues={[workId]}

@ -1129,6 +1129,8 @@ class CommonWorkSetting extends Component{
{<div className={"publicTimeTip color-red ml30"}>{publicTimeTip}</div>} {<div className={"publicTimeTip color-red ml30"}>{publicTimeTip}</div>}
</React.Fragment> : </React.Fragment> :
adaptered_group_settings && !!adaptered_group_settings.length && <PollDetailTabForthRules adaptered_group_settings && !!adaptered_group_settings.length && <PollDetailTabForthRules
{...this.props}
{...this.state}
ref="pollDetailTabForthRules" ref="pollDetailTabForthRules"
rules={rules} rules={rules}
course_group={adaptered_group_settings} course_group={adaptered_group_settings}

@ -161,7 +161,7 @@ class NewWork extends Component{
doNew: this.doNew, doNew: this.doNew,
doEdit: this.doEdit, doEdit: this.doEdit,
} }
document.title=this.state.course_name && this.state.course_name
return( return(
<div className="newMain"> <div className="newMain">
<div className="educontent mt20 mb50"> <div className="educontent mt20 mb50">

@ -61,7 +61,8 @@ class Titlesearchsection extends Component{
<p className="clearfix padding30 bor-bottom-greyE"> <p className="clearfix padding30 bor-bottom-greyE">
<p style={{height: '20px'}}> <p style={{height: '20px'}}>
<span className="font-18 fl color-dark-21">{title}</span> {/* title={title} */}
<span className="font-18 fl color-dark-21 filesnameslist" >{title}</span>
<li className="fr font-16"> <li className="fr font-16">
{ firstRowRight } { firstRowRight }
</li> </li>

@ -248,8 +248,8 @@ class CoursesBanner extends Component {
} }
} }
if (i ===5) { if (i ===5) {
s = "复制将在后台执行,作业、资源、试卷都将复制到新课堂平台"; s = "复制”功能将会为您创建一个新的课堂旧课堂的作业、资源、试卷";
ss = "将为你创建一个新的同名课堂,请问是否继续"; ss = "都将被复制到新的课堂里面请问是否继续?";
this.showActionPoll(i,s,ss) this.showActionPoll(i,s,ss)
} }
@ -400,11 +400,13 @@ class CoursesBanner extends Component {
if(sum===1){ if(sum===1){
let url =`/courses/${id}/switch_to_student.json`; let url =`/courses/${id}/switch_to_student.json`;
axios.post(url).then((response) => { axios.post(url).then((response) => {
if(response!=undefined){
if(response.data.status===0){ if(response.data.status===0){
// window.location.href = "/users/" + this.props.current_user.login; // window.location.href = "/users/" + this.props.current_user.login;
// this.props.history.replace(newurl); // this.props.history.replace(newurl);
window.location.href=newurl window.location.href=newurl
} }
}
}) })
} }
@ -412,11 +414,13 @@ class CoursesBanner extends Component {
if(sum===2){ if(sum===2){
let url =`/courses/${id}/switch_to_teacher.json`; let url =`/courses/${id}/switch_to_teacher.json`;
axios.post(url).then((response) => { axios.post(url).then((response) => {
if(response!=undefined){
if(response.data.status===0){ if(response.data.status===0){
// window.location.href = "/users/" + this.props.current_user.login; // window.location.href = "/users/" + this.props.current_user.login;
// this.props.history.replace(newurl); // this.props.history.replace(newurl);
window.location.href=newurl window.location.href=newurl
} }
}
}) })
} }
@ -481,6 +485,7 @@ class CoursesBanner extends Component {
render() { render() {
let { Addcoursestypes, coursedata,excellent, modalsType, modalsTopval, loadtype,modalsBottomval,antIcon,is_guide,AccountProfiletype} = this.state; let { Addcoursestypes, coursedata,excellent, modalsType, modalsTopval, loadtype,modalsBottomval,antIcon,is_guide,AccountProfiletype} = this.state;
const isCourseEnd = this.props.isCourseEnd() const isCourseEnd = this.props.isCourseEnd()
document.title=coursedata===undefined || coursedata.status===401 || coursedata.status===407?"":coursedata.name;
return ( return (
<div> <div>
{ {

@ -238,6 +238,37 @@ class Coursesleftnav extends Component{
this.props.updataleftNavfun() this.props.updataleftNavfun()
} }
componentDidUpdate=(prevProps)=>{
if(prevProps!=this.props){
let courstype=this.props.match.url;
courstype = courstype.split('/');
courstype=courstype[3];
const query =this.props.location.search;
let category_id;
if(courstype==="board"){
category_id=parseInt(this.props.match.params.boardId);
}else{
category_id=parseInt(this.props.match.params.category_id);
}
if(query===""){
this.setState({
positiontype:courstype,
})
}else{
if(isNaN(category_id)){
this.setState({
positiontype:courstype,
})
}else{
this.setState({
positiontype:courstype,
})
}
}
}
}
setnavid=(e,key,id,type,url)=>{ setnavid=(e,key,id,type,url)=>{
// this.props.getleftNavid && this.props.getleftNavid(key,type); // this.props.getleftNavid && this.props.getleftNavid(key,type);
// let {selectnavid,navid}=this.state; // let {selectnavid,navid}=this.state;
@ -401,7 +432,7 @@ class Coursesleftnav extends Component{
axios.get(url).then((result)=>{ axios.get(url).then((result)=>{
navidtype=true navidtype=true
this.props.updataleftNavfun(); this.props.updataleftNavfun();
console.log(this.props) // console.log(this.props)
let list=this.props.course_modules; let list=this.props.course_modules;
for(var i=0; i<list.length;i++){ for(var i=0; i<list.length;i++){
if(list[i].id!=id){ if(list[i].id!=id){
@ -442,7 +473,7 @@ class Coursesleftnav extends Component{
navidtype=false navidtype=false
if(id===1||id===2||id===6){ if(id===1||id===2||id===6){
this.setState({ this.setState({
Navmodalname:id===2?"新建分班":"添加目录", Navmodalname:id===2?"新建分班":"新建目录",
Navtitles:id===2?"分班名称":"目录名称", Navtitles:id===2?"分班名称":"目录名称",
Navplaceholder:"请输入名称最大限制60个字符", Navplaceholder:"请输入名称最大限制60个字符",
Navmodalnametype:true, Navmodalnametype:true,
@ -493,7 +524,8 @@ class Coursesleftnav extends Component{
navidtype=true navidtype=true
} }
saveNavmodapost=(url,value)=>{ saveNavmodapost=(url,value,positiontype,coursesId)=>{
axios.post(url, axios.post(url,
{name:value}).then((result)=>{ {name:value}).then((result)=>{
if(result.data.status===0){ if(result.data.status===0){
@ -505,6 +537,10 @@ class Coursesleftnav extends Component{
description:result.data.message description:result.data.message
}); });
trigger('updateNavSuccess') trigger('updateNavSuccess')
if(positiontype==="files"){
window.location.href=`/courses/${coursesId}/file/${result.data.category_id}`;
// this.props.history.push(`/courses/${coursesId}/file/${result.data.category_id}`)
}
} }
}).catch((error)=>{ }).catch((error)=>{
console.log(error) console.log(error)
@ -556,9 +592,8 @@ class Coursesleftnav extends Component{
} }
if(Navmodaltypename===1){ if(Navmodaltypename===1){
let url="/course_modules/"+id+"/add_second_category.json" let url="/course_modules/"+id+"/add_second_category.json"
this.saveNavmodapost(url,NavmodalValue) this.saveNavmodapost(url,NavmodalValue,this.state.positiontype,this.props.match.params.coursesId)
} else if(Navmodaltypename===2){ } else if(Navmodaltypename===2){
@ -781,15 +816,15 @@ class Coursesleftnav extends Component{
return ( <div className={"sandianbox"}> return ( <div className={"sandianbox"}>
{/*公告栏*/} {/*公告栏*/}
{/*作业*/} {/*作业*/}
{item.type==="shixun_homework"?<div onClick={e=>this.Navmodalnames(e,1,"shixun_homework",item.id)}>添加目录</div>:""} {item.type==="shixun_homework"?<div onClick={e=>this.Navmodalnames(e,1,"shixun_homework",item.id)}>新建目录</div>:""}
{/*资源*/} {/*资源*/}
{item.type==="attachment"?<div onClick={e=>this.Navmodalnames(e,1,"attachment",item.id)}>添加目录</div>:""} {item.type==="attachment"?<div onClick={e=>this.Navmodalnames(e,1,"attachment",item.id)}>新建目录</div>:""}
{/*毕业设计*/} {/*毕业设计*/}
{/*{item.type==="graduation"?<div onClick={()=>this.Navmodalnames(1,"attachment",item.id)}>添加目录</div>:""}*/} {/*{item.type==="graduation"?<div onClick={()=>this.Navmodalnames(1,"attachment",item.id)}>添加目录</div>:""}*/}
{/*讨论区*/} {/*讨论区*/}
{item.type==="board"?this.props.current_user&&this.props.current_user.course_is_end===true?"":<div onClick={e=>this.Navmodalnames(e,6,"board",item.main_id)}>添加目录</div>:""} {item.type==="board"?this.props.current_user&&this.props.current_user.course_is_end===true?"":<div onClick={e=>this.Navmodalnames(e,6,"board",item.main_id)}>新建目录</div>:""}
{/*分班*/} {/*分班*/}
{item.type==="course_group"?this.props.current_user&&this.props.current_user.course_is_end===true?"":<div onClick={e=>this.Navmodalnames(e,2,"course_group",item.id)}>添加分班</div>:""} {item.type==="course_group"?this.props.current_user&&this.props.current_user.course_is_end===true?"":<div onClick={e=>this.Navmodalnames(e,2,"course_group",item.id)}>新建分班</div>:""}
{/*分班*/} {/*分班*/}
{/*{item.type==="course_group"? :""}*/} {/*{item.type==="course_group"? :""}*/}
<div onClick={e=>this.Navmodalnames(e,3,"editname",item.id,item.name)}>重命名</div> <div onClick={e=>this.Navmodalnames(e,3,"editname",item.id,item.name)}>重命名</div>

@ -53,6 +53,7 @@ class CoursesHome extends Component{
} }
componentDidMount(){ componentDidMount(){
document.title="翻转课堂";
const upsystem=`/users/system_update.json`; const upsystem=`/users/system_update.json`;
axios.get(upsystem).then((response)=>{ axios.get(upsystem).then((response)=>{
let updata=response.data; let updata=response.data;

@ -46,11 +46,17 @@ class HomeworkModal extends Component{
} }
if(this.props.starttimes!=undefined&&this.props.starttimes!=""){ if(this.props.starttimes!=undefined&&this.props.starttimes!=""){
if(this.props.starttimesend!=undefined&&this.props.starttimesend!=""){
this.setState({
endtime:this.props.starttimesend,
})
}else {
this.setState({ this.setState({
endtime:moment(moment(handleDateString(this.props.starttimes)).add(1, 'week')).format("YYYY-MM-DD HH:mm") endtime:moment(moment(handleDateString(this.props.starttimes)).add(1, 'week')).format("YYYY-MM-DD HH:mm")
}) })
} }
}
} }
componentDidUpdate=(prevProps)=>{ componentDidUpdate=(prevProps)=>{
// if(prevProps.visible!=this.props.visible){ // if(prevProps.visible!=this.props.visible){
@ -69,10 +75,17 @@ class HomeworkModal extends Component{
if(prevProps.starttimes!=this.props.starttimes){ if(prevProps.starttimes!=this.props.starttimes){
if(this.props.starttimes!=undefined&&this.props.starttimes!=""){ if(this.props.starttimes!=undefined&&this.props.starttimes!=""){
if(this.props.starttimesend!=undefined&&this.props.starttimesend!=""){
this.setState({
endtime:this.props.starttimesend,
})
}else{
this.setState({ this.setState({
endtime:moment(moment(handleDateString(this.props.starttimes)).add(1, 'week')).format("YYYY-MM-DD HH:mm") endtime:moment(moment(handleDateString(this.props.starttimes)).add(1, 'week')).format("YYYY-MM-DD HH:mm")
}) })
} }
}
} }
} }

@ -0,0 +1,310 @@
import React,{ Component } from "react";
import { Modal,Checkbox,DatePicker} from "antd";
import { handleDateString } from 'educoder';
import locale from 'antd/lib/date-picker/locale/zh_CN';
import moment from 'moment';
const CheckboxGroup = Checkbox.Group;
const dateFormat = 'YYYY-MM-DD HH:mm';
function range(start, end) {
const result = [];
for (let i = start; i < end; i++) {
result.push(i);
}
return result;
}
function disabledDateTime() {
return {
// disabledHours: () => range(0, 24).splice(4, 20),
disabledMinutes: () => range(1, 30).concat(range(31, 60)),
// disabledSeconds: () => [55, 56],
};
}
function disabledDate(current) {
return current && current < moment().endOf('day').subtract(1, 'days');
}
class OneSelfOrderModal extends Component{
constructor(props){
super(props);
this.state={
group_ids:[],
endtime:""
}
}
componentDidMount() {
if(this.props.course_groups!=undefined&&this.props.course_groups.length!=0){
let arr=this.props.course_groups.map(item => item.id);
this.shixunhomeworkedit(arr);
}
if(this.props.starttimes===undefined||this.props.starttimes===""||this.props.starttimes===null){
this.setState({
endtime:moment(moment(handleDateString(this.props.staytime)).add(1, 'months')).format("YYYY-MM-DD HH:mm")
})
}else{
this.setState({
endtime:moment(handleDateString(this.props.starttimes)).format("YYYY-MM-DD HH:mm")
})
}
}
componentDidUpdate=(prevProps)=>{
// if(prevProps.visible!=this.props.visible){
//
// if(this.props.course_groups!=undefined){
// let arr=this.props.course_groups.map(item => item.id);
// this.shixunhomeworkedit(arr);
// }
// }
if(prevProps.course_groups!=this.props.course_groups){
if(this.props.course_groups!=undefined){
let arr=this.props.course_groups.map(item => item.id);
this.shixunhomeworkedit(arr);
}
}
if(prevProps.starttimes!=this.props.starttimes){
if(this.props.starttimes===undefined||this.props.starttimes===""||this.props.starttimes===null){
this.setState({
endtime:moment(moment(handleDateString(this.props.staytime)).add(1, 'months')).format("YYYY-MM-DD HH:mm")
})
}else{
this.setState({
endtime:moment(handleDateString(this.props.starttimes)).format("YYYY-MM-DD HH:mm")
})
}
}
}
//勾选实训
shixunhomeworkedit=(list)=>{
this.setState({
group_ids:list
})
this.props.getcourse_groupslist && this.props.getcourse_groupslist(list)
}
onChangeTimeend= (date, dateString) => {
// console.log('startValue',dateString);
this.setState({
endtime: date===null?"":handleDateString(dateString),
})
}
propsSaves=(ds,endtime)=>{
if(ds.length ===0&&endtime === ""){
this.props.Saves()
}else{
if(this.props.typs!="end"){
if(endtime === ""||endtime===undefined||endtime===null){
this.setState({
endtimetype:true,
endtimetypevalue:"截止时间不能为空"
})
return
}
if(moment(endtime,"YYYY-MM-DD HH:mm") <= moment(this.props.starttimes,"YYYY-MM-DD HH:mm")){
this.setState({
endtimetype:true,
endtimetypevalue:"必须晚于发布时间"
})
return
}
}
this.props.Saves(ds,moment(handleDateString(endtime),"YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm"))
}
}
render(){
let {group_ids,endtime}=this.state;
let {course_groups}=this.props;
// console.log(this.props.starttimes)
// console.log(endtime)
// console.log(this.props.starttimes)
// console.log(this.state.endtime)
// console.log(this.props.starttime,this.props.endtime)
// TODO course_groups为空时的处理
// let endtimelist=this.props.starttimes===undefined||this.props.starttimes===""?"":moment(handleDateString(endtime)).add(1,'months')
return(
<div>
{
this.props.OneSelftype===true?<style>
{
`
body {
overflow: hidden !important;
}
`
}
</style>:""
}
{
this.props.OneSelftype===true? <Modal
keyboard={false}
className={"HomeworkModal"}
title={this.props.modalname}
visible={this.props.OneSelftype}
closable={false}
footer={null}
destroyOnClose={true}
>
<div className="task-popup-content">
{ this.props.usingCheckBeforePost ?
<React.Fragment>
<p className="task-popup-text-center font-16">
<span>发布设置均可修改</span>
<span className={"color-blue underline"} onClick={this.props.onToPublishClick}>
点击修改
</span>
</p>
<p className="task-popup-text-center font-16 mt10">
此设置将对所有分班生效
</p>
</React.Fragment> :
<React.Fragment>
<p className="task-popup-text-center font-16">
{this.props.Topval}
<span className={"color-blue underline"}>{this.props.Topvalright}</span>
</p>
<p className="task-popup-text-center font-16 mt10">
{this.props.Botvalleft===undefined?"":<span className={"colorFF6800"}>"{this.props.Botvalleft}"</span>}
{this.props.Botval}
</p>
</React.Fragment> }
{this.props.starttime===undefined||
this.props.starttime===""?""
: <p className="task-popup-text-center font-16 mt20">
<span className={"font-14 mr20 color979797"}>
<span className={"mr10"}>发布时间:</span>
{this.props.starttime}</span>
{this.props.modaltype===undefined||this.props.modaltype===2? <span className={"font-14 color979797"}>
{/*{this.props.endtime}*/}
<span className={"mr10"}>截止时间:</span>
<DatePicker
dropdownClassName="hideDisable"
showTime={{ format: 'HH:mm' }}
disabledTime={disabledDateTime}
disabledDate={disabledDate}
showToday={false}
locale={locale}
format={dateFormat}
placeholder="请选择截止时间"
id={"endTime"}
width={"210px"}
value={endtime===null||endtime===""?"":moment(endtime, dateFormat)}
onChange={this.onChangeTimeend}
className={ this.state.endtimetype===true?"noticeTip":""}
/>
{this.state.endtimetype===true?<div className={"color-red fr mr90 mt5"}>{this.state.endtimetypevalue}</div>:""}
</span>:""}
</p>}
{/* usingCheckBeforePost 为true的时候 全选所有分班 */}
<style>
{
`
.ant-checkbox-wrapper {
margin-top: 0px;
float: left;
}
.upload_select_box li:hover {
background: transparent;
}
.F4FAFF{
background: #F4FAFF;
}
`
}
</style>
{this.props.modaltype===undefined||this.props.modaltype===2
|| this.props.usingCheckBeforePost ?"":<div className="clearfix edu-txt-center lineh-40 F4FAFF">
<li style={{ width: '100%',padding: "0px 10px"}} className={"mb10"}>
<span style={{"float":"left","color":"#05101A"}} className="task-hide color-grey-name ml50">分班名称</span>
<span style={{"float":"right","color":"#05101A"}} className="task-hide color-grey-name mr70">截止时间</span>
</li>
</div>}
{this.props.modaltype===undefined||this.props.modaltype===2
|| this.props.usingCheckBeforePost ?"":<ul className="upload_select_box fl clearfix mb30"
style={{"overflow-y":"auto",padding:"10px 0px"}}
id="search_not_members_list"
>
{ <Checkbox.Group style={{ width: '100%' }} value={group_ids} onChange={this.shixunhomeworkedit}>
{
course_groups.map((item,key)=>{
return(
<div className="clearfix edu-txt-center lineh-40" key={key}>
<li style={{ width: '100%',padding: "0px 10px"}} className={"mb10"}>
<Checkbox
className="task-hide edu-txt-left"
name="shixun_homework[]"
value={item.id}
key={item.id}
>
<span style={{"textAlign":"left","color":"#05101A"}} className="task-hide color-grey-name">{item.name}</span>
</Checkbox>
<DatePicker
dropdownClassName="hideDisable"
showTime={{ format: 'HH:mm' }}
disabledTime={disabledDateTime}
disabledDate={disabledDate}
showToday={false}
locale={locale}
format={dateFormat}
placeholder="请选择截止时间"
id={"endTime"}
width={"210px"}
value={item.end_time===null||item.end_time===""?"":moment(item.end_time, dateFormat)}
onChange={this.onChangeTimeend}
className={ this.state.endtimetype===true?"noticeTip fr":"fr"}
/>
</li>
</div>
)
})
}
</Checkbox.Group>}
</ul>
}
<div className="clearfix mt30 edu-txt-center mb10">
<a className="task-btn color-white mr30" onClick={this.props.Cancel}>{this.props.Cancelname}</a>
<a className="task-btn task-btn-orange" onClick={()=>this.propsSaves(group_ids,this.state.endtime)}>{this.props.Savesname}</a>
</div>
</div>
</Modal>:""}
</div>
)
}
}
export default OneSelfOrderModal;

@ -1,17 +1,34 @@
import React,{ Component } from "react"; import React,{ Component } from "react";
import { Modal,Checkbox,Select,Input,Spin,Icon} from "antd"; import { Modal,Checkbox,Select,Input,Spin,Icon,Radio,DatePicker} from "antd";
import locale from 'antd/lib/date-picker/locale/zh_CN';
import axios from'axios'; import axios from'axios';
import {handleDateString} from 'educoder';
import NoneData from "../coursesPublic/NoneData"; import NoneData from "../coursesPublic/NoneData";
import Modals from '../../modals/Modals'; import Modals from '../../modals/Modals';
import moment from 'moment';
const Option = Select.Option; const Option = Select.Option;
const Search = Input.Search; const Search = Input.Search;
const dateFormat ="YYYY-MM-DD HH:mm"
function formatDate(date) { function formatDate(date) {
var dateee = new Date(date).toJSON(); var dateee = new Date(date).toJSON();
return new Date(+new Date(dateee) + 8 * 3600 * 1000).toISOString().replace(/T/g, ' ').replace(/\.[\d]{3}Z/, '') return new Date(+new Date(dateee) + 8 * 3600 * 1000).toISOString().replace(/T/g, ' ').replace(/\.[\d]{3}Z/, '')
} }
function range(start, end) {
const result = [];
for (let i = start; i < end; i++) {
result.push(i);
}
return result;
}
function disabledDateTime() {
return {
disabledMinutes: () => range(1, 30).concat(range(31, 60)),
// disabledSeconds: () => range(1,60)
}
}
function disabledDate(current) {
return current && current < moment().endOf('day').subtract(1, 'days');
}
class Selectresource extends Component{ class Selectresource extends Component{
constructor(props){ constructor(props){
super(props); super(props);
@ -23,7 +40,9 @@ class Selectresource extends Component{
Resourcelist:undefined, Resourcelist:undefined,
hometypepvisible:true, hometypepvisible:true,
getallfiles:false, getallfiles:false,
searchtype:'getallfiles' searchtype:'getallfiles',
Radiovalue:0,
datatime:undefined
} }
} }
componentDidMount() { componentDidMount() {
@ -32,11 +51,7 @@ class Selectresource extends Component{
componentDidUpdate = (prevProps) => { componentDidUpdate = (prevProps) => {
let {getallfiles}=this.state;
if ( prevProps.visible != this.props.visible ) {
}
} }
@ -197,7 +212,7 @@ class Selectresource extends Component{
savecouseShixunModal=()=>{ savecouseShixunModal=()=>{
let {patheditarry}=this.state; let {patheditarry,datatime,Radiovalue}=this.state;
let {coursesId,attachmentId}=this.props; let {coursesId,attachmentId}=this.props;
let url="/files/import.json"; let url="/files/import.json";
@ -212,19 +227,28 @@ class Selectresource extends Component{
}) })
} }
if(this.state.Radiovalue===1){
if(datatime===undefined||datatime===null||datatime=== ""){
this.setState({
Radiovaluetype:true
})
return
}else{
this.setState({
Radiovaluetype:false
})
}
}
axios.post(url, { axios.post(url, {
course_id:coursesId, course_id:coursesId,
attachment_ids:patheditarry, attachment_ids:patheditarry,
course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId, course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId,
delay_publish:Radiovalue,
publish_time:Radiovalue===1?datatime:undefined
} }
).then((response) => { ).then((response) => {
if(response.data.status===0){ if(response.data.status===0){
// this.setState({
// Modalstype:true,
// Modalstopval:response.data.message,
// ModalSave:this.ModalCancelModalCancel,
// loadtype:true
// })
this.ModalCancelModalCancel(); this.ModalCancelModalCancel();
this.props.updataleftNavfun(); this.props.updataleftNavfun();
this.props.showNotification("选用资源成功"); this.props.showNotification("选用资源成功");
@ -236,15 +260,33 @@ class Selectresource extends Component{
} }
selectCloseList=(value)=>{ RadioonChange=(e)=>{
if(e.target.value===0){
this.setState({
datatime:undefined
})
}
this.setState({
Radiovalue: e.target.value,
});
}
onChangeTimepublish= (date, dateString) => {
this.setState({ this.setState({
category_id:value datatime:handleDateString(dateString),
}) })
} }
render(){ render(){
let {Searchvalue,type,category_id,Resourcelist,hometypepvisible,patheditarry}=this.state; let {Searchvalue,type,Resourcelist,hometypepvisible,patheditarry,datatime}=this.state;
let {visible,shixunmodallist}=this.props; let {visible}=this.props;
const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />; const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;
const radioStyle = {
display: 'block',
height: '30px',
lineHeight: '30px',
};
return( return(
<div> <div>
{/*提示*/} {/*提示*/}
@ -373,10 +415,36 @@ class Selectresource extends Component{
} }
</div> </div>
<div className={"mt10"}>
<span className={"color-ooo fl mt6 ml20"}>发布设置</span>
<Radio.Group onChange={this.RadioonChange} value={this.state.Radiovalue} style={{'width': '460px'}}>
<Radio style={radioStyle} value={0}>
立即发布
</Radio>
<Radio style={radioStyle} value={1} className={"fl"}>
<span className={"mr5"}>延迟发布</span>
<DatePicker
dropdownClassName="hideDisable"
showTime={{ format: 'HH:mm' }}
locale={locale}
format={dateFormat}
placeholder="请选择发布时间"
id={"startime"}
showToday={false}
width={"210px"}
value={this.state.Radiovalue===1?datatime===undefined||datatime===""?undefined:moment(datatime, dateFormat):undefined}
onChange={(e,index)=>this.onChangeTimepublish(e,index,undefined,1)}
disabledTime={disabledDateTime}
disabledDate={disabledDate}
disabled={this.state.Radiovalue===1?false:true}
/>
</Radio>
<span className={"fl mt5 color-grey-c"}>(按照设置的时间定时发布)</span>
</Radio.Group>
</div>
{this.state.patheditarrytype===true?<p className={"color-red ml20"}>请选择资源</p>:""} {this.state.patheditarrytype===true?<p className={"color-red ml20"}>请选择资源</p>:""}
{this.state.Radiovaluetype===true?<p className={"color-red ml20"}>发布时间不能为空</p>:""}
<div className="mt20 marginauto clearfix edu-txt-center"> <div className="mt20 marginauto clearfix edu-txt-center">
<a className="pop_close task-btn mr30 margin-tp26" onClick={this.hidecouseShixunModal}>取消</a> <a className="pop_close task-btn mr30 margin-tp26" onClick={this.hidecouseShixunModal}>取消</a>
<a className="task-btn task-btn-orange margin-tp26" id="submit_send_shixun" onClick={this.savecouseShixunModal}>确定</a> <a className="task-btn task-btn-orange margin-tp26" id="submit_send_shixun" onClick={this.savecouseShixunModal}>确定</a>

@ -1,5 +1,5 @@
import React,{ Component } from "react"; import React,{ Component } from "react";
import { Modal,Checkbox,Select,Input,Upload,Button,Icon,message,DatePicker,Tooltip} from "antd"; import { Modal,Checkbox,Select,Input,Upload,Button,Icon,message,DatePicker,Tooltip,Radio} from "antd";
import axios from'axios'; import axios from'axios';
import {getUrl,handleDateString,appendFileSizeToUploadFileAll} from 'educoder'; import {getUrl,handleDateString,appendFileSizeToUploadFileAll} from 'educoder';
import locale from 'antd/lib/date-picker/locale/zh_CN'; import locale from 'antd/lib/date-picker/locale/zh_CN';
@ -36,9 +36,10 @@ class Selectsetting extends Component{
course_groups:undefined, course_groups:undefined,
attachment_histories:undefined, attachment_histories:undefined,
datatime:undefined, datatime:undefined,
unified_setting:true,
fileList:[], fileList:[],
fileListtype:false fileListtype:false,
is_public:false,
Radiovaluetype:false
} }
} }
@ -54,53 +55,13 @@ class Selectsetting extends Component{
}) })
.then((response) => { .then((response) => {
if(response.status===200){ if(response.status===200){
let newcourse_groups=[];
let list =response.data.course_groups;
// let list=[
// {
// "course_group_id": 820,
// "course_group_name": "示例A班",
// "course_group_publish_time": "2019-04-18T17:00:00.000+08:00"
// },
// {
// "course_group_id": 821,
// "course_group_name": "示例B班",
// "course_group_publish_time": "2019-04-19T19:00:00.000+08:00"
// },
// {
// "course_group_id": 822,
// "course_group_name": "示例C班",
// "course_group_publish_time": "2019-04-10T19:00:00.000+08:00"
// }
// ]
if(list.length!=0){
list.forEach((item,key)=>{
newcourse_groups.push ({
course_group_id:item.course_group_id,
course_group_name:item.course_group_id,
publish_time:moment(item.course_group_publish_time).format(dateFormat)
})
})
}else{
newcourse_groups.push ({
course_group_id:undefined,
course_group_name:undefined,
publish_time:""
})
}
this.setState({ this.setState({
datalist:response.data, datalist:response.data,
description: response.data.description, description: response.data.description,
is_public: response.data.is_public, is_public:response.data.is_public,
unified_setting: response.data.unified_setting,
datatime:response.data.publish_time, datatime:response.data.publish_time,
// is_public:response.data.course_groups, Radiovalue:response.data.delay_publish==false?0:1,
//attachment_histories:response.data.attachment_histories //attachment_histories:response.data.attachment_histories
course_groups:newcourse_groups
}) })
} }
@ -110,23 +71,6 @@ class Selectsetting extends Component{
}); });
let coursesId=this.props.match.params.coursesId;
if(this.props.isAdmin()){
let url = `/courses/${coursesId}/all_course_groups.json`
axios.get(url, {
})
.then((response) => {
this.setState({
course_groupss: response.data.course_groups,
})
})
.catch(function (error) {
console.log(error);
});
}
} }
@ -145,21 +89,6 @@ class Selectsetting extends Component{
this.getalldata() this.getalldata()
} }
}
onChangepublics=(e)=>{
console.log(e.target.checked)
this.setState({
is_public:e.target.checked
})
}
onChangesettings=(e)=>{
console.log(e.target.checked)
this.setState({
unified_setting:e.target.checked
})
} }
settextarea=(e)=>{ settextarea=(e)=>{
@ -180,13 +109,26 @@ class Selectsetting extends Component{
} }
savecouseShixunModal=()=>{ savecouseShixunModal=()=>{
let {fileList,is_public,unified_setting,description,datatime,course_groups}=this.state; let {fileList,is_public,description,datatime,Radiovalue}=this.state;
let newfileList=[]; let newfileList=[];
for(var list of fileList){ for(var list of fileList){
newfileList.push(list.response.id) newfileList.push(list.response.id)
} }
if(this.state.Radiovalue===1){
if(datatime===undefined||datatime===null||datatime=== ""){
this.setState({
Radiovaluetype:true
})
return
}else{
this.setState({
Radiovaluetype:false
})
}
}
if(description===undefined||description===null){ if(description===undefined||description===null){
}else if(description.length>100){ }else if(description.length>100){
@ -196,29 +138,6 @@ class Selectsetting extends Component{
return return
} }
// course_groups.forEach((item,key)=>{
// if(item.course_group_id===undefined||item.publish_time===undefined){
// this.setState({
// course_group_publish_timestype:true
// })
// return
// }
// })
// if(unified_setting===false){
//
// course_groups.forEach((item,key)=>{
// if(item.course_group_id===undefined){
// this.setState({
// course_group_idtypes:true
// })
// return
// }
// })
//
// }
let coursesId=this.props.match.params.coursesId; let coursesId=this.props.match.params.coursesId;
let attachmentId=this.props.attachmentId; let attachmentId=this.props.attachmentId;
let url="/files/"+this.props.discussMessageid+".json"; let url="/files/"+this.props.discussMessageid+".json";
@ -228,12 +147,10 @@ class Selectsetting extends Component{
new_attachment_id:newfileList.length===0?undefined:newfileList, new_attachment_id:newfileList.length===0?undefined:newfileList,
course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId, course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId,
is_public:is_public, is_public:is_public,
is_unified_setting:unified_setting, publish_time:Radiovalue===0?undefined:datatime===undefined?moment(new Date(),dateFormat):datatime,
publish_time:unified_setting===true?datatime===undefined?moment(new Date()).format('YYYY-MM-DD HH'):datatime:undefined,
description:description, description:description,
course_group_publish_times:unified_setting===false?course_groups:undefined delay_publish:Radiovalue
}).then((result)=>{ }).then((result)=>{
if(result.data.status===0){ if(result.data.status===0){
this.props.setupdate(attachmentId) this.props.setupdate(attachmentId)
this.props.showNotification("设置资源成功"); this.props.showNotification("设置资源成功");
@ -244,7 +161,6 @@ class Selectsetting extends Component{
} }
onChangeTimepublish= (date, dateString) => { onChangeTimepublish= (date, dateString) => {
// console.log('startValue', dateString);
this.setState({ this.setState({
datatime:handleDateString(dateString), datatime:handleDateString(dateString),
}) })
@ -268,31 +184,6 @@ class Selectsetting extends Component{
} }
} }
// onAttachmentRemove = (file) => {
// // confirm({
// // title: '确定要删除这个附件吗?',
// // okText: '确定',
// // cancelText: '取消',
// // // content: 'Some descriptions',
// // onOk: () => {
// // this.deleteAttachment(file)
// // },
// // onCancel() {
// // console.log('Cancel');
// // },
// // });
// // return false;
//
// // this.setState({
// // Modalstype:true,
// // Modalstopval:'确定要删除这个附件吗?',
// // ModalSave: ()=>this.deleteAttachment(file),
// // ModalCancel:this.cancelAttachment
// // })
// // return false;
//
// this.deleteAttachment(file);
// }
onAttachmentRemove = (file) => { onAttachmentRemove = (file) => {
@ -309,14 +200,7 @@ class Selectsetting extends Component{
fileListtype:false, fileListtype:false,
fileList:[] fileList:[]
}) })
// this.setState((state) => {
// const index = state.fileList.indexOf(file);
// const newFileList = state.fileList.slice();
// newFileList.splice(index, 1);
// return {
// fileList: newFileList,
// };
// });
} }
} }
}) })
@ -332,63 +216,28 @@ class Selectsetting extends Component{
fileList:[] fileList:[]
}) })
} }
// const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
} }
onChangeTimepublishs= (date, dateString,key) => { onChangepublic=(e)=>{
let {course_groups}=this.state;
let newgroup_publish=course_groups;
for(var i=0; i<newgroup_publish.length; i++){
if(i===parseInt(key)){
newgroup_publish[i].publish_time=handleDateString(dateString);
}
}
this.setState({ this.setState({
course_groups:newgroup_publish, is_public:e.target.checked
})
}
selectassigngroups=(e,index,key)=>{
let {course_groups}=this.state;
let newgroup_publish=course_groups;
for(var i=0; i<newgroup_publish.length; i++){
if(i===parseInt(key)){
newgroup_publish[i].course_group_id=index.props.value;
}
}
this.setState({
course_groups:newgroup_publish,
}) })
} }
deletegrouppublish=(key)=>{ RadioonChange=(e)=>{
let newlist=this.state.course_groups; if(e.target.value===0){
newlist.splice(key,1);
this.setState({ this.setState({
course_groups:newlist datatime:undefined
}) })
} }
addgrouppublish=()=>{
let newlist=this.state.course_groups;
newlist.push( {
course_group_id : undefined,
publish_time :""
// moment(new Date()).format('YYYY-MM-DD HH:mm')
})
this.setState({ this.setState({
course_groups:newlist Radiovalue: e.target.value,
}) });
} }
render(){ render(){
let {is_public,unified_setting,course_groups,datatime,description,datalist,course_group_publish_timestype}=this.state; let {datatime,description,datalist}=this.state;
const uploadProps = { const uploadProps = {
width: 600, width: 600,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`, action: `${getUrl()}/api/attachments.json`,
onChange: this.handleChange, onChange: this.handleChange,
onRemove: this.onAttachmentRemove, onRemove: this.onAttachmentRemove,
@ -401,9 +250,13 @@ class Selectsetting extends Component{
return isLt150M; return isLt150M;
}, },
}; };
const radioStyle = {
display: 'block',
height: '30px',
lineHeight: '30px',
};
console.log(this.state.Radiovalue)
// console.log(this.props.has_course_groups)
return( return(
<div> <div>
<style> <style>
@ -461,9 +314,9 @@ class Selectsetting extends Component{
.fontlefts{text-align: left; text-align: center;} .fontlefts{text-align: left; text-align: center;}
`}</style> `}</style>
<ul className="clearfix greybackHead edu-txt-center"> <ul className="clearfix greybackHead edu-txt-center">
<li className="fl paddingleft22 fontlefts" style={{width:'220px'}}>资源名称</li> <li className="fl paddingleft22 fontlefts" style={{width:'330px'}}>资源名称</li>
<li className="fl edu-txt-left" style={{width:'80px'}}>下载</li> <li className="fl edu-txt-left" style={{width:'80px'}}>下载</li>
<li className="fl" style={{width:'100px'}}>引用</li> {/*<li className="fl" style={{width:'100px'}}>引用</li>*/}
<li className="fl" style={{width:'130px'}}>版本号</li> <li className="fl" style={{width:'130px'}}>版本号</li>
</ul> </ul>
@ -490,7 +343,7 @@ class Selectsetting extends Component{
`}</style> `}</style>
<div className="pl20 pr20 settingbox"> <div className="pl20 pr20 settingbox">
<div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE"> <div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE">
<li className="fl" style={{width: '241px'}}> <li className="fl" style={{width: '350px'}}>
<span className={"isabox"} title={datalist&&datalist.title}> {datalist&&datalist.title} </span> <span className={"isabox"} title={datalist&&datalist.title}> {datalist&&datalist.title} </span>
{datalist&&datalist.attachment_histories.length===0?"":<span className={"newcolor-orange fl"}>当前版本</span>} {datalist&&datalist.attachment_histories.length===0?"":<span className={"newcolor-orange fl"}>当前版本</span>}
</li> </li>
@ -505,13 +358,13 @@ class Selectsetting extends Component{
{datalist&&datalist.attachment_histories.map((item,key)=>{ {datalist&&datalist.attachment_histories.map((item,key)=>{
return( return(
<div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE" key={key}> <div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE" key={key}>
<li className="fl" style={{width: '241px'}}> <li className="fl" style={{width: '350px'}}>
<span className={"isabox"} title={item.title}> {item.title} </span> <span className={"isabox"} title={item.title}> {item.title} </span>
{/*<span className={"newcolor-orange fl"}>当前版本</span>*/} {/*<span className={"newcolor-orange fl"}>当前版本</span>*/}
</li> </li>
<li className="fl edu-txt-left task-hide paddingl5 " <li className="fl edu-txt-left task-hide paddingl5 "
style={{width: '76px'}}> {item.downloads_count} </li> style={{width: '76px'}}> {item.downloads_count} </li>
<li className="fl paddingl10 " style={{width: '100px'}}> {item.quotes} </li> {/*<li className="fl paddingl10 " style={{width: '100px'}}> {item.quotes} </li>*/}
<li className="fl paddingl10 datastyle"> <li className="fl paddingl10 datastyle">
{moment(item.created_on).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(item.created_on).format('YYYY-MM-DD HH:mm')} {moment(item.created_on).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(item.created_on).format('YYYY-MM-DD HH:mm')}
</li> </li>
@ -607,61 +460,15 @@ class Selectsetting extends Component{
</Upload> </Upload>
</p> </p>
{/*<style>*/}
{/*{*/}
{/*`*/}
{/*.maxwidth400{*/}
{/*max-width: 400px;*/}
{/*overflow: hidden;*/}
{/*text-overflow: ellipsis;*/}
{/*white-space: nowrap;*/}
{/*}*/}
{/*`*/}
{/*}*/}
{/*</style>*/}
{/*{this.state.fileList.length===0?"":this.state.fileList.map((item,key)=>{*/}
{/*return(*/}
{/*<p className="color-grey mt10" key={key} >*/}
{/*<a className="color-grey fl">*/}
{/*<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>*/}
{/*</a>*/}
{/*<span className="mr12 color9B9B maxwidth400 fl" length="58">*/}
{/*{item.name}*/}
{/*</span>*/}
{/*<span className="color656565 mt2 color-grey-6 font-12 mr8">*/}
{/*{item.response===undefined?"":isNaN(bytesToSize(item.filesize))?"123":bytesToSize(item.filesize)}*/}
{/*</span>*/}
{/*<i className="font-14 iconfont icon-guanbi "*/}
{/*id={item.response===undefined?"":item.response.id}*/}
{/*aria-hidden="true" onClick={()=>this.onAttachmentRemove(item.response===undefined?"":item.response.id&&item.response.id)}></i>*/}
{/*</p>*/}
{/*)*/}
{/*})}*/}
{this.state.newfileListtypes===true?<p className={"color-red"}>请先上传资源</p>:""} {this.state.newfileListtypes===true?<p className={"color-red"}>请先上传资源</p>:""}
<p className={this.state.fileListtype===true?"mt15":""}> <p className={this.state.fileListtype===true?"mt15 selecboxfilas":"selecboxfilas"}>
<style>{` <style>{`
.ant-checkbox-wrapper{ .selecboxfilas .ant-checkbox-wrapper{
margin-left:0px !important; margin-left:0px !important;
margin-top:10px; margin-top:10px;
} }
`}</style> `}</style>
{/*<div className={this.state.fileListtype===true?"mt30":""}>*/}
{/*<Checkbox*/}
{/*checked={is_public}*/}
{/*onChange={this.onChangepublics}>*/}
{/*<span className={"font-14"}>勾选后所有用户可见,否则仅课堂成员可见</span>*/}
{/*</Checkbox>*/}
{/*</div>*/}
{/*{this.props.has_course_groups&&this.props.has_course_groups===true?:""}*/}
{this.state.course_groupss&&this.state.course_groupss.length>0?<Checkbox
checked={unified_setting}
onChange={this.onChangesettings}>
<span>统一设置</span><span className={"font-14 color-grey-9"}>(使)</span>
</Checkbox>:""}
<style> <style>
{` {`
.Selectleft20{ .Selectleft20{
@ -675,53 +482,11 @@ class Selectsetting extends Component{
} }
`} `}
</style> </style>
{this.props.course_is_public===true?<div>
<span className={"color-ooo"}>公开</span><Checkbox checked={this.state.is_public} onChange={(e)=>this.onChangepublic(e)}>
{/*this.props.has_course_groups&&this.props.has_course_groups===true?:""*/} <span className={"font-14 color-ooo"}>选中所有用户可见否则课堂成员可见</span>
<div className={"resourcebox"}> </Checkbox>
{unified_setting===false? </div>:""}
this.state.course_groups&&this.state.course_groups.map((item,key)=>{
return(
<div className={"mt10 "} key={key}>
<Select placeholder="请选择分班名称"
value={item.course_group_id}
style={{ width: 200 }}
onChange={(e,index)=>this.selectassigngroups(e,index,key)}
>
{ this.state.course_groupss&&this.state.course_groupss.map((item,key)=>{
return(
<Option value={item.id} key={key}>{item.name}</Option>
)
})}
</Select>
<DatePicker
showToday={false}
dropdownClassName="hideDisable"
showTime={{ format: 'HH:mm' }}
format="YYYY-MM-DD HH:mm"
locale={locale}
placeholder="请选择发布时间"
id={"startimes"}
className={"Selectleft20"}
width={"200px"}
value={item.publish_time===undefined||item.publish_time===""?"":item.publish_time===null?"":moment(item.publish_time, dateFormat)}
onChange={(e,index)=>this.onChangeTimepublishs(e,index,key)}
// onChange={ this.onChangeTimepublish }
disabledTime={disabledDateTime}
disabledDate={disabledDate}
/>
{key!=0?<i className="iconfont icon-shanchu color-grey-c font-14 font-n ml20" onClick={()=>this.deletegrouppublish(key)}></i>:""}
{key===course_groups.length-1?<i className="iconfont icon-tianjiafangda color-green ml15" onClick={this.addgrouppublish}></i>:""}
</div>
)
}):""}
</div>
</p> </p>
<style> <style>
{` {`
@ -730,10 +495,17 @@ class Selectsetting extends Component{
} }
`} `}
</style> </style>
{unified_setting===true?
<p className={"mt10"}> <div className={this.props.course_is_public===true?"mt10":""}>
<span> <span className={"color-ooo fl mt6"}>发布设置</span>
<Radio.Group onChange={(e)=>this.RadioonChange(e)} value={this.state.Radiovalue} style={{'width': '460px'}}>
<Radio style={radioStyle} value={0}>
立即发布
</Radio>
<Radio style={radioStyle} value={1} className={"fl"}>
<span className={"mr5"}>延迟发布</span>
<DatePicker <DatePicker
showToday={false} showToday={false}
dropdownClassName="hideDisable" dropdownClassName="hideDisable"
showTime={{ format: 'HH:mm' }} showTime={{ format: 'HH:mm' }}
@ -746,12 +518,13 @@ class Selectsetting extends Component{
onChange={this.onChangeTimepublish} onChange={this.onChangeTimepublish}
disabledTime={disabledDateTime} disabledTime={disabledDateTime}
disabledDate={disabledDate} disabledDate={disabledDate}
disabled={this.state.Radiovalue===1?false:true}
/> />
</span> </Radio>
</p>:""} <span className={"fl mt5 color-grey-c"}>(按照设置的时间定时发布)</span>
{/*{this.state.course_group_idtypes===true?<p className={"color-red"}>请选择分班</p>:""}*/} </Radio.Group>
</div>
{/*{course_group_publish_timestype===true?<p className={"color-red mt10"}>请填写完整</p>:""}*/}
<textarea placeholder="请输入资源描述最大限制100个字符" className={"mt10"} value={description} onInput={this.settextarea} style={{ <textarea placeholder="请输入资源描述最大限制100个字符" className={"mt10"} value={description} onInput={this.settextarea} style={{
width: '100%', width: '100%',
@ -760,6 +533,7 @@ class Selectsetting extends Component{
padding: '10px' padding: '10px'
}}></textarea> }}></textarea>
{this.state.descriptiontypes===true?<p className={"color-red"}>描述不能超过最大限制100个字符</p>:""} {this.state.descriptiontypes===true?<p className={"color-red"}>描述不能超过最大限制100个字符</p>:""}
{this.state.Radiovaluetype===true?<p className={"color-red"}>发布时间不能为空</p>:""}
</div> </div>
<div className="mt20 marginauto clearfix edu-txt-center"> <div className="mt20 marginauto clearfix edu-txt-center">

@ -1,9 +1,11 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { Modal, Checkbox, Input, Spin} from "antd"; import { Modal, Checkbox, Input, Spin} from "antd";
import axios from 'axios' import axios from 'axios';
import moment from 'moment';
import ModalWrapper from "../common/ModalWrapper"; import ModalWrapper from "../common/ModalWrapper";
import InfiniteScroll from 'react-infinite-scroller'; import InfiniteScroll from 'react-infinite-scroller';
const dateFormat ="YYYY-MM-DD HH:mm"
const Search = Input.Search const Search = Input.Search
const pageCount = 15; const pageCount = 15;
class Sendtofilesmodal extends Component{ class Sendtofilesmodal extends Component{
@ -170,7 +172,12 @@ class Sendtofilesmodal extends Component{
bottom: 93px; bottom: 93px;
width: 82%; width: 82%;
text-align: center; text-align: center;
}`} }
.ModalWrappertitle{
background: #D0E8FC;
padding: 10px;
}
`}
</style> </style>
<p className="color-grey-6 mb20 edu-txt-center" style={{ fontWeight: "bold" }} >选择的{moduleName}发送到<span className="color-orange-tip">指定课堂</span></p> <p className="color-grey-6 mb20 edu-txt-center" style={{ fontWeight: "bold" }} >选择的{moduleName}发送到<span className="color-orange-tip">指定课堂</span></p>
@ -183,7 +190,12 @@ class Sendtofilesmodal extends Component{
></Search> ></Search>
<div> <div>
{/* https://github.com/CassetteRocks/react-infinite-scroller/issues/70 */}
<p className="clearfix ModalWrappertitle">
<div className="task-hide fl pagemancenter" style={{"width":'215px'}}>课堂名称</div>
<div className="task-hide fl pagemancenter" style={{"width":'140px'}}>创建时间</div>
<div className="task-hide fl pagemancenter" style={{"width":'110px'}}>结束时间</div>
</p>
<div className="edu-back-skyblue padding15" style={{"height":"300px", overflowY: "scroll", overflowAnchor: 'none' }}> <div className="edu-back-skyblue padding15" style={{"height":"300px", overflowY: "scroll", overflowAnchor: 'none' }}>
<InfiniteScroll <InfiniteScroll
threshold={10} threshold={10}
@ -199,20 +211,14 @@ class Sendtofilesmodal extends Component{
return ( return (
<p className="clearfix mb7" key={course.id}> <p className="clearfix mb7" key={course.id}>
<Checkbox className="fl" value={course.id} key={course.id} ></Checkbox> <Checkbox className="fl" value={course.id} key={course.id} ></Checkbox>
<span className="fl with45"><label className="task-hide fl" style={{"maxWidth":"208px;"}}>{course.name}</label></span> <div className="task-hide fl" style={{"width":'224px'}} title={course.name}>{course.name}</div>
<div className="task-hide fl" style={{"width":'130px'}}>{moment(course.created_at).format('YYYY-MM-DD')}</div>
<div className="task-hide fl" style={{"width":'110px'}}>{course.end_date}</div>
</p> </p>
) )
}) } }) }
</Checkbox.Group> </Checkbox.Group>
{loading && hasMore && (
<div className="demo-loading-container">
<Spin />
</div>
)}
{/* TODO */}
{/* {
!hasMore && <div>没有更多了</div>
} */}
</InfiniteScroll> </InfiniteScroll>
</div> </div>

@ -1,5 +1,5 @@
import React,{ Component } from "react"; import React,{ Component } from "react";
import { Modal,Checkbox,Upload,Button,Icon,message,DatePicker,Select,Tooltip} from "antd"; import { Modal,Checkbox,Upload,Button,Icon,message,DatePicker,Select,Tooltip,Radio} from "antd";
import axios from 'axios'; import axios from 'axios';
import Modals from '../../modals/Modals'; import Modals from '../../modals/Modals';
import {getUrl,handleDateString,bytesToSize,appendFileSizeToUploadFileAll} from 'educoder'; import {getUrl,handleDateString,bytesToSize,appendFileSizeToUploadFileAll} from 'educoder';
@ -40,7 +40,6 @@ class Sendresource extends Component{
ModalSave:"", ModalSave:"",
fileListtype:false, fileListtype:false,
loadtype:false, loadtype:false,
is_unified_setting:true,
is_public:false, is_public:false,
datatime:undefined, datatime:undefined,
// moment(new Date()).format('YYYY-MM-DD HH:mm:ss'), // moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),
@ -50,30 +49,15 @@ class Sendresource extends Component{
publish_time :"" publish_time :""
}], }],
course_groups:undefined, course_groups:undefined,
course_groups_count:undefined course_groups_count:undefined,
Radiovalue:0,
Radiovaluetype:false
} }
} }
componentDidMount() { componentDidMount() {
let coursesId=this.props.match.params.coursesId;
if(this.props.isAdmin()){
let url = `/courses/${coursesId}/all_course_groups.json`
axios.get(url, {
})
.then((response) => {
this.setState({
course_groups: response.data.course_groups,
course_groups_count:response.data.course_groups_count
})
})
.catch(function (error) {
console.log(error);
});
}
} }
//勾选实训 //勾选实训
@ -101,37 +85,6 @@ class Sendresource extends Component{
} }
} }
// onAttachmentRemove = (file) => {
//
// this.setState({
// fileListtype:false,
// })
// // confirm({
// // title: '确定要删除这个附件吗?',
// // okText: '确定',
// // cancelText: '取消',
// // // content: 'Some descriptions',
// // onOk: () => {
// // this.deleteAttachment(file)
// // },
// // onCancel() {
// // console.log('Cancel');
// // },
// // });
// // return false;
//
// // this.setState({
// // Modalstype:true,
// // Modalstopval:'确定要删除这个附件吗?',
// // ModalSave: ()=>this.deleteAttachment(file),
// // ModalCancel:this.cancelAttachment
// // })
// // return false;
//
// this.deleteAttachment(file);
// }
onAttachmentRemove = (file) => { onAttachmentRemove = (file) => {
if(!file.percent || file.percent == 100){ if(!file.percent || file.percent == 100){
const url = `/attachments/${file.response ? file.response.id : file.uid}.json` const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
@ -174,8 +127,7 @@ class Sendresource extends Component{
} }
Saves=()=>{ Saves=()=>{
let id=this.props.categoryid; let {fileList,description,is_public,datatime,Radiovalue} =this.state;
let {fileList,description,is_public,is_unified_setting,datatime,course_group_publish_times} =this.state;
let newfileList=[]; let newfileList=[];
for(var list of fileList){ for(var list of fileList){
@ -188,17 +140,19 @@ class Sendresource extends Component{
}) })
return return
} }
// if(is_unified_setting===false){
// course_group_publish_times.forEach((item,key)=>{ if(this.state.Radiovalue===1){
// if(item.course_group_id===undefined||item.publish_time===undefined){ if(datatime===undefined||datatime===null||datatime=== ""){
// this.setState({ this.setState({
// course_group_publish_timestype:true Radiovaluetype:true
// }) })
// return return
// } }else{
// }) this.setState({
// Radiovaluetype:false
// } })
}
}
@ -222,22 +176,14 @@ class Sendresource extends Component{
course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId, course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId,
attachment_ids:newfileList, attachment_ids:newfileList,
is_public:is_public, is_public:is_public,
is_unified_setting:is_unified_setting, publish_time:Radiovalue===1?datatime===undefined? undefined:datatime:undefined,
publish_time:is_unified_setting===true?datatime===undefined? moment(new Date()).format('YYYY-MM-DD HH:mm'):datatime:undefined,
description:description, description:description,
course_group_publish_times:is_unified_setting===false?course_group_publish_times:undefined delay_publish:Radiovalue,
}).then((result)=>{ }).then((result)=>{
if(result.data.status===0){ if(result.data.status===0){
// this.setState({
// Modalstype:true,
// Modalstopval:result.data.message,
// ModalSave:this.ModalCancelModalCancel,
// loadtype:true
// })
this.ModalCancelModalCancel(); this.ModalCancelModalCancel();
this.props.updataleftNavfun(); this.props.updataleftNavfun();
// this.props.showNotification(result.data.message);
this.props.showNotification("上传资源成功"); this.props.showNotification("上传资源成功");
this.props.setupdate(this.props.attachmentId) this.props.setupdate(this.props.attachmentId)
} }
@ -253,14 +199,6 @@ class Sendresource extends Component{
}) })
} }
onChangesetting=(e)=>{
this.setState({
is_unified_setting:e.target.checked
})
}
onChangepublic=(e)=>{ onChangepublic=(e)=>{
this.setState({ this.setState({
@ -289,50 +227,20 @@ class Sendresource extends Component{
} }
selectassigngroups=(e,index,key)=>{ RadioonChange=(e)=>{
let {course_group_publish_times}=this.state; if(e.target.value===0){
let newgroup_publish=course_group_publish_times;
for(var i=0; i<newgroup_publish.length; i++){
if(i===parseInt(key)){
newgroup_publish[i].course_group_id=index.props.value;
}
}
this.setState({ this.setState({
course_group_publish_times:newgroup_publish, datatime:undefined
}) })
} }
deletegrouppublish=(key)=>{
let newlist=this.state.course_group_publish_times;
newlist.splice(key,1);
this.setState({ this.setState({
course_group_publish_times:newlist Radiovalue: e.target.value,
}) });
}
addgrouppublish=()=>{
let newlist=this.state.course_group_publish_times;
newlist.push( {
course_group_id : undefined,
publish_time :undefined
})
this.setState({
course_group_publish_times:newlist
})
} }
render(){ render(){
let {settextarea,newfileListtype,descriptiontype, let { newfileListtype,descriptiontype,
course_group_publish_timestype,
Modalstopval,
ModalCancel,
ModalSave,
loadtype,
is_unified_setting,
is_public, is_public,
datatime, datatime,
course_group_publish_times,
course_groups
}=this.state; }=this.state;
const uploadProps = { const uploadProps = {
@ -350,7 +258,11 @@ class Sendresource extends Component{
return isLt150M; return isLt150M;
}, },
}; };
const radioStyle = {
display: 'block',
height: '30px',
lineHeight: '30px',
};
return( return(
<div> <div>
{/*提示*/} {/*提示*/}
@ -389,6 +301,7 @@ class Sendresource extends Component{
margin-right: 5px; margin-right: 5px;
} }
.ant-upload-list-item:hover .ant-upload-list-item-info{ .ant-upload-list-item:hover .ant-upload-list-item-info{
padding: 0 12px 0 0px;
background-color:#fff; background-color:#fff;
} }
.upload_1 .ant-upload-list { .upload_1 .ant-upload-list {
@ -437,42 +350,12 @@ class Sendresource extends Component{
<Button className="uploadBtn"> <Button className="uploadBtn">
<Icon type="upload" /> 选择文件 <Icon type="upload" /> 选择文件
</Button> </Button>
<span className={"ml10"}>(单个文件最大150M)</span> <span className={"ml10 color-ooo"}>(单个文件最大150M)</span>
</span>:""} </span>:""}
</Upload> </Upload>
</p> </p>
{/*<style>*/}
{/*{*/}
{/*`*/}
{/*.maxwidth400{*/}
{/*max-width: 400px;*/}
{/*overflow: hidden;*/}
{/*text-overflow: ellipsis;*/}
{/*white-space: nowrap;*/}
{/*}*/}
{/*`*/}
{/*}*/}
{/*</style>*/}
{/*{this.state.fileList.length===0?"":this.state.fileList.map((item,key)=>{*/}
{/*debugger*/}
{/*return(*/}
{/*<p className="color-grey mt10" key={key} >*/}
{/*<a className="color-grey fl">*/}
{/*<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>*/}
{/*</a>*/}
{/*<span className="mr12 color9B9B maxwidth400 fl" length="58">*/}
{/*{item.name}*/}
{/*</span>*/}
{/*<span className="color656565 mt2 color-grey-6 font-12 mr8">*/}
{/*{item.response===undefined?"":isNaN(bytesToSize(item.filesize))?"":bytesToSize(item.filesize)}*/}
{/*</span>*/}
{/*<i className="font-14 iconfont icon-guanbi "*/}
{/*id={item.response===undefined?"":item.response.id}*/}
{/*aria-hidden="true" onClick={()=>this.onAttachmentRemove(item.response===undefined?"":item.response.id&&item.response.id)}></i>*/}
{/*</p>*/}
{/*)*/}
{/*})}*/}
{newfileListtype===true&&this.state.fileListtype===false?<p className={"color-red"}>请先上传资源</p>:""} {newfileListtype===true&&this.state.fileListtype===false?<p className={"color-red"}>请先上传资源</p>:""}
@ -484,13 +367,12 @@ class Sendresource extends Component{
} }
`}</style> `}</style>
{/*<div className={this.state.fileListtype===true?"mt30":""}></div><Checkbox checked={is_public} onChange={this.onChangepublic}>*/} {this.props.course_is_public===true?<div>
{/*<span className={"font-14"}>勾选后所有用户可见,否则仅课堂成员可见</span>*/} <span className={"color-ooo"}>公开</span><Checkbox checked={is_public} onChange={this.onChangepublic}>
{/*</Checkbox>*/} <span className={"font-14 color-ooo"}>选中所有用户可见否则课堂成员可见</span>
</Checkbox>
</div>:""}
{this.state.course_groups_count&&this.state.course_groups_count>0?<Checkbox checked={is_unified_setting} onChange={this.onChangesetting}>
<span>统一设置</span><span className={"font-14 color-grey-9"}>(使)</span>
</Checkbox>:""}
<style>{` <style>{`
.Selectleft20{ .Selectleft20{
margin-left: 20px !important; margin-left: 20px !important;
@ -505,54 +387,19 @@ class Sendresource extends Component{
overflow: auto; overflow: auto;
} }
`}</style> `}</style>
<div className={"resourcebox"}> </p>
{is_unified_setting===false?
course_group_publish_times.map((item,key)=>{
return(
<div className={"mt10"} key={key}>
<Select placeholder="请选择分班名称"
value={item.course_group_id}
style={{ width: 200 }}
onChange={(e,index)=>this.selectassigngroups(e,index,key)}
>
{course_groups&&course_groups.map((item,key)=>{
return(
<Option value={item.id} key={key}>{item.name}</Option>
)
})}
</Select>
<div className={this.props.course_is_public===true?"mt10":""}>
<span className={"color-ooo fl mt6"}>发布设置</span>
<Radio.Group onChange={this.RadioonChange} value={this.state.Radiovalue} style={{'width': '460px'}}>
<Radio style={radioStyle} value={0}>
立即发布
</Radio>
<Radio style={radioStyle} value={1} className={"fl"}>
<span className={"mr5"}>延迟发布</span>
<DatePicker <DatePicker
dropdownClassName="hideDisable"
showTime={{ format: 'HH:mm' }}
locale={locale}
showToday={false}
format={dateFormat}
placeholder="请选择发布时间"
id={"startimes"}
className={"Selectleft20 "}
width={"200px"}
value={item.publish_time===undefined||item.publish_time===""?undefined:moment(item.publish_time, dateFormat)}
onChange={(e,index)=>this.onChangeTimepublish(e,index,key,2)}
// onChange={ this.onChangeTimepublish }
disabledTime={disabledDateTime}
disabledDate={disabledDate}
/>
{key!=0?<i className="iconfont icon-shanchu color-grey-c font-14 font-n ml20" onClick={()=>this.deletegrouppublish(key)}></i>:""}
{key===course_group_publish_times.length-1&&key<this.state.course_groups_count-1?<i className="iconfont icon-tianjiafangda color-green ml15" onClick={this.addgrouppublish}></i>:""}
</div>
)
})
:""}
</div>
</p>
{is_unified_setting===true?<p className={"mt10"}>
<span>
<DatePicker
dropdownClassName="hideDisable" dropdownClassName="hideDisable"
showTime={{ format: 'HH:mm' }} showTime={{ format: 'HH:mm' }}
locale={locale} locale={locale}
@ -561,13 +408,17 @@ class Sendresource extends Component{
id={"startime"} id={"startime"}
showToday={false} showToday={false}
width={"210px"} width={"210px"}
value={datatime===undefined||datatime===""?undefined:moment(datatime, dateFormat)} value={this.state.Radiovalue===1?datatime===undefined||datatime===""?undefined:moment(datatime, dateFormat):undefined}
onChange={(e,index)=>this.onChangeTimepublish(e,index,undefined,1)} onChange={(e,index)=>this.onChangeTimepublish(e,index,undefined,1)}
disabledTime={disabledDateTime} disabledTime={disabledDateTime}
disabledDate={disabledDate} disabledDate={disabledDate}
disabled={this.state.Radiovalue===1?false:true}
/> />
</span> </Radio>
</p>:""} <span className={"fl mt5 color-grey-c"}>(按照设置的时间定时发布)</span>
</Radio.Group>
</div>
{/*{course_group_publish_timestype===true?<p className={"color-red mt10"}>请填写完整</p>:""}*/} {/*{course_group_publish_timestype===true?<p className={"color-red mt10"}>请填写完整</p>:""}*/}
<textarea placeholder="请在此输入资源描述最大限制100个字符" className={"mt10"} value={this.state.description} onInput={this.settextarea} style={{ <textarea placeholder="请在此输入资源描述最大限制100个字符" className={"mt10"} value={this.state.description} onInput={this.settextarea} style={{
@ -577,6 +428,7 @@ class Sendresource extends Component{
padding: '10px' padding: '10px'
}}></textarea> }}></textarea>
{descriptiontype===true?<p className={"color-red"}>请输入资源描述最大限制100个字符</p>:""} {descriptiontype===true?<p className={"color-red"}>请输入资源描述最大限制100个字符</p>:""}
{this.state.Radiovaluetype===true?<p className={"color-red"}>发布时间不能为空</p>:""}
<div className="clearfix mt30 edu-txt-center mb10"> <div className="clearfix mt30 edu-txt-center mb10">
<a className="task-btn color-white mr70" onClick={this.props.Cancel}>{this.props.Cancelname}</a> <a className="task-btn color-white mr70" onClick={this.props.Cancel}>{this.props.Cancelname}</a>
<a className="task-btn task-btn-orange" onClick={()=>this.Saves()}>{this.props.Savesname}</a> <a className="task-btn task-btn-orange" onClick={()=>this.Saves()}>{this.props.Savesname}</a>

@ -1702,3 +1702,46 @@ input.ant-input-number-input:focus {
.yslinputcourput .ant-form-explain{ .yslinputcourput .ant-form-explain{
padding-left: 0px !important; padding-left: 0px !important;
} }
.wechatloginfont{
font-size: 14px;
font-family: PingFangSC-Regular,PingFangSC;
font-weight: 400;
color: #555555;
line-height: 20px;
margin-top: 10px;
}
.wechatdiv{
margin-top: 40px !important;
width: 800px !important;
}
.wechatContent{
padding: 0px 50px;
}
.wechatpass{
width: 300px;
height: 46px;
}
.wechatnewchat{
width: 62px;
height: 62px;
background: rgba(255,170,170,1);
border-radius: 50%;
text-align: center;
line-height: 62px;
color: #fff;
margin: 0 auto;
}
.wechatweoldchat{
width: 62px;
height: 62px;
background:rgba(164,211,255,1);
border-radius: 50%;
text-align: center;
line-height: 62px;
color: #fff;
margin: 0 auto;
}

@ -57,8 +57,9 @@ class ExerciceNew extends Component{
const courseId=this.props.match.params.coursesId; const courseId=this.props.match.params.coursesId;
const isEdit = this.isEdit const isEdit = this.isEdit;
document.title=this.props.coursedata&&this.props.coursedata.name;
return( return(
<div className="newMain exerciseNew"> <div className="newMain exerciseNew">

@ -612,6 +612,7 @@ class ExerciseReviewAndAnswer extends Component{
let isStudent =this.props.isStudent(); let isStudent =this.props.isStudent();
const { current_user } = this.props const { current_user } = this.props
// console.log(data&&data.exercise.user_name) // console.log(data&&data.exercise.user_name)
document.title=courseName&&courseName.name;
return( return(
<div className="newMain" style={{paddingTop:"0px"}}> <div className="newMain" style={{paddingTop:"0px"}}>
<Spin size="large" spinning={isSpin}> <Spin size="large" spinning={isSpin}>

@ -350,6 +350,7 @@ class Exercisesetting extends Component{
this.commitSetting((result)=>{ this.commitSetting((result)=>{
console.log(result)
if(result.status==200){ if(result.status==200){
this.props.showNotification(`${result.data.message}`); this.props.showNotification(`${result.data.message}`);
this.getSettingInfo(); this.getSettingInfo();
@ -369,6 +370,7 @@ class Exercisesetting extends Component{
} }
this.commitSetting((result)=>{ this.commitSetting((result)=>{
console.log(result)
if(result.status==200){ if(result.status==200){
this.props.showNotification(`${result.data.message}`); this.props.showNotification(`${result.data.message}`);
this.cancelEdit(); this.cancelEdit();
@ -702,6 +704,8 @@ class Exercisesetting extends Component{
</div> </div>
: :
<PollDetailTabForthRules <PollDetailTabForthRules
{...this.props}
{...this.state}
ref="pollDetailTabForthRules" ref="pollDetailTabForthRules"
rules={rules} rules={rules}
type={"Exercise"} type={"Exercise"}

@ -2663,8 +2663,14 @@ class Studentshavecompletedthelist extends Component {
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot { .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;} top: 72%;}
} }
.ysltableows2 .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 9px;
}
mysjysltable1 .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 9px;
}
`}</style> `}</style>
<div className="edu-table edu-back-white"> <div className="edu-table edu-back-white ysltableows2">
{data === undefined ? "" : <Table {data === undefined ? "" : <Table
dataSource={data} dataSource={data}
columns={columnsys} columns={columnsys}
@ -2767,8 +2773,14 @@ class Studentshavecompletedthelist extends Component {
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot { .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;} top: 72%;}
} }
.ysltableows2 .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 9px;
}
mysjysltable2 .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 9px;
}
`}</style> `}</style>
<div className="edu-table edu-back-white minH-560"> <div className="edu-table edu-back-white minH-560 ysltableows2">
{datas === undefined ? "" : <Table {datas === undefined ? "" : <Table
dataSource={datas} dataSource={datas}
columns={columnss} columns={columnss}
@ -2820,6 +2832,9 @@ class Studentshavecompletedthelist extends Component {
.ysltableows .ant-table-thead > tr > th, .ant-table-tbody > tr > td { .ysltableows .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 9px; padding: 9px;
} }
mysjysltable3 .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 9px;
}
` `
} }
</style> </style>
@ -2828,7 +2843,7 @@ class Studentshavecompletedthelist extends Component {
{data === undefined ? "" : <Table {data === undefined ? "" : <Table
dataSource={data} dataSource={data}
columns={columnstwo} columns={columnstwo}
className="mysjysltable3" className="mysjysltable3 "
pagination={false} pagination={false}
loading={false} loading={false}
showHeader={false} showHeader={false}
@ -2911,6 +2926,9 @@ class Studentshavecompletedthelist extends Component {
.ysltableowss .ant-table-thead > tr > th, .ant-table-tbody > tr > td { .ysltableowss .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 9px; padding: 9px;
} }
mysjysltable4 .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 9px;
}
`}</style> `}</style>
<div className="edu-table edu-back-white minH-560 ysltableowss"> <div className="edu-table edu-back-white minH-560 ysltableowss">
{datas === undefined ? "" : <Table {datas === undefined ? "" : <Table

@ -61,7 +61,7 @@ class Testpapersettinghomepage extends Component{
} }
//试卷公用头部 //试卷公用头部
Commonheadofthetestpaper=()=>{ Commonheadofthetestpaper=()=>{
// console.log("Commonheadofthetestpaper"); console.log("Commonheadofthetestpaper 试卷公用头部");
var exercise_id = this.props.match.params.Id; var exercise_id = this.props.match.params.Id;
var url = `/exercises/${exercise_id}/common_header.json`; var url = `/exercises/${exercise_id}/common_header.json`;
axios.get(url).then((response) => { axios.get(url).then((response) => {
@ -249,6 +249,28 @@ class Testpapersettinghomepage extends Component{
// DownloadMessageval:undefined // DownloadMessageval:undefined
// }) // })
// } // }
getsetdata =()=>{
// console.log("Testpapersettinghomepage");
// console.log("getsetdatassssss");
let{tab}=this.state;
try {
if(tab[0]==="0"){
this.child.Teacherliststudentlist();
}
if(tab[0]==="1"){
this.child.Teacherliststudentlist();
}
if(tab[0]==="2"){
this.child.Teacherliststudentlist();
}
if(tab[0]==="3"){
this.child.getSettingInfo();
}
}catch (e) {
}
}
bindRef = ref => { this.child = ref }; bindRef = ref => { this.child = ref };
goback=()=>{ goback=()=>{
// let {datalist}=this.state; // let {datalist}=this.state;
@ -271,7 +293,7 @@ class Testpapersettinghomepage extends Component{
// TODO // TODO
// console.log(Commonheadofthetestpaper.exercise_status); // console.log(Commonheadofthetestpaper.exercise_status);
document.title=this.props.coursedata&&this.props.coursedata.name;
return( return(
<div className="newMain clearfix "> <div className="newMain clearfix ">
{/*<DownloadMessage*/} {/*<DownloadMessage*/}
@ -410,6 +432,7 @@ class Testpapersettinghomepage extends Component{
Exercisetype={"exercise"} Exercisetype={"exercise"}
action={this.Commonheadofthetestpaper} action={this.Commonheadofthetestpaper}
single={true} single={true}
getsetdata={this.getsetdata}
></ImmediatelyPublish> ></ImmediatelyPublish>
:"":""} :"":""}
{isAdmin === true? <Link className="fr color-blue font-16 mt20 mr20" to={`/courses/${this.props.match.params.coursesId}/exercises/${this.props.match.params.Id}/edit`}>编辑试卷</Link>:""} {isAdmin === true? <Link className="fr color-blue font-16 mt20 mr20" to={`/courses/${this.props.match.params.coursesId}/exercises/${this.props.match.params.Id}/edit`}>编辑试卷</Link>:""}

@ -316,6 +316,8 @@ class GraduationTaskDetail extends Component{
setTab:this.setTab, setTab:this.setTab,
getdatas:this.getdatas getdatas:this.getdatas
} }
document.title=questionslist&&questionslist.course_name;
return( return(
<div className="newMain clearfix"> <div className="newMain clearfix">
{ {

@ -537,7 +537,7 @@ class GraduationTasksSubmitedit extends Component{
}, },
}; };
document.title=workslist&&workslist.course_name;
return( return(
<React.Fragment> <React.Fragment>

@ -560,10 +560,10 @@ render(){
}, },
}; };
console.log(this.props) // console.log(this.props)
document.title=workslist&&workslist.course_name;
return( return(
<React.Fragment> <React.Fragment>

@ -146,6 +146,8 @@ class GraduationTasksappraise extends Component{
let graduation_id=datalist===undefined?"":datalist.graduation_id; let graduation_id=datalist===undefined?"":datalist.graduation_id;
let task_id=datalist===undefined?"":datalist.task_id; let task_id=datalist===undefined?"":datalist.task_id;
// console.log(datalist); // console.log(datalist);
document.title=datalist&&datalist.course_name;
return( return(
<React.Fragment> <React.Fragment>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save