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

video_log
caicai8 5 years ago
commit af1e1a7831

@ -5,6 +5,14 @@ class Admins::DashboardsController < Admins::BaseController
@month_active_user_count = User.where(last_login_on: current_month).count @month_active_user_count = User.where(last_login_on: current_month).count
@new_user_count = User.where(created_on: current_month).count @new_user_count = User.where(created_on: current_month).count
shixun_tomcat = edu_setting('cloud_bridge')
uri = "#{shixun_tomcat}/bridge/monitor/getPodsInfo"
res = interface_get uri, 502, "数据接口延迟"
if res['code'] == 0
@pod_num = res['sum'] || 0
end
end end
def month_active_user def month_active_user

@ -448,6 +448,25 @@ class ApplicationController < ActionController::Base
end end
end end
# 无参类型处理
def interface_get(uri, status, message)
begin
uid_logger_dubug("--uri_exec: url is #{uri}")
uri = URI.parse(URI.encode(uri.strip))
res = Net::HTTP.get(uri)
uid_logger_dubug("--uri_exec: .....res is #{res}")
res = JSON.parse(res)
if (res && res['code'] != 0)
tip_exception(status, message)
else
res
end
rescue Exception => e
uid_logger("--uri_exec: exception #{e.message}")
raise Educoder::TipException.new(message)
end
end
# json格式请求 # json格式请求
def interface_json_post(uri, params, status, message) def interface_json_post(uri, params, status, message)
begin begin

@ -35,6 +35,7 @@ module LoginHelper
UserAction.create(action_id: user&.id, action_type: 'Login', user_id: user&.id, ip: request.remote_ip) UserAction.create(action_id: user&.id, action_type: 'Login', user_id: user&.id, ip: request.remote_ip)
user.update_column(:last_login_on, Time.now) user.update_column(:last_login_on, Time.now)
# 注册完成后有一天的试用申请(先去掉) # 注册完成后有一天的试用申请(先去掉)
# UserDayCertification.create(user_id: user.id, status: 1) # UserDayCertification.create(user_id: user.id, status: 1)
end end
@ -44,6 +45,8 @@ module LoginHelper
if autologin = cookies.delete(autologin_cookie_name) if autologin = cookies.delete(autologin_cookie_name)
User.current.delete_autologin_token(autologin) User.current.delete_autologin_token(autologin)
end end
UserOnline.logout(User.current.id)
User.current.delete_session_token(session[:tk]) User.current.delete_session_token(session[:tk])
self.logged_user = nil self.logged_user = nil
end end
@ -52,6 +55,7 @@ module LoginHelper
default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id" default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id"
# end # end
session[:"#{default_yun_session}"] = nil session[:"#{default_yun_session}"] = nil
session[:request_user_id] = nil
end end
# Sets the logged in user # Sets the logged in user
@ -78,6 +82,8 @@ module LoginHelper
# # end # # end
# session[:user_id] = user.id # session[:user_id] = user.id
UserOnline.login(user.id)
session[:request_user_id] = user.id
session[:"#{default_yun_session}"] = user.id session[:"#{default_yun_session}"] = user.id
session[:ctime] = Time.now.utc.to_i session[:ctime] = Time.now.utc.to_i
session[:atime] = Time.now.utc.to_i session[:atime] = Time.now.utc.to_i

@ -262,7 +262,7 @@ class EcloudController < ApplicationController
u.login = "ecoder_#{user_info['mobile']}" u.login = "ecoder_#{user_info['mobile']}"
u.type ='User' u.type ='User'
u.status = User::STATUS_ACTIVE u.status = User::STATUS_ACTIVE
u.nickname = user_info[:username] u.nickname = user_info['username']
u.lastname = user_info['username'] u.lastname = user_info['username']
end end

@ -4,6 +4,7 @@ class MainController < ApplicationController
skip_before_action :setup_laboratory skip_before_action :setup_laboratory
def first_stamp def first_stamp
UserOnline.login(session[:request_user_id]) if session[:request_user_id]
render :json => { status: 0, message: Time.now.to_i } render :json => { status: 0, message: Time.now.to_i }
end end

@ -0,0 +1,41 @@
module UserOnline
class << self
def login(user_id)
set_bit(user_id, 1)
end
def logout(user_id)
set_bit(user_id, 0)
end
def set_bit(user_id, flag)
if !Rails.cache.data.exists(cache_key)
Rails.cache.data.setbit(cache_key, user_id, flag)
Rails.cache.data.expire(cache_key, 20 * 60 + 10)
else
Rails.cache.data.setbit(cache_key, user_id, flag)
end
end
def count
if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
Rails.cache.data.bitcount(cache_key)
else
0
end
end
def cache_key
if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
# 10分钟为一段记录用户在线, 统计范围为20分钟内的线用户
# TODO 更精确时长
begin_hour = Time.now.beginning_of_hour
minutes_piece = (Time.now - begin_hour) / 600
time = begin_hour.since((minutes_piece.to_i - 1) * 600).strftime("%H-%M")
"online_user_#{time}"
else
raise '请配置config.cache_store = redis_store'
end
end
end
end

@ -9,6 +9,10 @@ class ApplicationService
content.gsub(regex, '') content.gsub(regex, '')
end end
def convert_https content
content.gsub("http:", "https:")
end
private private
def strip(str) def strip(str)

@ -12,7 +12,7 @@ class Videos::DispatchCallbackService < ApplicationService
# TODO:: 拆分事件分发 # TODO:: 拆分事件分发
case params['EventType'] case params['EventType']
when 'FileUploadComplete' then # 视频上传完成 when 'FileUploadComplete' then # 视频上传完成
video.file_url = params['FileUrl'] video.file_url = convert_https(params['FileUrl'])
video.filesize = params['Size'] video.filesize = params['Size']
video.upload_success video.upload_success
video.save! video.save!

