diff --git a/README.md b/README.md
index 8dcb6d131..90f519de4 100644
--- a/README.md
+++ b/README.md
@@ -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
\ No newline at end of file
diff --git a/app/controllers/admins/competitions_controller.rb b/app/controllers/admins/competitions_controller.rb
new file mode 100644
index 000000000..3d6bef819
--- /dev/null
+++ b/app/controllers/admins/competitions_controller.rb
@@ -0,0 +1,15 @@
+class Admins::CompetitionsController < Admins::BaseController
+
+ 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
+
+ respond_to do |format|
+ format.js
+ format.html
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb
index 1081a82ce..2bcc8d8f6 100644
--- a/app/controllers/boards_controller.rb
+++ b/app/controllers/boards_controller.rb
@@ -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])
diff --git a/app/controllers/course_groups_controller.rb b/app/controllers/course_groups_controller.rb
index 0e16d1bac..bfdb959b4 100644
--- a/app/controllers/course_groups_controller.rb
+++ b/app/controllers/course_groups_controller.rb
@@ -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?
diff --git a/app/controllers/course_modules_controller.rb b/app/controllers/course_modules_controller.rb
index 6e8afd525..0bef519fd 100644
--- a/app/controllers/course_modules_controller.rb
+++ b/app/controllers/course_modules_controller.rb
@@ -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("添加子目录失败")
diff --git a/app/controllers/course_second_categories_controller.rb b/app/controllers/course_second_categories_controller.rb
index e5c3366cd..2de1637f2 100644
--- a/app/controllers/course_second_categories_controller.rb
+++ b/app/controllers/course_second_categories_controller.rb
@@ -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
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index 0c643d15c..0b3e35519 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -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
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
index 791d145c2..117475894 100644
--- a/app/controllers/files_controller.rb
+++ b/app/controllers/files_controller.rb
@@ -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
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index ae28e7d52..8b7034ab9 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -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)
diff --git a/app/models/competition_mode_setting.rb b/app/models/competition_mode_setting.rb
new file mode 100644
index 000000000..b6bafa7c3
--- /dev/null
+++ b/app/models/competition_mode_setting.rb
@@ -0,0 +1,3 @@
+class CompetitionModeSetting < ApplicationRecord
+ belongs_to :course
+end
diff --git a/app/models/laboratory.rb b/app/models/laboratory.rb
index 53e66ece0..f319ace80 100644
--- a/app/models/laboratory.rb
+++ b/app/models/laboratory.rb
@@ -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
diff --git a/app/services/admins/save_laboratory_setting_service.rb b/app/services/admins/save_laboratory_setting_service.rb
index 00e202cd9..f2a5c151e 100644
--- a/app/services/admins/save_laboratory_setting_service.rb
+++ b/app/services/admins/save_laboratory_setting_service.rb
@@ -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
diff --git a/app/views/admins/competitions/index.html.erb b/app/views/admins/competitions/index.html.erb
new file mode 100644
index 000000000..8fa238181
--- /dev/null
+++ b/app/views/admins/competitions/index.html.erb
@@ -0,0 +1,7 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('竞赛列表', admins_competitions_path) %>
+<% end %>
+
+
+ <%= render partial: 'admins/shixuns/shared/list', locals: { shixuns: @shixuns } %>
+
diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb
index 145910928..ca6fb2a46 100644
--- a/app/views/admins/shared/_sidebar.html.erb
+++ b/app/views/admins/shared/_sidebar.html.erb
@@ -66,6 +66,8 @@
<% end %>
+ <%= sidebar_item(admins_competitions_path, '竞赛', icon: 'trophy', controller: 'admins-competitions') %>
+
<%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
<%= sidebar_item(admins_carousels_path, '轮播图', icon: 'image', controller: 'admins-carousels') %>
diff --git a/app/views/attachments/_attachment.json.jbuilder b/app/views/attachments/_attachment.json.jbuilder
index a8ad0a286..a21bf31c4 100644
--- a/app/views/attachments/_attachment.json.jbuilder
+++ b/app/views/attachments/_attachment.json.jbuilder
@@ -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
diff --git a/app/views/competitions/competitions/index.json.jbuilder b/app/views/competitions/competitions/index.json.jbuilder
index f0d70f69e..400f17379 100644
--- a/app/views/competitions/competitions/index.json.jbuilder
+++ b/app/views/competitions/competitions/index.json.jbuilder
@@ -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
diff --git a/app/views/courses/left_banner.json.jbuilder b/app/views/courses/left_banner.json.jbuilder
index 681145769..f3b80b4f5 100644
--- a/app/views/courses/left_banner.json.jbuilder
+++ b/app/views/courses/left_banner.json.jbuilder
@@ -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?
diff --git a/app/views/courses/mine.json.jbuilder b/app/views/courses/mine.json.jbuilder
index c82e31f6b..fc6a5becc 100644
--- a/app/views/courses/mine.json.jbuilder
+++ b/app/views/courses/mine.json.jbuilder
@@ -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
diff --git a/app/views/courses/top_banner.json.jbuilder b/app/views/courses/top_banner.json.jbuilder
index 877ffcdf1..9a0554585 100644
--- a/app/views/courses/top_banner.json.jbuilder
+++ b/app/views/courses/top_banner.json.jbuilder
@@ -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)
diff --git a/app/views/files/index.json.jbuilder b/app/views/files/index.json.jbuilder
index 7fe3bf5b7..0002cf299 100644
--- a/app/views/files/index.json.jbuilder
+++ b/app/views/files/index.json.jbuilder
@@ -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
diff --git a/app/views/files/show.json.jbuilder b/app/views/files/show.json.jbuilder
index 941e66619..71359ccfd 100644
--- a/app/views/files/show.json.jbuilder
+++ b/app/views/files/show.json.jbuilder
@@ -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
\ No newline at end of file
diff --git a/app/views/homework_commons/show.json.jbuilder b/app/views/homework_commons/show.json.jbuilder
index e78166fe0..74b60af48 100644
--- a/app/views/homework_commons/show.json.jbuilder
+++ b/app/views/homework_commons/show.json.jbuilder
@@ -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
# 附件
diff --git a/config/routes.rb b/config/routes.rb
index 32725e8e9..f6f8db066 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -980,6 +980,8 @@ Rails.application.routes.draw do
resource :laboratory_setting, only: [:show, :update]
resource :laboratory_user, only: [:create, :destroy]
end
+
+ resources :competitions, only: [:index, :destroy]
end
resources :colleges, only: [] do
diff --git a/db/migrate/20191014061301_migrate_course_atta.rb b/db/migrate/20191014061301_migrate_course_atta.rb
new file mode 100644
index 000000000..04d085c0d
--- /dev/null
+++ b/db/migrate/20191014061301_migrate_course_atta.rb
@@ -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
diff --git a/db/migrate/20191015013924_add_new_column_to_competitions.rb b/db/migrate/20191015013924_add_new_column_to_competitions.rb
new file mode 100644
index 000000000..616a46059
--- /dev/null
+++ b/db/migrate/20191015013924_add_new_column_to_competitions.rb
@@ -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
diff --git a/db/migrate/20191015015723_create_competition_mode_settings.rb b/db/migrate/20191015015723_create_competition_mode_settings.rb
new file mode 100644
index 000000000..5d170eeab
--- /dev/null
+++ b/db/migrate/20191015015723_create_competition_mode_settings.rb
@@ -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
diff --git a/public/react/public/index.html b/public/react/public/index.html
index f6eef196a..9b757d2c4 100755
--- a/public/react/public/index.html
+++ b/public/react/public/index.html
@@ -13,7 +13,7 @@
-
+
- EduCoder
+
+
diff --git a/public/react/src/App.js b/public/react/src/App.js
index 34b5d1a4f..fd945914a 100644
--- a/public/react/src/App.js
+++ b/public/react/src/App.js
@@ -9,7 +9,7 @@ import {
Route,
Switch
} from 'react-router-dom';
-
+import axios from 'axios';
import '@icedesign/base/dist/ICEDesignBase.css';
import '@icedesign/base/index.scss';
@@ -287,6 +287,7 @@ class App extends Component {
Addcoursestypes:false,
mydisplay:false,
occupation:0,
+ mygetHelmetapi:undefined,
}
}
@@ -327,7 +328,6 @@ class App extends Component {
}
componentDidMount() {
this.disableVideoContextMenu();
-
// force an update if the URL changes
history.listen(() => {
this.forceUpdate()
@@ -336,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);
@@ -362,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 (
+
+
this.Modifyloginvalue()}>
@@ -413,10 +477,22 @@ class App extends Component {
{
+
+ return ()
+ }
+ }
/>
{
+
+ return ()
+ }
+ }
/>
{
+
+ return ()
+ }
+ }
/>
{/*课堂*/}
-
+
{/*
*/}
@@ -502,7 +584,12 @@ class App extends Component {
render={
(props)=>()
}/>
-
+ ()
+ }
+ />
@@ -625,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);
\ No newline at end of file
+export default SnackbarHOC()(App) ;
\ No newline at end of file
diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js
index e1d5da561..9cf68503d 100644
--- a/public/react/src/AppConfig.js
+++ b/public/react/src/AppConfig.js
@@ -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;
diff --git a/public/react/src/modules/courses/Resource/Fileslistitem.js b/public/react/src/modules/courses/Resource/Fileslistitem.js
index d364f7ada..2610656cc 100644
--- a/public/react/src/modules/courses/Resource/Fileslistitem.js
+++ b/public/react/src/modules/courses/Resource/Fileslistitem.js
@@ -209,6 +209,9 @@ class Fileslistitem extends Component{
text-overflow:ellipsis;
white-space:nowrap
}
+ .mt2{
+ margin-top:2px;
+ }
`}
window.$(`.sourceitem${index} input`).click() }>
this.eventStop(event)}>
@@ -248,6 +251,29 @@ class Fileslistitem extends Component{
:""
}
{discussMessage.is_publish===false?:""}
+
+ {this.props.isAdmin?
+ this.eventStop(event)}>
+
+ this.settingList()}>设置
+
+ :""}
+
+ {this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login?
+ this.eventStop(event)}>
+
+
+ this.settingList()}>设置
+
+
+
+ this.onDelete(discussMessage.id)}>删除
+
+
+ :""}
}
- {title}
+ {title}
{ firstRowRight }
diff --git a/public/react/src/modules/courses/coursesPublic/SelectResource.js b/public/react/src/modules/courses/coursesPublic/SelectResource.js
index c323d1bae..0e76059c8 100644
--- a/public/react/src/modules/courses/coursesPublic/SelectResource.js
+++ b/public/react/src/modules/courses/coursesPublic/SelectResource.js
@@ -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 = ;
+ const radioStyle = {
+ display: 'block',
+ height: '30px',
+ lineHeight: '30px',
+ };
return(
{/*提示*/}
@@ -373,10 +415,36 @@ class Selectresource extends Component{
}
-
+
+ 发布设置:
+
+
+ 立即发布
+
+
+ 延迟发布
+ this.onChangeTimepublish(e,index,undefined,1)}
+ disabledTime={disabledDateTime}
+ disabledDate={disabledDate}
+ disabled={this.state.Radiovalue===1?false:true}
+ />
+
+ (按照设置的时间定时发布)
+
+
{this.state.patheditarrytype===true?请选择资源
:""}
-
+ {this.state.Radiovaluetype===true?发布时间不能为空
:""}
取消
确定
diff --git a/public/react/src/modules/courses/coursesPublic/SelectSetting.js b/public/react/src/modules/courses/coursesPublic/SelectSetting.js
index 37b22c205..ff5751cc6 100644
--- a/public/react/src/modules/courses/coursesPublic/SelectSetting.js
+++ b/public/react/src/modules/courses/coursesPublic/SelectSetting.js
@@ -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
{
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{
+ 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(
- - 资源名称
+ - 资源名称
- 下载
- - 引用
+ {/*- 引用
*/}
- 版本号
@@ -490,7 +343,7 @@ class Selectsetting extends Component{
`}
-
+
{datalist&&datalist.title}
{datalist&&datalist.attachment_histories.length===0?"":当前版本}
@@ -505,13 +358,13 @@ class Selectsetting extends Component{
{datalist&&datalist.attachment_histories.map((item,key)=>{
return(
-
+
{item.title}
{/*当前版本*/}
{item.downloads_count}
-
{item.quotes}
+ {/*
{item.quotes} */}
{moment(item.created_on).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(item.created_on).format('YYYY-MM-DD HH:mm')}
@@ -607,61 +460,15 @@ class Selectsetting extends Component{
- {/**/}
- {/*{this.state.fileList.length===0?"":this.state.fileList.map((item,key)=>{*/}
- {/*return(*/}
- {/*
*/}
- {/**/}
- {/**/}
- {/**/}
- {/**/}
- {/*{item.name}*/}
- {/**/}
- {/**/}
- {/*{item.response===undefined?"":isNaN(bytesToSize(item.filesize))?"123":bytesToSize(item.filesize)}*/}
- {/**/}
- {/*this.onAttachmentRemove(item.response===undefined?"":item.response.id&&item.response.id)}>*/}
- {/*
*/}
- {/*)*/}
- {/*})}*/}
-
{this.state.newfileListtypes===true?
请先上传资源
:""}
-
+
-
- {/*
*/}
- {/**/}
- {/*勾选后所有用户可见,否则仅课堂成员可见*/}
- {/**/}
- {/*
*/}
- {/*{this.props.has_course_groups&&this.props.has_course_groups===true?:""}*/}
- {this.state.course_groupss&&this.state.course_groupss.length>0?
- 统一设置(选中则所有分班使用相同的发布设置,否则各个单独设置)
- :""}
-
-
-
- {/*this.props.has_course_groups&&this.props.has_course_groups===true?:""*/}
-
- {unified_setting===false?
- this.state.course_groups&&this.state.course_groups.map((item,key)=>{
- return(
-
-
-
-
-
-
- this.onChangeTimepublishs(e,index,key)}
- // onChange={ this.onChangeTimepublish }
- disabledTime={disabledDateTime}
- disabledDate={disabledDate}
- />
-
- {key!=0?this.deletegrouppublish(key)}>:""}
- {key===course_groups.length-1?:""}
-
- )
- }):""}
-
-
+ {this.props.course_is_public===true?
+ 公开:this.onChangepublic(e)}>
+ 选中,所有用户可见,否则课堂成员可见
+
+
:""}
- {unified_setting===true?
-
-
-
-
-
:""}
- {/*{this.state.course_group_idtypes===true?
请选择分班
:""}*/}
-
- {/*{course_group_publish_timestype===true?
请填写完整
:""}*/}
+
+
+ 发布设置:
+ this.RadioonChange(e)} value={this.state.Radiovalue} style={{'width': '460px'}}>
+
+ 立即发布
+
+
+ 延迟发布
+
+
+ (按照设置的时间定时发布)
+
+
+
{this.state.descriptiontypes===true?
描述不能超过最大限制:100个字符
:""}
+ {this.state.Radiovaluetype===true?
发布时间不能为空
:""}
diff --git a/public/react/src/modules/courses/coursesPublic/SendToFilesModal.js b/public/react/src/modules/courses/coursesPublic/SendToFilesModal.js
index d14d5d267..c3f2db8c5 100644
--- a/public/react/src/modules/courses/coursesPublic/SendToFilesModal.js
+++ b/public/react/src/modules/courses/coursesPublic/SendToFilesModal.js
@@ -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;
+ }
+ `}
选择的{moduleName}发送到指定课堂
@@ -183,7 +190,12 @@ class Sendtofilesmodal extends Component{
>
- {/* https://github.com/CassetteRocks/react-infinite-scroller/issues/70 */}
+
+
+
课堂名称
+
创建时间
+
结束时间
+
-
+ {course.name}
+ {moment(course.created_at).format('YYYY-MM-DD')}
+ {course.end_date}
)
}) }
- {loading && hasMore && (
-
-
-
- )}
- {/* TODO */}
- {/* {
- !hasMore && 没有更多了。。
- } */}
+
diff --git a/public/react/src/modules/courses/coursesPublic/sendResource.js b/public/react/src/modules/courses/coursesPublic/sendResource.js
index fbc2ebeb2..48677a8e1 100644
--- a/public/react/src/modules/courses/coursesPublic/sendResource.js
+++ b/public/react/src/modules/courses/coursesPublic/sendResource.js
@@ -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
{
+ 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(
{/*提示*/}
@@ -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{
-
(单个文件最大150M)
+
(单个文件最大150M)
:""}
- {/**/}
- {/*{this.state.fileList.length===0?"":this.state.fileList.map((item,key)=>{*/}
- {/*debugger*/}
- {/*return(*/}
- {/*
*/}
- {/**/}
- {/**/}
- {/**/}
- {/**/}
- {/*{item.name}*/}
- {/**/}
- {/**/}
- {/*{item.response===undefined?"":isNaN(bytesToSize(item.filesize))?"":bytesToSize(item.filesize)}*/}
- {/**/}
- {/*this.onAttachmentRemove(item.response===undefined?"":item.response.id&&item.response.id)}>*/}
- {/*
*/}
- {/*)*/}
- {/*})}*/}
+
{newfileListtype===true&&this.state.fileListtype===false?
请先上传资源
:""}
@@ -484,13 +367,12 @@ class Sendresource extends Component{
}
`}
- {/*
*/}
- {/*勾选后所有用户可见,否则仅课堂成员可见*/}
- {/**/}
+ {this.props.course_is_public===true?
+ 公开:
+ 选中,所有用户可见,否则课堂成员可见
+
+
:""}
- {this.state.course_groups_count&&this.state.course_groups_count>0?
- 统一设置(选中则所有分班使用相同的发布设置,否则各个单独设置)
- :""}
-
- {is_unified_setting===false?
- course_group_publish_times.map((item,key)=>{
- return(
-
-
-
-
- this.onChangeTimepublish(e,index,key,2)}
- // onChange={ this.onChangeTimepublish }
- disabledTime={disabledDateTime}
- disabledDate={disabledDate}
- />
- {key!=0?this.deletegrouppublish(key)}>:""}
- {key===course_group_publish_times.length-1&&key:""}
-
- )
- })
-
- :""}
-
-
- {is_unified_setting===true?
-
- this.onChangeTimepublish(e,index,undefined,1)}
- disabledTime={disabledDateTime}
- disabledDate={disabledDate}
- />
-
-
:""}
+
+
+ 发布设置:
+
+
+ 立即发布
+
+
+ 延迟发布
+ this.onChangeTimepublish(e,index,undefined,1)}
+ disabledTime={disabledDateTime}
+ disabledDate={disabledDate}
+ disabled={this.state.Radiovalue===1?false:true}
+ />
+
+ (按照设置的时间定时发布)
+
+
+
{/*{course_group_publish_timestype===true?
请填写完整
:""}*/}
{descriptiontype===true?
请输入资源描述,最大限制100个字符
:""}
+ {this.state.Radiovaluetype===true?
发布时间不能为空
:""}
{this.props.Cancelname}
this.Saves()}>{this.props.Savesname}
diff --git a/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js b/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js
index e1a1f17f9..ae5a50e6d 100644
--- a/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js
+++ b/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js
@@ -2666,8 +2666,11 @@ class Studentshavecompletedthelist extends Component {
.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;
+ }
`}
-
+
{data === undefined ? "" :
div > .ant-spin .ant-spin-dot {
top: 72%;}
}
- .ysltableows2 .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
+ .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;
}
`}
@@ -2823,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;
}
`
@@ -2834,7 +2843,7 @@ class Studentshavecompletedthelist extends Component {
{data === undefined ? "" : tr > th, .ant-table-tbody > tr > td {
padding: 9px;
}
+ mysjysltable4 .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
+ padding: 9px;
+ }
`}
{datas === undefined ? "" :
{
- setCheckBoxRoles(member_roles)
- }, [member_roles])
+ // useEffect(() => {
+ // if (checkBoxRoles.length != member_roles.length) { // 死循环
+ // setCheckBoxRoles(member_roles)
+ // }
+ // }, [member_roles])
function onCheckBoxChange(val) {
console.log(val)
@@ -73,8 +75,8 @@ function ChangeRolePop({ member_roles = [], record, courseId, onChangeRoleSucces
}
>
- 修改角色
+ 修改角色
)
}
-export default ChangeRolePop
\ No newline at end of file
+export default memo(ChangeRolePop)
\ No newline at end of file
diff --git a/public/react/src/modules/courses/members/CourseGroupChooser.js b/public/react/src/modules/courses/members/CourseGroupChooser.js
index 125f10b51..655754dc4 100644
--- a/public/react/src/modules/courses/members/CourseGroupChooser.js
+++ b/public/react/src/modules/courses/members/CourseGroupChooser.js
@@ -89,7 +89,7 @@ function CourseGroupChooser({ course_groups, isAdminOrCreator = true, item, inde
trigger('groupAdd')}
- >添加分班
+ >新建分班
)
diff --git a/public/react/src/modules/courses/members/CourseGroupList.js b/public/react/src/modules/courses/members/CourseGroupList.js
index ec0b23fb3..6c0e915cc 100644
--- a/public/react/src/modules/courses/members/CourseGroupList.js
+++ b/public/react/src/modules/courses/members/CourseGroupList.js
@@ -152,7 +152,7 @@ function CourseGroupList(props) {
}
{
// pageType !== TYPE_STUDENTS &&
- !isCourseEnd && isAdmin && isParent && addDir()}>新建分班 }
+ !isCourseEnd && isAdmin && addDir()}>新建分班 }
{/* {
isAdmin && !isParent && course_group_id != 0 && deleteDir()}>删除分班 } */}
{/* {
@@ -210,13 +210,13 @@ function CourseGroupList(props) {
onPressEnter={onPressEnter}
>
-
+ {!!none_group_member_count &&
未分班:
{none_group_member_count}个学生
{props.history.push(`/courses/${courseId}/course_groups/0`)}}>查看
-
+
}
{course_groups && !!course_groups.length ?
diff --git a/public/react/src/modules/courses/members/CourseGroupListTable.js b/public/react/src/modules/courses/members/CourseGroupListTable.js
index 4645cf838..656ae67bc 100644
--- a/public/react/src/modules/courses/members/CourseGroupListTable.js
+++ b/public/react/src/modules/courses/members/CourseGroupListTable.js
@@ -28,7 +28,6 @@ function CourseGroupListTable(props) {
}
course_groups.forEach((record) => {
const id = record.id
- debugger;
let _clipboard = new ClipboardJS(`.copyBtn_${id}`);
_clipboard.on('success', (e) => {
props.showNotification('复制成功')
@@ -135,14 +134,14 @@ function CourseGroupListTable(props) {
{isAdmin && 复制邀请码 }
{isStudent && addToDir(record)} style={''}>加入分班}
- onGoDetail(record)} style={''}>查看
+ onGoDetail(record)} style={''}>查看
}
})
return columns
}
- const addToDir = async (record) => {
+ const doAddToDir = async (record) => {
const courseId = props.match.params.coursesId
const url = `/courses/${courseId}/join_course_group.json`
const course_group_id = record.id
@@ -151,11 +150,27 @@ function CourseGroupListTable(props) {
course_group_id
})
if (response && response.data.status == 0) {
- props.showNotification('加入成功')
+ props.showNotification(`已加入分班:${record.name}`)
props.updataleftNavfun()
props.onOperationSuccess && props.onOperationSuccess()
}
}
+ const addToDir = (record) => {
+ props.confirm({
+
+ content: `是否确认加入分班: ${record.name}?`,
+
+ okText: '确认',
+ cancelText: '取消',
+
+ onOk: () => {
+ doAddToDir(record)
+ },
+ onCancel() {
+ console.log('Cancel');
+ },
+ });
+ }
function onDelete(record) {
props.confirm({
diff --git a/public/react/src/modules/courses/members/studentsList.js b/public/react/src/modules/courses/members/studentsList.js
index 9acc4c0bf..a63509c59 100644
--- a/public/react/src/modules/courses/members/studentsList.js
+++ b/public/react/src/modules/courses/members/studentsList.js
@@ -107,7 +107,7 @@ const buildColumns = (that,isParent) => {
}
];
if (course_groups && course_groups.length) {
- columns.push({
+ this.isStudentPage && columns.push({
title: '分班',
dataIndex: 'course_group_name',
key: 'course_group_name',
@@ -130,7 +130,7 @@ const buildColumns = (that,isParent) => {
}
const isAdmin = that.props.isAdmin()
if (isAdmin) {
- columns.unshift({
+ !that.isStudentPage && columns.unshift({
title: '',
dataIndex: 'check',
key: 'check',
@@ -148,8 +148,9 @@ const buildColumns = (that,isParent) => {
render: (text, record) => {
return (
- that.onDelete(record)} style={'grey'}>删除学生
- that.onDelete(record)} style={'grey'}>删除学生
+ {record.member_roles && record.member_roles.length && {
showNotification={that.props.showNotification}
getUserId={that.props.isUserid}
fetchUser={that.props.fetchUser}
- >
+ >}
)
},
@@ -319,6 +320,9 @@ class studentsList extends Component{
isAdmin && on('updateNavSuccess', this.updateNavSuccess)
}
componentWillUnmount() {
+ if (this.clipboard) {
+ this.clipboard.destroy()
+ }
const isAdmin = this.props.isAdmin()
if (isAdmin) {
off('addStudentSuccess', this.addStudentSuccessListener)
@@ -330,6 +334,7 @@ class studentsList extends Component{
}
updateNavSuccess = () => {
this.fetchCourseGroups()
+ this.fetchAll()
}
addStudentSuccessListener=(e, data)=>{
@@ -418,12 +423,14 @@ class studentsList extends Component{
invite_code: result.data.invite_code,
isSpin:false
}, () => {
- if (!this.clipboard) {
- const clipboard = new ClipboardJS('.copybtn');
- clipboard.on('success', (e) => {
- this.props.showNotification('复制成功')
- });
- this.clipboard = clipboard
+ if (course_group_id) {
+ if (!this.clipboard) {
+ const clipboard = new ClipboardJS('.copybtn');
+ clipboard.on('success', (e) => {
+ this.props.showNotification('复制成功')
+ });
+ this.clipboard = clipboard
+ }
}
})
}
@@ -547,7 +554,7 @@ class studentsList extends Component{
addDir = () => {
trigger('groupAdd', this.props.coursesids)
}
- addToDir = async () => {
+ doAddToDir = async () => {
const courseId = this.props.match.params.coursesId
const url = `/courses/${courseId}/join_course_group.json`
const course_group_id = this.props.match.params.course_group_id
@@ -556,11 +563,27 @@ class studentsList extends Component{
course_group_id
})
if (response && response.data.status == 0) {
- this.props.showNotification('加入成功')
+ this.props.showNotification(`已加入分班:${this.state.course_group_name}`)
this.props.updataleftNavfun()
this.fetchAll()
}
}
+ addToDir = (record) => {
+ this.props.confirm({
+
+ content: `是否确认加入分班: ${this.state.course_group_name}?`,
+
+ okText: '确认',
+ cancelText: '取消',
+
+ onOk: () => {
+ this.doAddToDir()
+ },
+ onCancel() {
+ console.log('Cancel');
+ },
+ });
+ }
renameDir = () => {
const course_group_id = this.props.match.params.course_group_id
trigger('groupRename', { id: parseInt(course_group_id), name: this.state.course_group_name})
@@ -572,15 +595,15 @@ class studentsList extends Component{
是否确认删除?
,
onOk: () => {
- // const cid = this.props.match.params.coursesId
const course_group_id = this.props.match.params.course_group_id
+ const courseId = this.props.match.params.coursesId
const url = `/course_groups/${course_group_id}.json`
axios.delete(url)
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification('删除成功')
- this.props.history.push(response.data.right_url)
+ this.props.history.push(`/courses/${courseId}/course_groups`)
}
})
.catch(function (error) {
@@ -666,11 +689,14 @@ class studentsList extends Component{
if (this.props.match.path.endsWith('students')) {
} else if (course_group_id) {
- pageType = TYPE_COURSE_GOURP_PARENT
- } else {
pageType = TYPE_COURSE_GOURP_CHILD
+ } else {
+ pageType = TYPE_COURSE_GOURP_PARENT
}
-
+ // 本页面有2个状态,学生列表、具体分班
+ const isStudentPage = pageType == TYPE_STUDENTS
+ this.isStudentPage = isStudentPage
+ const isGroupChildPage = pageType == TYPE_COURSE_GOURP_CHILD
return(
@@ -683,7 +709,12 @@ class studentsList extends Component{
- {course_group_name || '未分班'}
+
+
+ { this.props.history.push(`/courses/${courseId}/course_groups`)}}
+ style={{color: '#212121', verticalAlign: 'initial', marginRight: '14px' }}
+ >
+ {course_group_name || '未分班'}
{isAdmin && invite_code &&
邀请码:
@@ -708,23 +739,24 @@ class studentsList extends Component{
searchPlaceholder={ '请输入姓名、学号进行搜索' }
firstRowRight={
- {
+ {/* {
// pageType !== TYPE_STUDENTS &&
- isSuperAdmin &&
+ !isStudentPage && isSuperAdmin &&
this.refs['createGroupByImportModal'].setVisible(true)}>导入创建分班
- }
+ } */}
+
{
- // pageType !== TYPE_STUDENTS &&
- !isCourseEnd && isAdmin && isParent && this.addDir()}>添加分班 }
+ !isStudentPage && isAdmin && !isParent && course_group_id != 0 && this.deleteDir()}>删除分班 }
{
- isStudent && !isParent && course_group_id != 0 && this.addToDir()}>加入分班 }
+ !isStudentPage && isAdmin && !isParent && course_group_id != 0 && this.renameDir()}>分班重命名 }
{
- isAdmin && !isParent && course_group_id != 0 && this.deleteDir()}>删除分班 }
+ !isStudentPage && !isCourseEnd && isAdmin && this.addDir()}>新建分班 }
+
{
- isAdmin && !isParent && course_group_id != 0 && this.renameDir()}>分班重命名 }
+ !isStudentPage && isStudent && !isParent && course_group_id != 0 && this.addToDir()}>加入分班 }
+ }
- {datas&&datas.category_name===undefined||datas&&datas.category_name===null?datas&&datas.main_category_name:datas&&datas.category_name+" 作业列表"}
+
+ {datas&&datas.category_name===undefined||datas&&datas.category_name===null?datas&&datas.main_category_name:
+ {datas&&datas.category_name}
+ 作业列表
+ }
+
{datas===undefined?"":datas.homeworks && datas.homeworks.length>1?this.props.isAdminOrCreator()===true?datas&&datas.category_name===undefined||datas&&datas.category_name===null?
diff --git a/public/react/src/modules/forums/MemoTechShare.js b/public/react/src/modules/forums/MemoTechShare.js
index de6ba074c..d32bd2e2f 100644
--- a/public/react/src/modules/forums/MemoTechShare.js
+++ b/public/react/src/modules/forums/MemoTechShare.js
@@ -1,116 +1,116 @@
-import React, { Component } from 'react';
-import { Redirect } from 'react-router';
-
-import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
-
-import PropTypes from 'prop-types';
-
-import classNames from 'classnames'
-
-import Pagination from 'rc-pagination';
-
-import { postPaginationHOC } from './PostPaginationHOC'
-
-import PostItem from './PostItem'
-
-import ForumsNavTab from './ForumsNavTab'
-
-// import queryString from 'query-string'
-import { queryString } from 'educoder'
-
-import MemoList from './MemoList'
-
-
-class MemoTechShare extends Component {
- constructor(props) {
- super(props)
-
- this.handleLocationChange = this.handleLocationChange.bind(this);
-
- this.state = {
-
- }
- }
-
- onPaginationChange(pageNum, pageSize) {
- this.props.onPaginationChange(pageNum, pageSize)
- }
-
- componentDidMount() {
- // this.handleLocationChange(this.props.history.location);
- // this.unlisten = this.props.history.listen(this.handleLocationChange);
- }
-
- componentWillUnmount() {
- // this.unlisten();
- }
- componentDidUpdate(prevProps) {
- if(this.props.match.params.memoType !== prevProps.match.params.memoType) {
- // do something
- console.log(`memoType changed`)
- this.props.fetchMemos();
- }
- }
-
- componentWillReceiveProps(newProps, newContext) {
- if (newProps.match.url === this.props.match.url) {
- const oldParsed = queryString.parse(this.props.location.search);
- const newParsed = queryString.parse(newProps.location.search);
- if (!newParsed.page && oldParsed.page ||
- (oldParsed.order && newParsed.order && oldParsed.order != newParsed.order)) {
- this.props.fetchMemos();
- }
- console.log('componentWillReceiveProps...')
- }
- }
-
- handleLocationChange(location) {
- console.log(`- - - location: '${location.pathname}'`);
- if (location.pathname) {
- if (location.pathname.indexOf('/forums/categories/all') != -1
- && this.props.location.search && this.props.location.search.indexOf('order=') != -1
- && location.search.indexOf('order=') != -1) {
- const oldParsed = queryString.parse(this.props.location.search);
- const newParsed = queryString.parse(location.search);
- if (oldParsed.order != newParsed.order) { // 只有在热门和最新间跳转时,才需要处理
- this.props.fetchMemos();
- }
- }
- }
- }
-
- renderMemoList() {
-
-
- // const { memo_list, user } = this.props;
- // if (!memo_list) {
- // return ''
- // }
- // return memo_list.map( (item, index) => {
-
- // return (
- // this.setTop(memo)}
- // setDown={(memo)=>this.setDown(memo)} memo={item}
- // >
- // )
- // })
- return this.props.renderMemoList();
- }
-
- render() {
- const { match, history, currentPage, memo_count ,memo_list } = this.props
-
- return (
-
-
- this.renderMemoList()}
- onPaginationChange={ (pageNum, pageSize) => this.props.onPaginationChange(pageNum, pageSize) }
- >
-
-
- );
- }
-}
-
-export default postPaginationHOC() ( MemoTechShare );
+import React, { Component } from 'react';
+import { Redirect } from 'react-router';
+
+import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
+
+import PropTypes from 'prop-types';
+
+import classNames from 'classnames'
+
+import Pagination from 'rc-pagination';
+
+import { postPaginationHOC } from './PostPaginationHOC'
+
+import PostItem from './PostItem'
+
+import ForumsNavTab from './ForumsNavTab'
+
+// import queryString from 'query-string'
+import { queryString } from 'educoder'
+
+import MemoList from './MemoList'
+
+
+class MemoTechShare extends Component {
+ constructor(props) {
+ super(props)
+
+ this.handleLocationChange = this.handleLocationChange.bind(this);
+
+ this.state = {
+
+ }
+ }
+
+ onPaginationChange(pageNum, pageSize) {
+ this.props.onPaginationChange(pageNum, pageSize)
+ }
+
+ componentDidMount() {
+ // this.handleLocationChange(this.props.history.location);
+ // this.unlisten = this.props.history.listen(this.handleLocationChange);
+ }
+
+ componentWillUnmount() {
+ // this.unlisten();
+ }
+ componentDidUpdate(prevProps) {
+ if(this.props.match.params.memoType !== prevProps.match.params.memoType) {
+ // do something
+ console.log(`memoType changed`)
+ this.props.fetchMemos();
+ }
+ }
+
+ componentWillReceiveProps(newProps, newContext) {
+ if (newProps.match.url === this.props.match.url) {
+ const oldParsed = queryString.parse(this.props.location.search);
+ const newParsed = queryString.parse(newProps.location.search);
+ if (!newParsed.page && oldParsed.page ||
+ (oldParsed.order && newParsed.order && oldParsed.order != newParsed.order)) {
+ this.props.fetchMemos();
+ }
+ // console.log('componentWillReceiveProps...')
+ }
+ }
+
+ handleLocationChange(location) {
+ console.log(`- - - location: '${location.pathname}'`);
+ if (location.pathname) {
+ if (location.pathname.indexOf('/forums/categories/all') != -1
+ && this.props.location.search && this.props.location.search.indexOf('order=') != -1
+ && location.search.indexOf('order=') != -1) {
+ const oldParsed = queryString.parse(this.props.location.search);
+ const newParsed = queryString.parse(location.search);
+ if (oldParsed.order != newParsed.order) { // 只有在热门和最新间跳转时,才需要处理
+ this.props.fetchMemos();
+ }
+ }
+ }
+ }
+
+ renderMemoList() {
+
+
+ // const { memo_list, user } = this.props;
+ // if (!memo_list) {
+ // return ''
+ // }
+ // return memo_list.map( (item, index) => {
+
+ // return (
+ // this.setTop(memo)}
+ // setDown={(memo)=>this.setDown(memo)} memo={item}
+ // >
+ // )
+ // })
+ return this.props.renderMemoList();
+ }
+
+ render() {
+ const { match, history, currentPage, memo_count ,memo_list } = this.props
+
+ return (
+
+
+ this.renderMemoList()}
+ onPaginationChange={ (pageNum, pageSize) => this.props.onPaginationChange(pageNum, pageSize) }
+ >
+
+
+ );
+ }
+}
+
+export default postPaginationHOC() ( MemoTechShare );
diff --git a/public/react/src/modules/login/EducoderLogin.js b/public/react/src/modules/login/EducoderLogin.js
index a6600b1e0..680c4bbc7 100644
--- a/public/react/src/modules/login/EducoderLogin.js
+++ b/public/react/src/modules/login/EducoderLogin.js
@@ -19,6 +19,8 @@ import {
notification
} from "antd";
import {Link, Switch, Route, Redirect} from 'react-router-dom';
+import { SnackbarHOC,getImageUrl } from 'educoder';
+import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
import '../courses/css/members.css';
import "../courses/common/formCommon.css"
import '../courses/css/Courses.css';
@@ -108,7 +110,8 @@ class EducoderLogin extends Component {
}
componentDidMount() {
-
+ // console.log("EducoderLogin");
+ // console.log(this.props);
}
Setlogins=(i)=>{
@@ -137,6 +140,9 @@ class EducoderLogin extends Component {
render() {
let {showbool,loginstatus,logini} = this.state;
+ console.log("EducoderLogingetHelmetapi");
+ console.log(this.props);
+ // console.log(this.props.mygetHelmetapi);
return (
@@ -148,7 +154,13 @@ class EducoderLogin extends Component {
"width": "100%"
}}>
-
this.gohome()} src={educodernet}/>
+ {
+ this.props.mygetHelmetapi===undefined||this.props.mygetHelmetapi.login_logo_url===null|| this.props.mygetHelmetapi.login_logo_url===undefined?
+
this.gohome()} src={educodernet}/>
+ :
+
this.gohome()} src={getImageUrl(this.props.mygetHelmetapi.login_logo_url)}/>
+ }
+
@@ -196,8 +208,7 @@ class EducoderLogin extends Component {
}
}
-
-export default EducoderLogin;
+export default EducoderLogin ;
// showbool === 2 ?
//
:""}
{isRender===true?
-
{this.handleDialogClose()}}>
+
{this.handleDialogClose()}}>
diff --git a/public/react/src/modules/tpm/NewFooter.js b/public/react/src/modules/tpm/NewFooter.js
index be1a1ed29..5d2403a04 100644
--- a/public/react/src/modules/tpm/NewFooter.js
+++ b/public/react/src/modules/tpm/NewFooter.js
@@ -39,16 +39,23 @@ class NewFooter extends Component {
diff --git a/public/react/src/modules/tpm/NewHeader.js b/public/react/src/modules/tpm/NewHeader.js
index de8fade26..330573f81 100644
--- a/public/react/src/modules/tpm/NewHeader.js
+++ b/public/react/src/modules/tpm/NewHeader.js
@@ -65,13 +65,26 @@ class NewHeader extends Component {
showTrial:false,
setevaluatinghides:false,
occupation:0,
- mydisplay:false
+ mydisplay:false,
+ headtypesonClickbool:false,
+ headtypess:"/",
+ mygetHelmetapi2:undefined,
}
- // console.log("176")
+ console.log("176")
// console.log(props);
+ // console.log("NewHeader1234567890");
+ // console.log(this.props);
}
-
+ componentDidUpdate = (prevProps) => {
+ // console.log("componentDidMount2");
+ // console.log(this.state.mygetHelmetapi2);
+ if(this.state.mygetHelmetapi2===undefined){
+ this.getAppdata();
+ }
+ }
componentDidMount() {
+ console.log("componentDidMount1");
+ this.getAppdata();
window._header_componentHandler = this;
//下拉框的显示隐藏
@@ -633,11 +646,80 @@ submittojoinclass=(value)=>{
this.setState({
AccountProfiletype:false
})
+ };
+ headtypesonClick=(url,bool)=>{
+ this.setState({
+ headtypess:url,
+ headtypesonClickbool:bool,
+ })
}
+ getAppdata=()=>{
+ // console.log("开始刷新数据了")
+ let url = "/setting.json";
+ axios.get(url).then((response) => {
+ // console.log("axios.get");
+ // console.log(response);
+
+ if(response){
+ if(response.data){
+ this.setState({
+ mygetHelmetapi2: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) => {
+ console.log("开始刷新定制数据了但报错了");
+ console.log(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() {
const isLogin = true; // 这里不会出现未登录的情况,服务端在服务端路由时发现如果是未登录,则跳转到登录页了。
- const {match ,} = this.props;
+ const {match,} = this.props;
let {Addcoursestypes,
tojoinitemtype,
@@ -655,35 +737,127 @@ submittojoinclass=(value)=>{
user,
isRender,
showSearchOpentype,
+ headtypesonClickbool,
+ headtypess,
+ mygetHelmetapi2,
}=this.state;
/*
用户名称 用户头像url
*/
- let activeIndex = false;
- let activeForums = false;
- let activeShixuns = false;
- let activePaths = false;
- let coursestype=false;
+ let activeIndex = false;
+ let activeForums = false;
+ let activeShixuns = false;
+ let activePaths = false;
+ let coursestype=false;
let activePackages=false;
let activeMoopCases=false;
- if (match.path === '/forums') {
- activeForums = true;
- } else if (match.path.startsWith('/shixuns')) {
- activeShixuns = true;
- }else if (match.path.startsWith('/paths')) {
- activePaths = true;
- } else if (match.path.startsWith('/courses')) {
- coursestype = true;
- }else if (match.path.startsWith('/crowdsourcing')) {
+ if (match.path === '/forums') {
+ activeForums = true;
+ } else if (match.path.startsWith('/shixuns')) {
+ activeShixuns = true;
+ }else if (match.path.startsWith('/paths')) {
+ activePaths = true;
+ } else if (match.path.startsWith('/courses')) {
+ coursestype = true;
+ }else if (match.path.startsWith('/crowdsourcing')) {
activePackages = true;
- }else if(match.path.startsWith('/moop_cases')){
- activeMoopCases = true;
- }else {
- activeIndex = true;
- }
+ }else if(match.path.startsWith('/moop_cases')){
+ activeMoopCases = true;
+ }else {
+ activeIndex = true;
+ }
+ let headtypes='/';
+
+ // console.log("mygetHelmetapi2");
+ // console.log(mygetHelmetapi2);
+ if(mygetHelmetapi2){
+ if(mygetHelmetapi2.navbar){
+ if(mygetHelmetapi2.navbar.length>0){
+ // console.log("mygetHelmetapi2.navbar.length>0====-=-=--=-=-=-=");
+ //
+ // console.log(match.path);
+ if(match.path==='/'){
+ if(headtypesonClickbool===false){
+ headtypes=undefined;
+ }else{
+ headtypes=headtypess;
+ }
+
+ }else {
+ for(var i=0;i