diff --git a/app/controllers/challenges_controller.rb b/app/controllers/challenges_controller.rb
index c69f5bbfb..47c8fc68c 100644
--- a/app/controllers/challenges_controller.rb
+++ b/app/controllers/challenges_controller.rb
@@ -159,11 +159,12 @@ class ChallengesController < ApplicationController
challenges.shixun_id, games.identifier, games.status"
join_sql = "LEFT JOIN games ON games.challenge_id = challenges.id AND games.user_id = #{current_user.id}"
# 下面2个参数是为了解决列表获取通关人数与正在游玩人数的问题
- @pass_games_map = @shixun.challenges.joins(:games).where(games: {status:2}).group(:challenge_id).reorder(nil).count
- @play_games_map = @shixun.challenges.joins(:games).where(games: {status:[0,1]}).group(:challenge_id).reorder(nil).count
+ #@pass_games_map = @shixun.challenges.joins(:games).where(games: {status:2}).group(:challenge_id).reorder(nil).count
+ #@play_games_map = @shixun.challenges.joins(:games).where(games: {status:[0,1]}).group(:challenge_id).reorder(nil).count
@challenges = @shixun.challenges.joins(join_sql).select(base_columns)
+ #@challenges = @shixun.challenges.fields_for_list
@editable = @shixun.status == 0 # before_action:有判断权限,如果没发布,则肯定是管理人员
@user = current_user
@shixun.increment!(:visits)
diff --git a/app/controllers/course_videos_controller.rb b/app/controllers/course_videos_controller.rb
index 0d5a3e460..090c7e29a 100644
--- a/app/controllers/course_videos_controller.rb
+++ b/app/controllers/course_videos_controller.rb
@@ -8,7 +8,8 @@ class CourseVideosController < ApplicationController
def create
title = params[:name].strip
link = params[:link].strip
- @course.course_videos.create!(title: title, link: link, is_link: 1, user_id: current_user.id)
+ course_second_category_id = params[:category_id] || 0
+ @course.course_videos.create!(title: title, link: link, is_link: 1, user_id: current_user.id, course_second_category_id: course_second_category_id)
render_ok
end
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index 4a40c84b3..2e94e435d 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -137,7 +137,7 @@ class CoursesController < ApplicationController
category = @course.course_second_categories.find_by(id: params[:new_category_id])
if params[:new_category_id].to_i == 0 || category.present?
- videos = @course.course_videos.where(video_id: params[:video_ids])
+ videos = @course.course_videos.where(video_id: params[:video_ids]).or(@course.course_videos.where(id: params[:video_ids]))
videos.update_all(course_second_category_id: params[:new_category_id])
normal_status(0, "操作成功")
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
index 25e0de44a..427545716 100644
--- a/app/controllers/files_controller.rb
+++ b/app/controllers/files_controller.rb
@@ -2,13 +2,13 @@ class FilesController < ApplicationController
include MessagesHelper
before_action :require_login, :check_auth, except: %i[index]
- before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project]
+ before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project update_visits]
before_action :find_ids, only: %i[bulk_delete bulk_send bulk_move bulk_public bulk_publish]
before_action :file_validate_sort_type, only: :index
before_action :validate_send_message_to_course_params, only: :bulk_send
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 :validate_upload_params, only: %i[import]
+ before_action :find_file, only: %i[show setting update update_visits]
before_action :publish_params, only: %i[upload import update]
SORT_TYPE = %w[created_on downloads quotes]
@@ -163,6 +163,7 @@ class FilesController < ApplicationController
# 上传资源
def upload
+ find_course_second_category_id
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
@@ -170,25 +171,48 @@ class FilesController < ApplicationController
# course_group_publish_times = params[:course_group_publish_times] || []
begin
- attachment_ids.each do |attchment_id|
- attachment = Attachment.find_by_id attchment_id
- unless attachment.nil?
- attachment.container = @course
- attachment.course_second_category_id = course_second_category_id
- attachment.description = params[:description]
- 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.unified_setting = @unified_setting
- if @unified_setting == 0
- attachment_group_setting attachment, params[:group_settings]
+ if attachment_ids.present?
+ attachment_ids.each do |attchment_id|
+ attachment = Attachment.find_by_id attchment_id
+ unless attachment.nil?
+ attachment.container = @course
+ attachment.course_second_category_id = course_second_category_id
+ attachment.description = params[:description]
+ 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.unified_setting = @unified_setting
+ if @unified_setting == 0
+ attachment_group_setting attachment, params[:group_settings]
+ end
+ # 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
- # 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
+ else
+ tip_exception("资源名称不能为空") if params[:name].blank?
+ tip_exception("资源名称不能超过60个字符") if params[:name].strip.length > 60
+ tip_exception("链接地址不能为空") if params[:link].blank?
+ attachment = Attachment.new
+ attachment.container = @course
+ attachment.course_second_category_id = course_second_category_id
+ attachment.author_id = current_user.id
+ attachment.filename = params[:name].strip
+ attachment.link = params[:link].strip
+ attachment.description = params[:description]
+ 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.unified_setting = @unified_setting
+ if @unified_setting == 0
+ attachment_group_setting attachment, params[:group_settings]
+ end
+ attachment.save!
end
+
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@@ -265,6 +289,11 @@ class FilesController < ApplicationController
@old_attachment.save!
@new_attachment.delete
end
+ if params[:name].present? && params[:link].present?
+ tip_exception("资源名称不能超过60个字符") if params[:name].strip.length > 60
+ @old_attachment.filename = params[:name].strip
+ @old_attachment.link = params[:link].strip
+ 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
@@ -326,6 +355,11 @@ class FilesController < ApplicationController
end
end
+ def update_visits
+ @file.increment!(:downloads)
+ render_ok
+ end
+
private
def find_file
@file = Attachment.find params[:id]
diff --git a/app/controllers/users/videos_controller.rb b/app/controllers/users/videos_controller.rb
index 0ae240dd7..32f81f6ed 100644
--- a/app/controllers/users/videos_controller.rb
+++ b/app/controllers/users/videos_controller.rb
@@ -1,6 +1,6 @@
class Users::VideosController < Users::BaseController
before_action :private_user_resources!, :check_account
- before_action :require_teacher!
+ before_action :require_teacher!, except: [:destroy]
before_action :require_auth_teacher!, except: [:index, :review]
helper_method :current_video
@@ -53,6 +53,19 @@ class Users::VideosController < Users::BaseController
render_error(ex.message)
end
+ def destroy
+ video = Video.find_by(id: params[:id])
+ return render_forbidden unless video.user_id == current_user.id || current_user.admin_or_business?
+ return render_not_found if video.blank?
+ return render_error('该状态下不能删除视频') unless video.published?
+
+ video.destroy!
+
+ AliyunVod::Service.delete_video([video.uuid]) rescue nil
+
+ render_ok
+ end
+
private
def current_video
@@ -72,6 +85,6 @@ class Users::VideosController < Users::BaseController
end
def batch_publish_params
- params.permit(videos: %i[video_id title course_id])
+ params.permit(videos: %i[video_id title course_id category_id])
end
end
\ No newline at end of file
diff --git a/app/controllers/weapps/attendances_controller.rb b/app/controllers/weapps/attendances_controller.rb
index 57e1e10df..7da852393 100644
--- a/app/controllers/weapps/attendances_controller.rb
+++ b/app/controllers/weapps/attendances_controller.rb
@@ -42,6 +42,7 @@ class Weapps::AttendancesController < ApplicationController
end
def student_attendances
+ tip_exception(403) if @user_course_identity > Course::STUDENT
# tip_exception("学生身份的签到列表") if @user_course_identity != Course::STUDENT
member = @course.students.find_by(user_id: current_user.id)
if member.present?
@@ -62,11 +63,11 @@ class Weapps::AttendancesController < ApplicationController
where("attendance_date = '#{current_date}' and start_time <= '#{current_end_time}' and end_time > '#{current_end_time}'")
@history_count = @history_attendances.size
- # 当前签到如果存在快捷签到,则直接签到
- quick_attendances = @current_attendances.where(mode: "QUICK")
- if quick_attendances.present?
- student_direct_attendance quick_attendances, member
- end
+ # 当前签到如果存在快捷签到,则直接签到(不在这里处理)
+ # quick_attendances = @current_attendances.where(mode: "QUICK")
+ # if quick_attendances.present?
+ # student_direct_attendance quick_attendances, member
+ # end
student_attendance_ids = @history_attendances.pluck(:id)
student_attendance_ids += @current_attendances.present? ? @current_attendances.pluck(:id) : []
diff --git a/app/controllers/weapps/course_member_attendances_controller.rb b/app/controllers/weapps/course_member_attendances_controller.rb
index 7e315fc85..5e92d5928 100644
--- a/app/controllers/weapps/course_member_attendances_controller.rb
+++ b/app/controllers/weapps/course_member_attendances_controller.rb
@@ -28,19 +28,24 @@ class Weapps::CourseMemberAttendancesController < ApplicationController
end
def create
- tip_exception("签到码不能为空") if params[:code].blank?
- tip_exception("attendance_mode参数不对") unless ["NUMBER", "QRCODE"].include?(params[:attendance_mode])
+ tip_exception("签到码不能为空") if params[:attendance_mode] != "QUICK" && params[:code].blank?
+ tip_exception("attendance_mode参数不对") unless ["NUMBER", "QRCODE", "QUICK"].include?(params[:attendance_mode])
- attendance = CourseAttendance.find_by(attendance_code: params[:code])
- tip_exception("签到码输入有误") if attendance.blank? || attendance.course.blank?
+ if params[:attendance_mode] == "QUICK"
+ attendance = CourseAttendance.find_by(id: params[:attendance_id])
+ else
+ attendance = CourseAttendance.find_by(attendance_code: params[:code])
+ end
+ tip_exception("该签到不存在") if attendance.blank? || attendance.course.blank?
member = attendance.course.students.find_by(user_id: current_user.id)
- tip_exception("签到码输入有误") if member.blank?
+ tip_exception("该签到不存在") if member.blank?
tip_exception("不在签到时间内") unless attendance.current_attendance?
- tip_exception("只支持数字签到") if attendance.mode != "ALL" && attendance.mode == "NUMBER" && params[:attendance_mode] == "QRCODE"
- tip_exception("只支持二维码签到") if attendance.mode != "ALL" && attendance.mode == "QRCODE" && params[:attendance_mode] == "NUMBER"
+ tip_exception("只支持数字签到") if attendance.mode != "ALL" && attendance.mode == "NUMBER" && params[:attendance_mode] != "NUMBER"
+ tip_exception("只支持二维码签到") if attendance.mode != "ALL" && attendance.mode == "QRCODE" && params[:attendance_mode] != "QRCODE"
+ tip_exception("只支持快捷签到") if attendance.mode == "QUICK" && params[:attendance_mode] != "QUICK"
current_attendance = attendance.course_member_attendances.find_by(user_id: current_user.id)
if current_attendance.present?
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index e352d6cec..d1d2499f0 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -70,6 +70,8 @@ module ApplicationHelper
# shixun开启挑战对应的行为名及url
def task_operation_url current_myshixun, shixun
+ return ["开启挑战", "/shixuns/#{shixun.identifier}/shixun_exec"] unless current_user.logged?
+
if current_myshixun.blank?
name = shixun.status == 0 ? "模拟实战" : "开启挑战"
url = "/shixuns/#{shixun.identifier}/shixun_exec"
diff --git a/app/models/challenge.rb b/app/models/challenge.rb
index 5646da363..31a683760 100644
--- a/app/models/challenge.rb
+++ b/app/models/challenge.rb
@@ -79,20 +79,34 @@ class Challenge < ApplicationRecord
end
end
- # # 开启挑战
- # def open_game(user_id, shixun)
- #
- #
- # game = self.games.select([:status, :identifier]).where(user_id: user_id).first
- # game = self.games.select{|game| game.user_id == user_id}
+ # def open_game shixun, user_id
+ # game = self.games.map{|g| g.user_id == user_id}.first
# if game.present?
# shixun.task_pass || game.status != 3 ? "/tasks/#{game.identifier}" : ""
# else
- # "/api/shixuns/#{shixun.identifier}/shixun_exec"
+ # self.position == 1 ? "/api/shixuns/#{shixun.identifier}/shixun_exec" : ""
# end
# end
## 用户关卡状态 0: 不能开启实训; 1:直接开启; 2表示已完成
+ # def user_tpi_status shixun, user_id
+ # # todo: 以前没加索引导致相同关卡,同一用户有多个games
+ # # 允许跳关则直接开启
+ # game = games.where(user_id: user_id).take
+ # if game.blank?
+ # position == 1 ? 1 : 0
+ # else
+ # if game.status == 3
+ # shixun.task_pass ? 1 : 0
+ # elsif game.status == 2
+ # 2
+ # else
+ # 1
+ # end
+ # end
+ # end
+
+ # ## 用户关卡状态 0: 不能开启实训; 1:直接开启; 2表示已完成
def user_tpi_status shixun
# todo: 以前没加索引导致相同关卡,同一用户有多个games
# 允许跳关则直接开启
@@ -128,12 +142,14 @@ class Challenge < ApplicationRecord
# 关卡用户通关数
def user_passed_count
- games.where(status: 2).count
+ #games.map{|g| g.status == 2}.count
+ self.games.where(status: 1).count
end
# 关卡用户正在挑战的人数
def playing_count
- games.where(status: [0, 1]).count
+ #games.map{|g| g.status == 0 || g.status == 1}.count
+ self.games.where(status: [0,1]).count
end
def last_challenge
diff --git a/app/models/course_video.rb b/app/models/course_video.rb
index 246be34fd..2cfa151ce 100644
--- a/app/models/course_video.rb
+++ b/app/models/course_video.rb
@@ -3,5 +3,6 @@ class CourseVideo < ApplicationRecord
belongs_to :video, optional: true
belongs_to :user, optional: true
- validates :title, length: { maximum: 60, too_long: "不能超过60个字符" }
+ validates :title, length: { maximum: 60, too_long: "不能超过60个字符" }, allow_blank: true
+ validates :link, format: { with: CustomRegexp::URL, message: "必须为网址超链接" }, allow_blank: true
end
diff --git a/app/models/shixun.rb b/app/models/shixun.rb
index c3c5cec78..b9bd372b0 100644
--- a/app/models/shixun.rb
+++ b/app/models/shixun.rb
@@ -210,8 +210,9 @@ class Shixun < ApplicationRecord
end
# 当前用户开启的实训
- def current_myshixun(user_id)
- myshixuns.find_by(user_id: user_id)
+ def current_myshixun(user)
+ return nil unless user.logged?
+ myshixuns.find_by(user_id: user.id)
end
# 实训技术平台
@@ -264,7 +265,7 @@ class Shixun < ApplicationRecord
# 实训关卡的总分(由于大部分是实践题,因此没关联查choose表)
# 提前加载问题:由于选择题比较少,所以几乎不会触发选择题的查询,所以没必要提前载入choose_score
def all_score
- self.challenges.pluck(:score).sum
+ self.challenges.sum(:score)
end
### fork 数量
diff --git a/app/models/user.rb b/app/models/user.rb
index 7e60983d1..b0bd191d2 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -339,7 +339,7 @@ class User < ApplicationRecord
# 实训管理员:实训合作者、admin
def manager_of_shixun?(shixun)
logger.info("############id: #{id}")
- shixun.shixun_members.exists?(role: [1,2], user_id: id) || admin? || business?
+ shixun.shixun_members.exists?(user_id: id, role: [1,2]) || admin? || business?
end
# 实训管理员
diff --git a/app/services/videos/batch_publish_service.rb b/app/services/videos/batch_publish_service.rb
index c9b1b69c7..7349799c9 100644
--- a/app/services/videos/batch_publish_service.rb
+++ b/app/services/videos/batch_publish_service.rb
@@ -49,7 +49,8 @@ class Videos::BatchPublishService < ApplicationService
# 如果是课堂上传则创建课堂记录
Rails.logger.info("#####param: #{ param[:course_id]}")
if param[:course_id].present?
- video.course_videos.create!(course_id: param[:course_id])
+ course_second_category_id = params[:category_id] || 0
+ video.course_videos.create!(course_id: param[:course_id], course_second_category_id: course_second_category_id)
end
end
end
diff --git a/app/views/attachments/_attachment.json.jbuilder b/app/views/attachments/_attachment.json.jbuilder
index b30869d57..c87f8372e 100644
--- a/app/views/attachments/_attachment.json.jbuilder
+++ b/app/views/attachments/_attachment.json.jbuilder
@@ -1,5 +1,6 @@
json.id attachment.id
json.title attachment.title
+json.link attachment.link
json.is_public attachment.publiced?
# json.is_lock attachment.locked?(@is_member)
json.is_lock !attachment.publiced?
@@ -15,4 +16,4 @@ json.created_on attachment.created_on
json.content_type attachment.content_type
json.is_pdf attachment.is_pdf?
json.url attachment.is_pdf? ? download_url(attachment,disposition:"inline") : download_url(attachment)
-json.play_url attachment_show_users_path(file_name: local_path(attachment))
+json.play_url attachment.link.present? ? nil : attachment_show_users_path(file_name: local_path(attachment))
diff --git a/app/views/challenges/index.json.jbuilder b/app/views/challenges/index.json.jbuilder
index d4f2a7f59..eae72dad2 100644
--- a/app/views/challenges/index.json.jbuilder
+++ b/app/views/challenges/index.json.jbuilder
@@ -16,12 +16,14 @@ if @challenges.present?
json.st challenge.st
json.name challenge.subject
json.score challenge.score
- json.passed_count @pass_games_map.fetch(challenge.id, 0)
- #json.passed_count challenge.user_passed_count
- json.playing_count @play_games_map.fetch(challenge.id, 0)
- #json.playing_count challenge.playing_count
+ #json.passed_count @pass_games_map.fetch(challenge.id, 0)
+ user_passed_count = challenge.user_passed_count
+ json.passed_count user_passed_count
+ #json.playing_count @play_games_map.fetch(challenge.id, 0)
+ json.playing_count (challenge.games.count - user_passed_count)
json.name_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)
json.open_game challenge.open_game(@shixun)
+ #json.open_game challenge.open_game(@shixun, @user.id)
if @editable
json.edit_url edit_shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)
json.delete_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)
@@ -29,6 +31,7 @@ if @challenges.present?
json.down_url index_down_shixun_challenge_path(challenge, :shixun_identifier => @shixun.identifier) if @shixun.challenges_count != challenge.position
end
#json.passed challenge.has_passed?(@user.id)
+ #json.status challenge.user_tpi_status(@shixun, @user.id)
json.status challenge.user_tpi_status(@shixun)
end
end
diff --git a/app/views/shixuns/_top.json.jbuilder b/app/views/shixuns/_top.json.jbuilder
index 362cfd15b..c90de5e5b 100644
--- a/app/views/shixuns/_top.json.jbuilder
+++ b/app/views/shixuns/_top.json.jbuilder
@@ -14,7 +14,7 @@ json.name shixun.name
json.stu_num shixun.myshixuns_count
json.experience shixun.all_score
json.diffcult level_to_s(shixun.trainee)
-json.score_info shixun.shixun_preference_info # todo: 这块可以改成只显示实训的平均分,不用每次都去取每种星的分数了。
+json.score_info shixun.averge_star # todo: 这块可以改成只显示实训的平均分,不用每次都去取每种星的分数了。
json.is_jupyter shixun.is_jupyter
# 用于是否显示导航栏中的'背景知识'
json.propaedeutics shixun.propaedeutics.present?
diff --git a/app/views/weapps/attendances/_student_attendance.json.jbuilder b/app/views/weapps/attendances/_student_attendance.json.jbuilder
index 9461c4976..6fd5e9d70 100644
--- a/app/views/weapps/attendances/_student_attendance.json.jbuilder
+++ b/app/views/weapps/attendances/_student_attendance.json.jbuilder
@@ -1,4 +1,4 @@
-json.(attendance, :name, :mode)
+json.(attendance, :id, :name, :mode)
json.attendance_date attendance.attendance_date.strftime("%Y/%m/%d")
json.start_time attendance.start_time.strftime("%H:%M")
json.end_time attendance.end_time.strftime("%H:%M")
diff --git a/config/routes.rb b/config/routes.rb
index 7bf1b6c1b..9c6b73ddc 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -195,7 +195,7 @@ Rails.application.routes.draw do
resource :unread_message_info, only: [:show]
# 视频
- resources :videos, only: [:index, :update] do
+ resources :videos, only: [:index, :update, :destroy] do
collection do
get :review
post :batch_publish
@@ -464,6 +464,7 @@ Rails.application.routes.draw do
end
member do
get :histories
+ post :update_visits
end
end
diff --git a/db/migrate/20200309123121_add_link_to_attachments.rb b/db/migrate/20200309123121_add_link_to_attachments.rb
new file mode 100644
index 000000000..23510be26
--- /dev/null
+++ b/db/migrate/20200309123121_add_link_to_attachments.rb
@@ -0,0 +1,5 @@
+class AddLinkToAttachments < ActiveRecord::Migration[5.2]
+ def change
+ add_column :attachments, :link, :string
+ end
+end
diff --git a/public/react/public/css/demo_index.html b/public/react/public/css/demo_index.html
index 281ac40d0..7b0854698 100644
--- a/public/react/public/css/demo_index.html
+++ b/public/react/public/css/demo_index.html
@@ -30,6 +30,54 @@
+ -
+
+
移动
+ 
+
+
+ -
+
+
下移2
+ 
+
+
+ -
+
+
上移2
+ 
+
+
+ -
+
+
下移
+ 
+
+
+ -
+
+
上移
+ 
+
+
+ -
+
+
编辑
+ 
+
+
+ -
+
+
删除
+ 
+
+
+ -
+
+
选择
+ 
+
+
-
编辑
@@ -2012,6 +2060,78 @@
+ -
+
+
+ 移动
+
+ .icon-yidong
+
+
+
+ -
+
+
+ 下移2
+
+ .icon-xiayi1
+
+
+
+ -
+
+
+ 上移2
+
+ .icon-shangyi1
+
+
+
+ -
+
+
+ 下移
+
+ .icon-xiayi
+
+
+
+ -
+
+
+ 上移
+
+ .icon-shangyi
+
+
+
+ -
+
+
+ 编辑
+
+ .icon-bianji5
+
+
+
+ -
+
+
+ 删除
+
+ .icon-shanchu3
+
+
+
+ -
+
+
+ 选择
+
+ .icon-xuanze
+
+
+
-
@@ -4939,6 +5059,70 @@
+ -
+
+
移动
+ #icon-yidong
+
+
+ -
+
+
下移2
+ #icon-xiayi1
+
+
+ -
+
+
上移2
+ #icon-shangyi1
+
+
+ -
+
+
下移
+ #icon-xiayi
+
+
+ -
+
+
上移
+ #icon-shangyi
+
+
+ -
+
+
编辑
+ #icon-bianji5
+
+
+ -
+
+
删除
+ #icon-shanchu3
+
+
+ -
+
+
选择
+ #icon-xuanze
+
+
-
- {/* 显示上传的图片信息 */}
diff --git a/public/react/src/common/quillForEditor/FillBlot.js b/public/react/src/common/quillForEditor/FillBlot.js
index 5e5e2aa77..07b8b4a47 100644
--- a/public/react/src/common/quillForEditor/FillBlot.js
+++ b/public/react/src/common/quillForEditor/FillBlot.js
@@ -8,19 +8,15 @@
*/
import Quill from 'quill';
let Inline = Quill.import('blots/inline');
-// const BlockEmbed = Quill.import('blots/embed');
class FillBlot extends Inline {
- static create (value) {
+ static create(value) {
const node = super.cerate(value);
- // node.classList.add('icon icon-bianji2');
- // node.setAttribute('data-fill', 'fill');
- console.log('编辑器值===》》》》》', value);
node.setAttribute('data_index', value.data_index);
- node.nodeValue = value.text;
+ node.nodeValue = value.text;
return node;
}
-
- static value (node) {
+
+ static value(node) {
return {
// dataSet: node.getAttribute('data-fill'),
data_index: node.getAttribute('data_index')
diff --git a/public/react/src/common/quillForEditor/ImageBlot.js b/public/react/src/common/quillForEditor/ImageBlot.js
index 5ff84b249..0a9bec733 100644
--- a/public/react/src/common/quillForEditor/ImageBlot.js
+++ b/public/react/src/common/quillForEditor/ImageBlot.js
@@ -17,7 +17,6 @@ export default class ImageBlot extends BlockEmbed {
const node = super.create();
node.setAttribute('alt', value.alt);
node.setAttribute('src', value.url);
- // console.log('~~~~~~~~~~~', node, value);
node.addEventListener('click', function () {
value.onclick(value.url);
}, false);
@@ -33,25 +32,14 @@ export default class ImageBlot extends BlockEmbed {
}
// 宽度和高度都不存在时,
if (!value.width && !value.height) {
- // node.setAttribute('display', 'block');
node.setAttribute('width', '100%');
}
- // node.setAttribute('style', { cursor: 'pointer' });
-
- // if (node.onclick) {
- // console.log('image 有图片点击事件======》》》》》》');
- // // node.setAttribute('onclick', node.onCLick);
- // }
- // 给图片添加点击事件
- // node.onclick = () => {
- // value.onClick && value.onClick(value.url);
- // }
return node;
}
// 获取节点值
- static value (node) {
+ static value(node) {
return {
alt: node.getAttribute('alt'),
@@ -61,7 +49,6 @@ export default class ImageBlot extends BlockEmbed {
height: node.height,
display: node.getAttribute('display'),
id: node.id,
- // style: node.style
};
}
}
diff --git a/public/react/src/common/quillForEditor/index.js b/public/react/src/common/quillForEditor/index.js
index ba37059ba..46b02b94e 100644
--- a/public/react/src/common/quillForEditor/index.js
+++ b/public/react/src/common/quillForEditor/index.js
@@ -20,16 +20,17 @@ import { fetchUploadImage } from '../../services/ojService.js';
import { getImageUrl } from 'educoder'
import ImageBlot from './ImageBlot';
import FillBlot from './FillBlot';
+import LinkBlot from './link-blot'
var Size = Quill.import('attributors/style/size');
-// const Color = Quill.import('attributes/style/color');
Size.whitelist = ['14px', '16px', '18px', '20px', false];
-var fonts = ['Microsoft-YaHei','SimSun', 'SimHei','KaiTi','FangSong'];
+var fonts = ['Microsoft-YaHei', 'SimSun', 'SimHei', 'KaiTi', 'FangSong'];
var Font = Quill.import('formats/font');
Font.whitelist = fonts; //将字体加入到白名单
window.Quill = Quill;
window.katex = katex;
Quill.register(ImageBlot);
Quill.register(Size);
+Quill.register(LinkBlot);
Quill.register(Font, true);
// Quill.register({'modules/toolbar': Toolbar});
Quill.register({
@@ -38,7 +39,7 @@ Quill.register({
// Quill.register(Color);
-function QuillForEditor ({
+function QuillForEditor({
placeholder,
readOnly,
autoFocus = false,
@@ -51,17 +52,16 @@ function QuillForEditor ({
onContentChange,
addFill, // 点击填空成功的回调
deleteFill // 删除填空,返回删除的下标
- // getQuillContent
}) {
// toolbar 默认值
const defaultConfig = [
'bold', 'italic', 'underline',
- {size: ['14px', '16px', '18px', '20px']},
- {align: []}, {list: 'ordered'}, {list: 'bullet'}, // 列表
- {script: 'sub'}, {script: 'super'},
+ { size: ['14px', '16px', '18px', '20px'] },
+ { align: [] }, { list: 'ordered' }, { list: 'bullet' }, // 列表
+ { script: 'sub' }, { script: 'super' },
{ 'color': [] }, { 'background': [] },
- { 'font': []},
- {header: [1,2,3,4,5,false]},
+ { 'font': [] },
+ { header: [1, 2, 3, 4, 5, false] },
'blockquote', 'code-block',
'link', 'image', 'video',
'formula',
@@ -77,7 +77,6 @@ function QuillForEditor ({
// 文本内容变化时
const handleOnChange = content => {
- // getQuillContent && getQuillContent(quill);
onContentChange && onContentChange(content, quill);
};
@@ -86,9 +85,7 @@ function QuillForEditor ({
const bindings = {
tab: {
key: 9,
- handler: function () {
- console.log('调用了tab=====>>>>');
- }
+ handler: function () { }
},
backspace: {
key: 'Backspace',
@@ -104,11 +101,10 @@ function QuillForEditor ({
* index: 删除元素的位置
* length: 删除元素的个数
*/
- const {index, length} = range;
+ const { index, length } = range;
const _start = length === 0 ? index - 1 : index;
const _length = length || 1;
let delCtx = this.quill.getText(_start, _length); // 删除的元素
- // aa
const reg = /▁/g;
const delArrs = delCtx.match(reg);
if (delArrs) {
@@ -216,7 +212,7 @@ function QuillForEditor ({
const ops = value.ops || [];
ops.forEach((item, i) => {
if (item.insert['image']) {
- item.insert['image'] = Object.assign({}, item.insert['image'], {style: { cursor: 'pointer' }, onclick: (url) => showUploadImage(url)});
+ item.insert['image'] = Object.assign({}, item.insert['image'], { style: { cursor: 'pointer' }, onclick: (url) => showUploadImage(url) });
}
});
}
@@ -225,7 +221,7 @@ function QuillForEditor ({
if (!deepEqual(previous, current)) {
setSelection(quill.getSelection())
if (typeof value === 'string' && value) {
- // debugger
+ // debugger
quill.clipboard.dangerouslyPasteHTML(value, 'api');
if (autoFocus) {
quill.focus();
@@ -273,9 +269,9 @@ function QuillForEditor ({
// 返回结果
return (
-
+
);
}
diff --git a/public/react/src/common/quillForEditor/link-blot.js b/public/react/src/common/quillForEditor/link-blot.js
new file mode 100644
index 000000000..8f508dd34
--- /dev/null
+++ b/public/react/src/common/quillForEditor/link-blot.js
@@ -0,0 +1,21 @@
+import Quill from "quill";
+const Inline = Quill.import('blots/inline');
+
+export default class LinkBlot extends Inline {
+ static create(value) {
+ let node = super.create()
+ let rs = value
+ if (rs.indexOf('http://') < 0) {
+ rs = 'http://' + rs
+ }
+ node.setAttribute('href', rs)
+ node.setAttribute('target', '_blank')
+ return node;
+ }
+
+ static formats(node) {
+ return node.getAttribute('href');
+ }
+}
+LinkBlot.blotName = 'link'
+LinkBlot.tagName = 'a'
\ No newline at end of file
diff --git a/public/react/src/modules/courses/Index.js b/public/react/src/modules/courses/Index.js
index dc935ab1c..8a21e76da 100644
--- a/public/react/src/modules/courses/Index.js
+++ b/public/react/src/modules/courses/Index.js
@@ -10,7 +10,7 @@ import { CNotificationHOC } from './common/CNotificationHOC'
import {ImageLayerOfCommentHOC} from '../page/layers/ImageLayerOfCommentHOC'
import "./css/Courses.css"
//引入对应跳转的组件
-
+//里面有资源
const ListPageIndex = Loadable({
loader: () => import('./ListPageIndex'),
loading:Loading,
@@ -508,12 +508,16 @@ class CoursesIndex extends Component{
}
>
{/*视频列表*/}
-
+
()
+ }
+ >
()
}
- >
+ >
{/* 资源列表页 */}
{/*视频列表*/}
-
+
()
+ }
+ >
()
diff --git a/public/react/src/modules/courses/Resource/Fileslistitem.js b/public/react/src/modules/courses/Resource/Fileslistitem.js
index 53f607b2e..cb2198486 100644
--- a/public/react/src/modules/courses/Resource/Fileslistitem.js
+++ b/public/react/src/modules/courses/Resource/Fileslistitem.js
@@ -1,6 +1,6 @@
-import React,{ Component } from "react";
-import { WordsBtn } from 'educoder';
-import {Tooltip,message} from 'antd';
+import React, {Component} from "react";
+import {WordsBtn} from 'educoder';
+import {Tooltip, message} from 'antd';
import {Link} from 'react-router-dom';
import {getImageUrl} from 'educoder';
import axios from 'axios'
@@ -10,25 +10,40 @@ import CoursesListType from '../coursesPublic/CoursesListType';
import Showoldfiles from "../coursesPublic/Showoldfiles";
import Modals from '../../modals/Modals';
-class Fileslistitem extends Component{
- constructor(props){
+class Fileslistitem extends Component {
+ constructor(props) {
super(props);
- this.state = {
-
- }
+ this.state = {}
}
- settingList=()=>{
- let {discussMessage}=this.props
+ settingList = (bools) => {
+ let {discussMessage} = this.props
this.setState({
- discussMessageid:discussMessage.id
+ discussMessageid: discussMessage.id
})
- this.props.Settingtypes(discussMessage.id)
- }
+ if (bools === true) {
+ this.props.Settingtypes(discussMessage.id)
+ } else {
+ this.props.Settingtypess(discussMessage.id,discussMessage.title,discussMessage.link)
+ }
- showfiles=(list)=>{
- if(this.props.checkIfLogin()===false){
+ }
+ //外链
+ showfiless = (url,id) => {
+ window.open(url)
+ let urls=`/files/${id}/update_visits.json`;
+ axios.post(urls,{
+ }).then((result)=>{
+ if(result.data.status===0){
+ this.props.Updateresourcepage()
+ }else{
+ this.props.showNotification(result.data.message);
+ }
+ })
+ }
+ showfiles = (list) => {
+ if (this.props.checkIfLogin() === false) {
this.props.showLoginDialog()
return
}
@@ -43,21 +58,21 @@ class Fileslistitem extends Component{
// return
// }
- if(list.is_history_file===false){
+ if (list.is_history_file === false) {
// this.props.DownloadFileA(list.title,list.url)
//window.location.href=list.url;
window.open(list.url, '_blank');
- }else{
- let {discussMessage,coursesId}=this.props
- let file_id=discussMessage.id
- let url="/files/"+file_id+"/histories.json"
- axios.get(url,{
- params:{
- course_id:coursesId
+ } else {
+ let {discussMessage, coursesId} = this.props
+ let file_id = discussMessage.id
+ let url = "/files/" + file_id + "/histories.json"
+ axios.get(url, {
+ params: {
+ course_id: coursesId
},
- }).then((result)=>{
+ }).then((result) => {
- if(result.data.attachment_histories.length===0){
+ if (result.data.attachment_histories.length === 0) {
// if(result.data.is_pdf===true){
// this.props.ShowOnlinePdf(result.data.url)
// //预览pdf
@@ -66,64 +81,66 @@ class Fileslistitem extends Component{
// }
// this.props.DownloadFileA(result.data.title,result.data.url)
window.open(list.url, '_blank');
- }else{
+ } else {
this.setState({
- Showoldfiles:true,
- allfiles:result.data
+ Showoldfiles: true,
+ allfiles: result.data
})
}
- }).catch((error)=>{
+ }).catch((error) => {
console.log(error)
})
}
}
- closaoldfilesprops=()=>{
+ closaoldfilesprops = () => {
this.setState({
- Showoldfiles:false,
+ Showoldfiles: false,
})
}
onDelete = (id) => {
this.setState({
- Modalstype:true,
- Modalstopval:"是否确认删除?",
- ModalCancel:this.cancelmodel,
- ModalSave:()=>this.savedelete(id),
+ Modalstype: true,
+ Modalstopval: "是否确认删除?",
+ ModalCancel: this.cancelmodel,
+ ModalSave: () => this.savedelete(id),
})
}
- cancelmodel=()=>{
+ cancelmodel = () => {
this.setState({
- Modalstype:false,
- Loadtype:false,
- Modalstopval:"",
- ModalCancel:"",
- ModalSave:"",
- checkBoxValues:[],
+ Modalstype: false,
+ Loadtype: false,
+ Modalstopval: "",
+ ModalCancel: "",
+ ModalSave: "",
+ checkBoxValues: [],
})
}
- savedelete=(id)=>{
+ savedelete = (id) => {
this.setState({
- Modalstype:false,
+ Modalstype: false,
})
const cid = this.props.match.params.coursesId
const url = `/files/bulk_delete.json`;
- axios.delete(url, { data: {
- course_id:cid,
+ axios.delete(url, {
+ data: {
+ course_id: cid,
ids: [id],
- }})
+ }
+ })
.then((response) => {
if (response.data.status == 0) {
//Modalstopval:response.data.message,
@@ -132,11 +149,11 @@ class Fileslistitem extends Component{
this.setState({
// Modalstype:true,
// Modalstopval:"删除成功",
- ModalsBottomval:"",
+ ModalsBottomval: "",
// ModalSave:this.cancelmodel,
// Loadtype:true,
- checkBoxValues:[],
- checkAllValue:false
+ checkBoxValues: [],
+ checkAllValue: false
})
this.props.showNotification("删除成功");
@@ -147,28 +164,30 @@ class Fileslistitem extends Component{
});
}
- eventStop = (event) =>{
+ eventStop = (event) => {
event.stopPropagation()
}
- render(){
+ render() {
- const { checkBox,
- discussMessage,index
+ const {
+ checkBox,
+ discussMessage, index
} = this.props;
- return(
+ let bools = discussMessage.link && discussMessage.link ? false : true;
+ return (
{/*提示*/}
- {this.state.Modalstype&&this.state.Modalstype===true?
:""}
+ /> : ""}
- window.$(`.sourceitem${index} input`).click() }>
-
this.eventStop(event)}>
+ window.$(`.sourceitem${index} input`).click()}>
+
-
-
资源描述 :{discussMessage.description===null?"暂无描述":discussMessage.description}
+
资源描述 :{discussMessage.description === null ? "暂无描述" : discussMessage.description}
{/*
*/}
{/*/!**!/*/}
{/**/}
@@ -365,4 +466,5 @@ class Fileslistitem extends Component{
)
}
}
+
export default Fileslistitem;
diff --git a/public/react/src/modules/courses/Resource/index.js b/public/react/src/modules/courses/Resource/index.js
index 8187cd5af..787865219 100644
--- a/public/react/src/modules/courses/Resource/index.js
+++ b/public/react/src/modules/courses/Resource/index.js
@@ -6,6 +6,8 @@ import Modals from '../../modals/Modals';
import Sendtofilesmodal from "../coursesPublic/SendToFilesModal";
import Selectresource from "../coursesPublic/SelectResource";
import Sendresource from "../coursesPublic/sendResource";
+import SendResources from "../coursesPublic/sendResources";
+
import Selectsetting from "../coursesPublic/SelectSetting";
import HomeworkModal from "../coursesPublic/HomeworkModal";
import Fileslistitem from './Fileslistitem';
@@ -34,12 +36,16 @@ class Fileslists extends Component{
name:"",
sendTotype:false,
Accessoryvisible:false,
- discussMessageid:undefined,
+ Addanexternallink:false,
+ Exterchainname:"添加外链",
+ discussMessageid:undefined,
course_modules:undefined,
has_course_groups:false,
course_is_public:undefined,
isSpin:false,
- course_second_categories:[]
+ course_second_categories:[],
+ title: "",
+ link: ""
}
}
@@ -229,16 +235,15 @@ class Fileslists extends Component{
filesId:list.id,
name:list.name,
course_is_public:result.data.data.course_is_public,
- isSpin:false,
+
page:page
})
}
}
- }else{
- this.setState({
+ }
+ this.setState({
isSpin:false
})
- }
}).catch((error)=>{
console.log(error)
this.setState({
@@ -570,8 +575,48 @@ class Fileslists extends Component{
})
}
+ //添加外链资源设置
+ sendResourcessls = (ints,bool) => {
+ if(bool===true){
+
+ if(ints===1){
+ this.setState({
+ Addanexternallink:true,
+ Exterchainname:"添加外链"
+ })
+
+ }else{
+ this.setState({
+ Addanexternallink:true,
+ Exterchainname:"资源设置"
+ })
+
+ }
+
+
+ }else{
+ this.setState({
+ Addanexternallink:false,
+ title: "",
+ link: "",
+ discussMessageid:null,
+ })
+ if(ints===1){
+ this.Updateresourcepage();
+ }
+
+ }
+
+ }
+
+
+ Updateresourcepage=()=>{
+ let{pagesize,tagname,searchValue,page,sort,sorttype,coursesecondcategoryid}=this.state;
+ this.getfileslist(pagesize,page,tagname,searchValue,sort,sorttype,coursesecondcategoryid);
+ }
- Cancelvisible=()=>{
+
+ Cancelvisible=()=>{
this.setState({
Accessoryvisible:false,
@@ -587,6 +632,17 @@ class Fileslists extends Component{
})
}
+ Settingtypess=(id,title,link)=>{
+ debugger
+ this.setState({
+ Addanexternallink:true,
+ Exterchainname:"资源设置",
+ discussMessageid:id,
+ title: title,
+ link: link
+ })
+ }
+
moveTos=(id)=>{
let {checkBoxValues} = this.state;
@@ -729,7 +785,11 @@ class Fileslists extends Component{
course_is_public,
filesId,
child,
- sort
+ sort,
+ Addanexternallink,
+ Exterchainname,
+ title,
+ link,
} = this.state;
let category_id= this.props.match.params.category_id;
@@ -781,7 +841,7 @@ class Fileslists extends Component{
loadtype={Loadtype}
/>:""}
{
- shixunmodal===true||Accessoryvisible===true||Settingtype===true?
+
+ {
+ list && list.map((item,key)=>{
+ return(
+
+ {item.name}
+
+ )
+ })
+ }
+
+
+
+
+ )
+ }
+}
+export default MoveBox;
\ No newline at end of file
diff --git a/public/react/src/modules/courses/Video/Video.js b/public/react/src/modules/courses/Video/Video.js
index 0827c74e0..b082ef25a 100644
--- a/public/react/src/modules/courses/Video/Video.js
+++ b/public/react/src/modules/courses/Video/Video.js
@@ -5,7 +5,8 @@ import { NoneData, ActionBtn } from 'educoder';
import VideoUploadList from '../../user/usersInfo/video/VideoUploadList';
import VideoInReviewItem from '../../user/usersInfo/video/VideoInReviewItem';
import HeadlessModal from '../../user/usersInfo/common/HeadlessModal';
-import EditVideoModal from '../../user/usersInfo/video/EditVideoModal'
+import EditVideoModal from '../../user/usersInfo/video/EditVideoModal';
+import MoveBox from './MoveBox';
import ClipboardJS from 'clipboard'
import VideoPanel from './video-play'
@@ -28,7 +29,10 @@ class Video extends Component {
videoId: undefined,
videoVisible: false,
- visible: false
+ visible: false,
+
+ moveVisible:false,
+ moveVideoId:undefined
}
}
@@ -69,7 +73,7 @@ class Video extends Component {
// 编辑成功后回调的方法
editSuccess = () => {
- this.props.showNotification("视频名称修改成功!");
+ this.props.showNotification("视频信息修改成功!");
const { listFunc, page } = this.props;
listFunc && listFunc(page);
}
@@ -77,7 +81,8 @@ class Video extends Component {
onEditVideo = (item) => {
let videoId = {
videoId: item.id,
- title: item.title
+ title: item.title,
+ link:item.link
}
this.setState({
videoId,
@@ -142,7 +147,8 @@ class Video extends Component {
const url = `/courses/${CourseId}/delete_course_video.json`;
axios.delete(url, {
params: {
- video_id: item.id
+ video_id: item.id,
+ is_link:item.link ? true : undefined
}
}).then(result => {
if (result) {
@@ -161,9 +167,25 @@ class Video extends Component {
});
}
+ // 移动到
+ moveVideo=(id)=>{
+ this.setState({
+ moveVisible:true,
+ moveVideoId:id
+ })
+ }
+ setMoveVisible=(flag)=>{
+ this.setState({
+ moveVisible:flag,
+ moveVideoId:undefined
+ })
+ }
+
render() {
- const { visible, videoVisible, videoId } = this.state;
+ const { visible, videoVisible, videoId , moveVisible , moveVideoId } = this.state;
const CourseId = this.props.match.params.coursesId;
+ const VID=this.props.match.params.videoId;
+
const login = this.props.user && this.props.user.login;
const _inputValue = videoId && this.getCopyText(videoId.file_url, videoId.cover_url);
@@ -171,13 +193,21 @@ class Video extends Component {
const { videos, upload, uploadVideo, videoData, changePage, pageSize, page } = this.props;
- const operation = admin || business || (is_teacher && this.props.checkIfProfessionalCertification())
+ const operation = admin || business;
return (
+
this.setMoveVisible(flag)}
+ successFunc={()=>uploadVideo()}
+ id={moveVideoId}
+ >
{
upload ?
- uploadVideo()}>
+ uploadVideo()}>
:
{
@@ -215,8 +245,9 @@ class Video extends Component {
onEditVideo={this.onEditVideo}
onMaskClick={this.onMaskClick}
getCopyText={this.getCopyText}
- operation={operation}
+ operation={operation || item.user_id === user_id}
deleteVideo={(admin || item.user_id === user_id) ? this.deleteVideo : undefined}
+ moveVideo={videoData && videoData.has_category && (operation || item.user_id === user_id) ? ()=>this.moveVideo(item.id):undefined}
>
)
diff --git a/public/react/src/modules/courses/Video/VideoIndex.js b/public/react/src/modules/courses/Video/VideoIndex.js
index d58a2f187..ff1129666 100644
--- a/public/react/src/modules/courses/Video/VideoIndex.js
+++ b/public/react/src/modules/courses/Video/VideoIndex.js
@@ -1,13 +1,13 @@
import React,{ Component } from "react";
+import { WordsBtn,on, trigger ,publicSearchs} from 'educoder';
import { Menu, Spin } from 'antd';
-import { WordsBtn } from 'educoder';
import axios from 'axios';
import Videos from './Video';
import Lives from './Live';
import LivesNew from './LiveNew';
-
+import VideoLink from './VideoLink';
import './video.css';
import '../css/Courses.css';
@@ -28,6 +28,7 @@ class VideoIndex extends Component{
upload:false,
videos:undefined,
videoData:undefined,
+ otherLinkVisible:false,
type:"video",
isSpining:false,
@@ -37,6 +38,7 @@ class VideoIndex extends Component{
liveId:undefined,
liveVisible:false
+
}
}
@@ -69,6 +71,15 @@ class VideoIndex extends Component{
this.checkType("video",page);
}
}
+ componentDidUpdate = (prevProps) => {
+ if(this.props.match.params.videoId !== prevProps.match.params.videoId ){
+ this.setState({
+ upload:false
+ })
+ const { page } = this.state;
+ this.checkType("video",page);
+ }
+ }
// 获取直播列表
getLiveList=(page)=>{
const CourseId=this.props.match.params.coursesId;
@@ -93,12 +104,13 @@ class VideoIndex extends Component{
// 获取视频列表
getList=(page)=>{
- const CourseId=this.props.match.params.coursesId;
- const fetchUrl = `/courses/${CourseId}/course_videos.json`;
+ const { coursesId , videoId }=this.props.match.params;
+ const fetchUrl = `/courses/${coursesId}/course_videos.json`;
axios.get(fetchUrl, {
params: {
page,
limit: PAGE_SIZE,
+ category_id:videoId
}
})
.then((response) => {
@@ -141,6 +153,7 @@ class VideoIndex extends Component{
this.setVisible(true);
}
uploadVideo=(upload)=>{
+
this.setState({
upload,
isSpining:true
@@ -200,12 +213,45 @@ class VideoIndex extends Component{
})
this.setliveVisibel(true);
}
+
+ // 新增目录
+ addDir=()=>{
+ let {videoData}=this.state;
+ trigger('videoAdd', parseInt(videoData.course_module_id));
+ }
+ // 目录重命名
+ editDir=(name,id)=>{
+ let data={id,name,update:this.getList}
+ trigger('editVideo',data);
+ }
+ // 增加外链
+ setLinkeVisible=(flag,refresh)=>{
+ this.setState({
+ otherLinkVisible:flag
+ })
+ if(refresh){
+ const { page } = this.state;
+ this.getList(page);
+ }
+ }
render(){
- const { videos , upload , videoData , type , liveData , lives , page , liveVisible , isSpining , liveId } = this.state;
+ const { videos , upload , videoData , type , liveData , lives , page , liveVisible , isSpining , liveId , otherLinkVisible } = this.state;
const { admin , is_teacher , business } = this.props.user;
- // console.log("p",this.props);
+ const { coursesId , videoId }=this.props.match.params;
+
+ const {course_identity} = this.props.coursedata;
+ const flag = parseInt(course_identity) < 5;
+ const newOperation = flag;
+ const new_upload = flag && (is_teacher && this.props.checkIfProfessionalCertification());
return(
+
-
-
-
{
- (admin || is_teacher || business) &&
-
-
- {
- type === "video" ?
-
+ videoData && videoData.category_name && type === "video" ?
+ {videoData.category_name}
+ :
+
+
+
+ }
+ -
+ {
+ type === "video" ?
+
+ {
+ newOperation ?
+
{
- upload ?
- this.uploadVideo(false)}>取消
+ videoId ?
+ this.editDir(videoData && videoData.category_name,videoId)} className={"mr30 font-16"}>目录重命名
:
- 上传视频
+ 新建目录
}
-
- :
- 添加直播
- }
-
- }
+ this.setLinkeVisible(true)}>增加外链
+ :""
+ }
+ {
+ new_upload ?
+
+ {
+ upload ?
+ this.uploadVideo(false)}>取消
+ :
+ 上传视频
+ }
+ :""
+ }
+
+ :
+ 添加直播
+ }
+
diff --git a/public/react/src/modules/courses/Video/VideoLink.js b/public/react/src/modules/courses/Video/VideoLink.js
new file mode 100644
index 000000000..3aa8b6725
--- /dev/null
+++ b/public/react/src/modules/courses/Video/VideoLink.js
@@ -0,0 +1,96 @@
+import React,{ Component } from "react";
+import { Modal , Form , Input , Spin , Select , AutoComplete , DatePicker , InputNumber } from 'antd';
+import axios from 'axios';
+
+class VideoLink extends Component{
+
+ componentDidUpdate=(prevProps)=>{
+ if(prevProps.visible !== this.props.visible){
+ this.props.form.setFieldsValue({
+ name:undefined,
+ link:undefined
+ })
+ }
+ }
+ cancelNew=()=>{
+ const { setVisible } = this.props;
+ setVisible && setVisible(false);
+ }
+ validateDesc= (rule, value, callback) => {
+ if(!value){
+ callback();
+ }
+ if (value.length > 60) {
+ callback("视频名称不能超过60个字!");
+ }else{
+ callback();
+ }
+ }
+ // 提交
+ handleSubmit=()=>{
+ this.props.form.validateFields((err, values) => {
+ if(!err){
+ const { coursesId , videoId } = this.props;
+ const url = `/courses/${coursesId}/course_videos.json`;
+ axios.post(url,{
+ ...values,
+ category_id:videoId
+ }).then(result=>{
+ if(result){
+ const { notification , setVisible } = this.props;
+ notification && notification('视频外链新增成功!');
+ setVisible && setVisible(false,true);
+ }
+ }).catch(error=>{
+ console.log(error);
+ })
+ }
+ })
+ }
+ render(){
+ const {getFieldDecorator} = this.props.form;
+
+ const { visible } = this.props;
+ const layout = {
+ labelCol: { span: 5 },
+ wrapperCol: { span: 19 },
+ }
+ return(
+
+
+
+ )
+ }
+}
+const WrappedVideoLink = Form.create({name: 'VideoLink'})(VideoLink);
+export default WrappedVideoLink;
\ No newline at end of file
diff --git a/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js b/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js
index 999ae4e15..75b788e16 100644
--- a/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js
+++ b/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js
@@ -61,6 +61,8 @@ class Coursesleftnav extends Component{
sandiantypes:undefined,
antIcon:false,
chapterupdate:false,
+
+ successFunc:undefined
}
}
@@ -138,61 +140,68 @@ class Coursesleftnav extends Component{
off('shixun_homeworkadd',this.addshixunchild)
off('editshixunname',this.editshixunchild)
off('editshixunmainname',this.editshixunmainname)
+ off('videoAdd',this.addVideo)
+ off('editVideo',this.editVideo)
}
addshixunchild=(e, data)=>{
- this.Navmodalnames(e,1,"shixun_homework",data)
+ this.Navmodalnames(e,1,"shixun_homework",data);
}
editshixunchild=(e, data)=>{
- this.Navmodalnames(e,4,"editSecondname",data.id,data.name)
+ this.Navmodalnames(e,4,"editSecondname",data.id,data.name);
}
editshixunmainname=(e, data)=>{
- this.Navmodalnames(e,3,"editname",data.id,data.name)
+ this.Navmodalnames(e,3,"editname",data.id,data.name);
}
boardAddListener = (e, data) => {
- this.Navmodalnames(e,6,"board", data)
+ this.Navmodalnames(e,6,"board", data);
+ }
+ addVideo=(e,id)=>{
+ this.Navmodalnames(e,1,"video",id);
+ }
+ editVideo=(e,data)=>{
+ this.setState({
+ successFunc:data.update
+ })
+ this.Navmodalnames(e,4,"editSecondname",data.id,data.name);
}
boardRenameListener = (e, data) => {
- this.Navmodalnames(e,7,"editSecondname", data.category_id, data.category_name)
+ this.Navmodalnames(e,7,"editSecondname", data.category_id, data.category_name);
}
groupAddListener = (e, data) => {
- this.Navmodalnames(e,2,"course_group", data)
+ this.Navmodalnames(e,2,"course_group", data);
}
groupRenameListener = (e, data) => {
- this.Navmodalnames(e,5,"editSecondname", data.id, data.name)
+ this.Navmodalnames(e,5,"editSecondname", data.id, data.name);
}
attachmentAddlog=(e,data)=>{
- this.Navmodalnames(e,1,"attachment",data)
+ this.Navmodalnames(e,1,"attachment",data);
}
flieseditDir=(e, data)=>{
- this.Navmodalnames(e,4,"editSecondname",data.id,data.name)
+ this.Navmodalnames(e,4,"editSecondname",data.id,data.name);
}
componentDidMount() {
-
this.setState({
url:this.props.match.url
})
- on('boardAdd', this.boardAddListener)
- on('boardRename', this.boardRenameListener)
- on('groupAdd', this.groupAddListener)
- on('groupRename', this.groupRenameListener)
- on('attachmentAddlog', this.attachmentAddlog)
- on('flieseditDir', this.flieseditDir)
- on('shixun_homeworkadd',this.addshixunchild)
- on('editshixunname',this.editshixunchild)
- on('editshixunmainname',this.editshixunmainname)
+ on('boardAdd', this.boardAddListener);
+ on('boardRename', this.boardRenameListener);
+ on('groupAdd', this.groupAddListener);
+ on('groupRename', this.groupRenameListener);
+ on('attachmentAddlog', this.attachmentAddlog);
+ on('flieseditDir', this.flieseditDir);
+ on('shixun_homeworkadd',this.addshixunchild);
+ on('editshixunname',this.editshixunchild);
+ on('editshixunmainname',this.editshixunmainname);
+ on('videoAdd',this.addVideo);
+ on('editVideo',this.editVideo)
- // this.props.updataleftNavfun();
- // this.props.getleftNavid && this.props.getleftNavid("shixun_homework");
- // const position =parseInt(this.props.match.params.position);
let courstype=this.props.match.url;
- courstype = courstype.split('/');
-
- courstype=courstype[3];
+ courstype = courstype.split('/');
- // console.log(courstype)
+ courstype=courstype[3];
const query =this.props.location.search;
@@ -520,7 +529,9 @@ class Coursesleftnav extends Component{
// loadtype:true,
// NavmodalValue:""
// })
- navidtype=true
+ navidtype=true;
+ const { successFunc } = this.state;
+ successFunc && successFunc(1);
}
saveNavmodapost=(url,value,positiontype,coursesId)=>{
@@ -658,32 +669,28 @@ class Coursesleftnav extends Component{
updatadeleteSecondary=(url)=>{
this.props.updataleftNavfun();
- // this.setState({
- // ModalsType:true,
- // Modalstopval:"删除成功",
- // loadtype:true,
- // })
- // notification.open({
- // message: "删除成功",
- // });
-
- // this.props.history.replace(url);
- window.location.href = url;
+ this.setState({
+ ModalsType:false,
+ Modalstopval:"",
+ loadtype:false,
+ })
+ notification.open({
+ message: "删除成功",
+ });
+
+ this.props.history.replace(url);
+
+ // window.location.href = url;
}
deletenavchilds=(url,mainurl)=>{
- this.setState({
- antIcon:true
- })
+ console.log(this.props);
+ this.setState({
+ antIcon:true
+ })
axios.delete(url).then((result)=>{
if(result.data.status===0){
-
- if(mainurl===undefined){
- this.updatadeleteSecondary(result.data.right_url)
- }else{
- this.updatadeleteSecondary(mainurl)
- }
-
+ this.updatadeleteSecondary(mainurl || result.data.right_url);
}
}).catch((error)=>{
console.log(error)
@@ -698,8 +705,8 @@ class Coursesleftnav extends Component{
ModalsType:true,
Modalstopval:"该目录下的内容将被移动到父目录,",
ModalsBottomval:"是否确认删除?",
- ModalSave:()=>this.deletenavchilds(url),
-
+ ModalSave:()=>this.deletenavchilds(url,mainurl),
+ loadtype:false
})
}else if(type===2){
@@ -709,7 +716,7 @@ class Coursesleftnav extends Component{
Modalstopval:"该分班的学生将被移动到“未分班”,",
ModalsBottomval:"是否确认删除?",
ModalSave:()=>this.deletenavchilds(url),
-
+ loadtype:false
})
}else if(type===3){
let url="/boards/"+id+".json"
@@ -718,7 +725,7 @@ class Coursesleftnav extends Component{
Modalstopval:"该目录下的内容将被移动到父目录,",
ModalsBottomval:"是否确认删除?",
ModalSave:()=>this.deletenavchilds(url,mainurl),
-
+ loadtype:false
})
}
@@ -838,6 +845,8 @@ class Coursesleftnav extends Component{
{item.type==="shixun_homework"?this.Navmodalnames(e,1,"shixun_homework",item.id)}>新建目录
:""}
{/*资源*/}
{item.type==="attachment"?this.Navmodalnames(e,1,"attachment",item.id)}>新建目录
:""}
+ {/* 视频 */}
+ {item.type==="video"?this.Navmodalnames(e,1,"video",item.id)}>新建目录
:""}
{/*毕业设计*/}
{/*{item.type==="graduation"?this.Navmodalnames(1,"attachment",item.id)}>添加目录
:""}*/}
{/*讨论区*/}
@@ -872,6 +881,9 @@ class Coursesleftnav extends Component{
{/*讨论区*/}
{item.type==="board"?this.Navmodalnames(e,7,"editSecondname",iem.category_id,iem.category_name)}>重命名
:""}
{item.type==="board"?this.deleteSecondary(e,3,iem.category_id,item.category_url)}>删除
:""}
+ {/*视频*/}
+ {item.type==="video"?this.Navmodalnames(e,4,"editSecondname",iem.category_id,iem.category_name)}>重命名
:""}
+ {item.type==="video"?this.deleteSecondary(e,1,iem.category_id,item.category_url)}>删除
:""}
)
};
diff --git a/public/react/src/modules/courses/coursesPublic/sendResources.js b/public/react/src/modules/courses/coursesPublic/sendResources.js
new file mode 100644
index 000000000..75726a51f
--- /dev/null
+++ b/public/react/src/modules/courses/coursesPublic/sendResources.js
@@ -0,0 +1,585 @@
+import React,{ Component } from "react";
+import { Modal,Checkbox,Upload,Button,Icon,message,DatePicker,Select,Tooltip,Radio,Input} from "antd";
+import axios from 'axios';
+import Modals from '../../modals/Modals';
+import {getUploadActionUrl,handleDateString,appendFileSizeToUploadFileAll} from 'educoder';
+import locale from 'antd/lib/date-picker/locale/zh_CN';
+import moment from 'moment';
+const CheckboxGroup = Checkbox.Group;
+const Option = Select.Option;
+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: () => [0, 60],
+ };
+}
+
+function disabledDate(current) {
+ return current && current < moment().endOf('day').subtract(1, 'days');
+}
+
+
+const dateFormat="YYYY-MM-DD HH:mm";
+class sendResources extends Component{
+ constructor(props){
+ super(props);
+ this.state={
+ group_ids:[],
+ fileList:[],
+ Modalstype:false,
+ Modalstopval:"",
+ ModalCancel:"",
+ ModalSave:"",
+ fileListtype:false,
+ loadtype:false,
+ is_public:false,
+ datatime:undefined,
+ resourcesname:"",
+ resourceurl:"",
+ addonAfteronelens3:0,
+ // moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),
+ course_group_publish_times:[
+ {
+ course_group_id : undefined,
+ publish_time :""
+ }],
+ course_groups:undefined,
+ course_groups_count:undefined,
+ Radiovalue:0,
+ Radiovaluetype:false,
+ resourceurlbool:false,
+ resourcesnamebool:false,
+ }
+ }
+
+
+ componentDidMount() {
+ let {discussMessageid} =this.props;
+ try {
+ this.setState({
+ resourcesname:this.props.title,
+ resourceurl:this.props.link,
+ addonAfteronelens3:this.props.title.length,
+ })
+ }catch (e) {
+
+ }
+ console.log(discussMessageid);
+ try {
+ if(discussMessageid){
+ this.getalldata();
+ }
+ }catch (e) {
+
+ }
+
+
+ }
+
+ getalldata=()=>{
+ let {discussMessageid} =this.props;
+ let course_id=this.props.course_id;
+ let url="/files/"+discussMessageid+".json";
+ axios.get(url, {
+ params:{
+ course_id:course_id,
+ }
+ })
+ .then((response) => {
+ if(response.status===200){
+ this.setState({
+ datalist:response.data,
+ description: response.data.description,
+ is_public:response.data.is_public,
+ datatime:response.data.publish_time,
+ Radiovalue:response.data.delay_publish==false?0:1,
+ //attachment_histories:response.data.attachment_histories
+ })
+
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+
+ }
+ //勾选实训
+ shixunhomeworkedit=(list)=>{
+
+ this.setState({
+ group_ids:list
+ })
+
+ }
+ // 附件相关 START
+ handleChange = (info) => {
+ console.log(info)
+
+ if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
+ let fileList = info.fileList;
+ if (info.file.status != "removed") {
+ this.setState({
+ fileList: appendFileSizeToUploadFileAll(fileList),
+ fileListtype: true
+ });
+ } else {
+ this.setState({
+ fileList: appendFileSizeToUploadFileAll(fileList),
+ });
+ }
+ }
+ }
+
+ onAttachmentRemove = (file) => {
+ if(!file.percent || file.percent == 100){
+ const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
+ axios.delete(url, {
+ })
+ .then((response) => {
+ if (response.data) {
+ const { status } = response.data;
+ if (status == 0) {
+ this.setState({
+ fileListtype:false,
+ fileList:[]
+ })
+ }
+
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ this.setState({
+ fileListtype:false,
+ })
+ }else{
+ this.setState({
+ fileListtype:false,
+ fileList:[]
+ })
+ }
+ }
+
+ ModalCancelModalCancel=()=>{
+ this.setState({
+ Modalstype:false,
+ Modalstopval:"",
+ ModalSave:this.ModalCancelModalCancel,
+ loadtype:false
+ })
+ this.props.Cancel()
+ }
+ Saves=()=>{
+
+
+ let {resourcesname,resourceurl,description,is_public,datatime,Radiovalue} =this.state;
+ const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
+
+ if (!reg.test(resourcesname)) {
+ this.setState({
+ resourcesnamebool:true
+ })
+ return;
+ }
+ if (!reg.test(resourceurl)) {
+ this.setState({
+ resourceurlbool:true
+ })
+ return;
+ }
+
+
+
+ if(this.state.Radiovalue===1){
+ if(datatime===undefined||datatime===null||datatime=== ""){
+ this.setState({
+ Radiovaluetype:true
+ })
+ return
+ }else{
+ this.setState({
+ Radiovaluetype:false
+ })
+ }
+ }
+
+
+
+ if(description===undefined){
+
+ }else if(description.length>100){
+
+ this.setState({
+ descriptiontype:true
+ })
+ return
+ }
+
+ if(this.props.Exterchainname==="资源设置"){
+ //设置
+ let coursesId=this.props.match.params.coursesId;
+ let attachmentId=this.props.attachmentId;
+ let url="/files/"+this.props.discussMessageid+".json";
+
+ axios.put(url,{
+ name:resourcesname,
+ link:resourceurl,
+ course_id:coursesId,
+ course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId,
+ is_public:is_public,
+ publish_time:Radiovalue===1?datatime===undefined? undefined:datatime:undefined,
+ description:description,
+ delay_publish:Radiovalue,
+ }).then((result)=>{
+ if(result.data.status===0){
+ this.ModalCancelModalCancel();
+ this.props.updataleftNavfun();
+ this.props.showNotification("设置资源成功");
+ this.props.setupdate(1,false)
+ }else{
+ this.props.showNotification(result.data.message);
+ }
+ })
+
+ }else{
+ let coursesId=this.props.match.params.coursesId;
+ let attachmentId=this.props.attachmentId;
+ let url="/files/upload.json";
+
+
+ axios.post(url,{
+ name:resourcesname,
+ link:resourceurl,
+ course_id:coursesId,
+ course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId,
+ is_public:is_public,
+ publish_time:Radiovalue===1?datatime===undefined? undefined:datatime:undefined,
+ description:description,
+ delay_publish:Radiovalue,
+ }).then((result)=>{
+
+
+ if(result.data.status===0){
+ this.ModalCancelModalCancel();
+ this.props.updataleftNavfun();
+ this.props.showNotification("上传资源成功");
+ this.props.setupdate(1,false)
+ }else{
+ this.props.showNotification(result.data.message);
+ }
+ })
+
+ }
+
+
+
+ }
+
+ settextarea=(e)=>{
+ this.setState({
+ description:e.target.value
+ })
+ }
+
+ onChangepublic=(e)=>{
+
+ this.setState({
+ is_public:e.target.checked
+ })
+
+ }
+
+ onChangeTimepublish= (date, dateString,key,type) => {
+ if(type===1){
+ this.setState({
+ datatime:handleDateString(dateString),
+ })
+ }else if(type===2){
+ 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({
+ Radiovalue: e.target.value,
+ });
+ }
+
+ handleChanges=(e)=>{
+ let les=e.target.value.length;
+
+ if(e.target.value.length>=61){
+
+
+ }else{
+ this.setState({
+ resourcesname:e.target.value,
+ addonAfteronelens3:les,
+ resourcesnamebool:false,
+
+ })
+
+ }
+
+ }
+
+ handleChangess=(e)=>{
+ this.setState({
+ resourceurl:e.target.value,
+ resourceurlbool:false,
+ })
+ }
+
+
+
+ render(){
+ let { newfileListtype,descriptiontype,
+ is_public,
+ datatime,
+ resourcesname,
+ resourceurl,
+ addonAfteronelens3,
+ resourceurlbool,
+ resourcesnamebool,
+ }=this.state;
+
+ const uploadProps = {
+ width: 600,
+ // showUploadList:false,
+ action: `${getUploadActionUrl()}`,
+ onChange: this.handleChange,
+ onRemove: this.onAttachmentRemove,
+ beforeUpload: (file) => {
+ // console.log('beforeUpload', file.name);
+ const isLt150M = file.size / 1024 / 1024 < 150;
+ if (!isLt150M) {
+ this.props.showNotification('文件大小必须小于150MB!');
+ }
+ return isLt150M;
+ },
+ };
+ const radioStyle = {
+ display: 'block',
+ height: '30px',
+ lineHeight: '30px',
+ };
+
+
+
+ return(
+
+ {/*提示*/}
+
+
+
+
+
+
+
+
+
+
+
+
+ 资源名称:
+
+
+
+
+ {
+ resourcesnamebool?
+
请输入资源名称
+ :
+ ""
+ }
+
+ 链接地址:
+
+
+ {
+ resourceurlbool?
+
请输入外链url
+ :
+ ""
+ }
+
+
+
+
+
+ {this.props.course_is_public===true?
+ 公开:
+ 选中,所有用户可见,否则课堂成员可见
+
+
:""}
+
+
+
+
+
+
+ 发布设置:
+
+
+ 立即发布
+
+
+
+ 延期发布
+ 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?
发布时间不能为空
:""}
+
+
+
+
+
+ )
+ }
+}
+export default sendResources;
diff --git a/public/react/src/modules/developer/newOrEditTask/index.js b/public/react/src/modules/developer/newOrEditTask/index.js
index 43cad6106..f80cece44 100644
--- a/public/react/src/modules/developer/newOrEditTask/index.js
+++ b/public/react/src/modules/developer/newOrEditTask/index.js
@@ -112,7 +112,7 @@ const NewOrEditTask = (props) => {
content: (发布后即可应用到自己管理的课堂
是否确认发布?
),
onOk() {
changePublishLoadingStatus(true);
- handlePublish(props, 'publish');
+ props.handlePublish(props, 'publish');
}
});
}
diff --git a/public/react/src/modules/user/usersInfo/video/AliyunUploaderManager.js b/public/react/src/modules/user/usersInfo/video/AliyunUploaderManager.js
index 3312473c4..ef2eaceda 100644
--- a/public/react/src/modules/user/usersInfo/video/AliyunUploaderManager.js
+++ b/public/react/src/modules/user/usersInfo/video/AliyunUploaderManager.js
@@ -73,7 +73,7 @@ function doCreateUploader (options) {
const _random = '' // Math.random().toString().substring(3, 6)+'-'
axios.post(createUrl, {
title: _random+fileName,
- file_name: _random+fileName
+ file_name: _random+fileName,
}).then((response) => {
// if (response.data.status == )
if(response){
diff --git a/public/react/src/modules/user/usersInfo/video/EditVideoModal.js b/public/react/src/modules/user/usersInfo/video/EditVideoModal.js
index 25aadd119..43486f43c 100644
--- a/public/react/src/modules/user/usersInfo/video/EditVideoModal.js
+++ b/public/react/src/modules/user/usersInfo/video/EditVideoModal.js
@@ -8,10 +8,12 @@ function EditVideoModal (props) {
const modalEl = useRef(null);
const theme = useContext(ThemeContext);
const { history, videoId, cover_url, title, created_at, isReview, onEditVideo, visible, setVisible,
- form, editSuccess } = props;
+ form, editSuccess , link } = props;
const getFieldDecorator = form.getFieldDecorator
let username = props.match.params.username
const _title = form.getFieldsValue().title;
+ const _link = form.getFieldsValue().link;
+
if(props.CourseUser){
username = props.CourseUser;
@@ -27,9 +29,14 @@ function EditVideoModal (props) {
form.validateFieldsAndScroll((err, values) => {
if (!err) {
- const url = `/users/${username}/videos/${videoId}.json`
- axios.put(url, {
- title: _title
+ const url = link?`/course_videos/${videoId}.json`:`/users/${username}/videos/${videoId}.json`;
+
+ axios.put(url, link ? {
+ name:_title,
+ link:_link
+ }:{
+ title: _title,
+ link:_link
}).then((response) => {
if (response.data) {
onCancel()
@@ -54,7 +61,7 @@ function EditVideoModal (props) {
}, [visible])
useEffect(() => {
visible && form.setFieldsValue({
- title,
+ title,link
})
}, [visible])
return (
@@ -71,10 +78,9 @@ function EditVideoModal (props) {
{
`
.exercicenewinputysl .ant-input{
- border-right: none !important;
- height: 40px !important;
- }
-
+ border-right: none !important;
+ height: 40px !important;
+ }
`
}
@@ -93,7 +99,24 @@ function EditVideoModal (props) {
)}
-
+
+ {
+ link ?
+
+
+ {getFieldDecorator('link', {
+ rules: [{
+ required: true, message: '请输入视频链接',
+ }],
+ })(
+
+ )}
+
+ :""
+ }
)
}
diff --git a/public/react/src/modules/user/usersInfo/video/InfosVideo.css b/public/react/src/modules/user/usersInfo/video/InfosVideo.css
index fd17ac49c..a28f7cf5d 100644
--- a/public/react/src/modules/user/usersInfo/video/InfosVideo.css
+++ b/public/react/src/modules/user/usersInfo/video/InfosVideo.css
@@ -142,4 +142,26 @@
.videoItem:hover{
box-shadow:0px 4px 10px 0px rgba(3,7,45,0.1);
border-radius:12px;
+}
+.otherLink{
+ position: absolute;
+ height:30px;
+ line-height: 30px;
+ padding:0px 18px;
+ background:rgba(249,117,26,1);
+ border-radius:0px 100px 100px 0px;
+ display: block;
+ left: 0;
+ top:32px;
+ color: #fff;
+ z-index:2;
+}
+.otherLinkPanel{
+ display: block;
+ position: absolute;
+ width: 100%;
+ top:0px;
+ left:0px;
+ height: 220px;
+ z-index: 1;
}
\ No newline at end of file
diff --git a/public/react/src/modules/user/usersInfo/video/VideoInReviewItem.js b/public/react/src/modules/user/usersInfo/video/VideoInReviewItem.js
index 5c0647ea1..b045f54b8 100644
--- a/public/react/src/modules/user/usersInfo/video/VideoInReviewItem.js
+++ b/public/react/src/modules/user/usersInfo/video/VideoInReviewItem.js
@@ -5,7 +5,8 @@ import axios from 'axios'
import moment from 'moment'
import playIcon from './images/play.png'
import ClipboardJS from 'clipboard'
-
+import defaultImg from './images/default.png';
+import './InfosVideo.css';
/**
cover_url: "http://video.educoder.net/f6ba49c3944b43ee98736898e31b7d88/snapshots/12da3f7df07c499b8f0fc6dc410094e9-00005.jpg"
created_at: "2019-08-12 13:48:26"
@@ -20,7 +21,7 @@ const clipboardMap = {}
function VideoInReviewItem (props) {
const theme = useContext(ThemeContext);
const { history, file_url, cover_url, title, created_at, published_at, isReview, id
- , onEditVideo, onMaskClick, getCopyText, showNotification,vv,play_duration,operation , deleteVideo} = props;
+ , onEditVideo, onMaskClick, getCopyText, showNotification,vv,play_duration,operation , deleteVideo , moveVideo ,link} = props;
useEffect(()=> {
if (!isReview) {
_clipboard = new ClipboardJS(`.copybtn_item_${id}`);
@@ -46,12 +47,16 @@ function VideoInReviewItem (props) {
return (
-

- {!isReview &&
onMaskClick(props)}>
+

+ { link ?
+
+ 外链
+
+ : ""
+ }
-
}
- {!isReview &&
+ {!isReview &&
onMaskClick(props)}>
}
+ {!isReview && !link &&
onMaskClick(props)}>

{play_duration===0?"":
累计学习时长:{play_duration} h
}
@@ -68,11 +73,19 @@ function VideoInReviewItem (props) {
{/* 2019-09-01 10:00:22 */}
- {vv===0?"":
+ {!vv || (vv && vv)===0 ? "" :
- } {vv===0?"":vv}
+ } {!vv || (vv && vv)===0?"":vv}
{ isReview != true &&
+ {
+ moveVideo &&
+
+ moveVideo(props)}
+ style={{ marginTop: '1px', display: 'inline-block'}}
+ >
+
+ }
{
deleteVideo &&
@@ -90,9 +103,13 @@ function VideoInReviewItem (props) {
>
}
-
-
-
+ {
+ !link ?
+
+
+ :""
+ }
+
}
diff --git a/public/react/src/modules/user/usersInfo/video/VideoUploadList.js b/public/react/src/modules/user/usersInfo/video/VideoUploadList.js
index 49529bdd8..7855fc39a 100644
--- a/public/react/src/modules/user/usersInfo/video/VideoUploadList.js
+++ b/public/react/src/modules/user/usersInfo/video/VideoUploadList.js
@@ -226,7 +226,7 @@ function VideoUploadList (props) {
}
function onPublish() {
// 下列这些参数只有是课堂里面上传视频才会有
- const { CourseId , CourseUser ,flag , successFunc } = props;
+ const { CourseId , CourseUser ,flag , successFunc , videoId } = props;
if (state.videos.length == 0) {
showNotification('请先上传视频')
return;
@@ -238,7 +238,8 @@ function VideoUploadList (props) {
video_id: item.videoId,
// todo
title: item.title,
- course_id:CourseId
+ course_id:CourseId,
+ category_id:videoId
}
})
}).then((response) => {
@@ -268,7 +269,6 @@ function VideoUploadList (props) {
:
上传内容协议
const protocolLine =
上传视频,即表示您已同意{urls},不得上传未经他人授权的作品
-
return (
{
}
- try {
+ let boolflad=false;
+ try {
if(ojForm.sub_discipline_id.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '课程必须选择!'
});
-
+ boolflad=true;
}else if(ojForm.timeLimit===null){
hasSuccess = false;
notification['error']({
message: '提示',
description: '时间限制必须输入!'
});
- } else if(ojForm.name.length===0){
+ boolflad=true;
+
+ } else if(ojForm.name.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '任务名称必须输入!'
});
-
+ boolflad=true;
}else if(ojForm.description.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '描述必须输入!'
});
- }
+ boolflad=true;
+ }
}catch (e) {
}
+ try {
+ if( hasSuccess === false){
+ if(boolflad===true){
+ props.changeSubmitLoadingStatus(false);
+ }
+ }
+ }catch (e) {
+
+ }
+ try {
+ if( hasSuccess === false){
+ if(boolflad===true){
+ props.changePublishLoadingStatus(false);
+ }
+ }
+ }catch (e) {
+
+ }
+
+
+