@ -42,10 +42,7 @@
</div> </div>
</div> </div>
</div> </div>
<!-- <p class="mt-3 mb-0 text-muted text-sm">-->
<!-- <span class="text-danger mr-2"><i class="fas fa-arrow-down"></i> 3.48%</span>-->
<!-- <span class="text-nowrap">Since last week</span>-->
<!-- </p>-->
</div> </div>
</div> </div>
</div> </div>
@ -63,13 +60,11 @@
</div> </div>
</div> </div>
</div> </div>
<!-- <p class="mt-3 mb-0 text-muted text-sm">-->
<!-- <span class="text-warning mr-2"><i class="fas fa-arrow-down"></i> 1.10%</span>-->
<!-- <span class="text-nowrap">Since yesterday</span>-->
<!-- </p>-->
</div> </div>
</div> </div>
</div> </div>
<div class="col-xl-3 col-lg-6"> <div class="col-xl-3 col-lg-6">
<div class="card card-stats mb-4 mb-xl-0"> <div class="card card-stats mb-4 mb-xl-0">
<div class="card-body"> <div class="card-body">
@ -91,6 +86,45 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-xl-3 col-lg-6" style="padding-top: 15px;">
<div class="card card-stats mb-4 mb-xl-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="card-title text-uppercase text-muted mb-0">当前在线用户数</h5>
<span class="h2 font-weight-bold mb-0"><%= UserOnline.count %></span>
</div>
<div class="col-auto">
<div class="icon icon-shape rounded-circle shadow">
<i class="fa fa-users"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-lg-6" style="padding-top: 15px;">
<div class="card card-stats mb-4 mb-xl-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="card-title text-uppercase text-muted mb-0">当前Pod总数</h5>
<span class="h2 font-weight-bold mb-0"><%= @pod_num.to_i %></span>
</div>
<div class="col-auto">
<div class="icon icon-shape rounded-circle shadow">
<i class="fa fa-users"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -100,14 +134,6 @@
<div class="row mt-5"> <div class="row mt-5">
<div class="col-xl-8 mb-5 mb-xl-0"> <div class="col-xl-8 mb-5 mb-xl-0">
<div class="card shadow"> <div class="card shadow">
<!-- <div class="card-header border-0">-->
<!-- <div class="row align-items-center">-->
<!-- <h5 class="mb-0">近7天评测次数</h5>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="table-responsive">-->
<!-- <div id="evaluate-pie" class="pie"></div>-->
<!-- </div>-->
</div> </div>
</div> </div>
@ -127,92 +153,3 @@
</div> </div>
<!--<div class="container-fluid mt--7">-->
<!-- <div class="row mt-5">-->
<!-- <div class="col-xl-8 mb-5 mb-xl-0">-->
<!-- <div class="card shadow">-->
<!-- <div class="card-header border-0">-->
<!-- <div class="row align-items-center">-->
<!-- <div class="col">-->
<!-- <h3 class="mb-0">Page visits</h3>-->
<!-- </div>-->
<!-- <div class="col text-right">-->
<!-- <a href="#!" class="btn btn-sm btn-primary">Test</a>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="table-responsive">-->
<!-- <table class="table align-items-center table-flush">-->
<!-- <thead class="thead-light">-->
<!-- <tr>-->
<!-- <th scope="col">Test</th>-->
<!-- <th scope="col">Test</th>-->
<!-- <th scope="col">Test</th>-->
<!-- <th scope="col">Test</th>-->
<!-- </tr>-->
<!-- </thead>-->
<!-- <tbody>-->
<%# 5.times do %>
<!-- <tr>-->
<!-- <th scope="row">/test/</th>-->
<!-- <td>4,569</td>-->
<!-- <td>340</td>-->
<!-- <td>-->
<!-- <i class="fas fa-arrow-up text-success mr-3"></i> 46,53%-->
<!-- </td>-->
<!-- </tr>-->
<%# end %>
<!-- </tbody>-->
<!-- </table>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="col-xl-4">-->
<!-- <div class="card shadow">-->
<!-- <div class="card-header border-0">-->
<!-- <div class="row align-items-center">-->
<!-- <div class="col">-->
<!-- <h3 class="mb-0">Test</h3>-->
<!-- </div>-->
<!-- <div class="col text-right">-->
<!-- <a href="#!" class="btn btn-sm btn-primary">Test</a>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="table-responsive">-->
<!-- <table class="table align-items-center table-flush">-->
<!-- <thead class="thead-light">-->
<!-- <tr>-->
<!-- <th scope="col">Test</th>-->
<!-- <th scope="col">Test</th>-->
<!-- <th scope="col"></th>-->
<!-- </tr>-->
<!-- </thead>-->
<!-- <tbody>-->
<%# 5.times do %>
<!-- <tr>-->
<!-- <th scope="row">-->
<!-- Test-->
<!-- </th>-->
<!-- <td>-->
<!-- 1,480-->
<!-- </td>-->
<!-- <td>-->
<!-- <div class="d-flex align-items-center">-->
<!-- <span class="mr-2">60%</span>-->
<!-- <div>-->
<!-- <div class="progress">-->
<!-- <div class="progress-bar bg-gradient-danger" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;"></div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </td>-->
<!-- </tr>-->
<%# end %>
<!-- </tbody>-->
<!-- </table>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!--</div>-->

@ -1,4 +1,4 @@
json.status 1 json.status 1
json.message "发送成功" json.message "发送成功"
json.course_id @course.id json.course_id @course.id
json.first_category_url module_url(@course.none_hidden_course_modules.first, @course) json.first_category_url module_url(@course.shixun_course_modules.first, @course)

@ -1,3 +1,3 @@
json.status 1 json.status 1
json.message "发送成功" json.message "发送成功"
json.url module_url(@course.none_hidden_course_modules.first, @course) json.url module_url(@course.shixun_course_modules.first, @course)

@ -29,6 +29,24 @@ namespace :video do
end end
end end
desc "将http修改成http"
task modify_http_to_https_file_url: :environment do
p "s"
if ENV['args']
course_id = ENV['args'].split(",")[0]
video_ids = CourseVideo.where(course_id: course_id).pluck(:video_id)
videos = Video.where(id: video_ids)
if videos
videos.each do |v|
if v.file_url
file_url = v.file_url.gsub("http:", "https:")
v.update_column(:file_url, file_url)
end
end
end
end
end
# 执行示例 bundle exec rake video:sample args=2933,'2019-08-19 00:00:00','2019-11-09 23:59:59' # 执行示例 bundle exec rake video:sample args=2933,'2019-08-19 00:00:00','2019-11-09 23:59:59'
task :sample => :environment do task :sample => :environment do
if ENV['args'] if ENV['args']

File diff suppressed because it is too large Load Diff

@ -39,6 +39,7 @@
"eslint-plugin-react": "7.4.0", "eslint-plugin-react": "7.4.0",
"extract-text-webpack-plugin": "3.0.2", "extract-text-webpack-plugin": "3.0.2",
"file-loader": "1.1.5", "file-loader": "1.1.5",
"flv.js": "^1.5.0",
"fs-extra": "3.0.1", "fs-extra": "3.0.1",
"html-webpack-plugin": "2.29.0", "html-webpack-plugin": "2.29.0",
"immutability-helper": "^2.6.6", "immutability-helper": "^2.6.6",

