Commit 0e9cbf2c authored by baixian's avatar baixian

闯关优化视频

parent 3ae7421e
......@@ -18,5 +18,5 @@
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="/dist/main.bcd241.js"></script></body>
<script type="text/javascript" src="/dist/main.05bc89.js"></script></body>
</html>
\ No newline at end of file
......@@ -166,6 +166,7 @@ export default {
storeId: 0, // 闯关ID
subjectList: [],
storeImg: '',
progressRate: 0,
},
subscriptions: {
setup({ dispatch, history }) { // eslint-disable-line
......@@ -533,13 +534,13 @@ export default {
},
* goTheme({ payload }, { call, put, select }) {
const { index } = payload;
yield put(routerRedux.push('/sjd/newtheme'));
yield put({
type: 'updateState',
payload: {
tabIndex: index,
},
});
yield put(routerRedux.push('/sjd/newtheme'));
},
* jobMoveContent({ payload }, { call, put, select }) {
const { index, direction } = payload;
......@@ -1072,34 +1073,55 @@ export default {
const { userInfo, sid } = yield select(state => state.webapp);
const {
files, uploadtype, orgIndex, contentSort,
progressCallBack,
} = payload;
const file = files.files ? files.files[0] : null;
if (file && file.size > 1000 * 1024 * 1024) {
message.error('视频的大小不能超过1GB,请重新上传', 1);
return;
}
const REGEXP_VIDEO = /^video\/\w+/;
const params = { type: 1, token: userInfo.token, schoolId: sid };
let signature = {};
if (file && (REGEXP_VIDEO.test(file.type) || file.type === '')) {
const uploadSignature = yield call(uploader.uploadVideoSignature, params);
signature = uploadSignature.data;
yield put({
type: 'uploadvideo',
payload: {
signature,
avatorUploader,
files,
uploadtype,
orgIndex,
contentSort,
},
});
if (uploadSignature.code == 200) {
yield put({
type: 'uploadvideo',
payload: {
signature,
avatorUploader,
files,
uploadtype,
orgIndex,
contentSort,
progressCallBack,
},
});
} else {
yield put({
type: 'updateState',
payload: {
progressRate: 0,
},
});
yield put({
type: 'webapp/errorrequestresolve',
payload: {
data: uploadSignature,
},
});
}
}
},
* uploadvideo({ payload }, { call, put, select }) {
const {
signature, files, uploadtype, orgIndex,
contentSort,
progressCallBack,
} = payload;
const file = files.files ? files.files[0] : null;
const uploaderLoading = message.loading('正在上传视频', 0);
const {
jobParams, calendarParams, emigrateParams, customsParams,
} = yield select(state => state.createtheme);
......@@ -1111,55 +1133,73 @@ export default {
signature: signature.signature,
file,
url: signature.host,
callback: signature.callback,
};
const uploadImg = yield call(uploader.uploadVideo, params);
const uploadImg = yield call(uploader.uploadVideo, params, (res) => {
progressCallBack(res);
});
const videoUrl = filename;
if (uploadtype == 'uploadVideoJob') {
jobParams.content.push({
type: 'video',
value: videoUrl,
});
yield put({
type: 'updateState',
payload: {
jobParams: { ...jobParams },
},
});
} else if (uploadtype == 'uploadVideoCalendar') {
calendarParams.content.push({
type: 'video',
value: videoUrl,
});
if (JSON.stringify(uploadImg) == '{"status":"ok"}') {
yield put({
type: 'updateState',
payload: {
calendarParams: { ...calendarParams },
progressRate: 0,
},
});
} else if (uploadtype == 'uploadVideoEmigrate') {
emigrateParams.content.push({
type: 'video',
value: videoUrl,
});
yield put({
type: 'updateState',
payload: {
emigrateParams: { ...emigrateParams },
},
});
} else if (uploadtype == 'uploadVideoCustoms') {
customsParams.content[contentSort].content.push({
type: 'video',
value: videoUrl,
});
if (uploadtype == 'uploadVideoJob') {
jobParams.content.push({
type: 'video',
value: videoUrl,
});
yield put({
type: 'updateState',
payload: {
jobParams: { ...jobParams },
},
});
} else if (uploadtype == 'uploadVideoCalendar') {
calendarParams.content.push({
type: 'video',
value: videoUrl,
});
yield put({
type: 'updateState',
payload: {
calendarParams: { ...calendarParams },
},
});
} else if (uploadtype == 'uploadVideoEmigrate') {
emigrateParams.content.push({
type: 'video',
value: videoUrl,
});
yield put({
type: 'updateState',
payload: {
emigrateParams: { ...emigrateParams },
},
});
} else if (uploadtype == 'uploadVideoCustoms') {
customsParams.content[contentSort].content.push({
type: 'video',
value: videoUrl,
});
yield put({
type: 'updateState',
payload: {
customsParams: { ...customsParams },
},
});
}
} else {
yield put({
type: 'updateState',
payload: {
customsParams: { ...customsParams },
progressRate: 0,
},
});
message.error('上传失败', 1);
}
setTimeout(uploaderLoading);
},
// 新闯关打卡逻辑
* addRadio({ payload }, { call, put, select }) {
......@@ -2265,6 +2305,7 @@ export default {
storeId: 0, // 闯关ID
subjectList: [],
storeImg: '',
progressRate: 0,
},
});
},
......
......@@ -1064,11 +1064,11 @@ export default {
});
}
if (pathname === '/sjd/newtheme') {
dispatch({
type: 'createtheme/pageInit',
payload: {
},
});
// dispatch({
// type: 'createtheme/pageInit',
// payload: {
// },
// });
dispatch({
type: 'createtheme/queryClassList',
payload: {
......
import { connect } from 'dva';
import React from 'react';
import { Icon, Divider, Tabs, Select, Form, Upload, Row, Col, Input, Radio, Modal, message } from 'antd';
import { Icon, Divider, Tabs, Select, Form, Upload, Row, Col, Input, Radio, Modal, message, Progress } from 'antd';
import pageStyle from './ThemeEditor.less';
import { pageIn, hasBtnPower, imagify, ossVideofy, audioorigin } from '../../utils/index';
const upImg = `${__IMGCDN__}subjectUp.png`;
......@@ -45,9 +45,16 @@ class ThemeEditor extends React.Component {
editorAddText,
moveContent,
editorUploadVoice,
progressRate,
} = this.props;
return (
<div className={pageStyle.container}>
{progressRate && progressRate > 0 ?
<div className={pageStyle.progressWrap}>
<Progress width={150} type="circle" percent={progressRate} />
<p> {progressRate == 100 ? '上传成功' : '上传中。。。'}</p>
</div> : ''
}
<div className={pageStyle.editorwrap}>
{/* eslint-disable-next-line array-callback-return,consistent-return */}
{commentParams.content.length > 0 && commentParams.content.map((item, index) => {
......@@ -124,6 +131,7 @@ class ThemeEditor extends React.Component {
<div className={pageStyle.uploadimg}><input type="file" id="uploadVoice" className={pageStyle.fileuploadinput} onChange={editorUploadVoice} accept="audio/mp3" /><Icon style={{ marginRight: 10 }} type="audio" />添加录音</div>
<div className={pageStyle.uploadimg}><input type="file" id="uploadVideo" className={pageStyle.fileuploadinput} onChange={editorUploadAudio} accept="video/mp4,video/*" /><Icon style={{ marginRight: 10 }} type="video-camera" />添加视频</div>
</div>
<p className={pageStyle.tip}>请上传视频小于1G,支持MP4格式</p>
<Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
<img alt="图片" style={{ width: '100%' }} src={imagify(previewImage)} />
</Modal>
......
......@@ -182,3 +182,28 @@
z-index: 1;
}
}
.progressWrap {
width: 300px;
height: 300px;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #f1f1f1;
border-radius: 15px;
z-index: 9999;
&>p {
font-size: 18px;
margin-top: 30px;
color: #1e8bff;
}
}
.tip {
color: #888;
margin-top: 8px;
line-height: 20px;
}
\ No newline at end of file
......@@ -137,6 +137,14 @@ class CalendarClockForm extends React.Component {
payload: {
files: e.target,
uploadtype: 'uploadVideoCalendar',
progressCallBack(res) {
dispatch({
type: 'createtheme/updateState',
payload: {
progressRate: ((res.loaded / res.total) * 100).toFixed(0),
},
});
},
},
});
}
......@@ -262,6 +270,7 @@ class CalendarClockForm extends React.Component {
currentTimestamp,
selectPlanDays,
isCopy,
progressRate,
} = this.props;
let new_rest_dates = [];
new_rest_dates = [...new Set(new_rest_dates.concat(...rest_dates))];
......@@ -632,6 +641,7 @@ class CalendarClockForm extends React.Component {
deleteThemeImg={this.deleteCalendarImg}
editorAddText={this.calendarAddText}
moveContent={this.calendarMoveContent}
progressRate={progressRate}
/>
<FormItem {...submitFormLayout} style={{ marginTop: 32 }}>
<Button type="primary" htmlType="submit" loading={themeAddLoading}>
......@@ -659,6 +669,7 @@ function mapStateToProps(state) {
currentTimestamp,
selectPlanDays,
isCopy,
progressRate,
} = state.createtheme;
return {
themeAddLoading,
......@@ -671,6 +682,7 @@ function mapStateToProps(state) {
currentTimestamp,
selectPlanDays,
isCopy,
progressRate,
};
}
export default connect(mapStateToProps)(CalendarClock);
......
......@@ -103,6 +103,14 @@ class ContentSettingForm extends React.Component {
payload: {
files: e.target,
uploadtype: 'uploadVideoEmigrate',
progressCallBack(res) {
dispatch({
type: 'createtheme/updateState',
payload: {
progressRate: ((res.loaded / res.total) * 100).toFixed(0),
},
});
},
},
});
}
......@@ -233,6 +241,7 @@ class ContentSettingForm extends React.Component {
screenIsBig,
isShowCustoms,
subjectList,
progressRate,
} = this.props;
const formItemModalLineLayout = {
labelCol: {
......@@ -330,6 +339,7 @@ class ContentSettingForm extends React.Component {
editorUploadAudio={this.emigrateUploadAudio}
editorChange={this.changeEmigrateText}
deleteThemeImg={this.deleteEmigrate}
progressRate={progressRate}
/>
</div>
</FormItem>
......@@ -488,6 +498,7 @@ function mapStateToProps(state) {
customsNumberList,
isShowCustoms,
subjectList,
progressRate,
} = state.createtheme;
const { collapsed, screenIsBig } = state.webapp;
return {
......@@ -502,6 +513,7 @@ function mapStateToProps(state) {
screenIsBig,
isShowCustoms,
subjectList,
progressRate,
};
}
export default connect(mapStateToProps)(ContentSetting);
......
......@@ -15,6 +15,7 @@ import {
Collapse,
DatePicker,
Select, Radio, InputNumber, Input, message,
Progress,
} from 'antd';
import moment from 'moment';
import pageStyle from './Unclock.less';
......@@ -158,6 +159,14 @@ class UnClockForm extends React.Component {
files: e.target,
uploadtype: 'uploadVideoCustoms',
contentSort: sort,
progressCallBack(res) {
dispatch({
type: 'createtheme/updateState',
payload: {
progressRate: ((res.loaded / res.total) * 100).toFixed(0),
},
});
},
},
});
}
......@@ -288,7 +297,9 @@ class UnClockForm extends React.Component {
radioList,
collapsed,
screenIsBig,
progressRate,
} = this.props;
console.log(progressRate, 'progressRate');
const formItemModalLineLayout = {
labelCol: {
xs: { span: 3 },
......@@ -531,6 +542,7 @@ class UnClockForm extends React.Component {
editorAddPlate={this.customsAddPlate}
editorChangeTitle={this.customsChangeTitle}
editorDeletePlate={this.customsDeletePlate}
progressRate={progressRate}
/>
</div>
</FormItem>
......@@ -575,6 +587,7 @@ function mapStateToProps(state) {
customsParams,
radioname,
radioList,
progressRate,
} = state.createtheme;
const { collapsed, screenIsBig } = state.webapp;
return {
......@@ -585,6 +598,7 @@ function mapStateToProps(state) {
radioList,
collapsed,
screenIsBig,
progressRate,
};
}
export default connect(mapStateToProps)(UnClock);
......
......@@ -103,6 +103,14 @@ class UnclockDetailForm extends React.Component {
payload: {
files: e.target,
uploadtype: 'uploadVideoEmigrate',
progressCallBack(res) {
dispatch({
type: 'createtheme/updateState',
payload: {
progressRate: ((res.loaded / res.total) * 100).toFixed(0),
},
});
},
},
});
}
......@@ -204,6 +212,7 @@ class UnclockDetailForm extends React.Component {
collapsed,
screenIsBig,
emigratedObj,
progressRate,
} = this.props;
const formItemModalLineLayout = {
labelCol: {
......@@ -284,6 +293,7 @@ class UnclockDetailForm extends React.Component {
editorUploadAudio={this.emigrateUploadAudio}
editorChange={this.changeEmigrateText}
deleteThemeImg={this.deleteEmigrate}
progressRate={progressRate}
/>
</div>
</FormItem>
......@@ -434,6 +444,7 @@ function mapStateToProps(state) {
emigratedObj,
releaseLoading,
customsNumberList,
progressRate,
} = state.createtheme;
const { collapsed, screenIsBig } = state.webapp;
return {
......@@ -444,6 +455,7 @@ function mapStateToProps(state) {
customsNumberList,
collapsed,
screenIsBig,
progressRate,
};
}
export default connect(mapStateToProps)(UnclockDetail);
......
......@@ -99,6 +99,14 @@ class UnclockDetailForm extends React.Component {
payload: {
files: e.target,
uploadtype: 'uploadVideoEmigrate',
progressCallBack(res) {
dispatch({
type: 'createtheme/updateState',
payload: {
progressRate: ((res.loaded / res.total) * 100).toFixed(0),
},
});
},
},
});
}
......@@ -192,6 +200,7 @@ class UnclockDetailForm extends React.Component {
collapsed,
screenIsBig,
emigratedObj,
progressRate,
} = this.props;
const formItemModalLineLayout = {
labelCol: {
......@@ -256,6 +265,7 @@ class UnclockDetailForm extends React.Component {
editorUploadAudio={this.emigrateUploadAudio}
editorChange={this.changeEmigrateText}
deleteThemeImg={this.deleteEmigrate}
progressRate={progressRate}
/>
</div>
</FormItem>
......@@ -406,6 +416,7 @@ function mapStateToProps(state) {
emigratedObj,
releaseLoading,
customsNumberList,
progressRate,
} = state.createtheme;
const { collapsed, screenIsBig } = state.webapp;
return {
......@@ -416,6 +427,7 @@ function mapStateToProps(state) {
customsNumberList,
collapsed,
screenIsBig,
progressRate,
};
}
export default connect(mapStateToProps)(UnclockDetail);
......
import { connect } from 'dva';
import React from 'react';
import { Icon, Divider, Tabs, Select, Form, Upload, Row, Col, Input, Radio, Modal, message } from 'antd';
import { Icon, Divider, Tabs, Select, Form, Upload, Row, Col, Input, Radio, Modal, message, Progress } from 'antd';
import pageStyle from './ThemeEditor.less';
import { pageIn, hasBtnPower, imagify, ossVideofy, audioorigin } from '../../../../utils/index';
const upImg = `${__IMGCDN__}subjectUp.png`;
......@@ -48,9 +48,17 @@ class ThemeEditor extends React.Component {
editorAddPlate,
editorChangeTitle,
editorDeletePlate,
progressRate,
} = this.props;
return (
<div className={pageStyle.container}>
{
progressRate && progressRate > 0 ?
<div className={pageStyle.progressWrap}>
<Progress width={150} type="circle" percent={progressRate} />
<p> {progressRate == 100 ? '上传成功' : '上传中。。。'}</p>
</div> : ''
}
<div className={pageStyle.editorwrap}>
{
commentParams.content && commentParams.content.length > 0 && commentParams.content.map((ele, sort) => {
......@@ -132,6 +140,7 @@ class ThemeEditor extends React.Component {
<div className={pageStyle.uploadimg}><input type="file" id="uploadVoice" className={pageStyle.fileuploadinput} onChange={e => editorUploadVoice(e, sort)} accept="audio/mp3" /><Icon style={{ marginRight: 10 }} type="audio" />添加录音</div>
<div className={pageStyle.uploadimg}><input type="file" id="uploadVideo" className={pageStyle.fileuploadinput} onChange={e => editorUploadAudio(e, sort)} accept="video/mp4,video/*" /><Icon style={{ marginRight: 10 }} type="video-camera" />添加视频</div>
</div>
<p>请上传视频小于1G,支持MP4格式</p>
</div>
);
})
......
......@@ -207,4 +207,24 @@
font-size: 30px;
color: #FF6060;
cursor: pointer;
}
.progressWrap {
width: 300px;
height: 300px;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #f1f1f1;
border-radius: 15px;
z-index: 9999;
&>p {
font-size: 18px;
margin-top: 30px;
color: #1e8bff;
}
}
\ No newline at end of file
......@@ -118,6 +118,14 @@ class JobClockForm extends React.Component {
payload: {
files: e.target,
uploadtype: 'uploadVideoJob',
progressCallBack(res) {
dispatch({
type: 'createtheme/updateState',
payload: {
progressRate: ((res.loaded / res.total) * 100).toFixed(0),
},
});
},
},
});
}
......@@ -205,6 +213,7 @@ class JobClockForm extends React.Component {
jobParams,
editorText,
isCopy,
progressRate,
} = this.props;
const formItemModalLineLayout = {
labelCol: {
......@@ -469,6 +478,7 @@ class JobClockForm extends React.Component {
deleteThemeImg={this.deleteJobImg}
moveContent={this.jobMoveContent}
editorAddText={this.jobAddText}
progressRate={progressRate}
/>
<FormItem {...submitFormLayout} style={{ marginTop: 32 }}>
<Button type="primary" htmlType="submit" loading={themeAddLoading}>
......@@ -491,6 +501,7 @@ function mapStateToProps(state) {
jobParams,
editorText,
isCopy,
progressRate,
} = state.createtheme;
return {
themeAddLoading,
......@@ -498,6 +509,7 @@ function mapStateToProps(state) {
jobParams,
editorText,
isCopy,
progressRate,
};
}
export default connect(mapStateToProps)(JobClock);
......
......@@ -26,7 +26,7 @@ export function uploadVideoSignature({ type, token, schoolId }) {
});
}
export function uploadVideo(params) {
export function uploadVideo(params, progressCallback) {
const {
OSSAccessKeyId,
file,
......@@ -34,12 +34,17 @@ export function uploadVideo(params) {
policy,
signature,
url,
callback,
} = params;
const formData = new FormData();
formData.append('key', key);
formData.append('policy', policy);
formData.append('OSSAccessKeyId', OSSAccessKeyId);
formData.append('signature', signature);
if (callback) {
formData.append('callback', callback);
}
formData.append('success_action_status', 200);
formData.append('file', file);
return request({
url: params.url,
......@@ -49,6 +54,16 @@ export function uploadVideo(params) {
'Content-Type': 'multipart/form-data',
},
data: formData,
retry: 0,
onUploadProgress(progressEvent) { // 原生获取上传进度的事件
if (progressEvent.lengthComputable) {
// 属性lengthComputable主要表明总共需要完成的工作量和已经完成的工作是否可以被测量
// 如果lengthComputable为false,就获取不到progressEvent.total和progressEvent.loaded
if (progressCallback && (typeof progressCallback == 'function')) {
progressCallback(progressEvent);
}
}
},
});
}
export function uploadImageSignature({ type, token, schoolId }) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment