Commit ab3abbcd authored by baixian's avatar baixian

111222dd

parent 09c6b068
......@@ -191,7 +191,7 @@ export default {
isFather: false,
noIcon: true,
path: '/sjd/coursegather',
relativePath: ['/sjd/coursegather'],
relativePath: ['/sjd/coursegather', '/sjd/gatherdetail/:id'],
},
{
id: '33',
......
......@@ -11,6 +11,7 @@ import {
getRandomFilename,
} from '../utils/index';
import * as onlineAjax from '../services/onlineclasses';
import * as uploader from '../services/uploader';
export default {
namespace: 'coursegatherdetail',
state: {
......@@ -42,6 +43,24 @@ export default {
start: '',
end: '',
},
addCourseObj: {
title: '',
start_time: '',
charge_type: '',
created_at: '',
cover: '',
type: '',
audio: '',
intro: [
{ type: 'text', value: '' },
],
remark: '',
study_count: '',
status: '',
content: '',
},
editLoading: false,
materialVisible: false,
},
subscriptions: {
setup({ dispatch, history }) { // eslint-disable-line
......@@ -126,7 +145,7 @@ export default {
}
},
* getGatherDetail({ payload }, { call, put, select }) {
const { id } = yield select(state => state.coursegatherdetail);
const { id, addCourseObj } = yield select(state => state.coursegatherdetail);
const loading = message.loading('数据加载中...', 0);
const detaildata = yield call(onlineAjax.findCourse, {
id,
......@@ -138,6 +157,21 @@ export default {
type: 'updateState',
payload: {
gatherDetail: { ...data },
addCourseObj: {
id: data.id,
title: data.title,
start_time: data.start_time,
charge_type: data.charge_type,
created_at: data.created_at,
type: data.type,
intro: data.intro && data.intro != null ? JSON.parse(data.intro) : addCourseObj.intro,
remark: data.remark,
study_count: data.study_count,
status: data.status,
cover: data.cover,
audio: data.audio,
content: data.content,
},
},
});
yield put({
......@@ -162,6 +196,24 @@ export default {
yield put({
type: 'updateState',
payload: {
editLoading: false,
materialVisible: false,
addCourseObj: {
title: '',
start_time: '',
charge_type: '',
created_at: '',
cover: '',
type: '',
audio: '',
intro: [
{ type: 'text', value: '' },
],
remark: '',
study_count: '',
status: '',
content: '',
},
},
});
},
......@@ -388,6 +440,374 @@ export default {
},
});
},
* updateCover({ payload }, { call, put, select }) {
const { values } = payload;
const { addCourseObj } = yield select(state => state.coursegatherdetail);
addCourseObj.cover = values.checkValue;
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
materialVisible: false,
},
});
},
* deleteCover({ payload }, { call, put, select }) {
const { addCourseObj } = yield select(state => state.coursegatherdetail);
addCourseObj.cover = '';
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
},
* queryimagesignature({ payload }, { call, put, select }) {
const { userInfo, sid } = yield select(state => state.webapp);
const { files, uploadtype } = payload;
const file = files.files ? files.files[0] : null;
const REGEXP_VIDEO = /^image\/\w+/;
const params = { type: 1, token: userInfo.token, schoolId: sid };
let signature = {};
if (file && (REGEXP_VIDEO.test(file.type) || file.type === '')) {
const uploaderLoading = message.loading('正在上传图片');
const uploadSignature = yield call(uploader.uploadImageSignature, params);
if (uploadSignature.code == 200) {
signature = uploadSignature.data;
yield put({
type: 'uploadimage',
payload: {
signature,
files,
uploaderLoading,
uploadtype,
},
});
} else {
setTimeout(uploaderLoading);
yield put({
type: 'webapp/errorrequestresolve',
payload: {
code: uploadSignature,
},
});
}
}
},
* uploadimage({ payload }, { call, put, select }) {
const {
signature, files, uploaderLoading, uploadtype,
} = payload;
const file = files.files ? files.files[0] : null;
const { addCourseObj } = yield select(state => state.coursegatherdetail);
const filename = `${signature.dir}${getRandomFilename(file.name)}`;
const params = {
key: filename,
policy: signature.policy,
OSSAccessKeyId: signature.accessid,
signature: signature.signature,
file,
url: signature.host,
};
const uploadImg = yield call(uploader.uploadImg, params);
const imageUrl = filename;
if (uploadtype == 'uploadImg') {
addCourseObj.intro.push({
type: 'img',
value: imageUrl,
});
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
} else if (uploadtype == 'uploadCover') {
addCourseObj.cover = imageUrl;
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
}
setTimeout(uploaderLoading);
},
* 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 file = files.files ? files.files[0] : null;
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,
},
});
}
},
* uploadvideo({ payload }, { call, put, select }) {
const {
signature, files, uploadtype, orgIndex,
} = payload;
const file = files.files ? files.files[0] : null;
const uploaderLoading = message.loading('正在上传视频', 0);
const { addCourseObj } = yield select(state => state.coursegatherdetail);
const filename = `${signature.dir}${getRandomFilename(file.name)}`;
const params = {
key: filename,
policy: signature.policy,
OSSAccessKeyId: signature.accessid,
signature: signature.signature,
file,
url: signature.host,
};
const uploadImg = yield call(uploader.uploadVideo, params);
const videoUrl = filename;
if (uploadtype == 'uploadVideo') {
addCourseObj.intro.push({
type: 'video',
value: videoUrl,
});
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
}
setTimeout(uploaderLoading);
},
* queryvoiceignature({ payload }, { call, put, select }) {
const { userInfo, sid } = yield select(state => state.webapp);
const { files, uploadtype } = payload;
const file = files.files ? files.files[0] : null;
const REGEXP_VIDEO = /^audio\/\w+/;
const params = { type: 2, token: userInfo.token, schoolId: sid };
let signature = {};
if (file && (REGEXP_VIDEO.test(file.type) || file.type === '')) {
const uploaderLoading = message.loading('正在上传音频');
const uploadSignature = yield call(uploader.uploadImageSignature, params);
if (uploadSignature.code == 200) {
signature = uploadSignature.data;
yield put({
type: 'uploadaudio',
payload: {
signature,
files,
uploaderLoading,
uploadtype,
},
});
} else {
setTimeout(uploaderLoading);
yield put({
type: 'webapp/errorrequestresolve',
payload: {
code: uploadSignature,
},
});
}
}
},
* uploadaudio({ payload }, { call, put, select }) {
const {
signature, files, uploaderLoading, uploadtype,
} = payload;
const file = files.files ? files.files[0] : null;
const { addCourseObj } = yield select(state => state.coursegatherdetail);
const filename = `${signature.dir}${getRandomFilename(file.name)}`;
const params = {
key: filename,
policy: signature.policy,
OSSAccessKeyId: signature.accessid,
signature: signature.signature,
file,
url: signature.host,
};
const audioUrl = filename;
const uploadImg = yield call(uploader.uploadImg, params);
if (uploadtype == 'uploadAudio') {
addCourseObj.audio = audioUrl;
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
} else if (uploadtype == 'uploadDescAudio') {
addCourseObj.intro.push({
type: 'audio',
value: audioUrl,
});
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
}
setTimeout(uploaderLoading);
},
* courseChangeSize({ payload }, { call, put, select }) {
const { textValue, index } = payload;
const { addCourseObj } = yield select(state => state.coursegatherdetail);
addCourseObj.intro[index] = {
type: 'text',
value: textValue,
};
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
},
* deleteCourseImg({ payload }, { call, put, select }) {
const { index } = payload;
const { addCourseObj } = yield select(state => state.coursegatherdetail);
const newContent = addCourseObj.intro;
newContent.splice(index, 1);
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
},
* deleteAudio({ payload }, { call, put, select }) {
const { addCourseObj } = yield select(state => state.coursegatherdetail);
addCourseObj.audio = '';
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
},
* courseMoveContent({ payload }, { call, put, select }) {
const { index, direction } = payload;
const { addCourseObj } = yield select(state => state.coursegatherdetail);
let newContent = [];
newContent = addCourseObj.intro;
const currentImg = addCourseObj.intro[index];
const preImg = addCourseObj.intro[index - 1];
const afterImg = addCourseObj.intro[index + 1];
if (direction == 'up') {
newContent.splice(index - 1, 2, currentImg, preImg);
} else if (direction == 'down') {
newContent.splice(index, 2, afterImg, currentImg);
}
addCourseObj.intro = newContent;
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
},
* courseAddText({ payload }, { call, put, select }) {
const { textValue } = payload;
const { addCourseObj } = yield select(state => state.coursegatherdetail);
addCourseObj.intro.push({
type: 'text',
value: '',
});
yield put({
type: 'updateState',
payload: {
addCourseObj: { ...addCourseObj },
},
});
},
* editCourse({ payload }, { call, put, select }) {
const { sid } = yield select(state => state.webapp);
const { editLoading, addCourseObj } = yield select(state => state.coursegatherdetail);
if (editLoading) {
return;
}
yield put({
type: 'updateState',
payload: {
editLoading: true,
},
});
const {
title,
remark,
start_time,
study_count,
callBack,
} = payload;
addCourseObj.intro = JSON.stringify(addCourseObj.intro);
const newCourseObj = { ...addCourseObj };
const loadmessage = message.loading('保存中...', 0);
const newParams = Object.assign(newCourseObj, {
title,
remark,
start_time,
study_count,
school_id: sid,
content: JSON.stringify([
{ type: 'mp4', value: 'clock_video-test/member/12351/2019-11-20/fa939b56ae68b1b0e35734a29284778f' },
]),
});
const data = yield call(onlineAjax.editCourse, newParams);
yield put({
type: 'updateState',
payload: {
editLoading: false,
},
});
setTimeout(loadmessage);
if (data.code == 200) {
message.success('保存成功', 0.5);
if (callBack && (typeof callBack == 'function')) {
callBack();
}
yield put({
type: 'updateState',
payload: {
addCourseObj: {
title: '',
start_time: '',
charge_type: '',
created_at: '',
cover: '',
type: '',
audio: '',
intro: [
{ type: 'text', value: '' },
],
remark: '',
study_count: '',
status: '',
content: '',
},
},
});
yield delay(50);
yield put(routerRedux.push('/sjd/coursegather'));
} else {
yield put({
type: 'webapp/errorrequestresolve',
payload: {
data,
},
});
}
},
},
reducers: {
save(state, action) {
......
......@@ -2,6 +2,7 @@
import { routerRedux } from 'dva/router';
import { message } from 'antd';
import { delay } from 'redux-saga';
import moment from 'moment';
import {
LocalStorage,
SessionStorage,
......@@ -36,6 +37,9 @@ export default {
content: '',
},
addLoading: false,
editLoading: false,
materialVisible: false,
courseChartData: {},
},
subscriptions: {
setup({ dispatch, history }) { // eslint-disable-line
......@@ -74,6 +78,50 @@ export default {
});
}
},
* selectChart({ payload }, { call, put, select }) {
const { start, end, id } = payload;
const data = yield call(onlineAjax.staticChart, {
course_id: id,
start,
end,
});
if (data.code == 200) {
yield put({
type: 'updateState',
payload: {
courseChartData: data.data,
},
});
} else {
yield put({
type: 'webapp/errorrequestresolve',
payload: {
data,
},
});
}
},
* selectTotal({ payload }, { call, put, select }) {
const { id } = payload;
const data = yield call(onlineAjax.staticTotal, {
course_id: id,
});
if (data.code == 200) {
yield put({
type: 'updateState',
payload: {
dataAllTotal: data.data,
},
});
} else {
yield put({
type: 'webapp/errorrequestresolve',
payload: {
data,
},
});
}
},
* findCourse({ payload }, { call, put, select }) {
const { sid } = yield select(state => state.webapp);
const { id } = payload;
......@@ -104,6 +152,20 @@ export default {
},
},
});
yield put({
type: 'selectChart',
payload: {
start: moment().subtract(6, 'days').format('YYYY-MM-DD'),
end: moment().format('YYYY-MM-DD'),
id: data.data.id,
},
});
yield put({
type: 'selectTotal',
payload: {
id: data.data.id,
},
});
} else {
yield put({
type: 'webapp/errorrequestresolve',
......@@ -190,7 +252,6 @@ export default {
} = payload;
addCourseObj.intro = JSON.stringify(addCourseObj.intro);
const newCourseObj = { ...addCourseObj };
console.log(addCourseObj, 'addCourseObj1111111111111111111');
const loadmessage = message.loading('保存中...', 0);
const newParams = Object.assign(newCourseObj, {
title,
......@@ -609,6 +670,9 @@ export default {
],
},
addLoading: false,
editLoading: false,
materialVisible: false,
courseChartData: {},
},
});
},
......
......@@ -14,12 +14,13 @@ import {
Avatar,
DatePicker,
Modal,
InputNumber, Checkbox, Radio,
InputNumber, Checkbox, Radio, message,
} from 'antd';
import moment from 'moment';
import ThemeEditor from '../../newtheme/ThemeEditor';
import ThemeEditor from '../../onlineclasses/ThemeEditor';
import pageStyle from './CourseDetail.less';
import { pageIn, hasBtnPower, imagify } from '../../../utils';
import MaterialModal from '../../../components/MaterialModal';
const { TabPane } = Tabs;
const FormItem = Form.Item;
const { Option } = Select;
......@@ -30,6 +31,7 @@ class CourseDetailForm extends React.Component {
constructor(props) {
super(props);
this.state = {
textLength: 0,
};
}
componentDidMount() { // 挂载
......@@ -39,10 +41,226 @@ class CourseDetailForm extends React.Component {
}
componentWillUnmount() { // 卸载
}
sizeChange = (e) => {
const { addCourseObj } = this.props;
this.setState({
textLength: e.target.value.length - addCourseObj.title.length,
});
}
courseUploadImg = (e) => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/queryimagesignature',
payload: {
files: e.target,
uploadtype: 'uploadImg',
},
});
}
courseUploadVideo = (e) => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/queryvideosignature',
payload: {
files: e.target,
uploadtype: 'uploadVideo',
},
});
}
courseChangeSize = (e, index) => {
const { dispatch } = this.props;
const textValue = e.target.value;
if (textValue.length > 500) {
message.error('最多500字', 0.5);
return;
}
dispatch({
type: 'coursegatherdetail/courseChangeSize',
payload: {
textValue,
index,
},
});
}
deleteCourseImg = (index) => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/deleteCourseImg',
payload: {
index,
},
});
}
courseMoveContent = (index, direction) => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/courseMoveContent',
payload: {
index,
direction,
},
});
}
courseAddText = () => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/courseAddText',
payload: {
},
});
}
courseUploadAudio = (e) => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/queryvoiceignature',
payload: {
files: e.target,
uploadtype: 'uploadDescAudio',
},
});
}
save = (e) => {
const { dispatch, form } = this.props;
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
const {
title,
remark,
study_count,
} = values;
dispatch({
type: 'coursegatherdetail/editCourse',
payload: {
title,
remark,
study_count,
callBack: () => {
form.resetFields();
this.setState({
textLength: 0,
});
},
},
});
}
});
}
uploadCover = (e) => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/queryimagesignature',
payload: {
files: e.target,
uploadtype: 'uploadCover',
},
});
}
deleteCover = () => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/deleteCover',
payload: {
},
});
}
deleteAudio = () => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/deleteAudio',
payload: {
},
});
}
uploadAudio = (e) => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/queryvoiceignature',
payload: {
files: e.target,
uploadtype: 'uploadAudio',
},
});
}
chooseMaterial = () => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/updateState',
payload: {
materialVisible: true,
},
});
dispatch({
type: 'coursemateria/querymaterialist',
payload: {
params: {
type: 1,
page: 1,
perPage: 12,
},
},
});
}
materialClose = () => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/updateState',
payload: {
materialVisible: false,
},
});
dispatch({
type: 'coursemateria/querymaterialist',
payload: {
params: {
type: '',
page: 1,
perPage: 20,
},
},
});
}
changeListPagination = (values) => {
const { dispatch } = this.props;
dispatch({
type: 'coursemateria/querymaterialist',
payload: {
params: {
type: 1,
page: values.page,
perPage: values.perPage,
},
},
});
}
materialSave = (values) => {
const { dispatch } = this.props;
dispatch({
type: 'coursegatherdetail/updateCover',
payload: {
values,
},
});
dispatch({
type: 'coursemateria/querymaterialist',
payload: {
params: {
type: '',
page: 1,
perPage: 20,
},
},
});
}
render() {
const {
form: { getFieldDecorator, getFieldValue },
addCourseObj,
editLoading,
materialVisible,
materiaList,
queryParams,
materiaListTotal,
} = this.props;
const formItemModalLineLayout = {
labelCol: {
......@@ -54,84 +272,123 @@ class CourseDetailForm extends React.Component {
sm: { span: 23 },
},
};
const { textLength } = this.state;
const { title } = addCourseObj;
const selectBefore = (
<div>0/40</div>
<div>{title.length + textLength}/40</div>
);
return (
<div className={pageStyle.container}>
<Form hideRequiredMark className={pageStyle.modalform} labelAlign="left" onSubmit={this.save}>
<FormItem {...formItemModalLineLayout} label="封面" className={pageStyle.imgFormItem}>
<div className={pageStyle.photoWrap}>
<div className={pageStyle.material}>
<img src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" alt="" />
<div className={pageStyle.tip}>从素材库选择</div>
</div>
<div className={pageStyle.material}>
<img src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" alt="" />
<div className={pageStyle.tip}>从素材库选择</div>
</div>
</div>
{
addCourseObj.cover ?
<div className={pageStyle.photoWrap}>
<div className={pageStyle.photoCover}>
<img src={imagify(addCourseObj.cover)} alt="封面" />
<Icon onClick={this.deleteCover} className={pageStyle.coverDelete} type="delete" />
</div>
</div> :
<div className={pageStyle.photoWrap}>
<div className={pageStyle.material} onClick={this.chooseMaterial}>
<img src={`${__IMGCDN__}/course/check.png`} alt="从素材库选择" />
<div className={pageStyle.tip}>从素材库选择</div>
</div>
<div className={pageStyle.material}>
<img src={`${__IMGCDN__}/course/uploadImg.png`} alt="上传图片" />
<div className={pageStyle.tip}>上传图片</div>
<input
type="file"
className={pageStyle.uploadInput}
accept="image/png, image/jpeg"
onChange={(e) => { this.uploadCover(e); }}
/>
</div>
</div>
}
<span className="ant-form-text">图片建议格式位JPG/PNG,尺寸140*140,图片大小不超过10MB</span>
</FormItem>
<FormItem {...formItemModalLineLayout} label="标题">
{getFieldDecorator('title', {
initialValue: '',
initialValue: addCourseObj.title,
rules: [
{
required: true,
message: '请输入标题',
},
],
})(<Input style={{ width: 520, marginRight: 30 }} addonAfter={selectBefore} placeholder="请输入标题" />)}
})(<Input maxLength={40} onChange={e => this.sizeChange(e)} style={{ width: 520, marginRight: 30 }} addonAfter={selectBefore} placeholder="请输入标题" />)}
<span className="ant-form-text">标题长度建议在40字以内</span>
</FormItem>
<FormItem {...formItemModalLineLayout} label="分享语">
{getFieldDecorator('title', {
initialValue: '',
<FormItem {...formItemModalLineLayout} label="课程简述">
{getFieldDecorator('remark', {
initialValue: addCourseObj.remark,
})(<Input style={{ width: 520, marginRight: 30 }} placeholder="请输入课程简述" />)}
<span className="ant-form-text">分享课程给好友时,作为描述信息在标题下方显示</span>
</FormItem>
<FormItem {...formItemModalLineLayout} label="学习人数">
{getFieldDecorator('study_count', {
initialValue: addCourseObj.study_count,
rules: [
{
required: true,
message: '请输入分享语',
required: false,
message: '请输入正整数',
pattern: new RegExp(/^[1-9]\d*$/, 'g'),
},
],
})(<Input style={{ width: 520, marginRight: 30 }} placeholder="请输入分享语" />)}
<span className="ant-form-text">分享课程给好友时,作为描述信息在标题下方显示</span>
})(<InputNumber max={999999} style={{ width: 520, marginRight: 30 }} placeholder="请输入学习人数" />)}
<span className="ant-form-text">设置学习人数基数,让学员更有东西学习喔</span>
</FormItem>
<FormItem {...formItemModalLineLayout} label="课程类型">
<div className={pageStyle.courseType}>免费</div>
<span className={pageStyle.typeEdit}>点击修改</span>
<span className="ant-form-text">有人报名则无法修改课程类型</span>
</FormItem>
<FormItem {...formItemModalLineLayout} label="开课时间">
{getFieldDecorator('title', {
initialValue: '',
rules: [
{
required: true,
message: '请选择时间',
},
],
})(<DatePicker
showTime={{ format: 'HH:mm' }}
format="YYYY-MM-DD HH:mm"
placeholder="选择时间"
/>)}
{/* <span className={pageStyle.typeEdit}>点击修改</span> */}
{/* <span className="ant-form-text">有人报名则无法修改课程类型</span> */}
</FormItem>
<FormItem {...formItemModalLineLayout} label="语音介绍">
<span className={pageStyle.voice}>添加语音介绍</span>
{
addCourseObj.audio ?
<div className={pageStyle.voice}>
<audio controls src={imagify(addCourseObj.audio)} />
<Icon onClick={this.deleteAudio} className={pageStyle.audioDelete} type="delete" />
</div> :
<div className={pageStyle.voice}>
添加语音介绍
<input
type="file"
className={pageStyle.voiceUpload}
accept="audio/*"
onChange={(e) => { this.uploadAudio(e); }}
/>
</div>
}
</FormItem>
<FormItem {...formItemModalLineLayout} label="课程介绍">
<ThemeEditor
commentParams={addCourseObj}
editorUploadImg={this.courseUploadImg}
editorUploadAudio={this.courseUploadAudio}
editorUploadVideo={this.courseUploadVideo}
editorChange={this.courseChangeSize}
deleteThemeImg={this.deleteCourseImg}
moveContent={this.courseMoveContent}
editorAddText={this.courseAddText}
editorUploadAudio={this.courseUploadAudio}
/>
</FormItem>
<FormItem {...formItemModalLineLayout}>
<Button loading={editLoading} type="primary" htmlType="submit" style={{ marginRight: 20 }}>保存</Button>
<Button style={{ marginRight: 20 }}>预览</Button>
<Button>上传课件</Button>
</FormItem>
</Form>
<MaterialModal
visible={materialVisible}
close={this.materialClose}
list={materiaList}
queryParams={queryParams}
total={materiaListTotal}
changePagination={this.changeListPagination}
save={this.materialSave}
/>
</div>
);
}
......@@ -144,9 +401,21 @@ const CourseDetail = Form.create()(CourseDetailForm);
function mapStateToProps(state) {
const {
addCourseObj,
} = state.onlineclasses;
editLoading,
materialVisible,
} = state.coursegatherdetail;
const {
materiaList,
queryParams,
materiaListTotal,
} = state.coursemateria;
return {
addCourseObj,
editLoading,
materialVisible,
materiaList,
queryParams,
materiaListTotal,
};
}
export default connect(mapStateToProps)(CourseDetail);
......
......@@ -12,6 +12,24 @@
.photoWrap {
display: inline-flex;
width: 320px;
.photoCover {
width: 140px;
height: 140px;
position: relative;
&>img {
width: 140px;
height: 140px;
border-radius: 6px;
}
.coverDelete {
font-size: 22px;
color: #fa4f53;
cursor: pointer;
position: absolute;
right: -40px;
top: 0;
}
}
.material {
width: 140px;
height: 140px;
......@@ -22,6 +40,18 @@
align-items: center;
flex-direction: column;
margin-right: 11px;
cursor: pointer;
position: relative;
.uploadInput {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
opacity: 0;
cursor: pointer;
z-index: 1;
}
.tip {
font-size:14px;
font-weight:400;
......@@ -62,4 +92,28 @@
}
.voice {
margin: 0;
position: relative;
width: 400px;
height: 40px;
&>audio {
height: 30px;
}
.audioDelete {
position: absolute;
top: 3px;
right: 0;
font-size: 22px;
color: #fa4f53;
cursor: pointer;
}
.voiceUpload {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
opacity: 0;
z-index: 1;
cursor: pointer;
}
}
......@@ -203,7 +203,7 @@ class StaticCenter extends React.Component {
<div className={pageStyle.container}>
<div className={pageStyle.tabbox}>
<div className={pageStyle.gatherInfo}>
<img className={pageStyle.titleicon} src="https://cdn.img.shangjiadao.cn/clock-test/member/12186/2019-07-08/240ef0e06262ffb11253e03bf986143c.jpg?x-oss-process=image/resize,w_640/rotate,360/crop,x_176,y_36,w_288,h_288" alt="" />
<img className={pageStyle.titleicon} src={`${__IMGCDN__}/course/book_icon.png`} alt="" />
<div className={pageStyle.gatherDetail}>
<div className={pageStyle.titlebox}>
<span className={pageStyle.title}>{gatherDetail.title || ''}</span>
......
import React from 'react';
import { Icon } from 'antd';
import pageStyle from './Card.less';
import { imagify } from '../../../utils';
const MediaCard = (props) => {
const {
info,
......@@ -8,7 +9,7 @@ const MediaCard = (props) => {
} = props;
return (
<div className={pageStyle.box} {...props} onClick={() => method.gogatherdetail(info.id)}>
<img className={pageStyle.image} src="https://cdn.img.shangjiadao.cn/clock-test/member/12186/2019-07-08/240ef0e06262ffb11253e03bf986143c.jpg?x-oss-process=image/resize,w_640/rotate,360/crop,x_176,y_36,w_288,h_288" alt="" />
<img className={pageStyle.image} src={imagify(info.cover)} alt="" />
<div className={pageStyle.infobox}>
<div className={pageStyle.topbox}>
<div className={pageStyle.title}>{info.title}</div>
......
......@@ -135,7 +135,7 @@ class CourseDetailForm extends React.Component {
payload: {
title,
remark,
start_time: moment(start_time[0]).format('YYYY-MM-DD HH:mm'),
start_time: moment(start_time).format('YYYY-MM-DD HH:mm'),
study_count,
callBack: () => {
form.resetFields();
......@@ -236,7 +236,6 @@ class CourseDetailForm extends React.Component {
});
}
materialSave = (values) => {
console.log(values, '1111111111111');
const { dispatch } = this.props;
dispatch({
type: 'onlineclasses/updateCover',
......@@ -265,7 +264,6 @@ class CourseDetailForm extends React.Component {
queryParams,
materiaListTotal,
} = this.props;
console.log(addCourseObj, 'addCourseObj');
const formItemModalLineLayout = {
labelCol: {
xs: { span: 24 },
......
import React from 'react';
import { connect } from 'dva';
import {
Row,
Col,
Select,
Button,
DatePicker,
Empty,
DatePicker, Form,
} from 'antd';
import {
G2,
Chart,
Geom,
Axis,
Tooltip,
Coord,
Label,
Legend,
View,
Guide,
Shape,
Facet,
Util,
} from 'bizcharts';
import pageStyle from './StaticBox.less';
const { RangePicker } = DatePicker;
const { Option } = Select;
......@@ -17,6 +33,20 @@ class StaticBox extends React.Component {
componentWillUnmount() { // 卸载
}
render() {
const { courseChartData, dataAllTotal } = this.props;
const dataCols = {
month: {
type: 'time',
tickCount: 10,
},
};
const courseChart = courseChartData;
const dataChart = [];
const month = courseChart.dates;
const visitorCount = courseChart.visitor_count;
for (let i = 0; i < month.length && i < visitorCount.length; i++) {
dataChart.push({ month: month[i], count: visitorCount[i], name: '访问人数' });
}
return (
<div>
<div className={pageStyle.StaticBox}>
......@@ -40,8 +70,52 @@ class StaticBox extends React.Component {
</div>
</Col>
</Row>
<Row style={{ marginBottom: '20px' }}>
图表页面
<Row style={{ marginBottom: '20px', width: 800 }}>
<div>
{dataChart.length > 0 ?
<Chart height={350} data={dataChart} padding="auto" scale={dataCols} forceFit>
<Legend
textStyle={{ fontSize: '15', fill: '#5c5c5c', textBaseline: 'middle' }}
marker="circle"
offsetY={-45}
position="top-left"
items={[
{
value: 'visitor_count',
marker: {
fill: '#FFB879',
radius: 2,
},
},
]}
/>
<Axis name="month" />
<Tooltip
g2-tooltip={{
backgroundColor: '#000',
opacity: '0.75',
color: '#FFFFFF',
}}
crosshairs={{
type: 'y',
fill: '#000',
stroke: '#000',
}}
/>
<Geom
type="line"
position="month*count"
color={['name', ['#FFB879']]}
size={3}
shape="smooth"
/>
</Chart>
:
<div className={pageStyle.chartEmpty}>
<Empty />
</div>
}
</div>
</Row>
</div>
<div className={pageStyle.divideLine} />
......@@ -50,17 +124,17 @@ class StaticBox extends React.Component {
<Row className={pageStyle.staticitemList}>
<Col className={pageStyle.staticitem} lg={4} md={24} xs={24} sm={24}>
<div className={pageStyle.staticIconBox}>
<img className={pageStyle.staticIcon} src="https://cdn.img.shangjiadao.cn/clock-test/member/12186/2019-07-08/240ef0e06262ffb11253e03bf986143c.jpg?x-oss-process=image/resize,w_640/rotate,360/crop,x_176,y_36,w_288,h_288" alt="" />
<img className={pageStyle.staticIcon} src={`${__IMGCDN__}/course/data_icon1.png`} alt="" />
</div>
<div className={pageStyle.staticRight}>
<div className={pageStyle.staticName}>访问人数</div>
<div className={pageStyle.staticCount}>
<span className={pageStyle.count}>1142</span>
<span className={pageStyle.count}>{dataAllTotal.visitor_count}</span>
<span className={pageStyle.countAfter}></span>
</div>
</div>
</Col>
<Col className={pageStyle.staticitem} lg={4} md={24} xs={24} sm={24}>
{/* <Col className={pageStyle.staticitem} lg={4} md={24} xs={24} sm={24}>
<div className={pageStyle.staticIconBox}>
<img className={pageStyle.staticIcon} src="https://cdn.img.shangjiadao.cn/clock-test/member/12186/2019-07-08/240ef0e06262ffb11253e03bf986143c.jpg?x-oss-process=image/resize,w_640/rotate,360/crop,x_176,y_36,w_288,h_288" alt="" />
</div>
......@@ -95,23 +169,23 @@ class StaticBox extends React.Component {
<span className={pageStyle.countAfter}>人</span>
</div>
</div>
</Col>
</Col> */}
</Row>
<div className={pageStyle.staticTitle}>分享数据</div>
<Row className={pageStyle.staticitemList}>
<Col className={pageStyle.staticitem} lg={4} md={24} xs={24} sm={24}>
<div className={pageStyle.staticIconBox}>
<img className={pageStyle.staticIcon} src="https://cdn.img.shangjiadao.cn/clock-test/member/12186/2019-07-08/240ef0e06262ffb11253e03bf986143c.jpg?x-oss-process=image/resize,w_640/rotate,360/crop,x_176,y_36,w_288,h_288" alt="" />
<img className={pageStyle.staticIcon} src={`${__IMGCDN__}/course/data_icon2.png`} alt="" />
</div>
<div className={pageStyle.staticRight}>
<div className={pageStyle.staticName}>分享好友</div>
<div className={pageStyle.staticCount}>
<span className={pageStyle.count}>1142</span>
<span className={pageStyle.count}>{dataAllTotal.share_friend_count}</span>
<span className={pageStyle.countAfter}></span>
</div>
</div>
</Col>
<Col className={pageStyle.staticitem} lg={4} md={24} xs={24} sm={24}>
{/* <Col className={pageStyle.staticitem} lg={4} md={24} xs={24} sm={24}>
<div className={pageStyle.staticIconBox}>
<img className={pageStyle.staticIcon} src="https://cdn.img.shangjiadao.cn/clock-test/member/12186/2019-07-08/240ef0e06262ffb11253e03bf986143c.jpg?x-oss-process=image/resize,w_640/rotate,360/crop,x_176,y_36,w_288,h_288" alt="" />
</div>
......@@ -122,15 +196,15 @@ class StaticBox extends React.Component {
<span className={pageStyle.countAfter}>人</span>
</div>
</div>
</Col>
</Col> */}
<Col className={pageStyle.staticitem} lg={4} md={24} xs={24} sm={24}>
<div className={pageStyle.staticIconBox}>
<img className={pageStyle.staticIcon} src="https://cdn.img.shangjiadao.cn/clock-test/member/12186/2019-07-08/240ef0e06262ffb11253e03bf986143c.jpg?x-oss-process=image/resize,w_640/rotate,360/crop,x_176,y_36,w_288,h_288" alt="" />
<img className={pageStyle.staticIcon} src={`${__IMGCDN__}/course/data_icon3.png`} alt="" />
</div>
<div className={pageStyle.staticRight}>
<div className={pageStyle.staticName}>分享邀请卡</div>
<div className={pageStyle.staticCount}>
<span className={pageStyle.count}>1142</span>
<span className={pageStyle.count}>{dataAllTotal.share_card_count}</span>
<span className={pageStyle.countAfter}></span>
</div>
</div>
......@@ -140,12 +214,12 @@ class StaticBox extends React.Component {
<Row className={pageStyle.staticitemList}>
<Col className={pageStyle.staticitem} lg={4} md={24} xs={24} sm={24}>
<div className={pageStyle.staticIconBox}>
<img className={pageStyle.staticIcon} src="https://cdn.img.shangjiadao.cn/clock-test/member/12186/2019-07-08/240ef0e06262ffb11253e03bf986143c.jpg?x-oss-process=image/resize,w_640/rotate,360/crop,x_176,y_36,w_288,h_288" alt="" />
<img className={pageStyle.staticIcon} src={`${__IMGCDN__}/course/data_icon4.png`} alt="" />
</div>
<div className={pageStyle.staticRight}>
<div className={pageStyle.staticName}>评论</div>
<div className={pageStyle.staticCount}>
<span className={pageStyle.count}>1142</span>
<span className={pageStyle.count}>{dataAllTotal.comment_count}</span>
<span className={pageStyle.countAfter}></span>
</div>
</div>
......@@ -160,5 +234,16 @@ StaticBox.propTypes = {
};
export default StaticBox;
const StaticBoxForm = Form.create()(StaticBox);
function mapStateToProps(state) {
const {
courseChartData,
dataAllTotal,
} = state.onlineclasses;
return {
courseChartData,
dataAllTotal,
};
}
export default connect(mapStateToProps)(StaticBoxForm);
......@@ -76,7 +76,7 @@ class singleDetailForm extends React.Component {
<div className={pageStyle.container}>
<div className={pageStyle.head}>
<div className={pageStyle.hedaTitle}>
<img src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" alt="" />
<img src={`${__IMGCDN__}/course/book_icon.png`} alt="" />
<div className={pageStyle.title}>{addCourseObj.title}</div>
<Dropdown className={pageStyle.editStatus} overlay={menu} trigger={['click']}>
<a className="ant-dropdown-link" href="#">
......
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