@ -1,34 +1,38 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<head>
<meta charset="utf-8">
<!--<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">--> <meta charset="utf-8">
<!--<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">-->
<!-- width=device-width, initial-scale=1 , shrink-to-fit=no -->
<!-- <meta name="viewport" content=""> --> <!-- width=device-width, initial-scale=1 , shrink-to-fit=no -->
<meta name=”Keywords” Content=”EduCoder,信息技术实践教学,精品课程网,慕课MOOC″> <!-- <meta name="viewport" content=""> -->
<meta name=”Keywords” Content=”实践课程,项目实战,java实训,python实战,人工智能技术,后端开发学习,移动开发入门″> <meta name=”Keywords” Content=”EduCoder,信息技术实践教学,精品课程网,慕课MOOC″>
<meta name=”Keywords” Content=”翻转课堂,高效课堂创建,教学模式″> <meta name=”Keywords” Content=”实践课程,项目实战,java实训,python实战,人工智能技术,后端开发学习,移动开发入门″>
<meta name=”Keywords” Content=”实训项目,python教程,C语言入门,java书,php后端开发,app前端开发,数据库技术″> <meta name=”Keywords” Content=”翻转课堂,高效课堂创建,教学模式″>
<meta name=”Keywords” Content=”在线竞赛,计算机应用大赛,编程大赛,大学生计算机设计大赛,全国高校绿色计算机大赛″> <meta name=”Keywords” Content=”实训项目,python教程,C语言入门,java书,php后端开发,app前端开发,数据库技术″>
<meta name=”Description” Content=”EduCoder是信息技术类实践教学平台。EduCoder涵盖了计算机、大数据、云计算、人工智能、软件工程、物联网等专业课程。超10000个实训案例及22000个技能评测点建立学、练、评、测一体化实验环境。”> <meta name=”Keywords” Content=”在线竞赛,计算机应用大赛,编程大赛,大学生计算机设计大赛,全国高校绿色计算机大赛″>
<meta name=”Description” Content=”EduCoder实践课程旨在于通过企业级实战实训案例帮助众多程序员提升各项业务能力。解决学生、学员、企业员工等程序设计能力、算法设计能力、问题求解能力、应用开发能力、系统运维能力等。”> <meta name=”Description”
<meta name=”Description” Content=”EduCoder翻转课堂教学模式颠覆了传统教学模式让教师与学生的关系由“权威”变成了“伙伴”。将学习的主动权转交给学生使学生可个性化化学学生的学习主体得到了彰显。”> Content=”EduCoder是信息技术类实践教学平台。EduCoder涵盖了计算机、大数据、云计算、人工智能、软件工程、物联网等专业课程。超10000个实训案例及22000个技能评测点建立学、练、评、测一体化实验环境。”>
<meta name=”Description” Content=”EduCoder实训项目为单个知识点关卡实践训练帮助学生巩固单一弱点强化学习。 > <meta name=”Description”
<meta name=”Description” Content=”EduCoder实践教学平台各类大赛为进一步提高各类学生综合运用高级语言程序设计能力培养创新意识和实践探索精神发掘优秀软件人才。 > Content=”EduCoder实践课程旨在于通过企业级实战实训案例帮助众多程序员提升各项业务能力。解决学生、学员、企业员工等程序设计能力、算法设计能力、问题求解能力、应用开发能力、系统运维能力等。”>
<!-- <meta name="viewport" id="viewport" content="width=device-width, initial-scale=0.3, maximum-scale=0.3, user-scalable=no">--> <meta name=”Description”
<meta name="viewport" id="viewport" content="width=device-width, initial-scale=0.3, maximum-scale=0.3"> Content=”EduCoder翻转课堂教学模式颠覆了传统教学模式让教师与学生的关系由“权威”变成了“伙伴”。将学习的主动权转交给学生使学生可个性化化学学生的学习主体得到了彰显。”>
<meta name=”Description” Content=”EduCoder实训项目为单个知识点关卡实践训练帮助学生巩固单一弱点强化学习。 >
<meta name="theme-color" content="#000000"> <meta name=”Description” Content=”EduCoder实践教学平台各类大赛为进一步提高各类学生综合运用高级语言程序设计能力培养创新意识和实践探索精神发掘优秀软件人才。 >
<!--<meta http-equiv="cache-control" content="no-cache,no-store, must-revalidate" />--> <!-- <meta name="viewport" id="viewport" content="width=device-width, initial-scale=0.3, maximum-scale=0.3, user-scalable=no">-->
<!--<meta http-equiv="pragma" content="no-cache" />--> <meta name="viewport" id="viewport" content="width=device-width, initial-scale=0.3, maximum-scale=0.3">
<!--<meta http-equiv="Expires" content="0" />-->
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"> <!--<meta http-equiv="cache-control" content="no-cache,no-store, must-revalidate" />-->
<!--<meta http-equiv="pragma" content="no-cache" />-->
<!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">--> <!--<meta http-equiv="Expires" content="0" />-->
<!--
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">-->
<!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build. It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML. Only files inside the `public` folder can be referenced from the HTML.
@ -37,29 +41,29 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<!-- <title>EduCoder</title>--> <!-- <title>EduCoder</title>-->
<!--react-ssr-head--> <!--react-ssr-head-->
<script type="text/javascript"> <script type="text/javascript">
window.__isR = true; window.__isR = true;
// 不支持ie9 ie10 // 不支持ie9 ie10
if ( if (
( navigator.userAgent.indexOf('MSIE 9') != -1 (navigator.userAgent.indexOf('MSIE 9') != -1
|| navigator.userAgent.indexOf('MSIE 10') != -1 ) || navigator.userAgent.indexOf('MSIE 10') != -1)
&& &&
location.pathname.indexOf("/compatibility") == -1) { location.pathname.indexOf("/compatibility") == -1) {
debugger; debugger;
// location.href = './compatibility' // location.href = './compatibility'
location.href = '/compatibility.html' location.href = '/compatibility.html'
} }
// const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase())); // const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
const isWeiXin = (/MicroMessenger/i.test(navigator.userAgent.toLowerCase())); const isWeiXin = (/MicroMessenger/i.test(navigator.userAgent.toLowerCase()));
if (isWeiXin) { if (isWeiXin) {
document.write('<script type="text/javascript" src="/javascripts/wx/jweixin-1.3.0.js"><\/script>'); document.write('<script type="text/javascript" src="/javascripts/wx/jweixin-1.3.0.js"><\/script>');
} }
</script> </script>
<!-- <link rel="stylesheet" type="text/css" href="/css/edu-common.css"> <!-- <link rel="stylesheet" type="text/css" href="/css/edu-common.css">
<link rel="stylesheet" type="text/css" href="/css/edu-public.css"> <link rel="stylesheet" type="text/css" href="/css/edu-public.css">
<link rel="stylesheet" type="text/css" href="/css/taskstyle.css"> <link rel="stylesheet" type="text/css" href="/css/taskstyle.css">
@ -70,143 +74,114 @@
<link rel="stylesheet" type="text/css" href="/css/merge.css"> --> <link rel="stylesheet" type="text/css" href="/css/merge.css"> -->
<link rel="stylesheet" type="text/css" href="/css/css_min_all.css"> <link rel="stylesheet" type="text/css" href="/css/css_min_all.css">
<!--<link rel="stylesheet" type="text/css" href="/css/css_min_all.css">--> <!--<link rel="stylesheet" type="text/css" href="/css/css_min_all.css">-->
<!--<link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_653600_nm6lho7nxxq.css">--> <!--<link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_653600_nm6lho7nxxq.css">-->
<!-- <link href="/react/build/css/iconfont.css" rel="stylesheet" type="text/css"> --> <!-- <link href="/react/build/css/iconfont.css" rel="stylesheet" type="text/css"> -->
<!--<link href="http://47.96.87.25:48080/stylesheets/educoder/edu-all.css" rel="stylesheet" type="text/css">--> <!--<link href="http://47.96.87.25:48080/stylesheets/educoder/edu-all.css" rel="stylesheet" type="text/css">-->
<!--<link href="https://pandao.github.io/editor.md/examples/css/style.css" rel="stylesheet" type="text/css">--> <!--<link href="https://pandao.github.io/editor.md/examples/css/style.css" rel="stylesheet" type="text/css">-->
<!--<link href="https://pandao.github.io/editor.md/css/editormd.preview.css" rel="stylesheet" type="text/css">--> <!--<link href="https://pandao.github.io/editor.md/css/editormd.preview.css" rel="stylesheet" type="text/css">-->
<!-- <link href="https://testeduplus2.educoder.net/stylesheets/css/edu-common.css" rel="stylesheet" type="text/css"> <!-- <link href="https://testeduplus2.educoder.net/stylesheets/css/edu-common.css" rel="stylesheet" type="text/css">
<link href="https://testeduplus2.educoder.net/stylesheets/educoder/edu-main.css" rel="stylesheet" type="text/css"> <link href="https://testeduplus2.educoder.net/stylesheets/educoder/edu-main.css" rel="stylesheet" type="text/css">
<link href="https://testeduplus2.educoder.net/stylesheets/educoder/antd.min.css" rel="stylesheet" type="text/css"> --> <link href="https://testeduplus2.educoder.net/stylesheets/educoder/antd.min.css" rel="stylesheet" type="text/css"> -->
<!-- <link rel="stylesheet" type="text/css" href="https://www.educoder.net/stylesheets/css/font-awesome.css?1510652321"> --> <!-- <link rel="stylesheet" type="text/css" href="https://www.educoder.net/stylesheets/css/font-awesome.css?1510652321"> -->
<!--<link rel="stylesheet" type="text/css" href="http://47.96.87.25:48080/stylesheets/educoder/iconfont/iconfont.css">--> <!--<link rel="stylesheet" type="text/css" href="http://47.96.87.25:48080/stylesheets/educoder/iconfont/iconfont.css">-->
<!--需要去build js配置--> <!--需要去build js配置-->
<link rel="stylesheet" type="text/css" href="/css/iconfont.css"> <link rel="stylesheet" type="text/css" href="/css/iconfont.css">
<link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/quill/1.3.7/quill.core.min.css"> <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/quill/1.3.7/quill.core.min.css">
<style> <style>
/*<!--去除浏览器点击操作后有蓝色的底块-->*/ /*<!--去除浏览器点击操作后有蓝色的底块-->*/
-moz-user-select: none; -moz-user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
</style> </style>
</head> </head>
<body>
<noscript> <body>
You need to enable JavaScript to run this app. <noscript>
</noscript> You need to enable JavaScript to run this app.
<!--用于markdown转html --> </noscript>
<div id="md_div" style="display: none;"></div> <!--用于markdown转html -->
<div id="root" class="page -layout-v -fit widthunit"> <div id="md_div" style="display: none;"></div>
<!--<div class="d2-home">--> <div id="root" class="page -layout-v -fit widthunit">
<!--<div class="d2-home__main">--> <!--<div class="d2-home">-->
<!--&lt;!&ndash;<img class="d2-home__loading"&ndash;&gt;--> <!--<div class="d2-home__main">-->
<!--&lt;!&ndash;src="loading-spin.svg"&ndash;&gt;--> <!--&lt;!&ndash;<img class="d2-home__loading"&ndash;&gt;-->
<!--&lt;!&ndash;alt="loading">&ndash;&gt;--> <!--&lt;!&ndash;src="loading-spin.svg"&ndash;&gt;-->
<!--<div class="lds-ripple"><div></div><div></div></div>--> <!--&lt;!&ndash;alt="loading">&ndash;&gt;-->
<!--<div class="d2-home__title">--> <!--<div class="lds-ripple"><div></div><div></div></div>-->
<!--正在加载资源--> <!--<div class="d2-home__title">-->
<!--</div>--> <!--正在加载资源-->
<!--<div class="d2-home__sub-title">--> <!--</div>-->
<!--加载资源可能需要较多时间 请耐心等待--> <!--<div class="d2-home__sub-title">-->
<!--</div>--> <!--加载资源可能需要较多时间 请耐心等待-->
<!--</div>--> <!--</div>-->
<!--<div class="d2-home__footer">--> <!--</div>-->
<!--&lt;!&ndash;<a href="www.educoder.net"&ndash;&gt;--> <!--<div class="d2-home__footer">-->
<!--&lt;!&ndash;target="_blank">&ndash;&gt;--> <!--&lt;!&ndash;<a href="www.educoder.net"&ndash;&gt;-->
<!--&lt;!&ndash;&ndash;&gt;--> <!--&lt;!&ndash;target="_blank">&ndash;&gt;-->
<!--&lt;!&ndash;</a>&ndash;&gt;--> <!--&lt;!&ndash;&ndash;&gt;-->
<!--EduCoder--> <!--&lt;!&ndash;</a>&ndash;&gt;-->
<!--</div>--> <!--EduCoder-->
<!--</div>--> <!--</div>-->
</div> <!--</div>-->
<div id="picture_display" style="display: none;"></div> </div>
<!-- js css合并 文件优先级的问题 --> <div id="picture_display" style="display: none;"></div>
<script type="text/javascript" src="/js/js_min_all.js"></script> <!-- js css合并 文件优先级的问题 -->
<!-- <script type="text/javascript" src="/js/js_min_all_2.js"></script> --> <script type="text/javascript" src="/js/js_min_all.js"></script>
<script type="text/javascript" src="/js/flv.min.js"></script>
<!--
<script type="text/javascript" src="/js/jquery-1.8.3.min.js"></script> <!-- 在tpi js里加载这3个脚本 -->
<script>
(function () { // Scoping function to avoid globals
<script type="text/javascript" src="/js/editormd/underscore.min.js"></script> var href = location.href;
if (window.location.port === "3007") {
<script type="text/javascript" src="/js/editormd/marked.min.js"></script> if (href.indexOf('/tasks/') != -1) {
<script type="text/javascript" src="/js/editormd/prettify.min.js"></script> document.write('<script type="text/javascript" src="https://newweb.educoder.net/assets/kindeditor/kindeditor.js"><\/script>');
<script type="text/javascript" src="/js/editormd/raphael.min.js"></script> // build.js中会将这个url附加一个前缀 react/build
<script type="text/javascript" src="/js/editormd/sequence-diagram.min.js"></script> document.write('<script type="text/javascript" src="/js/create_kindeditor.js"><\/script>');
document.write('<script type="text/javascript" src="https://newweb.educoder.net/javascripts/educoder/edu_application.js"><\/script>');
<script type="text/javascript" src="/js/editormd/flowchart.min.js"></script> } else if (href.indexOf('/paths/') != -1) {
<script type="text/javascript" src="/js/editormd/jquery.flowchart.min.js"></script> document.write('<script type="text/javascript" src="https://newweb.educoder.net/javascripts/educoder/edu_application.js"><\/script>');
<script type="text/javascript" src="/js/editormd/editormd.min.js"></script>
-->
<!-- codemirror addon -->
<!--
<script type="text/javascript" src="/js/codemirror/codemirror.js"></script>
<script type="text/javascript" src="/js/codemirror/mode/javascript.js"></script>
<script type="text/javascript" src="/js/diff_match_patch.js"></script>
<script type="text/javascript" src="/js/merge.js"></script>
<script type="text/javascript" src="/js/edu_tpi.js"></script>
-->
<!-- testbdweb.trustie.net testbdweb.educoder.net -->
<!-- 在tpi js里加载这3个脚本 -->
<script>
(function() { // Scoping function to avoid globals
var href = location.href;
if(window.location.port === "3007"){
if (href.indexOf('/tasks/') != -1) {
document.write('<script type="text/javascript" src="https://newweb.educoder.net/assets/kindeditor/kindeditor.js"><\/script>');
// build.js中会将这个url附加一个前缀 react/build
document.write('<script type="text/javascript" src="/js/create_kindeditor.js"><\/script>');
document.write('<script type="text/javascript" src="https://newweb.educoder.net/javascripts/educoder/edu_application.js"><\/script>');
} else if (href.indexOf('/paths/') != -1) {
document.write('<script type="text/javascript" src="https://newweb.educoder.net/javascripts/educoder/edu_application.js"><\/script>');
}
}else{
if (href.indexOf('/tasks/') != -1) {
document.write('<script type="text/javascript" src="/assets/kindeditor/kindeditor.js"><\/script>');
// build.js中会将这个url附加一个前缀 react/build
document.write('<script type="text/javascript" src="/js/create_kindeditor.js"><\/script>');
document.write('<script type="text/javascript" src="/javascripts/educoder/edu_application.js"><\/script>');
} else if (href.indexOf('/paths/') != -1) {
document.write('<script type="text/javascript" src="/javascripts/educoder/edu_application.js"><\/script>');
}
} }
} else {
if (href.indexOf('/tasks/') != -1) {
document.write('<script type="text/javascript" src="/assets/kindeditor/kindeditor.js"><\/script>');
// build.js中会将这个url附加一个前缀 react/build
document.write('<script type="text/javascript" src="/js/create_kindeditor.js"><\/script>');
document.write('<script type="text/javascript" src="/javascripts/educoder/edu_application.js"><\/script>');
} else if (href.indexOf('/paths/') != -1) {
document.write('<script type="text/javascript" src="/javascripts/educoder/edu_application.js"><\/script>');
}
}
})(); })();
</script> </script>
<!-- <script type="text/javascript" src="https://testeduplus2.educoder.net/assets/kindeditor/kindeditor.js"></script> <!-- <script type="text/javascript" src="https://testeduplus2.educoder.net/assets/kindeditor/kindeditor.js"></script>
<script type="text/javascript" src="/js/create_kindeditor.js"></script> <script type="text/javascript" src="/js/create_kindeditor.js"></script>
<script type="text/javascript" src="https://testeduplus2.educoder.net/javascripts/educoder/edu_application.js"></script> --> <script type="text/javascript" src="https://testeduplus2.educoder.net/javascripts/educoder/edu_application.js"></script> -->
<script type="text/javascript" src="https://cdn.bootcss.com/quill/1.3.7/quill.core.min.js"></script> <script type="text/javascript" src="https://cdn.bootcss.com/quill/1.3.7/quill.core.min.js"></script>
<!-- <script>--> <!-- <script>-->
<!-- document.body.addEventListener('touchmove', function (e) {--> <!-- document.body.addEventListener('touchmove', function (e) {-->
<!-- e.preventDefault(); //阻止默认的处理方式(阻止下拉滑动的效果)--> <!-- e.preventDefault(); //阻止默认的处理方式(阻止下拉滑动的效果)-->
<!-- }, {passive: false});--> <!-- }, {passive: false});-->
<!-- </script>--> <!-- </script>-->
</body> </body>
</html> </html>

File diff suppressed because one or more lines are too long

@ -209,15 +209,19 @@ function generateNewIndexJsp() {
} else if (window.location.host == 'www.educoder.net') { } else if (window.location.host == 'www.educoder.net') {
_host = 'https://ali-cdn.educoder.net/react/build/' _host = 'https://ali-cdn.educoder.net/react/build/'
} }
document.write('<script type="text/javascript" src="' + _host + 'js/js_min_all.js"><\\/script>'); document.write('<script type="text/javascript" src="' + _host + 'js/js_min_all.js"><\\/script>');
document.write('<script type="text/javascript" src="' + _host + 'js/flv.min.js"><\\/script>');
document.write('<script type="text/javascript" src="' + _host + 'static/js/main.${matchResult[1]}.js"><\\/script>'); document.write('<script type="text/javascript" src="' + _host + 'static/js/main.${matchResult[1]}.js"><\\/script>');
})() })()
</script> </script>
` `
var jsMinAllRegex = /<script type="text\/javascript" src="\/js\/js_min_all.js"><\/script>/ var jsMinAllRegex = /<script type="text\/javascript" src="\/js\/js_min_all.js"><\/script>/
var flvMinAllRegex = /<script type="text\/javascript" src="\/js\/flv.min.js"><\/script>/
// <script type="text/javascript" src="/js/js_min_all.js"></script> // <script type="text/javascript" src="/js/js_min_all.js"></script>
var result = data var result = data
.replace(jsMinAllRegex, code) .replace(jsMinAllRegex, code)
.replace(flvMinAllRegex, code)
// .replace('/js/js_min_all.js', `${cdnHost}/react/build/js/js_min_all.js?v=${newVersion}`) // .replace('/js/js_min_all.js', `${cdnHost}/react/build/js/js_min_all.js?v=${newVersion}`)
// .replace('/js/js_min_all_2.js', `${cdnHost}/react/build/js/js_min_all_2.js?v=${newVersion}`) // .replace('/js/js_min_all_2.js', `${cdnHost}/react/build/js/js_min_all_2.js?v=${newVersion}`)

