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

competitions
SylorHuang 5 years ago
commit 0d3e1b610d

@ -1,69 +1,70 @@
# README
This README would normally document whatever steps are necessary to get the
application up and running.
Things you may want to cover:
* Ruby version
* System dependencies
* Configuration
* Database creation
* Database initialization
* How to run the test suite
* Services (job queues, cache servers, search engines, etc.)
* Deployment instructions
* ...
#### Jbuilder介绍
Jbuilder https://github.com/rails/jbuilder
#### Rails5 介绍
rails guide https://ruby-china.github.io/rails-guides/v5.0/
#### API设计文档
doc for api https://www.showdoc.cc/web/#/127895880302646?page_id=729221359592009
user:Hjqreturn PW:12345678
#### 测试版访问地址https://testeduplus2.educoder.net
#### 实训平台繁忙
仓库异常繁忙等级81
#### 新版域名跳转规则
新版域名要求总结testeduplus2.educoder.net/(主要提供实训、实训课堂等业务)
目前有两个域名testbdweb.educoder.net(老版:主要提供课堂、项目、个人主页、后台等服务)
要求:
1、两服务域名都应该启动提供服务
2、如果请求链接包含以下的形式则域名跳至testeduplus2.educoder.net
testeduplus2.educoder.net/shixuns
testeduplus2.educoder.net/shixuns/*
testeduplus2.educoder.net/paths
testeduplus2.educoder.net/paths/*
testeduplus2.educoder.net/myshixuns/
testeduplus2.educoder.net/tasks/*
testeduplus2.educoder.net/games/*
如果不满足上述需求的域名全部跳转至testbdweb.educoder.net
比如门户首页如果访问testeduplus2.educoder.net 应为没包含上述链接。则调制testbdweb.educoder.net
在比如testeduplus2.educoder.net /users/Hjqreturn没包含上述规则则跳转到testbdweb.educoder.net/users/Hjqreturn
# 需要重构user_extensions 相关sql语句的地方标记 REDO:Extention
# 文件上传ActiveStorage
# 新能bootsnap
# 注意事项:
# 第一次部署需要执行一些rake任务
# 配置redis地址
# README
https://www.trustie.net/issues/24719
[云上实验室] Logo、导航、底部备案信息定制化
This README would normally document whatever steps are necessary to get the
application up and running.
Things you may want to cover:
* Ruby version
* System dependencies
* Configuration
* Database creation
* Database initialization
* How to run the test suite
* Services (job queues, cache servers, search engines, etc.)
* Deployment instructions
* ...
#### Jbuilder介绍
Jbuilder https://github.com/rails/jbuilder
#### Rails5 介绍
rails guide https://ruby-china.github.io/rails-guides/v5.0/
#### API设计文档
doc for api https://www.showdoc.cc/web/#/127895880302646?page_id=729221359592009
user:Hjqreturn PW:12345678
#### 测试版访问地址https://testeduplus2.educoder.net
#### 实训平台繁忙
仓库异常繁忙等级81
#### 新版域名跳转规则
新版域名要求总结testeduplus2.educoder.net/(主要提供实训、实训课堂等业务)
目前有两个域名testbdweb.educoder.net(老版:主要提供课堂、项目、个人主页、后台等服务)
要求:
1、两服务域名都应该启动提供服务
2、如果请求链接包含以下的形式则域名跳至testeduplus2.educoder.net
testeduplus2.educoder.net/shixuns
testeduplus2.educoder.net/shixuns/*
testeduplus2.educoder.net/paths
testeduplus2.educoder.net/paths/*
testeduplus2.educoder.net/myshixuns/
testeduplus2.educoder.net/tasks/*
testeduplus2.educoder.net/games/*
如果不满足上述需求的域名全部跳转至testbdweb.educoder.net
比如门户首页如果访问testeduplus2.educoder.net 应为没包含上述链接。则调制testbdweb.educoder.net
在比如testeduplus2.educoder.net /users/Hjqreturn没包含上述规则则跳转到testbdweb.educoder.net/users/Hjqreturn
# 需要重构user_extensions 相关sql语句的地方标记 REDO:Extention
# 文件上传ActiveStorage
# 新能bootsnap
# 注意事项:
# 第一次部署需要执行一些rake任务
# 配置redis地址
# 配置gitlab/intializers/gitlab_config.yml

@ -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
def create_params
params.permit(:login, :password, :type, :not_bind)
params.permit(:username, :password, :type, :not_bind)
end
end

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

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

@ -2,7 +2,8 @@ class CourseModulesController < ApplicationController
before_action :require_login, :check_auth
before_action :set_module, except: [: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
@ -48,9 +49,9 @@ class CourseModulesController < ApplicationController
tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip)
ActiveRecord::Base.transaction do
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)
normal_status(0, "添加成功")
render :json => {category_id: category.id, status: 0, message: "添加成功"}
rescue Exception => e
uid_logger_error(e.message)
tip_exception("添加子目录失败")

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

@ -35,7 +35,7 @@ class CoursesController < ApplicationController
:transfer_to_course_group, :delete_from_course, :export_member_scores_excel,
:search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup,
: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,
:set_course_group, :create_group_by_importing_file,
: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)
tip_exception("切换失败") if course_member.STUDENT?
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_student.update_attributes(is_active: 1)
course_student = CourseMember.find_by(user_id: current_user.id, role: %i[STUDENT], course_id: @course.id)
course_member.update_attributes!(is_active: 0)
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, "切换成功")
rescue => e
uid_logger_error("switch_to_student error: #{e.message}")
tip_exception("切换失败")
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -1127,7 +1133,7 @@ class CoursesController < ApplicationController
def top_banner
@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
@course.increment!(:visits)
end

@ -518,27 +518,27 @@ class ExercisesController < ApplicationController
common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的
new_group_ids = course_id - common_group #新传入的班级id
if common_group.count > 0 #判断试卷的分班设置是否存在,存在则更新,负责则新建
ex_group_params = {
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 = {
:publish_time => exercise_publish_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)
if the_group_setting_status == 2
ex_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => exercise_end_time
:publish_time => the_group_setting.publish_time,
:end_time => exercise_end_time
}
elsif the_group_setting_status == 3
ex_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => the_group_setting.end_time
:publish_time => the_group_setting.publish_time,
:end_time => the_group_setting.end_time
}
end
the_group_setting.update_attributes!(ex_group_params)
end
exercise_group_sets.update_all(ex_group_params)
end
if new_group_ids.size > 0
new_group_ids.each do |c|
@ -560,8 +560,9 @@ class ExercisesController < ApplicationController
error_count == 0
normal_status(-1,"已发布/已截止的试卷不允许修改时间")
else
# 未发布的分班设置才能删除
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
end
#试卷更新为exercise_group_setting的发布时间最小截止时间最大
@ -720,8 +721,8 @@ class ExercisesController < ApplicationController
if exercise.unified_setting
ex_status = exercise.exercise_status #则为试卷的状态
else
ex_status = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",params[:group_ids])
.exercise_group_not_published.present? ? 1 : 0
ex_status = @course.course_groups.where(id: params[:group_ids]).size !=
exercise.exercise_group_settings.where("course_group_id", params[:group_ids]).exercise_group_published.size ? 1 : 0
end
if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过
g_course = group_ids #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改
@ -739,8 +740,8 @@ class ExercisesController < ApplicationController
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寻找试卷所在的班级
group_end_time = params[:detail] ? group_end_times[index] : ex_end_time
if exercise_group_setting #如果该试卷分组存在,则更新,否则新建
exercise_group_setting.update_attributes(publish_time: Time.now, end_time: group_end_time)
if exercise_group_setting.present? #如果该试卷分组存在,则更新,否则新建
exercise_group_setting.update_attributes!(publish_time: Time.now, end_time: group_end_time)
else
p_course_group = {
:exercise_id => exercise.id,
@ -1152,7 +1153,7 @@ class ExercisesController < ApplicationController
# 1 老师权限0 学生权限
@is_teacher_or = (@user_course_identity < Course::STUDENT) ? 1 : 0
@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 = []
get_exercise_status = @exercise.get_exercise_status(current_user) #当前用户的试卷状态
@ex_answer_status = @exercise.get_exercise_status(@ex_user&.user) #当前试卷用户的试卷状态
@ -1715,9 +1716,9 @@ class ExercisesController < ApplicationController
ques_number = q.question_number
end
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
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
ques_status = 0
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 :validate_upload_params, only: %i[upload import]
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]
def index
sort = params[:sort] || 0 # 0: 降序1: 升序
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
@attachments = course_second_category_id.to_i == 0 ? @course.attachments : @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 = @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(author: [:user_extension, :course_members])
.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
@publish_count = @attachments.published.size
@unpublish_count = @total_count - @publish_count
@ -137,9 +138,9 @@ class FilesController < ApplicationController
def upload
attachment_ids = params[:attachment_ids]
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
publish_time = params[:publish_time]
course_group_publish_times = params[:course_group_publish_times] || []
# is_unified_setting = params.has_key?(:is_unified_setting) ? params[:is_unified_setting] : true
# publish_time = params[:publish_time]
# course_group_publish_times = params[:course_group_publish_times] || []
begin
attachment_ids.each do |attchment_id|
@ -148,9 +149,12 @@ class FilesController < ApplicationController
attachment.container = @course
attachment.course_second_category_id = course_second_category_id
attachment.description = params[:description]
attachment.is_public = params[:is_public] ? 1 : 0
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.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0
attachment.is_publish = @atta_is_publish
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!
end
end
@ -188,8 +192,9 @@ class FilesController < ApplicationController
attach_copied_obj.created_on = Time.now
attach_copied_obj.author = current_user
attach_copied_obj.is_public = 0
attach_copied_obj.is_publish = 1
attach_copied_obj.publish_time = Time.now
attach_copied_obj.is_publish = @atta_is_publish
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.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from
if attach_copied_obj.attachtype == nil
@ -209,11 +214,7 @@ class FilesController < ApplicationController
def update
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]
course_group_publish_times = params[:course_group_publish_times] || []
@old_attachment = @file
@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_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.save!
@new_attachment.delete
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
@old_attachment.description = params[:description]
end
@old_attachment.set_public(is_public)
# @old_attachment.set_public(is_public)
if is_unified_setting
@old_attachment.set_publish_time(publish_time)
@old_attachment.attachment_group_settings.destroy_all
end
# if is_unified_setting
# @old_attachment.set_publish_time(publish_time)
# @old_attachment.attachment_group_settings.destroy_all
# end
if publish_time.blank? && @course.course_groups.size > 0 && !is_unified_setting
@old_attachment.set_course_group_publish_time(@course, course_group_publish_times)
end
# if publish_time.blank? && @course.course_groups.size > 0 && !is_unified_setting
# @old_attachment.set_course_group_publish_time(@course, course_group_publish_times)
# end
@old_attachment.save!
rescue Exception => e
@ -304,11 +309,19 @@ class FilesController < ApplicationController
end
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
def validate_upload_params
find_attachment_ids
find_course_second_category_id
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

@ -160,7 +160,8 @@ class HomeworkCommonsController < ApplicationController
# 作品状态 0 未提交, 1 按时提交, 2 延迟提交
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)
@student_works = all_student_works.where(work_status: work_status)
@ -170,7 +171,8 @@ class HomeworkCommonsController < ApplicationController
# 分班情况
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)
end
@ -482,7 +484,7 @@ class HomeworkCommonsController < ApplicationController
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]).
update_all(publish_time: publish_time, end_time: end_time)
setting_group_ids << setting[:group_id]
@ -1170,7 +1172,7 @@ class HomeworkCommonsController < ApplicationController
# 可立即截止的分班:统一设置则是用户管理的所有分班,否则是当前用户管理的分班中已发布且未截止的
charge_group_ids = @course.charge_group_ids(@current_user) # 当前用户管理的分班
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)
else
tip_exception("没有可截止的分班")

@ -279,7 +279,8 @@ class PollsController < ApplicationController
if poll.unified_setting
pl_status = poll.polls_status #则为试卷的状态
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
if pl_status == 1 #如果问卷存在已发布的,或者是已截止的,那么则直接跳过
g_course = group_ids #表示是否传入分班参数,如果传入分班的参数那么poll的统一设置需修改
@ -782,27 +783,27 @@ class PollsController < ApplicationController
common_group = poll_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的
new_group_ids = course_id - common_group #新传入的班级id
if common_group.size > 0 #传入的参数存在已发布的分班
poll_group_params = {
poll_group = poll_groups.find_in_poll_group("course_group_id",common_group)
poll_group.each do |the_group_setting|
poll_group_params = {
:publish_time => poll_publish_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)
if the_group_setting_status == 2
poll_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => poll_end_time
:publish_time => the_group_setting.publish_time,
:end_time => poll_end_time
}
elsif the_group_setting_status == 3
poll_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => the_group_setting.end_time
:publish_time => the_group_setting.publish_time,
:end_time => the_group_setting.end_time
}
end
the_group_setting.update_attributes(poll_group_params)
end
poll_group.update_all(poll_group_params)
end
if new_group_ids.size > 0
new_group_ids.each do |c|
@ -824,8 +825,9 @@ class PollsController < ApplicationController
error_count == 0
normal_status(-1,"已发布/已截止的问卷不允许修改时间")
else
# 未发布的分班设置才能删除
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
end
#问卷更新为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
validates :password, presence: true
validates :old_password, presence: true
end

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

@ -10,9 +10,9 @@ module ExercisesHelper
exercise_obj_status.each do |q|
q_type = q.question_type
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
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
if q_type <= Exercise::JUDGMENT
@ -40,7 +40,7 @@ module ExercisesHelper
ques_score = 0.0
end
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
if ques_score >= q.question_score #满分作答为正确
@ -64,7 +64,7 @@ module ExercisesHelper
exercise_sub_status = exercise_questions.find_by_custom("question_type",Exercise::SUBJECTIVE) #主观题
@ex_sub_array = [] #主观题的已答/未答
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 s.question_score <= sub_answer.first.score
stand_status = 1
@ -772,12 +772,12 @@ module ExercisesHelper
question_comment = []
# user_score_pre = nil
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
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
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的分数时为空
user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : nil
elsif ques_type == 5 || ques_type == 3
@ -829,7 +829,7 @@ module ExercisesHelper
if ex_type == 4 #填空题/主观题/实训题有评论的
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
{
"user_score": (user_score.present? ? user_score.round(1).to_s : nil),

@ -452,7 +452,7 @@ module ExportHelper
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 = 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
has_many :attachment_group_settings, :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",
:search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank? }
@ -96,7 +98,7 @@ class Attachment < ApplicationRecord
def become_history
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,
version: history.nil? ? 1 : history.version + 1,
))
@ -104,7 +106,7 @@ class Attachment < ApplicationRecord
end
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
def set_public(is_public)

@ -18,6 +18,29 @@ class Competition < ApplicationRecord
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?
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 :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)}
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

@ -19,7 +19,7 @@ class Laboratory < ApplicationRecord
return if subdomain.blank?
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)
end

@ -43,7 +43,7 @@ class User < ApplicationRecord
has_many :myshixuns, :dependent => :destroy
has_many :study_shixuns, through: :myshixuns, source: :shixun # 已学习的实训
has_many :course_messages
has_many :courses, dependent: :destroy
has_many :courses, foreign_key: 'tea_id', dependent: :destroy
#试卷
has_many :exercise_banks, :dependent => :destroy
@ -274,7 +274,7 @@ class User < ApplicationRecord
# 课堂的学生
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
# 课堂成员
@ -642,6 +642,14 @@ class User < ApplicationRecord
login
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
def validate_password_length
# 管理员的初始密码是5位

@ -15,7 +15,7 @@ class Admins::LaboratoryQuery < ApplicationQuery
keyword = strip_param(:keyword)
if keyword.present?
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
custom_sort laboratories, params[:sort_by], params[:sort_direction]

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

@ -15,14 +15,16 @@ class CreateBindUserService < ApplicationService
return user
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.bind_open_user?(params[:type].to_s)
ActiveRecord::Base.transaction do
open_user.user_id = bind_user.id
open_user.save!
user.destroy!
user.user_extension.delete
user.delete
end
clear_can_bind_user_flag

@ -17,7 +17,7 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService
new_user = true
# 新用户
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
ActiveRecord::Base.transaction do

@ -24,7 +24,7 @@ class Oauth::CreateOrFindWechatAccountService < ApplicationService
new_user = true
# 新用户
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
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 %>
</li>
<li><%= sidebar_item(admins_competitions_path, '竞赛', icon: 'trophy', controller: 'admins-competitions') %></li>
<li>
<%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
<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.publiced?
json.is_publish attachment.published?
json.delay_publish attachment.delay_publish
json.publish_time attachment.publish_time
json.unified_setting attachment.unified_setting
json.filesize number_to_human_size(attachment.filesize)
json.quotes attachment.quotes_count
# json.quotes attachment.quotes_count
json.description attachment.description
json.downloads_count attachment.downloads_count
json.created_on attachment.created_on

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

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

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

@ -1,7 +1,7 @@
json.students do
json.array! @students do |student|
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_link user_path(student.user)
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.code_halt @course.invite_code_halt == 1
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_assistant switch_assistant_role(@is_student, @course, @user)
#json.join_course !@user.member_of_course?(@course)

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

@ -13,7 +13,10 @@ json.data do
json.author do
json.partial! "users/user_simple", user: attachment.author
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

@ -1,3 +1,3 @@
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

@ -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.description @homework.description
# 实训作业才有说明
if @homework.homework_type == "practice"
json.explanation @homework.explanation
# else
# json.description @homework.description
end
# 附件

@ -2,9 +2,9 @@ json.setting do
setting = @laboratory.laboratory_setting
json.name setting.name || default_setting.name
json.nav_logo_url setting.nav_logo_url || default_setting.nav_logo_url
json.login_logo_url setting.login_logo_url || default_setting.login_logo_url
json.tab_logo_url setting.tab_logo_url || default_setting.tab_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)&.[](1..-1)
json.tab_logo_url (setting.tab_logo_url || default_setting.tab_logo_url)&.[](1..-1)
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:
appid: 'test'
secret: 'test'
weapp:
appid: 'test'
secret: 'test'
development:
<<: *defaults

@ -1,9 +1,12 @@
wechat_config = {}
weapp_config = {}
begin
config = Rails.application.config_for(:configuration)
wechat_config = config['wechat']
weapp_config = config['weapp']
raise 'wechat config missing' if wechat_config.blank?
raise 'weapp config missing' if weapp_config.blank?
rescue => ex
raise ex if Rails.env.production?
@ -12,5 +15,10 @@ rescue => ex
wechat_config = {}
end
# 网站应用
Wechat::OfficialAccount.appid = wechat_config['appid']
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/wechat/callback', to: 'oauth/wechat#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
namespace :admins do
@ -980,6 +988,16 @@ Rails.application.routes.draw do
resource :laboratory_setting, only: [:show, :update]
resource :laboratory_user, only: [:create, :destroy]
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
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
// devtool: "cheap-module-eval-source-map",
// 开启调试
devtool: "source-map", // 开启调试
//devtool: "source-map", // 开启调试
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.

@ -8,10 +8,12 @@
<!-- width=device-width, initial-scale=1 , shrink-to-fit=no -->
<!-- <meta name="viewport" content=""> -->
<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="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.
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.
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">
window.__isR = true;

@ -10,7 +10,7 @@
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="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.
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.
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">
window.__isR = true;
</script>

@ -9,7 +9,7 @@ import {
Route,
Switch
} from 'react-router-dom';
import axios from 'axios';
import '@icedesign/base/dist/ICEDesignBase.css';
import '@icedesign/base/index.scss';
@ -64,6 +64,18 @@ const EducoderLogin = Loadable({
loader: () => import('./modules/login/EducoderLogin'),
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({
loader: () => import('./modules/test'),
loading: Loading,
@ -275,6 +287,7 @@ class App extends Component {
Addcoursestypes:false,
mydisplay:false,
occupation:0,
mygetHelmetapi:undefined,
}
}
@ -315,7 +328,6 @@ class App extends Component {
}
componentDidMount() {
this.disableVideoContextMenu();
// force an update if the URL changes
history.listen(() => {
this.forceUpdate()
@ -324,7 +336,8 @@ class App extends Component {
$("html").animate({ scrollTop: $('html').scrollTop() - 0 })
});
initAxiosInterceptors(this.props)
initAxiosInterceptors(this.props);
this.getAppdata();
//
// axios.interceptors.response.use((response) => {
// // console.log("response"+response);
@ -350,15 +363,78 @@ class App extends Component {
this.setState({
isRender:false,
})
}
render() {
};
//获取当前定制信息
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);
}
}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 (
<LocaleProvider locale={zhCN}>
<MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={()=>this.Modifyloginvalue()}></LoginDialog>
<Notcompletedysl {...this.props} {...this.state}></Notcompletedysl>
@ -401,10 +477,28 @@ class App extends Component {
<Route path="/compatibility" component={CompatibilityPageLoadable}/>
<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="/register" component={EducoderLogin}
path="/otherloginstart" component={Otherloginstart}
/>
<Route
path="/otherlogin" component={Otherlogin}
/>
<Route path="/users/:username"
render={
@ -422,7 +516,13 @@ class App extends Component {
}></Route>
<Route
path="/changepassword" component={EducoderLogin}
path="/changepassword"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
/>
<Route
path="/interesse" component={Interestpage}
@ -450,7 +550,7 @@ class App extends Component {
></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> */}
@ -484,7 +584,12 @@ class App extends Component {
render={
(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}/>
@ -607,4 +712,4 @@ moment.defineLocale('zh-cn', {
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;
}
}
// 非file_update请求
if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true;

@ -8,20 +8,20 @@ class WordsBtn extends Component {
}
render() {
let{to, href,targets, style2 }=this.props
let{to, href,targets, style2, style, className, ...others }=this.props
return(
<React.Fragment>
{
to==undefined&&targets==undefined ?
<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>:
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>
:
<Link to={to} className={"btn "+`${map[this.props.style]} ${this.props.className}`}
style={style2}
style={style2} {...others}
>{this.props.children}</Link>
}
</React.Fragment>

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

@ -209,6 +209,9 @@ class Fileslistitem extends Component{
text-overflow:ellipsis;
white-space:nowrap
}
.mt2{
margin-top:2px;
}
`}</style>
<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)}>
@ -248,6 +251,29 @@ class Fileslistitem extends Component{
:""
}
{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>
<style>
{
@ -275,25 +301,26 @@ class Fileslistitem extends Component{
`
}
</style>
{discussMessage.course_groups.length===0?"":
<p className="color-grey panel-lightgrey mt8 fl lightgreybox ml30" style={{width:'100%'}}>
{discussMessage.course_groups.map((item,key)=>{
return(
<div className="mr50">
<span className="mr15 color-dark">{item.course_group_name}</span>
<span className="mr15 color-grey9 ">将发布于 { moment(item.course_group_publish_time).format('YYYY-MM-DD HH:mm')}</span>
</div>
)
})}
</p>}
{/*资源分班*/}
{/*{discussMessage.course_groups.length===0?"":*/}
{/*<p className="color-grey panel-lightgrey mt8 fl lightgreybox ml30" style={{width:'100%'}}>*/}
{/*{discussMessage.course_groups.map((item,key)=>{*/}
{/*return(*/}
{/*<div className="mr50">*/}
{/*<span className="mr15 color-dark">{item.course_group_name}</span>*/}
{/*<span className="mr15 color-grey9 ">将发布于 { moment(item.course_group_publish_time).format('YYYY-MM-DD HH:mm')}</span>*/}
{/*</div>*/}
{/*)*/}
{/*})}*/}
{/*</p>}*/}
<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="mr15 color-dark">{discussMessage.author.name}</span>
<span className="mr15 color-grey9">大小 {discussMessage.filesize}</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">
{/*{moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm:ss')}*/}
{/*{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')}
</span>
</span>
{this.props.isAdmin?
<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>
</span>:""}
{discussMessage&&discussMessage.category_name===null?"":this.props.child===false?<div className="color-grey9 task-hide fr mr60" title={discussMessage&&discussMessage.category_name}
style={{"max-width":"268px"}}>所属目录{discussMessage&&discussMessage.category_name}
</div>:""}
</p>
{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 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>
{
`

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

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

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

@ -349,7 +349,7 @@ class Boards extends Component{
searchPlaceholder={ '请输入帖子名称进行搜索' }
firstRowRight={
<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> }
{ !isCourseEnd && isAdminOrStudent && <WordsBtn style="blue" className="" onClick={()=>this.onToBoardsNew()}>我要发贴</WordsBtn> }
</React.Fragment>
@ -393,7 +393,7 @@ class Boards extends Component{
<p className="drop_down_btn">
<a href="javascript:void(0)" className="color-grey-6"
onClick={()=>this.addDir()}
>添加目录...</a>
>新建目录...</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 studentWorkId=this.props.match.params.studentWorkId;
const isAdmin = this.props.isAdmin()
document.title=course_name&&course_name;
return(
<WorkDetailPageHeader
{...this.props} {...this.state}

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

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

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

@ -61,7 +61,8 @@ class Titlesearchsection extends Component{
<p className="clearfix padding30 bor-bottom-greyE">
<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">
{ firstRowRight }
</li>

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

@ -238,6 +238,37 @@ class Coursesleftnav extends Component{
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)=>{
// this.props.getleftNavid && this.props.getleftNavid(key,type);
// let {selectnavid,navid}=this.state;
@ -401,7 +432,7 @@ class Coursesleftnav extends Component{
axios.get(url).then((result)=>{
navidtype=true
this.props.updataleftNavfun();
console.log(this.props)
// console.log(this.props)
let list=this.props.course_modules;
for(var i=0; i<list.length;i++){
if(list[i].id!=id){
@ -442,7 +473,7 @@ class Coursesleftnav extends Component{
navidtype=false
if(id===1||id===2||id===6){
this.setState({
Navmodalname:id===2?"新建分班":"添加目录",
Navmodalname:id===2?"新建分班":"新建目录",
Navtitles:id===2?"分班名称":"目录名称",
Navplaceholder:"请输入名称最大限制60个字符",
Navmodalnametype:true,
@ -493,7 +524,8 @@ class Coursesleftnav extends Component{
navidtype=true
}
saveNavmodapost=(url,value)=>{
saveNavmodapost=(url,value,positiontype,coursesId)=>{
axios.post(url,
{name:value}).then((result)=>{
if(result.data.status===0){
@ -505,6 +537,10 @@ class Coursesleftnav extends Component{
description:result.data.message
});
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)=>{
console.log(error)
@ -556,9 +592,8 @@ class Coursesleftnav extends Component{
}
if(Navmodaltypename===1){
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){
@ -781,15 +816,15 @@ class Coursesleftnav extends Component{
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==="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"? :""}*/}
<div onClick={e=>this.Navmodalnames(e,3,"editname",item.id,item.name)}>重命名</div>

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

@ -46,10 +46,16 @@ class HomeworkModal extends Component{
}
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({
endtime:moment(moment(handleDateString(this.props.starttimes)).add(1, 'week')).format("YYYY-MM-DD HH:mm")
})
}
this.setState({
endtime:moment(moment(handleDateString(this.props.starttimes)).add(1, 'week')).format("YYYY-MM-DD HH:mm")
})
}
}
componentDidUpdate=(prevProps)=>{
@ -69,9 +75,16 @@ class HomeworkModal extends Component{
if(prevProps.starttimes!=this.props.starttimes){
if(this.props.starttimes!=undefined&&this.props.starttimes!=""){
this.setState({
endtime:moment(moment(handleDateString(this.props.starttimes)).add(1, 'week')).format("YYYY-MM-DD HH:mm")
})
if(this.props.starttimesend!=undefined&&this.props.starttimesend!=""){
this.setState({
endtime:this.props.starttimesend,
})
}else{
this.setState({
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 { 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 {handleDateString} from 'educoder';
import NoneData from "../coursesPublic/NoneData";
import Modals from '../../modals/Modals';
import moment from 'moment';
const Option = Select.Option;
const Search = Input.Search;
const dateFormat ="YYYY-MM-DD HH:mm"
function formatDate(date) {
var dateee = new Date(date).toJSON();
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{
constructor(props){
super(props);
@ -23,7 +40,9 @@ class Selectresource extends Component{
Resourcelist:undefined,
hometypepvisible:true,
getallfiles:false,
searchtype:'getallfiles'
searchtype:'getallfiles',
Radiovalue:0,
datatime:undefined
}
}
componentDidMount() {
@ -32,11 +51,7 @@ class Selectresource extends Component{
componentDidUpdate = (prevProps) => {
let {getallfiles}=this.state;
if ( prevProps.visible != this.props.visible ) {
}
}
@ -197,7 +212,7 @@ class Selectresource extends Component{
savecouseShixunModal=()=>{
let {patheditarry}=this.state;
let {patheditarry,datatime,Radiovalue}=this.state;
let {coursesId,attachmentId}=this.props;
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, {
course_id:coursesId,
attachment_ids:patheditarry,
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) => {
if(response.data.status===0){
// this.setState({
// Modalstype:true,
// Modalstopval:response.data.message,
// ModalSave:this.ModalCancelModalCancel,
// loadtype:true
// })
this.ModalCancelModalCancel();
this.props.updataleftNavfun();
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({
category_id:value
Radiovalue: e.target.value,
});
}
onChangeTimepublish= (date, dateString) => {
this.setState({
datatime:handleDateString(dateString),
})
}
render(){
let {Searchvalue,type,category_id,Resourcelist,hometypepvisible,patheditarry}=this.state;
let {visible,shixunmodallist}=this.props;
let {Searchvalue,type,Resourcelist,hometypepvisible,patheditarry,datatime}=this.state;
let {visible}=this.props;
const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;
const radioStyle = {
display: 'block',
height: '30px',
lineHeight: '30px',
};
return(
<div>
{/*提示*/}
@ -373,10 +415,36 @@ class Selectresource extends Component{
}
</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.Radiovaluetype===true?<p className={"color-red ml20"}>发布时间不能为空</p>:""}
<div className="mt20 marginauto clearfix edu-txt-center">
<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>

@ -1,5 +1,5 @@
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 {getUrl,handleDateString,appendFileSizeToUploadFileAll} from 'educoder';
import locale from 'antd/lib/date-picker/locale/zh_CN';
@ -36,9 +36,10 @@ class Selectsetting extends Component{
course_groups:undefined,
attachment_histories:undefined,
datatime:undefined,
unified_setting:true,
fileList:[],
fileListtype:false
fileListtype:false,
is_public:false,
Radiovaluetype:false
}
}
@ -54,53 +55,13 @@ class Selectsetting extends Component{
})
.then((response) => {
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({
datalist:response.data,
description: response.data.description,
is_public: response.data.is_public,
unified_setting: response.data.unified_setting,
is_public:response.data.is_public,
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
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()
}
}
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)=>{
@ -180,13 +109,26 @@ class Selectsetting extends Component{
}
savecouseShixunModal=()=>{
let {fileList,is_public,unified_setting,description,datatime,course_groups}=this.state;
let {fileList,is_public,description,datatime,Radiovalue}=this.state;
let newfileList=[];
for(var list of fileList){
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){
}else if(description.length>100){
@ -196,29 +138,6 @@ class Selectsetting extends Component{
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 attachmentId=this.props.attachmentId;
let url="/files/"+this.props.discussMessageid+".json";
@ -226,14 +145,12 @@ class Selectsetting extends Component{
axios.put(url,{
course_id:coursesId,
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_unified_setting:unified_setting,
publish_time:unified_setting===true?datatime===undefined?moment(new Date()).format('YYYY-MM-DD HH'):datatime:undefined,
publish_time:Radiovalue===0?undefined:datatime===undefined?moment(new Date(),dateFormat):datatime,
description:description,
course_group_publish_times:unified_setting===false?course_groups:undefined
delay_publish:Radiovalue
}).then((result)=>{
if(result.data.status===0){
this.props.setupdate(attachmentId)
this.props.showNotification("设置资源成功");
@ -244,7 +161,6 @@ class Selectsetting extends Component{
}
onChangeTimepublish= (date, dateString) => {
// console.log('startValue', dateString);
this.setState({
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) => {
@ -309,14 +200,7 @@ class Selectsetting extends Component{
fileListtype:false,
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:[]
})
}
// const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
}
onChangeTimepublishs= (date, dateString,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].publish_time=handleDateString(dateString);
}
}
onChangepublic=(e)=>{
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;
}
RadioonChange=(e)=>{
if(e.target.value===0){
this.setState({
datatime:undefined
})
}
this.setState({
course_groups:newgroup_publish,
})
}
deletegrouppublish=(key)=>{
let newlist=this.state.course_groups;
newlist.splice(key,1);
this.setState({
course_groups:newlist
})
}
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({
course_groups:newlist
})
Radiovalue: e.target.value,
});
}
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 = {
width: 600,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
@ -401,9 +250,13 @@ class Selectsetting extends Component{
return isLt150M;
},
};
const radioStyle = {
display: 'block',
height: '30px',
lineHeight: '30px',
};
// console.log(this.props.has_course_groups)
console.log(this.state.Radiovalue)
return(
<div>
<style>
@ -461,9 +314,9 @@ class Selectsetting extends Component{
.fontlefts{text-align: left; text-align: center;}
`}</style>
<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" style={{width:'100px'}}>引用</li>
{/*<li className="fl" style={{width:'100px'}}>引用</li>*/}
<li className="fl" style={{width:'130px'}}>版本号</li>
</ul>
@ -490,7 +343,7 @@ class Selectsetting extends Component{
`}</style>
<div className="pl20 pr20 settingbox">
<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>
{datalist&&datalist.attachment_histories.length===0?"":<span className={"newcolor-orange fl"}>当前版本</span>}
</li>
@ -505,13 +358,13 @@ class Selectsetting extends Component{
{datalist&&datalist.attachment_histories.map((item,key)=>{
return(
<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={"newcolor-orange fl"}>当前版本</span>*/}
</li>
<li className="fl edu-txt-left task-hide paddingl5 "
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">
{moment(item.created_on).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(item.created_on).format('YYYY-MM-DD HH:mm')}
</li>
@ -607,61 +460,15 @@ class Selectsetting extends Component{
</Upload>
</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>:""}
<p className={this.state.fileListtype===true?"mt15":""}>
<p className={this.state.fileListtype===true?"mt15 selecboxfilas":"selecboxfilas"}>
<style>{`
.ant-checkbox-wrapper{
.selecboxfilas .ant-checkbox-wrapper{
margin-left:0px !important;
margin-top:10px;
}
`}</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>
{`
.Selectleft20{
@ -675,53 +482,11 @@ class Selectsetting extends Component{
}
`}
</style>
{/*this.props.has_course_groups&&this.props.has_course_groups===true?:""*/}
<div className={"resourcebox"}>
{unified_setting===false?
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>
{this.props.course_is_public===true?<div>
<span className={"color-ooo"}>公开</span><Checkbox checked={this.state.is_public} onChange={(e)=>this.onChangepublic(e)}>
<span className={"font-14 color-ooo"}>选中所有用户可见否则课堂成员可见</span>
</Checkbox>
</div>:""}
</p>
<style>
{`
@ -730,28 +495,36 @@ class Selectsetting extends Component{
}
`}
</style>
{unified_setting===true?
<p className={"mt10"}>
<span>
<DatePicker
showToday={false}
dropdownClassName="hideDisable"
showTime={{ format: 'HH:mm' }}
format="YYYY-MM-DD HH:mm"
locale={locale}
placeholder="请选择发布时间"
id={"startime"}
width={"210px"}
value={datatime===undefined||datatime===""?"":moment(datatime, dateFormat)}
onChange={this.onChangeTimepublish}
disabledTime={disabledDateTime}
disabledDate={disabledDate}
/>
</span>
</p>:""}
{/*{this.state.course_group_idtypes===true?<p className={"color-red"}>请选择分班</p>:""}*/}
{/*{course_group_publish_timestype===true?<p className={"color-red mt10"}>请填写完整</p>:""}*/}
<div className={this.props.course_is_public===true?"mt10":""}>
<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
showToday={false}
dropdownClassName="hideDisable"
showTime={{ format: 'HH:mm' }}
format="YYYY-MM-DD HH:mm"
locale={locale}
placeholder="请选择发布时间"
id={"startime"}
width={"210px"}
value={datatime===undefined||datatime===""?"":moment(datatime, dateFormat)}
onChange={this.onChangeTimepublish}
disabledTime={disabledDateTime}
disabledDate={disabledDate}
disabled={this.state.Radiovalue===1?false:true}
/>
</Radio>
<span className={"fl mt5 color-grey-c"}>(按照设置的时间定时发布)</span>
</Radio.Group>
</div>
<textarea placeholder="请输入资源描述最大限制100个字符" className={"mt10"} value={description} onInput={this.settextarea} style={{
width: '100%',
@ -760,6 +533,7 @@ class Selectsetting extends Component{
padding: '10px'
}}></textarea>
{this.state.descriptiontypes===true?<p className={"color-red"}>描述不能超过最大限制100个字符</p>:""}
{this.state.Radiovaluetype===true?<p className={"color-red"}>发布时间不能为空</p>:""}
</div>
<div className="mt20 marginauto clearfix edu-txt-center">

@ -1,9 +1,11 @@
import React, { Component } from "react";
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 InfiniteScroll from 'react-infinite-scroller';
const dateFormat ="YYYY-MM-DD HH:mm"
const Search = Input.Search
const pageCount = 15;
class Sendtofilesmodal extends Component{
@ -170,7 +172,12 @@ class Sendtofilesmodal extends Component{
bottom: 93px;
width: 82%;
text-align: center;
}`}
}
.ModalWrappertitle{
background: #D0E8FC;
padding: 10px;
}
`}
</style>
<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>
<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' }}>
<InfiniteScroll
threshold={10}
@ -199,20 +211,14 @@ class Sendtofilesmodal extends Component{
return (
<p className="clearfix mb7" key={course.id}>
<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>
)
}) }
</Checkbox.Group>
{loading && hasMore && (
<div className="demo-loading-container">
<Spin />
</div>
)}
{/* TODO */}
{/* {
!hasMore && <div>没有更多了</div>
} */}
</InfiniteScroll>
</div>

@ -1,5 +1,5 @@
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 Modals from '../../modals/Modals';
import {getUrl,handleDateString,bytesToSize,appendFileSizeToUploadFileAll} from 'educoder';
@ -40,7 +40,6 @@ class Sendresource extends Component{
ModalSave:"",
fileListtype:false,
loadtype:false,
is_unified_setting:true,
is_public:false,
datatime:undefined,
// moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),
@ -50,30 +49,15 @@ class Sendresource extends Component{
publish_time :""
}],
course_groups:undefined,
course_groups_count:undefined
course_groups_count:undefined,
Radiovalue:0,
Radiovaluetype:false
}
}
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) => {
if(!file.percent || file.percent == 100){
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
@ -174,8 +127,7 @@ class Sendresource extends Component{
}
Saves=()=>{
let id=this.props.categoryid;
let {fileList,description,is_public,is_unified_setting,datatime,course_group_publish_times} =this.state;
let {fileList,description,is_public,datatime,Radiovalue} =this.state;
let newfileList=[];
for(var list of fileList){
@ -188,17 +140,19 @@ class Sendresource extends Component{
})
return
}
// if(is_unified_setting===false){
// course_group_publish_times.forEach((item,key)=>{
// if(item.course_group_id===undefined||item.publish_time===undefined){
// this.setState({
// course_group_publish_timestype:true
// })
// return
// }
// })
//
// }
if(this.state.Radiovalue===1){
if(datatime===undefined||datatime===null||datatime=== ""){
this.setState({
Radiovaluetype:true
})
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,
attachment_ids:newfileList,
is_public:is_public,
is_unified_setting:is_unified_setting,
publish_time:is_unified_setting===true?datatime===undefined? moment(new Date()).format('YYYY-MM-DD HH:mm'):datatime:undefined,
publish_time:Radiovalue===1?datatime===undefined? undefined:datatime:undefined,
description:description,
course_group_publish_times:is_unified_setting===false?course_group_publish_times:undefined
delay_publish:Radiovalue,
}).then((result)=>{
if(result.data.status===0){
// this.setState({
// Modalstype:true,
// Modalstopval:result.data.message,
// ModalSave:this.ModalCancelModalCancel,
// loadtype:true
// })
this.ModalCancelModalCancel();
this.props.updataleftNavfun();
// this.props.showNotification(result.data.message);
this.props.showNotification("上传资源成功");
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)=>{
this.setState({
@ -289,50 +227,20 @@ class Sendresource extends Component{
}
selectassigngroups=(e,index,key)=>{
let {course_group_publish_times}=this.state;
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;
}
RadioonChange=(e)=>{
if(e.target.value===0){
this.setState({
datatime:undefined
})
}
this.setState({
course_group_publish_times:newgroup_publish,
})
Radiovalue: e.target.value,
});
}
deletegrouppublish=(key)=>{
let newlist=this.state.course_group_publish_times;
newlist.splice(key,1);
this.setState({
course_group_publish_times:newlist
})
}
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(){
let {settextarea,newfileListtype,descriptiontype,
course_group_publish_timestype,
Modalstopval,
ModalCancel,
ModalSave,
loadtype,
is_unified_setting,
let { newfileListtype,descriptiontype,
is_public,
datatime,
course_group_publish_times,
course_groups
}=this.state;
const uploadProps = {
@ -350,7 +258,11 @@ class Sendresource extends Component{
return isLt150M;
},
};
const radioStyle = {
display: 'block',
height: '30px',
lineHeight: '30px',
};
return(
<div>
{/*提示*/}
@ -389,6 +301,7 @@ class Sendresource extends Component{
margin-right: 5px;
}
.ant-upload-list-item:hover .ant-upload-list-item-info{
padding: 0 12px 0 0px;
background-color:#fff;
}
.upload_1 .ant-upload-list {
@ -437,42 +350,12 @@ class Sendresource extends Component{
<Button className="uploadBtn">
<Icon type="upload" /> 选择文件
</Button>
<span className={"ml10"}>(单个文件最大150M)</span>
<span className={"ml10 color-ooo"}>(单个文件最大150M)</span>
</span>:""}
</Upload>
</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>:""}
@ -484,13 +367,12 @@ class Sendresource extends Component{
}
`}</style>
{/*<div className={this.state.fileListtype===true?"mt30":""}></div><Checkbox checked={is_public} onChange={this.onChangepublic}>*/}
{/*<span className={"font-14"}>勾选后所有用户可见,否则仅课堂成员可见</span>*/}
{/*</Checkbox>*/}
{this.props.course_is_public===true?<div>
<span className={"color-ooo"}>公开</span><Checkbox checked={is_public} onChange={this.onChangepublic}>
<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>{`
.Selectleft20{
margin-left: 20px !important;
@ -505,69 +387,38 @@ class Sendresource extends Component{
overflow: auto;
}
`}</style>
<div className={"resourcebox"}>
{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>
<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"
showTime={{ format: 'HH:mm' }}
locale={locale}
format={dateFormat}
placeholder="请选择发布时间"
id={"startime"}
showToday={false}
width={"210px"}
value={datatime===undefined||datatime===""?undefined:moment(datatime, dateFormat)}
onChange={(e,index)=>this.onChangeTimepublish(e,index,undefined,1)}
disabledTime={disabledDateTime}
disabledDate={disabledDate}
/>
</span>
</p>:""}
<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
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>
{/*{course_group_publish_timestype===true?<p className={"color-red mt10"}>请填写完整</p>:""}*/}
<textarea placeholder="请在此输入资源描述最大限制100个字符" className={"mt10"} value={this.state.description} onInput={this.settextarea} style={{
@ -577,6 +428,7 @@ class Sendresource extends Component{
padding: '10px'
}}></textarea>
{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">
<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>

@ -1701,4 +1701,47 @@ input.ant-input-number-input:focus {
/*}*/
.yslinputcourput .ant-form-explain{
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 isEdit = this.isEdit
const isEdit = this.isEdit;
document.title=this.props.coursedata&&this.props.coursedata.name;
return(
<div className="newMain exerciseNew">

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

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

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

@ -61,7 +61,7 @@ class Testpapersettinghomepage extends Component{
}
//试卷公用头部
Commonheadofthetestpaper=()=>{
// console.log("Commonheadofthetestpaper");
console.log("Commonheadofthetestpaper 试卷公用头部");
var exercise_id = this.props.match.params.Id;
var url = `/exercises/${exercise_id}/common_header.json`;
axios.get(url).then((response) => {
@ -249,6 +249,28 @@ class Testpapersettinghomepage extends Component{
// 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 };
goback=()=>{
// let {datalist}=this.state;
@ -271,7 +293,7 @@ class Testpapersettinghomepage extends Component{
// TODO
// console.log(Commonheadofthetestpaper.exercise_status);
document.title=this.props.coursedata&&this.props.coursedata.name;
return(
<div className="newMain clearfix ">
{/*<DownloadMessage*/}
@ -410,6 +432,7 @@ class Testpapersettinghomepage extends Component{
Exercisetype={"exercise"}
action={this.Commonheadofthetestpaper}
single={true}
getsetdata={this.getsetdata}
></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>:""}

@ -20,89 +20,89 @@ import Modals from '../../../modals/Modals';
//毕设描述
const GraduationTasksquestions= Loadable({
loader: () => import('./GraduationTaskssettingquestions'),
loading: Loading,
loader: () => import('./GraduationTaskssettingquestions'),
loading: Loading,
})
//毕设任务设置
const GraduationTaskssetting=Loadable({
loader: () => import('./GraduationTaskssetting'),
loading: Loading,
loader: () => import('./GraduationTaskssetting'),
loading: Loading,
})
//毕设任务列表
const GraduationTaskslist=Loadable({
loader: () => import('./GraduationTaskssettinglist'),
loading: Loading,
loader: () => import('./GraduationTaskssettinglist'),
loading: Loading,
})
class GraduationTaskDetail extends Component{
constructor(props){
super(props);
this.state={
modalname:undefined,
visible:false,
constructor(props){
super(props);
this.state={
modalname:undefined,
visible:false,
Topval:undefined,
starttime:undefined,
starttimes:undefined,
typs:undefined,
endtime:undefined,
Cancelname:undefined,
Savesname:undefined,
Cancel:undefined,
Saves:undefined,
Topvalright:undefined,
Botvalleft:undefined,
course_groupslist:undefined,
course_groups:undefined,
questionslist:undefined,
tab:"list",
visibles:undefined,
Modalstype:undefined,
Modalstopval:undefined,
ModalCancel:undefined,
ModalSave:undefined,
acrossVisible:undefined
}
}
componentDidMount(){
this.getdatas()
}
getdatas=()=>{
const task_Id = this.props.match.params.task_Id;
let url="/graduation_tasks/"+task_Id+".json";
axios.get(url).then((result)=>{
if(result.status===200){
this.setState({
questionslist:result.data
})
}
}).catch((error)=>{
console.log(error)
})
}
// 交叉评阅设置弹框
openAcross=()=>{
this.setState({
acrossVisible:true
})
}
closeAcross=()=>{
this.setState({
acrossVisible:false
})
endtime:undefined,
Cancelname:undefined,
Savesname:undefined,
Cancel:undefined,
Saves:undefined,
Topvalright:undefined,
Botvalleft:undefined,
course_groupslist:undefined,
course_groups:undefined,
questionslist:undefined,
tab:"list",
visibles:undefined,
Modalstype:undefined,
Modalstopval:undefined,
ModalCancel:undefined,
ModalSave:undefined,
acrossVisible:undefined
}
}
componentDidMount(){
this.getdatas()
}
}
getdatas=()=>{
const task_Id = this.props.match.params.task_Id;
let url="/graduation_tasks/"+task_Id+".json";
axios.get(url).then((result)=>{
if(result.status===200){
this.setState({
questionslist:result.data
})
}
}).catch((error)=>{
console.log(error)
})
}
//返回
goback=()=>{
// let courseId=this.props.match.params.coursesId;
// let category_id=this.props.match.params.category_id;
// window.location.href="/courses/"+courseId+"/graduation_tasks/"+category_id;
// 交叉评阅设置弹框
openAcross=()=>{
this.setState({
acrossVisible:true
})
}
closeAcross=()=>{
this.setState({
acrossVisible:false
})
this.getdatas()
}
//返回
goback=()=>{
// let courseId=this.props.match.params.coursesId;
// let category_id=this.props.match.params.category_id;
// window.location.href="/courses/"+courseId+"/graduation_tasks/"+category_id;
// let courseId = this.props.match.params.coursesId;
// if(courseId===undefined){
// this.props.history.push("/courses");
@ -112,66 +112,66 @@ class GraduationTaskDetail extends Component{
// this.props.history.goBack()
this.props.history.replace(`/courses/${this.state.questionslist.course_id}/graduation_tasks/${this.state.questionslist.graduation_id}`);
}
//立即发布
publish=()=>{
let starttime= this.props.getNowFormatDates(1,1);
let endtime=this.props.getNowFormatDates(2,1);
// this.homeworkstart()
this.setState({
modalname:"立即发布",
visible:true,
}
//立即发布
publish=()=>{
let starttime= this.props.getNowFormatDates(1,1);
let endtime=this.props.getNowFormatDates(2,1);
// this.homeworkstart()
this.setState({
modalname:"立即发布",
visible:true,
Topval:"学生将立即收到毕设任务",
// Botvalleft:"点击修改",
// Botvalleft:"点击修改",
// Botval:`本操作只对"未发布"的分班有效`,
starttime:moment(moment(new Date())).format("YYYY-MM-DD HH:mm") ,
starttimes:this.props.getNowFormatDates(1),
typs:"start",
endtime:endtime,
Cancelname:"暂不发布",
Savesname:"立即发布",
Cancel:this.cancelmodel,
Saves:this.homepublish,
})
}
// 确定立即发布
homepublish=(ids,endtime)=>{
this.cancelmodel();
let task_Id=this.props.match.params.task_Id;
const cid = this.props.match.params.coursesId;
// let url = `/courses/${cid}/graduation_tasks/publish_task.json`;
let url="/courses/"+cid+"/graduation_tasks/publish_task.json"
axios.post(url,{
task_ids:[task_Id],
group_ids: this.state.course_groupslist,
endtime:endtime,
Cancelname:"暂不发布",
Savesname:"立即发布",
Cancel:this.cancelmodel,
Saves:this.homepublish,
})
}
// 确定立即发布
homepublish=(ids,endtime)=>{
this.cancelmodel();
let task_Id=this.props.match.params.task_Id;
const cid = this.props.match.params.coursesId;
// let url = `/courses/${cid}/graduation_tasks/publish_task.json`;
let url="/courses/"+cid+"/graduation_tasks/publish_task.json"
axios.post(url,{
task_ids:[task_Id],
group_ids: this.state.course_groupslist,
end_time:endtime,
}).then((response)=>{
if (response.data.status == 0) {
}).then((response)=>{
if (response.data.status == 0) {
this.getdatas()
this.props.showNotification(response.data.message);
this.setState({
// Modalstopval:response.data.message,
// ModalSave:this.cancelmodel,
// Loadtype:true,
course_groupslist:[],
checkAllValue:false
})
}
}).catch((error)=>{
})
}
// 刷新
resetList=()=>{
this.getdatas();
this.child && this.child.searchValue();
}
// 立即截止
end=()=>{
this.props.showNotification(response.data.message);
this.setState({
// Modalstopval:response.data.message,
// ModalSave:this.cancelmodel,
// Loadtype:true,
course_groupslist:[],
checkAllValue:false
})
}
}).catch((error)=>{
})
}
// 刷新
resetList=()=>{
this.getdatas();
this.child && this.child.searchValue();
}
// 立即截止
end=()=>{
// this.homeworkstart()
this.setState({
modalname:"立即截止",
@ -185,74 +185,74 @@ class GraduationTaskDetail extends Component{
Saves:this.coursetaskend,
typs:"end",
})
}
coursetaskend=()=>{
const coursesId = this.props.match.params.coursesId;
const task_Id = this.props.match.params.task_Id;
let url = `/courses/${coursesId}/graduation_tasks/end_task.json`;
axios.post(url,{
task_ids:[task_Id],
group_ids: this.state.course_groupslist,
}).then((response)=>{
if (response.data.status == 0) {
this.props.showNotification(response.data.message);
this.cancelmodel();
this.getdatas();
this.child && this.child.reInit();
}
}).catch((error)=>{
})
}
// 取消
cancelmodel=()=>{
this.setState({
Modalstype:false,
Loadtype:false,
visible:false,
Modulationtype:false,
Allocationtype:false,
Modalstopval:"",
ModalCancel:"",
ModalSave:"",
})
}
getcourse_groupslist=(id)=>{
this.setState({
course_groupslist:id
})
}
setTab = (tab) =>{
this.setState({
tab
})
}
// 关联项目
AssociationItems=()=>{
}
coursetaskend=()=>{
const coursesId = this.props.match.params.coursesId;
const task_Id = this.props.match.params.task_Id;
let url = `/courses/${coursesId}/graduation_tasks/end_task.json`;
axios.post(url,{
task_ids:[task_Id],
group_ids: this.state.course_groupslist,
}).then((response)=>{
if (response.data.status == 0) {
this.props.showNotification(response.data.message);
this.cancelmodel();
this.getdatas();
this.child && this.child.reInit();
}
}).catch((error)=>{
})
}
// 取消
cancelmodel=()=>{
this.setState({
Modalstype:false,
Loadtype:false,
visible:false,
Modulationtype:false,
Allocationtype:false,
Modalstopval:"",
ModalCancel:"",
ModalSave:"",
})
}
getcourse_groupslist=(id)=>{
this.setState({
course_groupslist:id
})
}
setTab = (tab) =>{
this.setState({
tab
})
}
// 关联项目
AssociationItems=()=>{
this.setState({
visibles:true
})
}
Cancel=()=>{
}
Cancel=()=>{
this.setState({
visibles:false
})
}
// 取消关联
cannelAssociation=()=>{
}
// 取消关联
cannelAssociation=()=>{
this.setState({
Modalstype:true,
Modalstopval:"确定要取消该项目关联?",
ModalCancel:this.cannerassocition,
ModalSave:this.savetassociton
})
}
savetassociton=()=>{
}
savetassociton=()=>{
this.cannerassocition();
let {questionslist}=this.state;
let url = "/graduation_tasks/"+questionslist.task_id+"/graduation_works/cancel_relate_project.json";
@ -266,7 +266,7 @@ class GraduationTaskDetail extends Component{
})
}
cannerassocition=()=>{
cannerassocition=()=>{
this.setState({
Modalstype:false,
Modalstopval:"",
@ -275,10 +275,10 @@ class GraduationTaskDetail extends Component{
loadtype:false,
visibles:false
})
}
// 补交附件
handaccessory=()=>{
// let {taskslistdata}=this.state;
}
// 补交附件
handaccessory=()=>{
// let {taskslistdata}=this.state;
// let courseId=this.props.match.params.coursesId;
//
// let url="/courses/"+courseId+"/graduation_tasks/"+taskslistdata.work_id+"/appraise"
@ -292,129 +292,131 @@ class GraduationTaskDetail extends Component{
this.setState({
avisible:false
})
}
bindRef = ref => { this.child = ref } ;
render(){
let courseId=this.props.match.params.coursesId;
let category_id=this.props.match.params.category_id;
let task_Id=this.props.match.params.task_Id;
let {
questionslist ,
tab ,
visibles ,
Modalstype,
Modalstopval,
ModalCancel,
ModalSave,
acrossVisible
} = this.state
const commom = {
setTab:this.setTab,
getdatas:this.getdatas
}
return(
<div className="newMain clearfix">
{
questionslist &&
<div className={"educontent mb20"}>
<HomeworkModal
starttimes={this.state.starttimes}
typs={this.state.typs}
modalname={this.state.modalname}
visible={this.state.visible}
Topval={this.state.Topval}
Topvalright={this.state.Topvalright}
Botvalleft={this.state.Botvalleft}
Botval={this.state.Botval}
starttime={this.state.starttime}
endtime={this.state.endtime}
Cancelname={this.state.Cancelname}
Savesname={this.state.Savesname}
Cancel={this.state.Cancel}
Saves={this.state.Saves}
course_groups={this.state.course_groups}
modaltype={this.state.modaltype}
getcourse_groupslist={(id) => this.getcourse_groupslist(id)}
/>
{/*关联项目*/}
{visibles===true?
<Associationmodel
modalname={"关联项目"}
visible={visibles}
Cancel={()=>this.Cancel()}
taskid={ questionslist && questionslist.task_id }
funlist={this.resetList}
/>
:""}
{this.state.avisible===true?<AccessoryModal
{...this.props}
modalname={"补交附件"}
visible={this.state.avisible}
Cancelname={"取消"}
Savesname={"确认"}
Cancel={this.Cancelvisible}
categoryid={questionslist.work_id}
setupdate={this.resetList}
/>:""}
{/*提示*/}
<Modals
modalsType={Modalstype}
modalsTopval={Modalstopval}
modalCancel={ModalCancel}
modalSave={ModalSave}
closable={false}
footer={null}
destroyOnClose={true}
centered={true}
/>
{
acrossVisible &&
<GraduationAcross
{...this.props}
{...this.state}
task_Id={task_Id}
modalVisible={acrossVisible}
modalCloss={this.closeAcross}
resetFun={this.resetList}
comment_status={ questionslist && questionslist.comment_status }
/>
}
<p className="clearfix mt10">
<a onClick={this.goback} className="color-grey-9 fl">{questionslist.course_name}</a>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<Link to={`/courses/${courseId}/graduation_tasks/${category_id}`} className="color-grey-9 fl">{questionslist.graduation_name}</Link>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<span className="color-grey-6">任务详情</span>
</p>
<div className="clearfix mt20 mb20 lineh-25 linbox">
<p className=" fl color-black summaryname">
<Link to={`/courses/${courseId}/graduation_tasks/${category_id}`} className="color-grey-3">{questionslist.task_name}</Link>
</p>
<CoursesListType
typelist={questionslist.task_status}
/>
<a className="color-grey-3 fr font-16 ml30 mr20" onClick={this.goback}>返回</a>
</div>
<div className="stud-class-set bor-bottom-greyE">
<div className="clearfix edu-back-white pl30 pr30 graduationTaskMenu">
<Link className={tab && tab == "list" ? "active" : ""} to={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/detail/"+task_Id+"/list"}>任务列表</Link>
<Link className={tab && tab == "questions" ? "active" : ""} to={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/detail/"+task_Id+"/questions"}>毕设描述</Link>
<Link className={tab && tab == "setting" ? "active" : ""} to={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/detail/"+task_Id+"/setting?tab=3"}>设置</Link>
{/*<a className={"fr color-blue font-16"}>导出成绩</a>*/}
{/*{this.props.isAdmin()?<a href={"/api/graduation_tasks/"+task_Id+"/tasks_list.xls"} className={"fr color-blue font-16"}>导出成绩</a>:""}*/}
{/*{this.props.isAdmin()?<a href={"/api/graduation_tasks/"+task_Id+"/tasks_list.zip"} className={"fr color-blue font-16"}>导出作品附件</a>:""}*/}
<style>
{ `
}
bindRef = ref => { this.child = ref } ;
render(){
let courseId=this.props.match.params.coursesId;
let category_id=this.props.match.params.category_id;
let task_Id=this.props.match.params.task_Id;
let {
questionslist ,
tab ,
visibles ,
Modalstype,
Modalstopval,
ModalCancel,
ModalSave,
acrossVisible
} = this.state
const commom = {
setTab:this.setTab,
getdatas:this.getdatas
}
document.title=questionslist&&questionslist.course_name;
return(
<div className="newMain clearfix">
{
questionslist &&
<div className={"educontent mb20"}>
<HomeworkModal
starttimes={this.state.starttimes}
typs={this.state.typs}
modalname={this.state.modalname}
visible={this.state.visible}
Topval={this.state.Topval}
Topvalright={this.state.Topvalright}
Botvalleft={this.state.Botvalleft}
Botval={this.state.Botval}
starttime={this.state.starttime}
endtime={this.state.endtime}
Cancelname={this.state.Cancelname}
Savesname={this.state.Savesname}
Cancel={this.state.Cancel}
Saves={this.state.Saves}
course_groups={this.state.course_groups}
modaltype={this.state.modaltype}
getcourse_groupslist={(id) => this.getcourse_groupslist(id)}
/>
{/*关联项目*/}
{visibles===true?
<Associationmodel
modalname={"关联项目"}
visible={visibles}
Cancel={()=>this.Cancel()}
taskid={ questionslist && questionslist.task_id }
funlist={this.resetList}
/>
:""}
{this.state.avisible===true?<AccessoryModal
{...this.props}
modalname={"补交附件"}
visible={this.state.avisible}
Cancelname={"取消"}
Savesname={"确认"}
Cancel={this.Cancelvisible}
categoryid={questionslist.work_id}
setupdate={this.resetList}
/>:""}
{/*提示*/}
<Modals
modalsType={Modalstype}
modalsTopval={Modalstopval}
modalCancel={ModalCancel}
modalSave={ModalSave}
closable={false}
footer={null}
destroyOnClose={true}
centered={true}
/>
{
acrossVisible &&
<GraduationAcross
{...this.props}
{...this.state}
task_Id={task_Id}
modalVisible={acrossVisible}
modalCloss={this.closeAcross}
resetFun={this.resetList}
comment_status={ questionslist && questionslist.comment_status }
/>
}
<p className="clearfix mt10">
<a onClick={this.goback} className="color-grey-9 fl">{questionslist.course_name}</a>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<Link to={`/courses/${courseId}/graduation_tasks/${category_id}`} className="color-grey-9 fl">{questionslist.graduation_name}</Link>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<span className="color-grey-6">任务详情</span>
</p>
<div className="clearfix mt20 mb20 lineh-25 linbox">
<p className=" fl color-black summaryname">
<Link to={`/courses/${courseId}/graduation_tasks/${category_id}`} className="color-grey-3">{questionslist.task_name}</Link>
</p>
<CoursesListType
typelist={questionslist.task_status}
/>
<a className="color-grey-3 fr font-16 ml30 mr20" onClick={this.goback}>返回</a>
</div>
<div className="stud-class-set bor-bottom-greyE">
<div className="clearfix edu-back-white pl30 pr30 graduationTaskMenu">
<Link className={tab && tab == "list" ? "active" : ""} to={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/detail/"+task_Id+"/list"}>任务列表</Link>
<Link className={tab && tab == "questions" ? "active" : ""} to={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/detail/"+task_Id+"/questions"}>毕设描述</Link>
<Link className={tab && tab == "setting" ? "active" : ""} to={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/detail/"+task_Id+"/setting?tab=3"}>设置</Link>
{/*<a className={"fr color-blue font-16"}>导出成绩</a>*/}
{/*{this.props.isAdmin()?<a href={"/api/graduation_tasks/"+task_Id+"/tasks_list.xls"} className={"fr color-blue font-16"}>导出成绩</a>:""}*/}
{/*{this.props.isAdmin()?<a href={"/api/graduation_tasks/"+task_Id+"/tasks_list.zip"} className={"fr color-blue font-16"}>导出作品附件</a>:""}*/}
<style>
{ `
.drop_down_menu{
height: 118px;
left:0px;
@ -442,63 +444,63 @@ class GraduationTaskDetail extends Component{
height: 26px;
}
`}
</style>
{this.props.isAdmin()? <li className="li_line drop_down fr color-blue font-16 mt20" style={{"paddingLeft":"0px"}}>
导出<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu" style={{"right":"-34px","left":"unset","height":"auto"}}>
<li><a onClick={()=>this.child.confirmysl("/graduation_tasks/"+task_Id+"/tasks_list.xlsx")} className="color-dark">导出成绩</a></li>
<li><a onClick={()=>this.child.confirmysl("/graduation_tasks/"+task_Id+"/tasks_list.zip")} className="color-dark">导出作品附件</a></li>
</ul>
</li>:""}
{questionslist.work_status===undefined||questionslist.work_status===null||questionslist.work_status.length===0?"":questionslist.work_status.map((item,key)=>{
return(
<span key={key} className="fr mt20">
</style>
{this.props.isAdmin()? <li className="li_line drop_down fr color-blue font-16 mt20" style={{"paddingLeft":"0px"}}>
导出<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu" style={{"right":"-34px","left":"unset","height":"auto"}}>
<li><a onClick={()=>this.child.confirmysl("/graduation_tasks/"+task_Id+"/tasks_list.xlsx")} className="color-dark">导出成绩</a></li>
<li><a onClick={()=>this.child.confirmysl("/graduation_tasks/"+task_Id+"/tasks_list.zip")} className="color-dark">导出作品附件</a></li>
</ul>
</li>:""}
{questionslist.work_status===undefined||questionslist.work_status===null||questionslist.work_status.length===0?"":questionslist.work_status.map((item,key)=>{
return(
<span key={key} className="fr mt20">
{item==="提交作品"?<a className={"fr color-blue font-16 ml20"} href={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/works/"+task_Id+"/new"}>提交作品</a>:""}
{item==="补交作品"?<a className={"fr color-blue font-16 ml20"} href={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/works/"+task_Id+"/new"}>补交作品</a>:""}
{item==="修改作品"?<a className={"fr color-blue font-16 ml20"} href={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/works"+"/"+ questionslist.work_id + "/edit"}>修改作品</a>:""}
{item==="查看作品"?<a className={"fr color-blue font-16 ml20"} target="_blank" href={"/courses/"+courseId+"/graduation_tasks/"+ questionslist.work_id + "/appraise"}>查看作品</a> :""}
{item==="创建项目"?<a className={"fr color-blue font-16 ml20"} href={'/projects/new'} target="_blank">创建项目</a>:""}
{item==="关联项目"?<a className={"fr color-blue font-16 ml20"} onClick={this.AssociationItems}>关联项目</a>:""}
{item==="取消关联"?<a className={"fr color-blue font-16 ml20"} onClick={this.cannelAssociation}>取消关联</a>:""}
{item==="补交附件"?<a className={"fr color-blue font-16 ml20"} onClick={this.handaccessory}>补交附件</a>:""}
{item==="补交作品"?<a className={"fr color-blue font-16 ml20"} href={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/works/"+task_Id+"/new"}>补交作品</a>:""}
{item==="修改作品"?<a className={"fr color-blue font-16 ml20"} href={"/courses/"+courseId+"/graduation_tasks/"+category_id+"/works"+"/"+ questionslist.work_id + "/edit"}>修改作品</a>:""}
{item==="查看作品"?<a className={"fr color-blue font-16 ml20"} target="_blank" href={"/courses/"+courseId+"/graduation_tasks/"+ questionslist.work_id + "/appraise"}>查看作品</a> :""}
{item==="创建项目"?<a className={"fr color-blue font-16 ml20"} href={'/projects/new'} target="_blank">创建项目</a>:""}
{item==="关联项目"?<a className={"fr color-blue font-16 ml20"} onClick={this.AssociationItems}>关联项目</a>:""}
{item==="取消关联"?<a className={"fr color-blue font-16 ml20"} onClick={this.cannelAssociation}>取消关联</a>:""}
{item==="补交附件"?<a className={"fr color-blue font-16 ml20"} onClick={this.handaccessory}>补交附件</a>:""}
</span>
)
})}
{/*<a className={"fr color-blue font-16"}>项目在线质量检测</a>*/}
{ this.props.isAdmin() ? questionslist.status===1 ? <a className={"fr color-blue font-16 mr20"} onClick={() => { this.end()} }>立即截止</a> : "" : "" }
{ this.props.isAdmin() ? questionslist.status===0 ? <a className={"fr color-blue font-16 mr20"} onClick={() => { this.publish()} }>立即发布</a> : "" : "" }
{ this.props.isAdmin() && questionslist.cross_comment ? <a className={"fr color-blue font-16"} onClick={this.openAcross}>交叉评阅设置</a> : "" }
{ this.props.isAdmin() ? <a className={"fr color-blue font-16"} href={"/courses/"+courseId+"/graduation_tasks/"+task_Id+"/edit"}>编辑任务</a> : "" }
</div>
</div>
<Switch {...this.props}>
<Route exact path="/courses/:coursesId/graduation_tasks/:category_id/detail/:task_Id/list"
render={
(props) => (<GraduationTaskslist {...this.props} {...props} {...this.state} {...commom} triggerRef={this.bindRef} tab={`list`}/>)
}
></Route>
<Route exact path="/courses/:coursesId/graduation_tasks/:category_id/detail/:task_Id/setting"
render={
(props) => (<GraduationTaskssetting {...this.props} {...props} {...this.state} {...commom} triggerRef={this.bindRef} tab={`setting`}/>)
}
></Route>
<Route exact path="/courses/:coursesId/graduation_tasks/:category_id/detail/:task_Id/questions"
render={
(props) => (<GraduationTasksquestions {...this.props} {...props} {...this.state} {...commom} triggerRef={this.bindRef} tab={`questions`}/>)
}></Route>
</Switch>
</div>
}
</div>
)
}
)
})}
{/*<a className={"fr color-blue font-16"}>项目在线质量检测</a>*/}
{ this.props.isAdmin() ? questionslist.status===1 ? <a className={"fr color-blue font-16 mr20"} onClick={() => { this.end()} }>立即截止</a> : "" : "" }
{ this.props.isAdmin() ? questionslist.status===0 ? <a className={"fr color-blue font-16 mr20"} onClick={() => { this.publish()} }>立即发布</a> : "" : "" }
{ this.props.isAdmin() && questionslist.cross_comment ? <a className={"fr color-blue font-16"} onClick={this.openAcross}>交叉评阅设置</a> : "" }
{ this.props.isAdmin() ? <a className={"fr color-blue font-16"} href={"/courses/"+courseId+"/graduation_tasks/"+task_Id+"/edit"}>编辑任务</a> : "" }
</div>
</div>
<Switch {...this.props}>
<Route exact path="/courses/:coursesId/graduation_tasks/:category_id/detail/:task_Id/list"
render={
(props) => (<GraduationTaskslist {...this.props} {...props} {...this.state} {...commom} triggerRef={this.bindRef} tab={`list`}/>)
}
></Route>
<Route exact path="/courses/:coursesId/graduation_tasks/:category_id/detail/:task_Id/setting"
render={
(props) => (<GraduationTaskssetting {...this.props} {...props} {...this.state} {...commom} triggerRef={this.bindRef} tab={`setting`}/>)
}
></Route>
<Route exact path="/courses/:coursesId/graduation_tasks/:category_id/detail/:task_Id/questions"
render={
(props) => (<GraduationTasksquestions {...this.props} {...props} {...this.state} {...commom} triggerRef={this.bindRef} tab={`questions`}/>)
}></Route>
</Switch>
</div>
}
</div>
)
}
}
// CNotificationHOC() ( SnackbarHOC() ( TPMIndexHOC))
export default (GraduationTaskDetail) ;

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

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

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

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

Loading…
Cancel
Save