Commit f5fc8c43 authored by baixian's avatar baixian

闯关优化

parent a9138e61
......@@ -116,7 +116,12 @@ export default {
push_time: '18:00',
sign_up_status: 2,
banner: 'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2c/sharemoretheme/newunlockbg.png',
content: [],
content: [
{
title: '',
content: [{ type: 'text', value: '' }],
},
],
sign_up_content: '',
},
radioname: '',
......@@ -471,7 +476,12 @@ export default {
push_time: emigratedDate.data.push_time,
sign_up_status: emigratedDate.data.sign_up_status,
banner: emigratedDate.data.banner ? emigratedDate.data.banner : '',
content: emigratedDate.data.introduce ? JSON.parse(emigratedDate.data.introduce) : [],
content: emigratedDate.data.introduce && emigratedDate.data.introduce != null && JSON.parse(emigratedDate.data.introduce)[0].content ? JSON.parse(emigratedDate.data.introduce) : [
{
title: emigratedDate.data.introduce && emigratedDate.data.introduce != null && JSON.parse(emigratedDate.data.introduce).title ? JSON.parse(emigratedDate.data.introduce).title : '',
content: emigratedDate.data.introduce && emigratedDate.data.introduce != null && JSON.parse(emigratedDate.data.introduce).content ? JSON.parse(emigratedDate.data.introduce).content : (JSON.parse(emigratedDate.data.introduce) || []),
},
],
},
radioname: emigratedDate.data.sign_up_content ? JSON.parse(emigratedDate.data.sign_up_content).radioname : '',
radioList: emigratedDate.data.sign_up_content ? JSON.parse(emigratedDate.data.sign_up_content).radioList : [],
......@@ -817,7 +827,7 @@ export default {
},
* queryimagesignature({ payload }, { call, put, select }) {
const { userInfo, sid } = yield select(state => state.webapp);
const { files, uploadtype } = payload;
const { files, uploadtype, contentSort } = payload;
const file = files.files ? files.files[0] : null;
const REGEXP_VIDEO = /^image\/\w+/;
const params = { type: 1, token: userInfo.token, schoolId: sid };
......@@ -834,6 +844,7 @@ export default {
files,
uploaderLoading,
uploadtype,
contentSort,
},
});
} else {
......@@ -850,6 +861,7 @@ export default {
* uploadimage({ payload }, { call, put, select }) {
const {
signature, files, uploaderLoading, uploadtype,
contentSort,
} = payload;
const file = files.files ? files.files[0] : null;
const {
......@@ -900,7 +912,7 @@ export default {
},
});
} else if (uploadtype == 'quickCustomsImg') {
customsParams.content.push({
customsParams.content[contentSort].content.push({
type: 'img',
value: imageUrl,
});
......@@ -924,7 +936,9 @@ export default {
* queryvoicesignature({ payload }, { call, put, select }) {
const { avatorUploader } = yield select(state => state.uploader);
const { userInfo, sid } = yield select(state => state.webapp);
const { files, uploadtype, orgIndex } = payload;
const {
files, uploadtype, orgIndex, contentSort,
} = payload;
const file = files.files ? files.files[0] : null;
const REGEXP_VIDEO = /^audio\/\w+/;
const params = { type: 2, token: userInfo.token, schoolId: sid };
......@@ -940,6 +954,7 @@ export default {
files,
uploadtype,
orgIndex,
contentSort,
},
});
}
......@@ -947,6 +962,7 @@ export default {
* uploadvoice({ payload }, { call, put, select }) {
const {
signature, files, uploadtype, orgIndex,
contentSort,
} = payload;
const file = files.files ? files.files[0] : null;
const uploaderLoading = message.loading('正在上传录音', 0);
......@@ -1003,7 +1019,7 @@ export default {
},
});
} else if (uploadtype == 'uploadVoiceCustoms') {
customsParams.content.push({
customsParams.content[contentSort].content.push({
type: 'voice',
value: videoUrl,
});
......@@ -1019,7 +1035,9 @@ export default {
* queryvideosignature({ payload }, { call, put, select }) {
const { avatorUploader } = yield select(state => state.uploader);
const { userInfo, sid } = yield select(state => state.webapp);
const { files, uploadtype, orgIndex } = payload;
const {
files, uploadtype, orgIndex, contentSort,
} = payload;
const file = files.files ? files.files[0] : null;
const REGEXP_VIDEO = /^video\/\w+/;
const params = { type: 1, token: userInfo.token, schoolId: sid };
......@@ -1035,6 +1053,7 @@ export default {
files,
uploadtype,
orgIndex,
contentSort,
},
});
}
......@@ -1042,6 +1061,7 @@ export default {
* uploadvideo({ payload }, { call, put, select }) {
const {
signature, files, uploadtype, orgIndex,
contentSort,
} = payload;
const file = files.files ? files.files[0] : null;
const uploaderLoading = message.loading('正在上传视频', 0);
......@@ -1093,7 +1113,7 @@ export default {
},
});
} else if (uploadtype == 'uploadVideoCustoms') {
customsParams.content.push({
customsParams.content[contentSort].content.push({
type: 'video',
value: videoUrl,
});
......@@ -1204,9 +1224,28 @@ export default {
},
});
},
* changeCustomsText({ payload }, { call, put, select }) {
* customsAddPlate({ payload }, { call, put, select }) {
const { customsParams } = yield select(state => state.createtheme);
customsParams.content.push({
title: '',
content: [
{
type: 'text',
value: '',
},
],
});
yield put({
type: 'updateState',
payload: {
customsParams: { ...customsParams },
},
});
},
* changeCustomsText({ payload }, { call, put, select }) {
const { index } = payload;
const { customsParams } = yield select(state => state.createtheme);
customsParams.content[index].content.push({
type: 'text',
value: '',
});
......@@ -1218,9 +1257,9 @@ export default {
});
},
* customsChangeSize({ payload }, { call, put, select }) {
const { textValue, index } = payload;
const { textValue, index, sort } = payload;
const { customsParams } = yield select(state => state.createtheme);
customsParams.content[index] = {
customsParams.content[sort].content[index] = {
type: 'text',
value: textValue,
};
......@@ -1231,20 +1270,31 @@ export default {
},
});
},
* customsChangeTitle({ payload }, { call, put, select }) {
const { textValue, sort } = payload;
const { customsParams } = yield select(state => state.createtheme);
customsParams.content[sort].title = textValue;
yield put({
type: 'updateState',
payload: {
customsParams: { ...customsParams },
},
});
},
* customsMoveContent({ payload }, { call, put, select }) {
const { index, direction } = payload;
const { index, direction, sort } = payload;
const { customsParams } = yield select(state => state.createtheme);
let newContent = [];
newContent = customsParams.content;
const currentImg = customsParams.content[index];
const preImg = customsParams.content[index - 1];
const afterImg = customsParams.content[index + 1];
newContent = customsParams.content[sort].content;
const currentImg = newContent[index];
const preImg = newContent[index - 1];
const afterImg = newContent[index + 1];
if (direction == 'up') {
newContent.splice(index - 1, 2, currentImg, preImg);
} else if (direction == 'down') {
newContent.splice(index, 2, afterImg, currentImg);
}
customsParams.content = newContent;
customsParams.content[sort].content = newContent;
yield put({
type: 'updateState',
payload: {
......@@ -1253,9 +1303,9 @@ export default {
});
},
* deleteCustomsImg({ payload }, { call, put, select }) {
const { index } = payload;
const { index, sort } = payload;
const { customsParams } = yield select(state => state.createtheme);
const newContent = customsParams.content;
const newContent = customsParams.content[sort].content;
newContent.splice(index, 1);
yield put({
type: 'updateState',
......@@ -1375,7 +1425,12 @@ export default {
push_time: '18:00',
sign_up_status: 2,
banner: 'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2c/sharemoretheme/newunlockbg.png',
content: [],
content: [
{
title: '',
content: [{ type: 'text', value: '' }],
},
],
sign_up_content: '',
},
radioList: [],
......@@ -1852,7 +1907,6 @@ export default {
},
* goEditShowCustoms({ payload }, { call, put, select }) {
const { item } = payload;
console.log(item);
yield put({
type: 'updateState',
payload: {
......@@ -2114,7 +2168,12 @@ export default {
push_time: '18:00',
sign_up_status: 2,
banner: 'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2c/sharemoretheme/newunlockbg.png',
content: [],
content: [
{
title: '',
content: [{ type: 'text', value: '' }],
},
],
sign_up_content: '',
},
radioname: '',
......
......@@ -18,8 +18,8 @@ import {
} from 'antd';
import moment from 'moment';
import pageStyle from './Unclock.less';
import { hasBtnPower, imagify } from '../../../utils';
import ThemeEditor from '../ThemeEditor';
import { hasBtnPower, imagify } from '../../../utils/index';
import ThemeEditorOne from './components/ThemeEditor';
const { TabPane } = Tabs;
const FormItem = Form.Item;
const { Option } = Select;
......@@ -139,37 +139,40 @@ class UnClockForm extends React.Component {
},
});
}
customsUploadImg = (e) => {
customsUploadImg = (e, sort) => {
const { dispatch } = this.props;
dispatch({
type: 'createtheme/queryimagesignature',
payload: {
files: e.target,
uploadtype: 'quickCustomsImg',
contentSort: sort,
},
});
}
customsUploadAudio = (e) => {
customsUploadAudio = (e, sort) => {
const { dispatch } = this.props;
dispatch({
type: 'createtheme/queryvideosignature',
payload: {
files: e.target,
uploadtype: 'uploadVideoCustoms',
contentSort: sort,
},
});
}
customsUploadVoice = (e) => {
customsUploadVoice = (e, sort) => {
const { dispatch } = this.props;
dispatch({
type: 'createtheme/queryvoicesignature',
payload: {
files: e.target,
uploadtype: 'uploadVoiceCustoms',
contentSort: sort,
},
});
}
customsChangeSize = (e, index) => {
customsChangeSize = (e, index, sort) => {
const { dispatch } = this.props;
const textValue = e.target.value;
if (textValue.length > 500) {
......@@ -181,32 +184,59 @@ class UnClockForm extends React.Component {
payload: {
textValue,
index,
sort,
},
});
}
deleteCustomsImg = (index) => {
customsChangeTitle = (e, sort) => {
const { dispatch } = this.props;
const textValue = e.target.value;
if (textValue.length > 20) {
message.warning('最多20字', 0.5);
return;
}
dispatch({
type: 'createtheme/customsChangeTitle',
payload: {
textValue,
sort,
},
});
}
deleteCustomsImg = (index, sort) => {
const { dispatch } = this.props;
dispatch({
type: 'createtheme/deleteCustomsImg',
payload: {
index,
sort,
},
});
}
customsAddText = () => {
customsAddText = (index) => {
const { dispatch } = this.props;
dispatch({
type: 'createtheme/changeCustomsText',
payload: {
index,
},
});
}
customsAddPlate = () => {
const { dispatch } = this.props;
dispatch({
type: 'createtheme/customsAddPlate',
payload: {
},
});
}
customsMoveContent = (index, direction) => {
customsMoveContent = (index, sort, direction) => {
const { dispatch } = this.props;
dispatch({
type: 'createtheme/customsMoveContent',
payload: {
index,
sort,
direction,
},
});
......@@ -480,7 +510,7 @@ class UnClockForm extends React.Component {
</FormItem>
<FormItem {...formItemModaltypeLayout} label="闯关介绍">
<div className={pageStyle.introduceWrap}>
<ThemeEditor
<ThemeEditorOne
commentParams={customsParams}
editorUploadImg={this.customsUploadImg}
editorUploadAudio={this.customsUploadAudio}
......@@ -489,6 +519,8 @@ class UnClockForm extends React.Component {
deleteThemeImg={this.deleteCustomsImg}
moveContent={this.customsMoveContent}
editorAddText={this.customsAddText}
editorAddPlate={this.customsAddPlate}
editorChangeTitle={this.customsChangeTitle}
/>
</div>
</FormItem>
......
import { connect } from 'dva';
import React from 'react';
import { Icon, Divider, Tabs, Select, Form, Upload, Row, Col, Input, Radio, Modal, message } from 'antd';
import pageStyle from './ThemeEditor.less';
import { pageIn, hasBtnPower, imagify, ossVideofy, audioorigin } from '../../../../utils/index';
const upImg = `${__IMGCDN__}subjectUp.png`;
const { TabPane } = Tabs;
const { TextArea } = Input;
class ThemeEditor extends React.Component {
constructor(props) {
super(props);
this.state = {
previewVisible: false,
previewImage: '',
};
}
componentDidMount() { // 挂载
pageIn('轻校-发布主题');
}
componentDidUpdate() {
}
componentWillUnmount() { // 卸载
}
priviewImg = (img) => {
this.setState({
previewVisible: true,
previewImage: img,
});
}
handleCancel = () => {
this.setState({
previewVisible: false,
});
}
render() {
const { previewVisible, previewImage } = this.state;
const {
editorUploadImg,
commentParams,
editorUploadAudio,
editorChange,
deleteThemeImg,
deleteThemeVideo,
editorText,
editorAddText,
moveContent,
editorUploadVoice,
editorAddPlate,
editorChangeTitle,
} = this.props;
console.log(commentParams, 'commentParams');
return (
<div className={pageStyle.container}>
<div className={pageStyle.editorwrap}>
{
commentParams.content.length > 0 && commentParams.content.map((ele, sort) => {
return (
<div>
<Input value={ele.title} maxLength={20} placeholder="请输入标题" onChange={e => editorChangeTitle(e, sort)} />
{
ele.content.length > 0 && ele.content.map((item, index) => {
switch (item.type) {
case 'text':
return (
<div key={index} className={pageStyle.textWrap}>
<TextArea autoSize={{ minRows: 4, maxRows: 10 }} value={item.value} onChange={e => editorChange(e, index, sort)} placeholder="请输入打卡主题的具体要求,如:演唱歌曲《小小少年》,具体要求1.跟随伴奏唱一段副歌 2.视频录下唱歌过程 3.上传歌唱视频打卡成功 如果有该歌曲示例视频,你可以点击上传视频,供学员参考。" style={{ width: 560 }} maxLength={500} />
<div className={pageStyle.sizeNumber}>{item.value.length}/500</div>
<div className={pageStyle.toolList}>
{ index === 0 && <div aria-disabled="true" className={pageStyle.noup}><img src={upImg} alt="" /> </div> }
{ index > 0 && <div className={pageStyle.up} onClick={() => moveContent(index, sort, 'up')}><img src={upImg} alt="" /> </div> }
{ index === (ele.content.length - 1) && <div className={pageStyle.nodown}><img src={upImg} alt="" /> </div> }
{ index < (ele.content.length - 1) && <div className={pageStyle.down} onClick={() => moveContent(index, sort, 'down')}><img src={upImg} alt="" /> </div> }
<div className={pageStyle.delete} onClick={() => deleteThemeImg(index, sort)}><Icon type="delete" theme="filled" /></div>
</div>
</div>
);
case 'img':
return (
<div key={index} className={pageStyle.uploadimgbox}>
<div className={pageStyle.imgwrap}>
<div className={pageStyle.uploadimgwrap}> <img alt={item.type} className={pageStyle.teacheruploadimg} src={imagify(item.value)} /></div>
<div className={pageStyle.imghide}>
<span title="预览文件" onClick={() => this.priviewImg(item.value)} ><Icon style={{ color: '#fff' }} type="eye" /> 预览</span>
</div>
<div className={pageStyle.toolList}>
{ index === 0 && <div aria-disabled="true" className={pageStyle.noup}><img src={upImg} alt="" /> </div> }
{ index > 0 && <div className={pageStyle.up} onClick={() => moveContent(index, sort, 'up')}><img src={upImg} alt="" /> </div> }
{ index === (ele.content.length - 1) && <div className={pageStyle.nodown}><img src={upImg} alt="" /> </div> }
{ index < (ele.content.length - 1) && <div className={pageStyle.down} onClick={() => moveContent(index, sort, 'down')}><img src={upImg} alt="" /> </div> }
<div className={pageStyle.delete} onClick={() => deleteThemeImg(index, sort)}><Icon type="delete" theme="filled" /></div>
</div>
</div>
</div>
);
case 'voice':
return (
<div key={index} className={pageStyle.uploadimgbox}>
<div className={pageStyle.imgwrap}>
<audio controls="controls" style={{ width: '100%' }} src={audioorigin(item.value)}></audio>
<div className={pageStyle.toolList}>
{ index === 0 && <div aria-disabled="true" className={pageStyle.noup}><img src={upImg} alt="" /> </div> }
{ index > 0 && <div className={pageStyle.up} onClick={() => moveContent(index, sort, 'up')}><img src={upImg} alt="" /> </div> }
{ index === (ele.content.length - 1) && <div className={pageStyle.nodown}><img src={upImg} alt="" /> </div> }
{ index < (ele.content.length - 1) && <div className={pageStyle.down} onClick={() => moveContent(index, sort, 'down')}><img src={upImg} alt="" /> </div> }
<div className={pageStyle.delete} onClick={() => deleteThemeImg(index, sort)}><Icon type="delete" theme="filled" /></div>
</div>
</div>
</div>
);
case 'video':
return (
<div key={index} className={pageStyle.videowrap}>
<video controls="controls" className={pageStyle.videoPoster} src={ossVideofy(item.value)} />
<div className={pageStyle.toolList}>
{ index === 0 && <div aria-disabled="true" className={pageStyle.noup}><img src={upImg} alt="" /> </div> }
{ index > 0 && <div className={pageStyle.up} onClick={() => moveContent(index, sort, 'up')}><img src={upImg} alt="" /> </div> }
{ index === (ele.content.length - 1) && <div className={pageStyle.nodown}><img src={upImg} alt="" /> </div> }
{ index < (ele.content.length - 1) && <div className={pageStyle.down} onClick={() => moveContent(index, sort, 'down')}><img src={upImg} alt="" /> </div> }
<div className={pageStyle.delete} onClick={() => deleteThemeImg(index, sort)}><Icon type="delete" theme="filled" /></div>
</div>
</div>
);
default:
return <div></div>;
}
})
}
<div className={pageStyle.uploadflex}>
<div className={pageStyle.uploadimg} onClick={() => editorAddText(sort)}><Icon style={{ marginRight: 10 }} type="font-size" />添加文字</div>
<div className={pageStyle.uploadimg}><input type="file" id="uploadImg" className={pageStyle.fileuploadinput} onChange={e => editorUploadImg(e, sort)} accept="image/*" /><Icon style={{ marginRight: 10 }} type="picture" />添加图片</div>
<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>
</div>
);
})
}
</div>
<div onClick={editorAddPlate}>添加版块</div>
<Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
<img alt="图片" style={{ width: '100%' }} src={imagify(previewImage)} />
</Modal>
</div>
);
}
}
ThemeEditor.propTypes = {
};
export default connect()(ThemeEditor);
.textWrap {
width: 560px;
height: auto;
position: relative;
margin-bottom:10px;
:global {
.ant-input {
padding: 6px 15px 20px;
}
}
.sizeNumber {
position: absolute;
bottom: 8px;
right: 10px;
}
}
.editorwrap {
width: 563px;
margin-top: 15px;
.videowrap {
width: 100%;
height: 200px;
position: relative;
margin-bottom: 10px;
.videoPoster {
width: 100%;
height: 100%;
}
}
.videowrap:hover {
cursor: pointer;
.videohide {
opacity: 1;
background-color: rgba(0,0,0,0.5);
transition: all .3s;
z-index: 1;
color: #fff;
}
}
.videohide {
position: absolute;
width: 100%;
height: 100%;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
color: #fff;
z-index: -1;
a {
color: #fff;
}
}
.uploadimgbox {
display: flex;
align-items: flex-end;
margin-bottom: 18px;
flex-wrap: wrap;
.imgwrap {
width: 100%;
// height: 120px;
border-radius: 4px;
margin-right: 6px;
position: relative;
.uploadimgwrap {
width: 100%;
// height: 120px;
overflow: hidden;
}
}
.imgwrap:hover {
cursor: pointer;
.imghide {
opacity: 1;
background-color: rgba(0,0,0,0.5);
transition: all .3s;
z-index: 1;
color: #fff;
}
}
.imghide {
position: absolute;
width: 100%;
height: 100%;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
color: #fff;
z-index: -1;
a {
color: #fff;
}
}
.teacheruploadimg {
object-fit: contain;
border-radius: 4px;
width: 100%;
}
.teacheruploadimg:nth-child(4n){
margin-right: 0;
}
}
}
.uploadflex {
display: flex;
align-items: center;
.uploadimg {
cursor: pointer;
width: 106px;
height: 32px;
line-height: 32px;
text-align: center;
border: 1px solid #D9D9D9;
border-radius: 4px;
color: rgba(0,0,0,0.65);
position: relative;
margin-right: 30px;
.fileuploadinput {
cursor: pointer;
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
opacity: 0;
left: 0;
top: 0;
}
}
}
.toolList {
position: absolute;
right: -30px;
top: 0;
width: 30px;
height: 90px;
display: flex;
flex-direction: column;
background-color: #D3D3D3;
opacity: 0;
border-radius: 2px;
z-index: -1;
div {
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 14px;
cursor: pointer;
}
div>img {
width: 14px;
height: 14px;
}
.up:hover {
background-color: #1890FF;
}
.down,.nodown {
transform: rotate(180deg);
}
.nodown,.noup {
cursor: not-allowed;
}
.down:hover {
background-color: #1890FF;
}
.delete:hover {
background-color: #FF6060;
}
}
.textWrap:hover,.imgwrap:hover,.videowrap:hover {
.toolList {
opacity: 1;
z-index: 1;
}
}
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