Merge branches 'dev_aliyun' and 'dev_hjm_a' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

dev_oauth
杨树明 6 years ago
commit 5c08820899

@ -470,6 +470,13 @@ class MessagSub extends Component{
}
case "Discuss":
return window.open(`/shixuns/${item.identifier}/shixun_discuss`);
case "Video":
if(item.tiding_type==="Apply"){
return window.open(`/managements/video_applies`);
}else if(item.tiding_type==="System"){
return window.open(`/users/${this.props.current_user.login}/videos`);
}
return '';
default :
return window.open("/")
}

@ -298,7 +298,7 @@ class Infos extends Component{
></Route>
{/* 项目 */}
<Route exact path="/users/:username/videoes"
<Route exact path="/users/:username/videos"
render={
(props) => (<InfosVideo {...this.props} {...props} {...this.state} {..._commonProps}/>)
}

@ -101,10 +101,10 @@ class InfosBanner extends Component{
to={`/users/${username}/package`}>众包</Link>
</li>
{((is_current && current_user && current_user.is_teacher ) || current_user && current_user.admin)
&& <li className={`${moduleName == 'videoes' ? 'active' : '' }`}>
&& <li className={`${moduleName == 'videos' ? 'active' : '' }`}>
<Link
onClick={() => this.setState({moduleName: 'videoes'})}
to={`/users/${username}/videoes`}>视频</Link>
onClick={() => this.setState({moduleName: 'videos'})}
to={`/users/${username}/videos`}>视频</Link>
</li>}
</div>
</div>

@ -23,6 +23,10 @@ const VideoPublishSuccess = Loadable({
loader: () => import('./video/VideoPublishSuccess'),
loading: Loading,
})
const VideoProtocol = Loadable({
loader: () => import('./video/VideoProtocol'),
loading: Loading,
})
const $ = window.$;
class InfosIndex extends Component{
@ -52,16 +56,23 @@ class InfosIndex extends Component{
{/* 视频发布 */}
<Route exact path="/users/:username/videoes/upload"
<Route exact path="/users/:username/videos/upload"
render={
(props) => (<VideoUploadList {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/users/:username/videoes/success"
<Route exact path="/users/:username/videos/success"
render={
(props) => (<VideoPublishSuccess {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/users/:username/videos/protocol"
render={
(props) => (<VideoProtocol {...this.props} {...props} {...this.state} />)
}
></Route>

@ -40,6 +40,7 @@ function HeadlessModal (props) {
width: 14px;
height: 8px;
margin-right: 0px;
z-index: 9;
}
.headless .icon-htmal5icon19:before {
left: -4px;

@ -7,6 +7,7 @@ let _path = isDev() ? 'public' : 'build'
let _testHost = '' ; // 'http://192.168.2.63:3001/api' ; // '' ;
let login = 'innov'
// https://help.aliyun.com/document_detail/52204.html?spm=5176.2020520165.120.d52204.19a47029YWhro7#%E4%B8%8A%E4%BC%A0%E5%9C%B0%E5%9D%80%E5%92%8C%E5%87%AD%E8%AF%81%E6%96%B9%E5%BC%8F(%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8)
let uploader;
let $ = window.$
function loadLib(callback) {
@ -46,7 +47,7 @@ function doCreateUploader (options) {
addFileSuccess: function (uploadInfo) {
console.log("addFileSuccess: " + uploadInfo.file.name)
options.addFileSuccess && options.addFileSuccess(uploadInfo)
uploader.startUpload()
},
// 开始上传
@ -63,10 +64,11 @@ function doCreateUploader (options) {
if (!uploadInfo.videoId) {
var createUrl = `${_testHost}/users/${login}/video_auths.json?debug=true`
var createUrl = `${_testHost}/users/${login}/video_auths.json`
const _random = '' // Math.random().toString().substring(3, 6)+'-'
axios.post(createUrl, {
title: fileName,
file_name: fileName
title: _random+fileName,
file_name: _random+fileName
}).then((response) => {
// if (response.data.status == )
const data = response.data.data
@ -75,7 +77,7 @@ function doCreateUploader (options) {
var videoId = data.VideoId
uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId)
options.addFileSuccess && options.addFileSuccess(uploadInfo)
}).catch((error) => {
// 删除当前出错的,并执行下一个任务
@ -89,10 +91,12 @@ function doCreateUploader (options) {
console.log("onUploadStarted:" + uploadInfo.file.name + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object)
} else {
// 如果videoId有值根据videoId刷新上传凭证
var refreshUrl = `${_testHost}/users/${login}/video_auths.json?debug=true`
var refreshUrl = `${_testHost}/users/${login}/video_auths.json`
axios.put(refreshUrl, {
video_id: uploadInfo.videoId,
title: fileName,
file_name: fileName
}).then((response) => {
if (response.data.status == -1) {
options.onUploadError && options.onUploadError(uploadInfo)
@ -102,9 +106,10 @@ function doCreateUploader (options) {
var uploadAuth = data.UploadAuth
var uploadAddress = data.UploadAddress
var videoId = data.VideoId
uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId)
uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress)
// , videoId
options.addFileSuccess && options.addFileSuccess(uploadInfo)
}).catch((error) => {
uploader.deleteFile(uploader._curIndex)
uploader.nextUpload()
@ -145,7 +150,7 @@ function doCreateUploader (options) {
// 需要根据 uploadInfo.videoId 调用刷新视频上传凭证接口(https://help.aliyun.com/document_detail/55408.html)重新获取 UploadAuth
// 然后调用 resumeUploadWithAuth 方法, 这里是测试接口, 所以我直接获取了 UploadAuth
$('#status').text('文件上传超时!')
var refreshUrl = `${_testHost}/users/${login}/video_auths.json?debug=true`
var refreshUrl = `${_testHost}/users/${login}/video_auths.json`
axios.put(refreshUrl, {

@ -14,10 +14,10 @@ function EditVideoModal (props) {
const _title = form.getFieldsValue().title;
function toList() {
history.push(`/users/${username}/videoes`)
history.push(`/users/${username}/videos`)
}
function toUpload() {
history.push(`/users/${username}/videoes/upload`)
history.push(`/users/${username}/videos/upload`)
}
function onOk() {
form.validateFieldsAndScroll((err, values) => {
@ -57,8 +57,9 @@ function EditVideoModal (props) {
<ModalWrapper
ref={modalEl}
width="600px"
title={`视频编辑`}
{ ...props }
title={`视频标题编辑`}
onOk={onOk}
onCancel={onCancel}
className="editVideoModal"

@ -50,8 +50,8 @@ const _items=[
{key: 'published_at-asc', name: '最早上传'},
]
function InfoVideo (props) {
const [videoes, setVideoes] = useState(undefined)
const [reviewVideoes, setReviewVideoes] = useState(undefined)
const [videos, setvideos] = useState(undefined)
const [reviewvideos, setReviewvideos] = useState(undefined)
const [count, setCount] = useState(0)
const [loading, setLoading] = useState(true)
const [sortKey, setSortKey] = useState(_items[0].key)
@ -70,13 +70,13 @@ function InfoVideo (props) {
function toUpload() {
if (props.current_user.admin || (props.current_user.is_teacher && props.checkIfProfessionalCertification())) {
history.push(`/users/${username}/videoes/upload`)
history.push(`/users/${username}/videos/upload`)
} else {
props.showProfessionalCertificationDialog()
}
}
function fetchVideoes() {
function fetchvideos() {
const fetchUrl = `/users/${username}/videos.json`
const sorts = sortKey.split('-')
setLoading(true)
@ -92,25 +92,29 @@ function InfoVideo (props) {
.then((response) => {
setLoading(false)
if (response.data.videos) {
setVideoes(response.data.videos)
setvideos(response.data.videos)
setCount(response.data.count)
}
}).catch(() => {
})
}
function fetchReviewVideoes() {
function fetchReviewvideos() {
const fetchUrl = `/users/${username}/videos/review.json`
const sorts = sortKey.split('-')
setLoading(true)
axios.get(fetchUrl, {
params: {
per_page: 200
page: pageObj.current,
per_page: PAGE_SIZE,
sort_by: sorts[0],
sort_direction: sorts[1],
}
})
.then((response) => {
setLoading(false)
if (response.data.videos) {
setReviewVideoes(response.data.videos)
setReviewvideos(response.data.videos)
setCount(response.data.count)
}
}).catch(() => {
@ -119,16 +123,24 @@ function InfoVideo (props) {
}
useEffect(() => {
fetchVideoes()
}, [pageObj.current, sortKey])
if (pageObj.current == 1) {
if (categoryObj.category == 'all') {
fetchvideos()
} else {
fetchReviewvideos()
}
} else {
pageObj.onChange(1)
}
}, [categoryObj.category])
useEffect(() => {
if (categoryObj.category == 'all') {
fetchVideoes()
fetchvideos()
} else {
fetchReviewVideoes()
fetchReviewvideos()
}
}, [categoryObj.category])
}, [ pageObj.current, sortKey ])
useEffect(() => {
if (videoModalObj.visible == false) {
@ -139,6 +151,8 @@ function InfoVideo (props) {
_clipboard = null;
}
} else {
videoEl.current && videoEl.current.play()
setTimeout(() => {
if (!_clipboard) {
_clipboard = new ClipboardJS('.copybtn');
@ -155,7 +169,7 @@ function InfoVideo (props) {
}, [])
function editSuccess() {
fetchVideoes()
fetchvideos()
}
function onEditVideo(item) {
@ -201,6 +215,7 @@ function InfoVideo (props) {
width={800 - 1}
>
<video
autoplay="true"
ref={videoEl}
src={videoId.file_url} controls="true" controlslist="nodownload">
您的浏览器不支持 video 标签
@ -285,9 +300,9 @@ function InfoVideo (props) {
{categoryObj.category == 'all' ?
<div className="itemWrap">
{
videoes == undefined ? '' :
videoes.length ?
videoes.map((item, index) => {
videos == undefined ? '' :
videos.length ?
videos.map((item, index) => {
return (<VideoInReviewItem
{...props}
@ -306,9 +321,9 @@ function InfoVideo (props) {
:
<div className="itemWrap">
{
reviewVideoes == undefined ? '' :
reviewVideoes.length ?
reviewVideoes.map((item, index) => {
reviewvideos == undefined ? '' :
reviewvideos.length ?
reviewvideos.map((item, index) => {
return (<VideoInReviewItem
{...props}
@ -324,9 +339,9 @@ function InfoVideo (props) {
}
{/* categoryObj.category == 'all' && */}
{
categoryObj.category == 'all' && count > PAGE_SIZE &&
count > PAGE_SIZE &&
<div className="mt30 mb50 edu-txt-center">
<Pagination showQuickJumper total={count} pageSize={PAGE_SIZE}
{...pageObj}

@ -16,6 +16,7 @@ title: "测试标题"
updated_at: "2019-08-12 17:17:09"
*/
let _clipboard = null;
const clipboardMap = {}
function VideoInReviewItem (props) {
const theme = useContext(ThemeContext);
const { history, file_url, cover_url, title, created_at, published_at, isReview, id
@ -26,17 +27,21 @@ function VideoInReviewItem (props) {
_clipboard.on('success', (e) => {
showNotification('复制成功')
});
clipboardMap[id] = _clipboard
}
return () => {
_clipboard && _clipboard.destroy();
if (clipboardMap[id]) {
clipboardMap[id].destroy();
clipboardMap[id] = null;
}
}
}, [])
const username = props.match.params.username
function toList() {
history.push(`/users/${username}/videoes`)
history.push(`/users/${username}/videos`)
}
function toUpload() {
history.push(`/users/${username}/videoes/upload`)
history.push(`/users/${username}/videos/upload`)
}
return (
<div className={`${isReview ? 'videoInReviewItem' : 'nItem'} videoItem`}>

@ -0,0 +1,186 @@
import React, { useState, useEffect, useContext, memo } from 'react';
import { Progress, Input } from 'antd'
import { getUrl2, isDev, CBreadcrumb, ActionBtn, ThemeContext } from 'educoder'
import axios from 'axios'
import okIcon from './images/ok_border.png'
function VideoProtocol (props) {
const theme = useContext(ThemeContext);
const username = props.match.params.username
const { history } = props;
return (
<div className={`educontent videoProtocol`}>
<CBreadcrumb
className="mb26 mt16"
separator=" > "
items={[
{ to: `/users/${username}/videos/upload`, name: '视频上传'},
{ name: '内容上传协议'}
]}
></CBreadcrumb>
<style>{`
.videoProtocol {
margin-bottom: 200px;
}
.videoProtocol .title {
padding: 4px 16px;
background: #fff;
margin-bottom: 12px;
margin-top: 30px;
font-size: 16px;
font-weight: bold;
}
.videoProtocol .content {
background: #fff;
padding: 30px;
}
.videoProtocol .subTitle {
font-size: 16px;
font-weight: bold;
}
.videoProtocol .p_paragraph {
font-size: 12px;
text-indent: 22.5pt;
margin: 10px 0;
}
.videoProtocol .p_paragraph.has_child {
margin-bottom: 2px;
}
.videoProtocol .p_child_paragraph {
font-size: 12px;
text-indent: 40pt;
}
`}</style>
<div className="title">内容上传协议</div>
<div className="content">
<div className="subTitle">
总则
</div>
<p className="p_paragraph">
1.1 用户同意本协议的条款并按照页面上的提示完成视频上传流程用户在点击视频上传的图标时即表示已阅读内容上传协议与湖南智擎科技有限公司以下简称EduCoder平台达成协议完全接受本协议项下全部条款
</p>
<p className="p_paragraph">
1.2 用户在EduCoder平台上www.educoder.net上传视频应当使用已注册的有效用户名和密码该用户帐号和密码由用户负责保管用户不得将帐号和密码转让给任何第三人用户应当对以其用户帐号进行的所有活动和事件负法律责任
</p>
<p className="p_paragraph">
1.3 EduCoder平台用户在上传视频时除遵守本协议的规定还同时应当遵守EduCoder平台的其他协议和规定以及遵守中华人民共和国的法律法规EduCoder平台上传用户协议及EduCoder平台的其他协议可由EduCoder平台随时更新且无需另行通知用户在使用相关服务时应关注并遵守其所适用的相关条款
</p>
<div className="subTitle">
合法使用视频上传服务
</div>
<p className="p_paragraph">
2.1 用户在使用视频上传服务时必须遵守中华人民共和国相关法律法规的规定用户同意将不会利用本服务进行任何违法或不正当的活动包括但不限于上传包含有下列内容之一的视频内容
</p>
<p className="p_paragraph">
1反对宪法确定的基本原则2危害国家统一主权和领土完整的3泄露国家秘密危害国家安全或者损害国家荣誉和利益的4煽动民族仇恨民族歧视破坏民族团结或者侵害民族风俗习惯的5宣扬邪教迷信的 6扰乱社会秩序破坏社会稳定的 7诱导未成年人违法犯罪和渲染暴力色情赌博恐怖活动的 8侮辱或者诽谤他人侵害公民个人隐私等他人合法权益的9危害社会公德损害民族优秀文化传统的10非法的广播电视频道视听节目网站提供的非法视频内容11有关法律行政法规和国家规定禁止的其他内容
</p>
<p className="p_paragraph">
2.2 用户不得对本服务任何部分或本服务之使用或获得进行复制拷贝出售转售或用于任何其它商业目的
</p>
<p className="p_paragraph">
2.3 用户须对自己在使用EduCoder平台服务过程中的行为承担法律责任用户承担法律责任的形式包括但不限于对受到侵害者进行赔偿以及在EduCoder平台首先承担了因用户行为导致的行政处罚或侵权损害赔偿责任后用户应给予EduCoder平台等额的赔偿
</p>
<div className="subTitle">
知识产权及其他合法权益保护
</div>
<p className="p_paragraph">
3.1 EduCoder平台提供视频上传功能专为用户自己创作或享有合法来源的作品提供服务EduCoder平台尊重他人知识产权和合法权益请用户在上传视频前确保拥有上传的视频内容的著作权及信息网络传播权或者已经取得上述全部权利人的许可
</p>
<p className="p_paragraph">
3.2 用户应确保上传的视频内容已经获得被拍摄人如有的许可并确保视频内容没有侵犯他人的人身权包括但不限于名誉权肖像权隐私权姓名权不存在任何著作权纠纷
</p>
<div className="subTitle">
服务风险及免费声明
</div>
<p className="p_paragraph">
4.1 用户完全理解并同意本服务涉及到互联网及移动通讯等服务可能会受到各个环节不稳定因素的影响因此服务存在因上述不可抗力计算机病毒或黑客攻击系统不稳定用户所在位置用户关机GSM网络互联网络通信线路原因等造成的服务中断或不能满足用户要求的风险使用本服务的用户须承担以上风险EduCoder平台对服务之及时性安全性准确性不作担保对因此导致用户不能发送和接受阅读消息或传递错误个人设定之时效未予储存或其他问题不承担任何责任对于不可抗力或非EduCoder平台过错原因导致的用户数据损失丢失或服务停止EduCoder平台将不承担任何责任
</p>
<p className="p_paragraph">
4.2 对于系统发生故障影响到本服务的正常运行EduCoder平台承诺及时处理进行修复但用户因此而产生的经济和精神损失EduCoder平台不承担责任此外EduCoder平台保留不经事先通知为维修保养升级或其他目的暂停本服务任何部分的权利
</p>
<p className="p_paragraph">
4.3 EduCoder平台郑重提请您注意任何经由本服务上传的视频内容均由内容提供者承担责任EduCoder平台无法控制经由本服务上载之内容也无法对用户的使用行为进行全面控制因此不保证内容的合法性正确性完整性真实性或品质您已预知使用本服务时可能会接触到令人不快不适当或令人厌恶之内容并同意将自行加以判断并承担所有风险而不依赖于EduCoder平台但在任何情况下EduCoder平台有权依法停止传输任何前述内容并采取相应行动包括但不限于暂停用户使用本服务的全部或部分保存有关记录并向有关机关报告EduCoder平台有权(但无义务)依其自行之考量拒绝和删除可经由本服务提供之违反本条款的或其他引起EduCoder平台或其他用户反感的任何内容
</p>
<p className="p_paragraph">
4.4 用户完全理解并同意若第三方在您不知情或未经您同意的前提下将您的视频作品上传于EduCoder平台及由此所产生的任何可能侵害您权益的行为EduCoder平台均不对任何人承担任何责任
</p>
<p className="p_paragraph">
4.5 用户完全理解并同意第三方可以通过访问EduCoder平台网站而获得educoder平台中的相关信息并可对信息进行使用行为对用户或第三方以任何方式进行的使用可能侵害您权益的行为EduCoder平台均不对任何人承担任何责任
</p>
<p className="p_paragraph has_child">
4.6 如发生下列任何一种情形EduCoder平台有权随时中断或终止向用户提供服务而无需通知该用户
</p>
<p className="p_child_paragraph">
4.6.1 用户提供的个人资料不真实
</p>
<p className="p_child_paragraph">
4.6.2 用户违反本服务条款的规定
</p>
<p className="p_child_paragraph">
4.6.3 按照主管部门的要求
</p>
<p className="p_child_paragraph">
4.6.4 EduCoder平台收到第三方投诉且该第三方出具相应证据的
</p>
<p className="p_child_paragraph">
4.6.5 其他EduCoder平台认为是符合整体服务需求的特殊情形
</p>
<div className="subTitle">
违约视频的处理原则   
</div>
<p className="p_paragraph">
5.1 如用户在使用视频上传服务时违反任何上述规定EduCoder平台或其授权的人有权要求用户改正或不经通知直接采取一切必要的措施包括但不限于删除上传的视频内容以减轻和消除用户不当行为造成的影响
</p>
<p className="p_paragraph">
5.2 如EduCoder平台认为用户的视频上传行为严重违反了本协议并给EduCoder平台造成了损害EduCoder平台无需进行事先通知即可终止用户的密码帐号或本服务之使用且EduCoder平台对用户或任何第三人均不承担任何责任
</p>
<p className="p_paragraph">
5.3 EduCoder平台有权启动必要的刑事及民事法律程序维护EduCoder平台的合法权益追究违法用户的法律责任
</p>
<div className="subTitle">
协议修改   
</div>
<p className="p_paragraph">
6.1 EduCoder平台有权随时修改本协议的任何条款一旦本协议的内容发生变动EduCoder平台将会通过适当方式向用户提示修改内容
</p>
<p className="p_paragraph">
6.2 如果不同意EduCoder平台对本协议相关条款所做的修改用户有权停止使用网络服务如果用户继续使用网络服务则视为用户接受EduCoder平台对本协议相关条款所做的修改
</p>
<div className="subTitle">
通知送达  
</div>
<p className="p_paragraph">
7.1 本协议项下EduCoder平台对于用户所有的通知均可通过公告电子邮件或常规的信件传送等方式进行该等通知于发送之日视为已送达收件人
</p>
<p className="p_paragraph">
7.2 用户对于EduCoder平台的通知应当通过EduCoder平台网站公布的通信地址传真号码电子邮件地址等联系信息进行送达
</p>
<div className="subTitle">
其他  
</div>
<p className="p_paragraph">
8.1 本协议的订立执行和解释及争议的解决均应适用中华人民共和国法律
</p>
<p className="p_paragraph">
8.2 如双方就本协议内容或其执行发生任何争议双方应尽量友好协商解决协商不成时任何一方均可向EduCoder平台所在地的人民法院提起诉讼
</p>
<p className="p_paragraph">
8.3 EduCoder平台未行使或执行本服务协议任何权利或规定不构成对前述权利或权利之放弃
</p>
<p className="p_paragraph">
8.4 如本协议中的任何条款无论因何种原因完全或部分无效或不具有执行力本协议的其余条款仍应有效并且有约束力
</p>
</div>
</div>
)
}
export default VideoProtocol

@ -10,10 +10,10 @@ function VideoUpload (props) {
const username = props.match.params.username
function toList() {
history.push(`/users/${username}/videoes`)
history.push(`/users/${username}/videos`)
}
function toUpload() {
history.push(`/users/${username}/videoes/upload`)
history.push(`/users/${username}/videos/upload`)
}
return (
@ -22,7 +22,7 @@ function VideoUpload (props) {
className="mb26 mt16"
separator=" > "
items={[
{ to: `/users/${username}/videoes`, name: '视频'},
{ to: `/users/${username}/videos`, name: '视频'},
{ name: '上传'}
]}
></CBreadcrumb>

@ -2,9 +2,9 @@ import update from 'immutability-helper'
function find(state, action) {
let _index = -1
state.videoes.some((item, index) => {
state.videos.some((item, index) => {
// 同文件不同名字 fileHash也是一样的
if (item.loaded != 100 && (action.uploadInfo.fileHash == item.fileHash && action.uploadInfo.file.name == item.name)) {
if (item.loaded != 100 && ((!item.fileHash || action.uploadInfo.fileHash == item.fileHash) && action.uploadInfo.file.name == item.name)) {
_index = index
return true;
}
@ -15,7 +15,7 @@ export function reducer(state, action) {
switch (action.type) {
case 'addVideo':
const uploadInfo = action.uploadInfo
return {videoes: [...state.videoes, {
return {videos: [...state.videos, {
name: uploadInfo.file.name,
size: uploadInfo.file.size,
type: uploadInfo.file.type,
@ -29,14 +29,18 @@ export function reducer(state, action) {
}]};
case 'removeVideo':
return {
videoes: update(state.videoes, {$splice: [[action.index, 1]]})
videos: update(state.videos, {$splice: [[action.index, 1]]})
}
case 'removeAll':
return {
videos: []
}
case 'updateProgress':
let _index = find(state, action)
let newVideoes = state.videoes
let newvideos = state.videos
// 删除先执行
if (_index != -1) {
newVideoes = update(state.videoes, {[_index]: {
newvideos = update(state.videos, {[_index]: {
loaded: {$set: action.progressPercent},
videoId: {$set: action.uploadInfo.videoId},
@ -44,21 +48,21 @@ export function reducer(state, action) {
fileHash: {$set: action.uploadInfo.fileHash}
}})
}
return {videoes: newVideoes};
return {videos: newvideos};
case 'updateTitle':
let _upadteIndex = action.index
let newVideoes2 = state.videoes
let newvideos2 = state.videos
if (_upadteIndex != -1) {
newVideoes2 = update(state.videoes, {[_upadteIndex]: {
newvideos2 = update(state.videos, {[_upadteIndex]: {
title: {$set: action.title},
}})
}
return {videoes: newVideoes2};
return {videos: newvideos2};
default:
throw new Error();
}
}
export const initialState = {videoes: []};
export const initialState = {videos: []};

@ -1,5 +1,5 @@
import React, { useState, useEffect, useReducer, useContext, memo } from 'react';
import { Link, Prompt } from "react-router-dom";
import { getUrl2, isDev, CBreadcrumb, ActionBtn, ThemeContext } from 'educoder'
import axios from 'axios'
@ -17,22 +17,28 @@ const files = []
const MAX_FILE_COUNT = 3
const MAX_FILE_SIZE = 200
let noUploads = true
function VideoUploadList (props) {
// const [videoes, setVideoes] = useState([]);
// const [videos, setvideos] = useState([]);
const [state, dispatch] = useReducer(reducer, initialState);
const theme = useContext(ThemeContext)
const [couldRouteNav, setCouldRouteNav] = useState(false)
useEffect(() => {
setCouldRouteNav(false);
// Chrome removed support for custom message in ver 51
// https://stackoverflow.com/questions/38879742/is-it-possible-to-display-a-custom-message-in-the-beforeunload-popup
window.addEventListener("beforeunload", beforeunload);
// window.onbeforeunload = beforeunload
return () => {
uploader = null;
// window.onbeforeunload = null;
window.removeEventListener("beforeunload", beforeunload);
}
}, [])
// TODO 闭包!
noUploads = (!state.videoes || state.videoes.length == 0);
noUploads = (!state.videos || state.videos.length == 0);
function beforeunload(e) {
if (noUploads) {
return true;
@ -62,7 +68,7 @@ function VideoUploadList (props) {
return;
}
let gotTheSameFileName = false;
state.videoes.some((item) => {
state.videos.some((item) => {
if (item.name == file.name) {
gotTheSameFileName = true;
return true;
@ -86,7 +92,7 @@ function VideoUploadList (props) {
addFileSuccess: (uploadInfo) => {
const file = uploadInfo.file
console.log('addFileSuccess', uploadInfo)
// const newVideoes = [...videoes, {
// const newvideos = [...videos, {
// name: file.name,
// size: file.size,
// type: file.type,
@ -96,7 +102,7 @@ function VideoUploadList (props) {
// videoId: uploadInfo.videoId, // "719b82c875c34ac39f94feb145d25ad2"
// loaded: 0
// }]
// setVideoes(newVideoes)
// setvideos(newvideos)
// files.push(file)
clearInput()
@ -107,7 +113,7 @@ function VideoUploadList (props) {
var progressPercent = Math.ceil(progress * 100)
// let _index = -1;
// videoes.some((item, index) => {
// videos.some((item, index) => {
// // addFileSuccess的时候没有fileHash
// // if (uploadInfo.fileHash == item.fileHash) {
// if (uploadInfo.file.name == item.name) {
@ -119,7 +125,7 @@ function VideoUploadList (props) {
// TODO 这里不用reducer会出现state被重置的问题
// if (_index == -1) {
// const newVideoes = [...videoes, {
// const newvideos = [...videos, {
// name: file.name,
// size: file.size,
// type: file.type,
@ -129,12 +135,12 @@ function VideoUploadList (props) {
// videoId: uploadInfo.videoId, // "719b82c875c34ac39f94feb145d25ad2"
// loaded: progressPercent
// }]
// setVideoes(newVideoes)
// setvideos(newvideos)
// return;
// }
// // exercise_questions : update(prevState.exercise_questions, {[index]: { isNew: {$set: false}}})
// setVideoes(update(videoes, {[_index]: { loaded: {$set: progressPercent}}}))
// setvideos(update(videos, {[_index]: { loaded: {$set: progressPercent}}}))
dispatch({type: 'updateProgress', uploadInfo, progressPercent})
},
@ -177,14 +183,16 @@ function VideoUploadList (props) {
}
function doDelete(index, isSuccess) {
uploader.deleteFile(index)
// uploader.cancelFile(index)
if (isSuccess) {
deleteVideoInCloud(username, state.videoes[index].videoId)
}
// uploader.deleteFile(index)
// deleteVideoInCloud(username, state.videos[index].videoId)
} else {
// uploader.cancelFile(index)
}
clearInput()
dispatch({type: 'removeVideo', index})
// setVideoes([...videoes.splice(index, 1)])
// setvideos([...videos.splice(index, 1)])
}
// uploader.deleteFile(index);
function cancelUpload(index, isSuccess) {
@ -199,13 +207,13 @@ function VideoUploadList (props) {
}
function onPublish() {
if (state.videoes.length == 0) {
if (state.videos.length == 0) {
showNotification('请先上传视频')
return;
}
const publishUrl = `/users/${username}/videos/batch_publish.json`
axios.post(publishUrl, {
videos: state.videoes.map(item => {
videos: state.videos.map(item => {
return {
video_id: item.videoId,
// todo
@ -215,7 +223,9 @@ function VideoUploadList (props) {
}).then((response) => {
// to success page
if (response.data.status == 0) {
history.push(`/users/${username}/videoes/success`)
dispatch({type: 'removeAll'})
// setCouldRouteNav(true)
history.push(`/users/${username}/videos/success`)
}
}).catch((error) => {
console.log(error)
@ -225,9 +235,14 @@ function VideoUploadList (props) {
dispatch({type: 'updateTitle', title, index})
}
// login
const protocolLine = <div>上传视频即表示您已同意<span style={{color: theme.foreground_select}}>上传内容协议</span></div>
const protocolLine = <div>上传视频即表示您已同意
<Link to={`/users/${username}/videos/protocol`} style={{color: theme.foreground_select}}>上传内容协议</Link></div>
return (
<div className="educontent videoUploadList" style={{ marginBottom: '200px' }}>
<Prompt
when={state.videos.length }
message='确认要离开当前页面,当前数据不可恢复'
/>
<style>{`
.videoUploadList .section {
background: #fff;
@ -294,6 +309,7 @@ function VideoUploadList (props) {
/* item */
.videoUploadList .cancelUpload {
flex: 0 0 200px;
margin-left: 2px;
}
.videoUploadList .titleInput {
width: 480px;
@ -332,7 +348,7 @@ function VideoUploadList (props) {
className="mb26"
separator=" > "
items={[
{ to: `/users/${username}/videoes`, name: '视频'},
{ to: `/users/${username}/videos`, name: '视频'},
{ name: '上传'}
]}
></CBreadcrumb>
@ -361,7 +377,7 @@ function VideoUploadList (props) {
</div>}
<div>
{state.videoes.map((item, vIndex) => {
{state.videos.map((item, vIndex) => {
return (
<VideoUpload {...props} {...item} className=""
cancelUpload={cancelUpload}
@ -372,24 +388,24 @@ function VideoUploadList (props) {
)
})}
</div>
{state.videoes && state.videoes.length === MAX_FILE_COUNT &&
{state.videos && state.videos.length === MAX_FILE_COUNT &&
<div className="uploadTip">
<i className="iconfont icon-tishi" style={{color: '#FF6F6F', verticalAlign: 'text-bottom'}}></i>
<span>单次最多支持3个视频文件上传</span>
{/* <i className="iconfont icon-tishi" style={{color: '#FF6F6F', verticalAlign: 'text-bottom'}}></i> */}
<span>提示单次最多支持3个视频文件上传</span>
</div>}
{(!noUploads && state.videoes.length < MAX_FILE_COUNT) && <ActionBtn className="publishBtn" onClick={() => document.getElementById('fileUpload').click()}
{(!noUploads && state.videos.length < MAX_FILE_COUNT) && <ActionBtn className="publishBtn" onClick={() => document.getElementById('fileUpload').click()}
>继续添加</ActionBtn>}
<div className={`description ${noUploads ? 'noUploads' : ''}`}>
<div className="">视频大小不支持断点续传单个视频文件最大200M单次最多支持3个视频文件上传 </div>
<div className="">视频规格aviflvf4vm4vmovmp4rmvbswfwebm </div>
<div className="">温馨提示请勿上传违法视频平台将为每一个视频分配一个地址您可以通过引用地址将视频使用在开发社区等模块</div>
<div className="">温馨提示请勿上传违法视频平台将为每一个视频分配一个地址您可以通过引用地址将视频使用在开发社区等模块</div>
</div>
{!noUploads && <React.Fragment>
{/* {(state.videoes.length < MAX_FILE_COUNT) && <Button type="primary" icon="plus-square"
{/* {(state.videos.length < MAX_FILE_COUNT) && <Button type="primary" icon="plus-square"
onClick={() => { document.getElementById('fileUpload').click()}}
className="fr addVideoBtn"
>
@ -405,8 +421,9 @@ function VideoUploadList (props) {
</React.Fragment>}
</div>
{/* windows video/* 不管用 TODO */}
<input type="file" id="fileUpload" style={{display: 'none'}} onChange={onUploadChange}
accept="video/*"
accept=".flv, .f4v, .rmvb, .swf, video/mp4,video/x-m4v,video/flv,video/f4v,video/rmvb,video/swf,video/*"
></input>
</div>
)

Loading…
Cancel
Save