hjm 6 years ago
parent 0e47f3e69d
commit 1703e76c78

@ -4,7 +4,9 @@ export const themes = {
light: {
foreground: '#000000',
background: '#eeeeee',
foreground_select: '#4CACFF'
foreground_select: '#4CACFF',
foreground_tip: '#333'
},
dark: {
foreground: '#ffffff',

@ -64,3 +64,5 @@ export { default as ImageLayerHook } from './hooks/ImageLayerHook'
// 外部
export { default as CBreadcrumb } from '../modules/courses/common/CBreadcrumb'
export { CNotificationHOC as CNotificationHOC } from '../modules/courses/common/CNotificationHOC'
export { default as ModalWrapper } from '../modules/courses/common/ModalWrapper'

@ -16,6 +16,7 @@ class ModalWrapper extends Component{
}
onCancel = () => {
this.setVisible(false)
this.props.onCancel && this.props.onCancel()
}
onOk = () => {
this.props.onOk && this.props.onOk()

@ -1173,6 +1173,7 @@ samp {
border-right: none!important;
box-shadow: none!important;
}
/* 这个加了干嘛的影响到了带addonAfter的input */
.searchViewAfter,.searchViewAfter:focus,.searchViewAfter .ant-input:hover,.ant-input-group .ant-input:focus{
border-right: none!important;
}

@ -19,6 +19,10 @@ const VideoUploadList = Loadable({
loader: () => import('./video/VideoUploadList'),
loading: Loading,
})
const VideoPublishSuccess = Loadable({
loader: () => import('./video/VideoPublishSuccess'),
loading: Loading,
})
const $ = window.$;
class InfosIndex extends Component{
@ -53,6 +57,13 @@ class InfosIndex extends Component{
(props) => (<VideoUploadList {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/users/:username/videoes/success"
render={
(props) => (<VideoPublishSuccess {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/users/:username"

@ -0,0 +1,70 @@
import React, { useState, useEffect, useContext, useRef, memo } from 'react';
import { Progress, Input, Tooltip, Form } from 'antd'
import { getUrl2, isDev, CBreadcrumb, ActionBtn, ThemeContext, ModalWrapper } from 'educoder'
import axios from 'axios'
function EditVideoModal (props) {
const modalEl = useRef(null);
const theme = useContext(ThemeContext);
const { history, id, cover_url, title, created_at, isReview, onEditVideo, visible, setVisible,
form } = props;
const getFieldDecorator = form.getFieldDecorator
const username = props.match.params.username
function toList() {
history.push(`/users/${username}/videoes`)
}
function toUpload() {
history.push(`/users/${username}/videoes/upload`)
}
function onOk() {
form.validateFieldsAndScroll((err, values) => {
if (!err) {
} else {
// $("html").animate({ scrollTop: $('html').scrollTop() - 100 })
}
})
// setVisible(false)
}
function onCancel() {
setVisible(false)
}
useEffect(() => {
modalEl.current.setVisible(visible)
}, [visible])
const _title = form.getFieldsValue().title;
return (
<ModalWrapper
ref={modalEl}
width="600px"
title={`视频编辑`}
{ ...props }
onOk={onOk}
onCancel={onCancel}
className="editVideoModal"
>
<Form.Item
label="视频标题"
className="title "
>
{getFieldDecorator('title', {
rules: [{
required: true, message: '请输入标题',
}, {
max: 30, message: '最大限制为30个字符',
}],
})(
<Input placeholder="" className="titleInput" maxLength="30"
addonAfter={String(_title ? _title.length : 0)} />
)}
</Form.Item>
</ModalWrapper>
)
}
const WrappedEditVideoModal = Form.create({ name: 'editVideoModal' })(EditVideoModal);
export default WrappedEditVideoModal

@ -0,0 +1,68 @@
.itemWrap {
display: flex;
flex-wrap: wrap;
}
/* item */
.videoItem {
width: 280px;
margin-right: 26px;
margin-bottom: 26px;
position: relative;
}
.videoItem:nth-child(4n+0) {
margin-right: 0px;
}
.videoItem img.cover {
width: 100%;
border-radius: 6px 6px 0px 0px;
height: 180px;
}
.nItem.videoItem:hover .mask {
display: block;
top: 0px;
width: 100%;
height: 180px;
cursor: pointer;
}
.nItem .mask {
border-radius: 6px 6px 0px 0px;
display: none;
text-align: center;
position: absolute;
background: #000;
opacity: 0.5;
}
.videoItem img.play {
margin-top: 20%;
}
.videoItem .square-main {
padding: 10px 8px;
background: #fff;
border-radius: 0px 0px 6px 6px;
}
.videoItem .square-main .title{
max-width: 256px;
line-height: 18px;
}
.videoInReviewItem .square-main {
background: #EAEAEA;
}
.videoItem .time {
color: #A0A0A0;
}
.videoItem .square-main .buttonRow {
justify-content: space-between;
line-height: 15px;
}
.nItem.videoItem:hover .square-main {
color: #fff;
background: #333;
}

@ -1,12 +1,33 @@
import React, { useState, useEffect, memo } from 'react';
import React, { useState, useEffect, useContext, useRef, memo } from 'react';
import {Link} from 'react-router-dom';
import { getUrl2, isDev } from 'educoder'
import { getUrl2, isDev, ThemeContext } from 'educoder'
import axios from 'axios'
import VideoInReviewItem from './VideoInReviewItem'
import EditVideoModal from './EditVideoModal'
import './InfosVideo.css'
function useModal(initValue) {
const [visible, setVisible] = useState(initValue)
return {
visible,
setVisible
}
}
const PAGE_SIZE = 12
function InfoVideo (props) {
const [videoes, setVideoes] = useState([])
const [reviewVideoes, setReviewVideoes] = useState([])
const editModalObj = useModal(false)
const theme = useContext(ThemeContext);
const editModalEl = useRef(null);
const username = props.match.params.username
let cVideo = {};
function fetchVideoes() {
const fetchUrl = `/users/${username}/videos.json`
@ -16,7 +37,9 @@ function InfoVideo (props) {
}
})
.then((response) => {
if (response.data.videos) {
setVideoes(response.data.videos)
}
}).catch(() => {
})
@ -29,7 +52,9 @@ function InfoVideo (props) {
}
})
.then((response) => {
if (response.data.videos) {
setReviewVideoes(response.data.videos)
}
}).catch(() => {
})
@ -40,9 +65,64 @@ function InfoVideo (props) {
fetchReviewVideoes()
}, [])
function onEditVideo(video) {
cVideo = video
editModalObj.setVisible(true)
// editModalEl.current.toList(true, video);
// this.refs['editVideoModal'].setVisible(true, video);
}
return (
<div>123
<div className="educontent infoVideo">
<EditVideoModal ref={editModalEl} {...props} {...cVideo} {...editModalObj}></EditVideoModal>
<style>{`
/* item */
.videoPublishSuccess .section {
background: #fff;
padding: 16px 20px;
padding-top: 0px;
position: relative;
text-align: center;
color: ${theme.foreground_tip};
}
.videoItem .square-main .buttonRow i {
vertical-align: top;
font-size: 16px;
color: ${theme.foreground_select} !important;
margin-left: 6px;
}
`}</style>
<div className="itemWrap">
{reviewVideoes.map((item, index) => {
return (<VideoInReviewItem
{...props}
{...item}
key={item.id}
isReview={true}
>
</VideoInReviewItem>)
})}
</div>
gogogo
<div className="itemWrap">
{videoes.map((item, index) => {
return (<VideoInReviewItem
{...props}
{...item}
key={item.id}
onEditVideo={onEditVideo}
>
</VideoInReviewItem>)
})}
</div>
<Link to={`/users/${username}/videoes/upload`}>to upload</Link>
</div>
)

@ -0,0 +1,57 @@
import React, { useState, useEffect, useContext, memo } from 'react';
import { Progress, Input, Tooltip } from 'antd'
import { getUrl2, isDev, CBreadcrumb, ActionBtn, ThemeContext } from 'educoder'
import axios from 'axios'
import moment from 'moment'
import playIcon from './images/play.png'
/**
cover_url: "http://video.educoder.net/f6ba49c3944b43ee98736898e31b7d88/snapshots/12da3f7df07c499b8f0fc6dc410094e9-00005.jpg"
created_at: "2019-08-12 13:48:26"
file_url: "http://video.educoder.net/sv/4c7eb4-16c845ee09c/4c7eb4-16c845ee09c.mp4"
id: 1
published_at: "2019-08-12 15:38:00"
title: "测试标题"
updated_at: "2019-08-12 17:17:09"
*/
function VideoInReviewItem (props) {
const theme = useContext(ThemeContext);
const { history, cover_url, title, created_at, isReview, onEditVideo } = props;
const username = props.match.params.username
function toList() {
history.push(`/users/${username}/videoes`)
}
function toUpload() {
history.push(`/users/${username}/videoes/upload`)
}
return (
<div className={`${isReview ? 'videoInReviewItem' : 'nItem'} videoItem`}>
<img className="cover" src={cover_url || "http://video.educoder.net/e7d18970482a46d2a6f0e951b504256c/snapshots/491e113950d74f1dab276097dae287dd-00005.jpg"}
></img>
{!isReview && <div className="mask">
<img className="play" src={playIcon}></img>
</div>}
<div className="square-main">
<div className="title overflowHidden1"
title={title && title.length > 20 ? title : ''}
>{title}</div>
<div className="df buttonRow">
{/* 2019-09-01 10:00:22 */}
<span className="time">{moment(created_at).format('YYYY-MM-DD HH:mm:ss')}</span>
{ isReview != true && <div>
<Tooltip title="编辑">
<i className="icon-fuzhi iconfont" onClick={() => onEditVideo(props)}></i>
</Tooltip>
<Tooltip title="复制视频地址">
<i className="icon-fuzhi iconfont"></i>
</Tooltip>
</div> }
</div>
</div>
</div>
)
}
export default VideoInReviewItem

@ -0,0 +1,67 @@
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'
function VideoUpload (props) {
const theme = useContext(ThemeContext);
const { history } = props;
const username = props.match.params.username
function toList() {
history.push(`/users/${username}/videoes`)
}
function toUpload() {
history.push(`/users/${username}/videoes/upload`)
}
return (
<div className={`videoPublishSuccess educontent`}>
<CBreadcrumb
className="mb26"
separator=" > "
items={[
{ to: `/users/${username}/videoes`, name: '视频'},
{ name: '上传'}
]}
></CBreadcrumb>
<style>{`
.videoPublishSuccess .section {
background: #fff;
padding: 16px 20px;
padding-top: 0px;
position: relative;
text-align: center;
color: ${theme.foreground_tip};
}
.videoPublishSuccess .tip {
margin-top: 10px;
margin-bottom: 12px;
}
.videoPublishSuccess .toListBtn {
margin-right: 10px;
}
.videoPublishSuccess .toUploadBtn {
width: 112px;
}
`}</style>
<div className="section">
<div>
<i className="icon-wanchenggouxuan iconfont font-36" style={{color: theme.foreground_select}}></i>
</div>
<div className="font-16" style={{ 'line-height': '16px'}}>恭喜</div>
<div className="font-16">提交成功</div>
<div className="tip">平台正在审核您的申请审核结果将以平台消息的形式通知您</div>
<div>
<ActionBtn className="toListBtn" onClick={toList}>查看已上传视频</ActionBtn>
<ActionBtn className="toUploadBtn" onClick={toUpload}>继续上传</ActionBtn>
</div>
</div>
</div>
)
}
export default VideoUpload

@ -1,6 +1,6 @@
import React, { useState, useEffect, useReducer, memo } from 'react';
import React, { useState, useEffect, useReducer, useContext, memo } from 'react';
import { getUrl2, isDev, CBreadcrumb, ActionBtn } from 'educoder'
import { getUrl2, isDev, CBreadcrumb, ActionBtn, ThemeContext } from 'educoder'
import axios from 'axios'
import VideoUpload from './VideoUpload'
@ -17,8 +17,10 @@ function VideoUploadList (props) {
const [videoes, setVideoes] = useState([]);
const [state, dispatch] = useReducer(reducer, initialState);
const theme = useContext(ThemeContext)
const username = props.match.params.username
const { showNotification } = props;
const { showNotification, history } = props;
const uploaderOptions = {
}
@ -163,13 +165,13 @@ function VideoUploadList (props) {
return {
video_id: item.videoId,
// todo
title: item.name
title: item.title
}
})
}).then((response) => {
// to success page
if (response.data.status == 0) {
history.push(`/users/${username}/videoes/success`)
}
}).catch((error) => {
console.log(error)
@ -180,12 +182,13 @@ function VideoUploadList (props) {
}
// login
return (
<div className="educontent videoUploadList">
<div className="educontent videoUploadList" style={{ marginBottom: '200px' }}>
<style>{`
.videoUploadList .section {
background: #fff;
padding: 16px 20px;
padding-top: 0px;
position: relative;
}
.videoUploadList .cBreadcrumb {
margin-top: 16px;
@ -202,6 +205,21 @@ function VideoUploadList (props) {
margin-top: 20px;
margin-bottom: 30px;
}
.videoUploadList .publishBtn {
padding: 0 16px
}
.videoUploadList .addVideoBtn {
position: absolute;
right: 30px;
}
.videoUploadList .publishRow {
text-align: center;
margin-top: 42px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/* item */
@ -222,7 +240,7 @@ function VideoUploadList (props) {
`}</style>
<CBreadcrumb
className="mb30"
className="mb26"
separator=" > "
items={[
{ to: `/users/${username}/videoes`, name: '视频'},
@ -232,7 +250,7 @@ function VideoUploadList (props) {
<div className="title">
<h2 className="head">上传视频</h2>
<span className="titleDescription">单次最多支持{MAX_FILE_COUNT}个视频文件上传不支持断点续传单个视频文件最大{MAX_FILE_SIZE}M</span>
{/* <span className="titleDescription">单次最多支持{MAX_FILE_COUNT}个视频文件上传,不支持断点续传,单个视频文件最大{MAX_FILE_SIZE}M</span> */}
</div>
<div className="section">
@ -248,21 +266,32 @@ function VideoUploadList (props) {
)
})}
</div>
{state.videoes && state.videoes.length === MAX_FILE_COUNT &&
<div className="tip">
<i className="iconfont icon-tishi" style={{color: '#FF6F6F', verticalAlign: 'text-bottom'}}></i>
<span>单次最多支持3个视频文件上传</span>
</div>}
<div className="description">
<div className="">视频大小不支持断点续传单个视频文件最大200M单次最多支持3个视频文件上传 </div>
<div className="">视频规格aviflvf4vm4vmovmp4rmvbswfwebm </div>
<div className="">温馨提示请勿上传违法视频平台将为每一个视频分配一个地址您可以通过引用改地址将视频使用在开发社区等模块</div>
</div>
<Button type="primary" icon="plus-square" onClick={() => { document.getElementById('fileUpload').click()}}>
{(!state.videoes || state.videoes.length < MAX_FILE_COUNT) && <Button type="primary" icon="plus-square"
onClick={() => { document.getElementById('fileUpload').click()}}
className="fr addVideoBtn"
>
添加更多视频
</Button>
</Button>}
<input type="file" id="fileUpload" style={{display: 'none'}} onChange={onUploadChange}
accept="video/*"
></input>
<div style={{}} className="publishRow">
<ActionBtn className="publishBtn" onClick={() => onPublish()}
>立即发布</ActionBtn>
<ActionBtn className="publishBtn" onClick={() => onPublish()}>立即发布</ActionBtn>
<div>上传视频即表示您已同意<span style={{color: theme.foreground_select}}>上传内容协议</span></div>
</div>
</div>
</div>
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Loading…
Cancel
Save