@ -1,12 +1,13 @@
import React,{ Component } from "react"; import React, { Component } from "react";
import { Input , Pagination } from 'antd'; import { Input, Pagination } from 'antd';
import { NoneData ,ActionBtn } from 'educoder'; import { NoneData, ActionBtn } from 'educoder';
import VideoUploadList from '../../user/usersInfo/video/VideoUploadList'; import VideoUploadList from '../../user/usersInfo/video/VideoUploadList';
import VideoInReviewItem from '../../user/usersInfo/video/VideoInReviewItem'; import VideoInReviewItem from '../../user/usersInfo/video/VideoInReviewItem';
import HeadlessModal from '../../user/usersInfo/common/HeadlessModal'; import HeadlessModal from '../../user/usersInfo/common/HeadlessModal';
import EditVideoModal from '../../user/usersInfo/video/EditVideoModal' import EditVideoModal from '../../user/usersInfo/video/EditVideoModal'
import ClipboardJS from 'clipboard' import ClipboardJS from 'clipboard'
import VideoPanel from './video-play'
import './video.css'; import './video.css';
import '../../user/usersInfo/video/InfosVideo.css' import '../../user/usersInfo/video/InfosVideo.css'
@ -15,77 +16,76 @@ import axios from 'axios';
const DEFAULT_VIDEO_WIDTH_IN_MD = "90%" // 400 const DEFAULT_VIDEO_WIDTH_IN_MD = "90%" // 400
const DEFAULT_VIDEO_HEIGHT_IN_MD = "55%" // 400 const DEFAULT_VIDEO_HEIGHT_IN_MD = "55%" // 400
const videoEl = null;
let _clipboard = null; let _clipboard = null;
class Video extends Component{ class Video extends Component {
constructor(props){ constructor(props) {
super(props); super(props);
this.state={ this.state = {
videos:undefined, videos: undefined,
count:0, count: 0,
page:1, page: 1,
videoId:undefined, videoId: undefined,
videoVisible:false, videoVisible: false,
visible:false visible: false
} }
} }
// 编辑的弹框visible // 编辑的弹框visible
setVisible=(flag)=>{ setVisible = (flag) => {
this.setState({ this.setState({
visible:flag visible: flag
}) })
} }
setVideoVisible=(flag)=>{ setVideoVisible = (flag) => {
this.setState({ this.setState({
videoVisible:flag videoVisible: flag
}) })
if (flag === false) { if (flag === false) {
if (_clipboard) { if (_clipboard) {
this.setState({ this.setState({
videoId:undefined videoId: undefined
}) })
_clipboard.listener.destroy(); _clipboard.listener.destroy();
_clipboard = null; _clipboard = null;
} }
} else { } else {
// videoEl.current && videoEl.current.play() // videoEl.current && videoEl.current.play()
setTimeout(() => { setTimeout(() => {
if (!_clipboard) { if (!_clipboard) {
_clipboard = new ClipboardJS('.copybtn'); _clipboard = new ClipboardJS('.copybtn');
_clipboard.on('success', (e) => { _clipboard.on('success', (e) => {
this.props.showNotification('复制成功'); this.props.showNotification('复制成功');
}); });
} }
}, 200) }, 200)
} }
} }
// 编辑成功后回调的方法 // 编辑成功后回调的方法
editSuccess=()=>{ editSuccess = () => {
this.props.showNotification("视频名称修改成功!"); this.props.showNotification("视频名称修改成功!");
const { listFunc , page } = this.props; const { listFunc, page } = this.props;
listFunc && listFunc(page); listFunc && listFunc(page);
} }
onEditVideo=(item)=>{ onEditVideo = (item) => {
let videoId = { let videoId = {
videoId: item.id, videoId: item.id,
title: item.title title: item.title
} }
this.setState({ this.setState({
videoId, videoId,
}) })
this.setVisible(true); this.setVisible(true);
} }
onMaskClick=(item)=> { onMaskClick = (item) => {
let videoId = { let videoId = {
videoId: item.id, videoId: item.id,
title: item.title, title: item.title,
@ -99,59 +99,59 @@ class Video extends Component{
} }
setVideoVisible=(flag)=>{ setVideoVisible = (flag) => {
this.setState({ this.setState({
videoVisible:flag videoVisible: flag
}) })
if (flag === false) { if (flag === false) {
if (_clipboard) { if (_clipboard) {
this.setState({ this.setState({
videoId:undefined videoId: undefined
}) })
_clipboard.listener.destroy(); _clipboard.listener.destroy();
_clipboard = null; _clipboard = null;
} }
} else { } else {
// videoEl.current && videoEl.current.play() // videoEl.current && videoEl.current.play()
setTimeout(() => { setTimeout(() => {
if (!_clipboard) { if (!_clipboard) {
_clipboard = new ClipboardJS('.copybtn'); _clipboard = new ClipboardJS('.copybtn');
_clipboard.on('success', (e) => { _clipboard.on('success', (e) => {
this.props.showNotification('复制成功'); this.props.showNotification('复制成功');
}); });
} }
}, 200) }, 200)
} }
} }
getCopyText = (file_url, cover_url)=>{ getCopyText = (file_url, cover_url) => {
return `<video src="${file_url}" controls="true" controlslist="nodownload" width="${DEFAULT_VIDEO_WIDTH_IN_MD}" height="${DEFAULT_VIDEO_HEIGHT_IN_MD}" poster="${cover_url}">您的浏览器不支持 video 标签。</video>` return `<video src="${file_url}" controls="true" controlslist="nodownload" width="${DEFAULT_VIDEO_WIDTH_IN_MD}" height="${DEFAULT_VIDEO_HEIGHT_IN_MD}" poster="${cover_url}">您的浏览器不支持 video 标签。</video>`
} }
// 删除事件 // 删除事件
deleteVideo=(item)=>{ deleteVideo = (item) => {
this.props.confirm({ this.props.confirm({
content: '该视频将被删除,不可恢复', content: '该视频将被删除,不可恢复',
subContent:'是否确认删除?', subContent: '是否确认删除?',
onOk: () => { onOk: () => {
const CourseId=this.props.match.params.coursesId; const CourseId = this.props.match.params.coursesId;
const url = `/courses/${CourseId}/delete_course_video.json`; const url = `/courses/${CourseId}/delete_course_video.json`;
axios.delete(url,{ axios.delete(url, {
params:{ params: {
video_id:item.id video_id: item.id
} }
}).then(result=>{ }).then(result => {
if(result){ if (result) {
this.props.showNotification(`删除成功!`); this.props.showNotification(`删除成功!`);
this.props.updataleftNavfun(); this.props.updataleftNavfun();
const { listFunc , page } = this.props; const { listFunc, page } = this.props;
listFunc && listFunc(page); listFunc && listFunc(page);
} }
}).catch(error=>{ }).catch(error => {
console.log(error); console.log(error);
}) })
}, },
@ -161,90 +161,82 @@ class Video extends Component{
}); });
} }
render(){ render() {
const { visible , videoVisible , videoId } = this.state; const { visible, videoVisible, videoId } = this.state;
const CourseId=this.props.match.params.coursesId; const CourseId = this.props.match.params.coursesId;
const login=this.props.user&&this.props.user.login; const login = this.props.user && this.props.user.login;
const _inputValue = videoId && this.getCopyText(videoId.file_url, videoId.cover_url); const _inputValue = videoId && this.getCopyText(videoId.file_url, videoId.cover_url);
const { admin , is_teacher ,business , user_id} = this.props.user; const { admin, is_teacher, business, user_id } = this.props.user;
const { videos , upload , uploadVideo , videoData , changePage ,pageSize ,page } = this.props; const { videos, upload, uploadVideo, videoData, changePage, pageSize, page } = this.props;
const operation = admin || business || (is_teacher && this.props.checkIfProfessionalCertification()) const operation = admin || business || (is_teacher && this.props.checkIfProfessionalCertification())
return( return (
<div> <div>
<EditVideoModal {...this.props} visible={visible} setVisible={this.setVisible} <EditVideoModal {...this.props} visible={visible} setVisible={this.setVisible}
editSuccess={this.editSuccess} editSuccess={this.editSuccess}
{...videoId} CourseUser={login} {...videoId} CourseUser={login}
></EditVideoModal> ></EditVideoModal>
<HeadlessModal <HeadlessModal
visible={videoVisible} visible={videoVisible}
setVisible={this.setVideoVisible} setVisible={this.setVideoVisible}
className="showVideoModal" className="showVideoModal"
width={800 - 1} width={800 - 1}
> >
{ {videoId && <VideoPanel src={videoId.file_url} />}
videoId &&
<video <div className="df copyLine">
autoplay="true" <Input value={_inputValue}
ref={videoEl} className="dark"
src={videoId.file_url} controls="true" controlslist="nodownload"> ></Input>
您的浏览器不支持 video 标签 <ActionBtn className="copybtn" data-clipboard-text={_inputValue}>复制视频地址</ActionBtn>
</video> </div>
} </HeadlessModal>
<div className="df copyLine">
<Input value={_inputValue}
className="dark"
></Input>
<ActionBtn className="copybtn" data-clipboard-text={_inputValue}>复制视频地址</ActionBtn>
</div>
</HeadlessModal>
<div className="videoPanel"> <div className="videoPanel">
{ {
upload ? upload ?
<VideoUploadList {...this.props} flag={true} CourseId={CourseId} CourseUser={login} successFunc={()=>uploadVideo()}></VideoUploadList> <VideoUploadList {...this.props} flag={true} CourseId={CourseId} CourseUser={login} successFunc={() => uploadVideo()}></VideoUploadList>
: :
<React.Fragment> <React.Fragment>
{ {
videos && videos.length > 0 ? videos && videos.length > 0 ?
<React.Fragment> <React.Fragment>
<p className="font-grey-9 mt20 mb20 pl5"> <span className="color-orange">{videoData && videoData.count}</span> </p> <p className="font-grey-9 mt20 mb20 pl5"> <span className="color-orange">{videoData && videoData.count}</span> </p>
<div className="videoContent"> <div className="videoContent">
{ {
videos.map((item,key)=>{ videos.map((item, key) => {
return( return (
<VideoInReviewItem <VideoInReviewItem
{...this.props} {...this.props}
{...item} {...item}
key={item.id} key={item.id}
onEditVideo={this.onEditVideo} onEditVideo={this.onEditVideo}
onMaskClick={this.onMaskClick} onMaskClick={this.onMaskClick}
getCopyText={this.getCopyText} getCopyText={this.getCopyText}
operation={operation} operation={operation}
deleteVideo={(admin || item.user_id === user_id) ? this.deleteVideo : undefined} deleteVideo={(admin || item.user_id === user_id) ? this.deleteVideo : undefined}
> >
</VideoInReviewItem> </VideoInReviewItem>
) )
}) })
} }
</div>
</React.Fragment>
:
<div className="edu-back-white">
<NoneData style={{ width: '100%' }}></NoneData>
</div>
}
{
videoData && videoData.count > pageSize &&
<div className="mt30 mb50 edu-txt-center">
<Pagination showQuickJumper total={videoData.count} current={page} pageSize={pageSize} onChange={(page) => changePage(page, 'video')}></Pagination>
</div> </div>
</React.Fragment> }
: </React.Fragment>
<div className="edu-back-white">
<NoneData style={{width: '100%'}}></NoneData>
</div>
}
{
videoData && videoData.count > pageSize &&
<div className="mt30 mb50 edu-txt-center">
<Pagination showQuickJumper total={videoData.count} current={page} pageSize={pageSize} onChange={(page)=>changePage(page,'video')}></Pagination>
</div>
}
</React.Fragment>
} }
</div> </div>
</div> </div>

@ -0,0 +1,37 @@
import React, { useEffect, useRef } from 'react'
export default ({ url }) => {
const ref = useRef()
useEffect(() => {
let player = null
if (window.flvjs.isSupported) {
player = window.flvjs.createPlayer({
type: 'flv',
volume: 0.8,
cors: true,
url,
muted: false
})
if (ref.current) {
player.attachMediaElement(ref.current)
player.load()
player.play()
}
}
return () => {
if (player) {
player.unload()
player.pause()
player.destroy()
player = null
}
}
}, [url, ref.current])
return (
<video ref={ref} controls autoPlay={true} muted={false} className="flv-player"></video>
)
}

@ -0,0 +1,18 @@
import React, { Fragment } from 'react'
import ReactFlvPlayer from './flv-player'
export default ({ src }) => {
const suf = src.split('.').pop()
const isFlv = suf === 'flv'
return (
<Fragment>
{
isFlv ? <ReactFlvPlayer url={src} isMuted={true} /> : <video src={src} controls autoPlay={true} controlsList="nodownload">
<source type={`video/${suf}`} src={src} />
您的浏览器不支持 video 标签
</video>
}
</Fragment>
)
}

@ -1,16 +1,15 @@
import React, { useState, useEffect, useContext, useRef, memo } from 'react'; import React, { useState, useEffect, useContext, useRef, memo } from 'react';
import {Link} from 'react-router-dom'; import { Pagination, Input, Button } from 'antd'
import {Pagination, Input, Button} from 'antd' import { ThemeContext, ActionBtn, NoneData } from 'educoder'
import { getUrl2, isDev, ThemeContext, ActionBtn, NoneData } from 'educoder'
import axios from 'axios' import axios from 'axios'
import VideoInReviewItem from './VideoInReviewItem' import VideoInReviewItem from './VideoInReviewItem'
import EditVideoModal from './EditVideoModal' import EditVideoModal from './EditVideoModal'
import './InfosVideo.css' import './InfosVideo.css'
import InfoTab from '../common/InfoTab' import InfoTab from '../common/InfoTab'
import HeadlessModal from '../common/HeadlessModal' import HeadlessModal from '../common/HeadlessModal'
import CRoundSelect from '../common/CRoundSelect'
import ClipboardJS from 'clipboard' import ClipboardJS from 'clipboard'
import VideoPlay from '../../../courses/Video/video-play';
function useModal(initValue) { function useModal(initValue) {
const [visible, setVisible] = useState(initValue) const [visible, setVisible] = useState(initValue)
@ -45,11 +44,11 @@ const DEFAULT_VIDEO_WIDTH_IN_MD = "90%" // 400
const DEFAULT_VIDEO_HEIGHT_IN_MD = "55%" // 400 const DEFAULT_VIDEO_HEIGHT_IN_MD = "55%" // 400
let videoId = {}; let videoId = {};
let _clipboard = null; let _clipboard = null;
const _items=[ const _items = [
{key: 'published_at-desc', name: '最新上传'}, { key: 'published_at-desc', name: '最新上传' },
{key: 'published_at-asc', name: '最早上传'}, { key: 'published_at-asc', name: '最早上传' },
] ]
function InfoVideo (props) { function InfoVideo(props) {
const [videos, setvideos] = useState(undefined) const [videos, setvideos] = useState(undefined)
const [reviewvideos, setReviewvideos] = useState(undefined) const [reviewvideos, setReviewvideos] = useState(undefined)
const [count, setCount] = useState(0) const [count, setCount] = useState(0)
@ -80,30 +79,30 @@ function InfoVideo (props) {
const fetchUrl = `/users/${username}/videos.json` const fetchUrl = `/users/${username}/videos.json`
const sorts = sortKey.split('-') const sorts = sortKey.split('-')
setLoading(true) setLoading(true)
axios.get(fetchUrl, { axios.get(fetchUrl, {
params: { params: {
page: pageObj.current, page: pageObj.current,
per_page: PAGE_SIZE, per_page: PAGE_SIZE,
sort_by: sorts[0], sort_by: sorts[0],
sort_direction: sorts[1], sort_direction: sorts[1],
// //
} }
}) })
.then((response) => { .then((response) => {
setLoading(false) setLoading(false)
if (response.data.videos) { if (response.data.videos) {
setvideos(response.data.videos) setvideos(response.data.videos)
setCount(response.data.count) setCount(response.data.count)
} }
}).catch(() => { }).catch(() => {
setLoading(false) setLoading(false)
}) })
} }
function fetchReviewvideos() { function fetchReviewvideos() {
const fetchUrl = `/users/${username}/videos/review.json` const fetchUrl = `/users/${username}/videos/review.json`
const sorts = sortKey.split('-') const sorts = sortKey.split('-')
setLoading(true) setLoading(true)
axios.get(fetchUrl, { axios.get(fetchUrl, {
params: { params: {
page: pageObj.current, page: pageObj.current,
per_page: PAGE_SIZE, per_page: PAGE_SIZE,
@ -111,15 +110,15 @@ function InfoVideo (props) {
sort_direction: sorts[1], sort_direction: sorts[1],
} }
}) })
.then((response) => { .then((response) => {
setLoading(false) setLoading(false)
if (response.data.videos) { if (response.data.videos) {
setReviewvideos(response.data.videos) setReviewvideos(response.data.videos)
setCount(response.data.count) setCount(response.data.count)
} }
}).catch(() => { }).catch(() => {
}) })
} }
useEffect(() => { useEffect(() => {
@ -130,7 +129,7 @@ function InfoVideo (props) {
fetchReviewvideos() fetchReviewvideos()
} }
} else { } else {
pageObj.onChange(1) pageObj.onChange(1)
} }
}, [categoryObj.category]) }, [categoryObj.category])
@ -140,7 +139,7 @@ function InfoVideo (props) {
} else { } else {
fetchReviewvideos() fetchReviewvideos()
} }
}, [ pageObj.current, sortKey ]) }, [pageObj.current, sortKey])
useEffect(() => { useEffect(() => {
if (videoModalObj.visible == false) { if (videoModalObj.visible == false) {
@ -158,9 +157,9 @@ function InfoVideo (props) {
_clipboard = new ClipboardJS('.copybtn'); _clipboard = new ClipboardJS('.copybtn');
_clipboard.on('success', (e) => { _clipboard.on('success', (e) => {
showNotification('复制成功') showNotification('复制成功')
}); });
} }
}, 200) }, 200)
} }
}, [videoModalObj.visible]) }, [videoModalObj.visible])
@ -173,7 +172,7 @@ function InfoVideo (props) {
} }
function onEditVideo(item) { function onEditVideo(item) {
videoId = { videoId = {
videoId: item.id, videoId: item.id,
title: item.title title: item.title
} }
@ -182,7 +181,7 @@ function InfoVideo (props) {
// this.refs['editVideoModal'].setVisible(true, video); // this.refs['editVideoModal'].setVisible(true, video);
} }
function onMaskClick(item) { function onMaskClick(item) {
videoId = { videoId = {
videoId: item.id, videoId: item.id,
title: item.title, title: item.title,
file_url: item.file_url, file_url: item.file_url,
@ -219,12 +218,12 @@ function InfoVideo (props) {
} }
function getCopyText (file_url, cover_url) { function getCopyText(file_url, cover_url) {
return `<video src="${file_url}" controls="true" controlslist="nodownload" width="${DEFAULT_VIDEO_WIDTH_IN_MD}" height="${DEFAULT_VIDEO_HEIGHT_IN_MD}" poster="${cover_url}">您的浏览器不支持 video 标签。</video>` return `<video src="${file_url}" controls="true" controlslist="nodownload" width="${DEFAULT_VIDEO_WIDTH_IN_MD}" height="${DEFAULT_VIDEO_HEIGHT_IN_MD}" poster="${cover_url}">您的浏览器不支持 video 标签。</video>`
} }
const _inputValue = getCopyText(videoId.file_url, videoId.cover_url); const _inputValue = getCopyText(videoId.file_url, videoId.cover_url);
const sorts = sortKey.split('-') const sorts = sortKey.split('-')
return ( return (
<div className="educontent infoVideo"> <div className="educontent infoVideo">
@ -238,12 +237,7 @@ function InfoVideo (props) {
className="showVideoModal" className="showVideoModal"
width={800 - 1} width={800 - 1}
> >
<video <VideoPlay src={videoId.file_url} />
autoplay="true"
ref={videoEl}
src={videoId.file_url} controls="true" controlslist="nodownload">
您的浏览器不支持 video 标签
</video>
<div className="df copyLine"> <div className="df copyLine">
<Input value={_inputValue} <Input value={_inputValue}
className="dark" className="dark"
@ -318,130 +312,130 @@ function InfoVideo (props) {
onClick={() => { toUpload() }} onClick={() => { toUpload() }}
className="toUploadBtn" className="toUploadBtn"
> >
上传视频 上传视频
</Button> </Button>
} }
></InfoTab> ></InfoTab>
<div className="toolbarRow df" style={{ <div className="toolbarRow df" style={{
lineHeight: "40px", lineHeight: "40px",
}}> }}>
<span> <span>
<span style={{color: theme.foreground_orange1}}> {count} </span> <span style={{ color: theme.foreground_orange1 }}> {count} </span>
个视频 个视频
</span> </span>
{/*{categoryObj.category == 'all' && <CRoundSelect {...props}*/} {/*{categoryObj.category == 'all' && <CRoundSelect {...props}*/}
{/*width={'90px'}*/} {/*width={'90px'}*/}
{/*items={_items}*/} {/*items={_items}*/}
{/*onSortChange={onSortChange}*/} {/*onSortChange={onSortChange}*/}
{/*sortKey={sortKey }*/} {/*sortKey={sortKey }*/}
{/*></CRoundSelect>}*/} {/*></CRoundSelect>}*/}
{categoryObj.category == 'all' &&<div className="fr"> {categoryObj.category == 'all' && <div className="fr">
<li className="drop_down"> <li className="drop_down">
<span className="color-grey-9 font-12" style={{ <span className="color-grey-9 font-12" style={{
marginRight: " 5px", marginRight: " 5px",
}}>{"最新上传"}</span> }}>{"最新上传"}</span>
<sapn className="relativef color-grey-9 fr" <sapn className="relativef color-grey-9 fr"
style={{ style={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
height: "40px", height: "40px",
lineHeight: "40px", lineHeight: "40px",
}} }}
> >
<span <span
style={{ style={{
flexDirection: "column", flexDirection: "column",
textAlign: "center", textAlign: "center",
height: "10px", height: "10px",
lineHeight: "10px", lineHeight: "10px",
display: "table", display: "table",
marginTop: "9px", marginTop: "9px",
}} }}
> >
<i className={sorts[1] === "asc" ? <i className={sorts[1] === "asc" ?
"iconfont icon-sanjiaoxing-up font-12 color-blue h10 " : "iconfont icon-sanjiaoxing-up font-12 h10"} "iconfont icon-sanjiaoxing-up font-12 color-blue h10 " : "iconfont icon-sanjiaoxing-up font-12 h10"}
onClick={() => onSortChange("published_at-asc", 0)}></i> onClick={() => onSortChange("published_at-asc", 0)}></i>
</span> </span>
<span <span
style={{ style={{
flexDirection: "column", flexDirection: "column",
height: "10px", height: "10px",
lineHeight: "10px", lineHeight: "10px",
textAlign: "center", textAlign: "center",
display: "table", display: "table",
}} }}
> >
<i className={sorts[1] === "desc" ? <i className={sorts[1] === "desc" ?
"iconfont icon-sanjiaoxing-down font-12 yslbottomsj color-blue h10" : "iconfont icon-sanjiaoxing-down font-12 yslbottomsj h10"} "iconfont icon-sanjiaoxing-down font-12 yslbottomsj color-blue h10" : "iconfont icon-sanjiaoxing-down font-12 yslbottomsj h10"}
onClick={() => onSortChange("published_at-desc", 0)}></i> onClick={() => onSortChange("published_at-desc", 0)}></i>
</span> </span>
</sapn> </sapn>
</li> </li>
</div>} </div>}
</div> </div>
{categoryObj.category == 'all' ? {categoryObj.category == 'all' ?
<div className="itemWrap"> <div className="itemWrap">
{ {
videos == undefined ? '' : videos == undefined ? '' :
videos.length ? videos.length ?
videos.map((item, index) => { videos.map((item, index) => {
return (<VideoInReviewItem return (<VideoInReviewItem
{...props} {...props}
{...item} {...item}
key={item.id} key={item.id}
onEditVideo={onEditVideo} onEditVideo={onEditVideo}
onMaskClick={onMaskClick} onMaskClick={onMaskClick}
getCopyText={getCopyText} getCopyText={getCopyText}
> >
</VideoInReviewItem>) </VideoInReviewItem>)
}) })
: <NoneData style={{width: '100%'}}></NoneData> : <NoneData style={{ width: '100%' }}></NoneData>
} }
</div> </div>
: :
<div className="itemWrap"> <div className="itemWrap">
{ {
reviewvideos == undefined ? '' : reviewvideos == undefined ? '' :
reviewvideos.length ? reviewvideos.length ?
reviewvideos.map((item, index) => { reviewvideos.map((item, index) => {
return (<VideoInReviewItem return (<VideoInReviewItem
{...props} {...props}
{...item} {...item}
key={item.id} key={item.id}
isReview={true} isReview={true}
> >
</VideoInReviewItem>) </VideoInReviewItem>)
}) })
: <NoneData style={{width: '100%'}}></NoneData> : <NoneData style={{ width: '100%' }}></NoneData>
} }
</div> </div>
} }
{/* categoryObj.category == 'all' && */} {/* categoryObj.category == 'all' && */}
{ {
count > PAGE_SIZE && count > PAGE_SIZE &&
<div className="mt30 mb50 edu-txt-center"> <div className="mt30 mb50 edu-txt-center">
<Pagination showQuickJumper total={count} pageSize={PAGE_SIZE} <Pagination showQuickJumper total={count} pageSize={PAGE_SIZE}
{...pageObj} {...pageObj}
/> />
</div> </div>
} }
</div> </div>
) )
} }

@ -74,7 +74,10 @@ function VideoUploadList (props) {
clearInput() clearInput()
return; return;
} }
if (file.size >(parseInt(MAX_FILE_SIZE) * 1024 * 1024)) {
if(props&&props.user.admin===true||props&&props.user.business===true){
}else if (file.size >(parseInt(MAX_FILE_SIZE) * 1024 * 1024)) {
// 超过500m TODO // 超过500m TODO
clearInput() clearInput()
showNotification(`视频大小超过${MAX_FILE_SIZE}M`) showNotification(`视频大小超过${MAX_FILE_SIZE}M`)

Loading…
Cancel
Save