Commit 1402a09b by guomingpang

fix:merge hotfix/hotfix/pangguoming/20210601/plan_list_add_cover to master

parents 5bd610bd e340da37
......@@ -4,7 +4,7 @@
* @Last Modified by: chenshu
* @Last Modified time: 2020-08-31 14:55:30
*/
@import "./variables.less";
@import './variables.less';
@active-color: #2966ff;
......@@ -234,7 +234,7 @@
}
.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
font-weight: 500!important;
font-weight: 500 !important;
}
.ant-tabs-nav .ant-tabs-tab-active {
......@@ -259,7 +259,7 @@
//display: none!important;
&:after {
content: "";
content: '';
display: inline-block;
position: absolute;
width: 30px;
......@@ -660,8 +660,8 @@ td.ant-table-column-sort {
background-color: #2966ff !important;
opacity: 0.8 !important;
}
&:active{
background-color:#5C8AFF !important;
&:active {
background-color: #5c8aff !important;
}
}
......
......@@ -7,7 +7,7 @@
left: 0px;
right: 0;
bottom: 0;
z-index:3;
z-index: 3;
background-color: #fff;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
......@@ -20,12 +20,12 @@
bottom: 0;
z-index: 102;
overflow: auto;
margin:0 16px;
.box{
&:first-child{
margin: 0 16px;
.box {
&:first-child {
margin-bottom: 8px;
}
&:last-child{
&:last-child {
margin-bottom: 16px;
}
}
......@@ -48,10 +48,10 @@
.content-header {
padding: 16px 16px 8px 16px;
line-height: 30px;
font-size:24px;
color:#333;
font-weight:bold;
background: #FFF;
font-size: 24px;
color: #333;
font-weight: bold;
background: #fff;
h1 {
font-weight: normal;
display: inline-block;
......
......@@ -2,56 +2,56 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: wufan
* @LastEditTime: 2021-05-30 17:33:09
* @LastEditTime: 2021-05-30 20:35:49
* @Description: 视频课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import React from 'react'
import { Button, Input, Radio, message, Modal, Cascader } from 'antd'
import { DISK_MAP, FileTypeIcon, FileVerifyMap } from '@/common/constants/academic/lessonEnum'
import { ImgCutModalNew } from '@/components'
import ShowTips from '@/components/ShowTips'
import Breadcrumbs from '@/components/Breadcrumbs'
import AddVideoIntro from './components/AddVideoIntro'
import SelectStudent from '../modal/select-student'
import SelectPrepareFileModal from '../../prepare-lesson/modal/SelectPrepareFileModal'
import PreviewCourseModal from '../modal/PreviewCourseModal'
import StoreService from '@/domains/store-domain/storeService'
import CourseService from '@/domains/course-domain/CourseService'
import Service from '@/common/js/service'
import User from '@/common/js/user'
import _ from 'underscore'
import Upload from '@/core/upload'
import { randomString } from '@/domains/basic-domain/utils'
import $ from 'jquery'
import React from 'react';
import { Button, Input, Radio, message, Modal, Cascader } from 'antd';
import { DISK_MAP, FileTypeIcon, FileVerifyMap } from '@/common/constants/academic/lessonEnum';
import { ImgCutModalNew } from '@/components';
import ShowTips from '@/components/ShowTips';
import Breadcrumbs from '@/components/Breadcrumbs';
import AddVideoIntro from './components/AddVideoIntro';
import SelectStudent from '../modal/select-student';
import SelectPrepareFileModal from '../../prepare-lesson/modal/SelectPrepareFileModal';
import PreviewCourseModal from '../modal/PreviewCourseModal';
import StoreService from '@/domains/store-domain/storeService';
import CourseService from '@/domains/course-domain/CourseService';
import Service from '@/common/js/service';
import User from '@/common/js/user';
import _ from 'underscore';
import Upload from '@/core/upload';
import { randomString } from '@/domains/basic-domain/utils';
import $ from 'jquery';
// import PhotoClip from 'photoclip';
import './AddVideoCourse.less'
import './AddVideoCourse.less';
const EDIT_BOX_KEY = Math.random()
const fieldNames = { label: 'categoryName', value: 'id', children: 'sonCategoryList' }
const EDIT_BOX_KEY = Math.random();
const fieldNames = { label: 'categoryName', value: 'id', children: 'sonCategoryList' };
//添加课程时课程默认的一些值
const defaultShelfState = 'YES'
const defaultShelfState = 'YES';
const defaultScheduleMedia = [
{
contentType: 'INTRO',
mediaType: 'TEXT',
mediaContent: '',
key: EDIT_BOX_KEY
}
]
const whetherVisitorsJoin = 'NO'
key: EDIT_BOX_KEY,
},
];
const whetherVisitorsJoin = 'NO';
let cutFlag = false
let cutFlag = false;
class AddVideoCourse extends React.Component {
constructor(props) {
super(props)
super(props);
const id = getParameterByName('id')
const pageType = getParameterByName('type')
const id = getParameterByName('id');
const pageType = getParameterByName('type');
this.state = {
id, // 视频课ID,编辑的时候从URL上带过来
......@@ -69,8 +69,8 @@ class AddVideoCourse extends React.Component {
contentType: 'INTRO',
mediaType: 'TEXT',
mediaContent: '',
key: EDIT_BOX_KEY
}
key: EDIT_BOX_KEY,
},
],
diskList: [], // 机构可见磁盘目录
selectedFileList: [], // 已经从资料云盘中勾选的文件
......@@ -83,15 +83,15 @@ class AddVideoCourse extends React.Component {
whetherVisitorsJoin: 'NO', // 是否允许游客加入
showSelectCoverModal: false,
cutImageBlob: null,
introduce: ''
}
introduce: '',
};
}
componentWillMount() {
const { id, pageType } = this.state
this.getCourseCatalogList()
const { id, pageType } = this.state;
this.getCourseCatalogList();
if (pageType === 'edit') {
this.handleFetchScheudleDetail(id)
this.handleFetchScheudleDetail(id);
}
}
......@@ -99,70 +99,70 @@ class AddVideoCourse extends React.Component {
getCourseCatalogList = () => {
StoreService.getCourseCatalogList({ current: 1, size: 1000 }).then((res) => {
this.setState({
courseCatalogList: res.result.records
})
})
}
courseCatalogList: res.result.records,
});
});
};
catalogChange = (value) => {
const changeValueLength = value.length
const changeValueLength = value.length;
switch (changeValueLength) {
case 1:
this.setState({ categoryId: value[0] })
break
this.setState({ categoryId: value[0] });
break;
case 2:
this.setState({ categoryId: value[1] })
break
this.setState({ categoryId: value[1] });
break;
default:
this.setState({ categoryId: null })
break
this.setState({ categoryId: null });
break;
}
}
};
// 获取视频课详情
handleFetchScheudleDetail = (courseId) => {
CourseService.videoScheduleDetail({
courseId
courseId,
}).then((res) => {
const { result = {} } = res || {}
const { courseName, shelfState, whetherVisitorsJoin, courseMediaVOS, categoryOneName, categoryTwoName, categoryId } = result
let coverId
let coverUrl
let videoType
let videoDuration
let videoName
let scheduleMedia = []
let scheduleVideoId
let scheduleVideoUrl
let hasIntro
const { result = {} } = res || {};
const { courseName, shelfState, whetherVisitorsJoin, courseMediaVOS, categoryOneName, categoryTwoName, categoryId } = result;
let coverId;
let coverUrl;
let videoType;
let videoDuration;
let videoName;
let scheduleMedia = [];
let scheduleVideoId;
let scheduleVideoUrl;
let hasIntro;
courseMediaVOS.map((item) => {
switch (item.contentType) {
case 'COVER':
coverId = item.mediaContent
coverUrl = item.mediaUrl
break
coverId = item.mediaContent;
coverUrl = item.mediaUrl;
break;
case 'SCHEDULE':
videoDuration = item.videoDuration
videoName = item.mediaName
scheduleVideoId = item.mediaContent
scheduleVideoUrl = item.mediaUrl
videoType = item.mediaType
break
videoDuration = item.videoDuration;
videoName = item.mediaName;
scheduleVideoId = item.mediaContent;
scheduleVideoUrl = item.mediaUrl;
videoType = item.mediaType;
break;
case 'INTRO':
hasIntro = true
this.getTextDetail('introduce', item.mediaUrl)
break
hasIntro = true;
this.getTextDetail('introduce', item.mediaUrl);
break;
default:
break
break;
}
return item
})
return item;
});
let categoryName
let categoryName;
if (categoryTwoName) {
categoryName = `${categoryOneName}-${categoryTwoName}`
categoryName = `${categoryOneName}-${categoryTwoName}`;
} else {
categoryName = `${categoryOneName}`
categoryName = `${categoryOneName}`;
}
this.setState({
loadintroduce: !hasIntro,
......@@ -178,10 +178,10 @@ class AddVideoCourse extends React.Component {
shelfState,
whetherVisitorsJoin,
categoryName,
categoryId
})
})
}
categoryId,
});
});
};
getTextDetail = (key, url) => {
$.ajax({
......@@ -190,13 +190,13 @@ class AddVideoCourse extends React.Component {
url,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: (res) => {
this.setState({ [key]: res, [`load${key}`]: true })
}
})
}
this.setState({ [key]: res, [`load${key}`]: true });
},
});
};
handleGoBack = () => {
const { coverId, videoName, videoDuration, courseName, scheduleMedia, scheduleVideoId, categoryId, shelfState, whetherVisitorsJoin } = this.state
const { coverId, videoName, videoDuration, courseName, scheduleMedia, scheduleVideoId, categoryId, shelfState, whetherVisitorsJoin } = this.state;
if (
videoName ||
videoDuration ||
......@@ -216,30 +216,30 @@ class AddVideoCourse extends React.Component {
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
window.RCHistory.push({
pathname: `/video-course`
})
}
})
pathname: `/video-course`,
});
},
});
} else {
window.RCHistory.push({
pathname: `/video-course`
})
pathname: `/video-course`,
});
}
}
};
// 修改表单
handleChangeForm = (field, value, coverUrl) => {
this.setState({
[field]: value,
coverUrl: coverUrl ? coverUrl : this.state.coverUrl
})
}
coverUrl: coverUrl ? coverUrl : this.state.coverUrl,
});
};
// 显示选择学员弹窗
handleShowSelectStuModal = () => {
this.setState({ studentModal: true })
this.setState({ studentModal: true });
const { studentList, selectedStuList } = this.state
const { studentList, selectedStuList } = this.state;
const studentModal = (
<SelectStudent
showTabs={true}
......@@ -249,38 +249,38 @@ class AddVideoCourse extends React.Component {
studentList={studentList}
close={() => {
this.setState({
studentModal: null
})
studentModal: null,
});
}}
/>
)
this.setState({ studentModal })
}
);
this.setState({ studentModal });
};
handleSelectStudent = (studentIds) => {
let studentList = []
let studentList = [];
_.each(studentIds, (item) => {
studentList.push({ studentId: item })
})
studentList.push({ studentId: item });
});
// this.setState({ studentModal: null });
this.setState({ studentList })
this.setState({ studentModal: false })
}
this.setState({ studentList });
this.setState({ studentModal: false });
};
// 显示预览弹窗
handleShowPreviewModal = () => {
const { coverUrl, scheduleVideoUrl, courseName, scheduleMedia, videoDuration, introduce } = this.state
const { coverUrl, scheduleVideoUrl, courseName, scheduleMedia, videoDuration, introduce } = this.state;
const courseBasinInfo = {
coverUrl,
scheduleVideoUrl,
courseName,
videoDuration
}
videoDuration,
};
const courseIntroInfo = {
liveCourseMediaRequests: scheduleMedia,
introduce
}
introduce,
};
const previewCourseModal = (
<PreviewCourseModal
......@@ -289,24 +289,24 @@ class AddVideoCourse extends React.Component {
courseIntroInfo={courseIntroInfo}
close={() => {
this.setState({
previewCourseModal: null
})
previewCourseModal: null,
});
}}
/>
)
);
this.setState({ previewCourseModal })
}
this.setState({ previewCourseModal });
};
// 选择视频
handleSelectVideo = (file) => {
this.setState({
showSelectFileModal: false
})
const { ossUrl, resourceId, folderName, folderFormat, folderSize } = file
showSelectFileModal: false,
});
const { ossUrl, resourceId, folderName, folderFormat, folderSize } = file;
const videoDom = document.createElement('video')
videoDom.src = ossUrl
const videoDom = document.createElement('video');
videoDom.src = ossUrl;
videoDom.onloadedmetadata = () => {
this.setState({
size: folderSize,
......@@ -314,14 +314,14 @@ class AddVideoCourse extends React.Component {
videoType: folderFormat,
scheduleVideoUrl: ossUrl,
scheduleVideoId: resourceId,
videoDuration: videoDom.duration
})
}
}
videoDuration: videoDom.duration,
});
};
};
// 保存
handleSubmit = () => {
const { instId, adminId } = window.currentUserInstInfo
const { instId, adminId } = window.currentUserInstInfo;
const {
id,
......@@ -340,8 +340,8 @@ class AddVideoCourse extends React.Component {
categoryId,
shelfState,
whetherVisitorsJoin,
introduce
} = this.state
introduce,
} = this.state;
const commonParams = {
videoName,
......@@ -355,144 +355,144 @@ class AddVideoCourse extends React.Component {
storeId: User.getStoreId(),
shelfState,
whetherVisitorsJoin,
courseType: 'VOICE'
}
courseType: 'VOICE',
};
// 校验必填字段:课程名称, 课程视频
this.handleValidate(courseName, scheduleVideoId, categoryId, scheduleMedia).then((res) => {
if (!res) return
if (!res) return;
Upload.uploadTextToOSS(introduce, `${randomString()}.txt`, (introduceId) => {
this.submitRemote({ id, pageType, commonParams: { ...commonParams, introduceId } })
})
})
}
this.submitRemote({ id, pageType, commonParams: { ...commonParams, introduceId } });
});
});
};
submitRemote = ({ id, pageType, commonParams }) => {
if (pageType === 'add') {
Service.Hades('public/hades/createMediaCourse', commonParams).then((res) => {
if (!res) return
message.success('新建成功')
if (!res) return;
message.success('新建成功');
window.RCHistory.push({
pathname: `/video-course`
})
})
pathname: `/video-course`,
});
});
} else {
const editParams = {
courseId: id,
...commonParams
}
...commonParams,
};
Service.Hades('public/hades/editMediaCourse', editParams).then((res) => {
if (!res) return
message.success('保存成功')
if (!res) return;
message.success('保存成功');
window.RCHistory.push({
pathname: `/video-course`
})
})
pathname: `/video-course`,
});
});
}
}
};
handleValidate = (courseName, scheduleVideoId, categoryId, scheduleMedia) => {
return new Promise((resolve) => {
if (!courseName) {
message.warning('请输入课程名称')
resolve(false)
return false
message.warning('请输入课程名称');
resolve(false);
return false;
}
if (!scheduleVideoId) {
message.warning('请上传视频')
resolve(false)
return false
message.warning('请上传视频');
resolve(false);
return false;
}
if (!categoryId) {
message.warning('请选择课程分类')
resolve(false)
return false
message.warning('请选择课程分类');
resolve(false);
return false;
}
const textMedia = scheduleMedia.filter((item) => item.mediaType === 'TEXT')
const textMedia = scheduleMedia.filter((item) => item.mediaType === 'TEXT');
for (let i = 0, len = textMedia.length; i < len; i++) {
if (textMedia[i].mediaContentLength && textMedia[i].mediaContentLength.length > 1000) {
message.warning(`第${i + 1}个文字简介的字数超过了1000个字`)
resolve(false)
return false
message.warning(`第${i + 1}个文字简介的字数超过了1000个字`);
resolve(false);
return false;
}
}
resolve(true)
})
}
resolve(true);
});
};
handleSelectCover = (file) => {
this.uploadImage(file)
}
this.uploadImage(file);
};
//上传图片
uploadImage = (imageFile) => {
const { folderName } = imageFile
const fileName = window.random_string(16) + folderName.slice(folderName.lastIndexOf('.'))
const self = this
const { folderName } = imageFile;
const fileName = window.random_string(16) + folderName.slice(folderName.lastIndexOf('.'));
const self = this;
this.setState(
{
visible: true
visible: true,
},
() => {
setTimeout(() => {
const okBtnDom = document.querySelector('#headPicModal')
const okBtnDom = document.querySelector('#headPicModal');
const options = {
size: [500, 282],
ok: okBtnDom,
maxZoom: 3,
style: {
jpgFillColor: 'transparent'
jpgFillColor: 'transparent',
},
done: function (dataUrl) {
clearTimeout(self.timer)
clearTimeout(self.timer);
self.timer = setTimeout(() => {
if (self.state.rotate != this.rotate() || self.state.scale != this.scale()) {
const _dataUrl = this.clip()
const cutImageBlob = self.convertBase64UrlToBlob(_dataUrl)
const _dataUrl = this.clip();
const cutImageBlob = self.convertBase64UrlToBlob(_dataUrl);
self.setState({
cutImageBlob,
dataUrl: _dataUrl,
rotate: this.rotate(),
scale: this.scale()
})
scale: this.scale(),
});
}
}, 500)
}, 500);
const cutImageBlob = self.convertBase64UrlToBlob(dataUrl)
const cutImageBlob = self.convertBase64UrlToBlob(dataUrl);
self.setState({
cutImageBlob,
dataUrl
})
dataUrl,
});
setTimeout(() => {
cutFlag = false
}, 2000)
cutFlag = false;
}, 2000);
},
fail: (failInfo) => {
message.error('图片上传失败了,请重新上传')
message.error('图片上传失败了,请重新上传');
},
loadComplete: function (img) {
setTimeout(() => {
const _dataUrl = this.clip()
const _dataUrl = this.clip();
self.setState({
dataUrl: _dataUrl,
hasImgReady: true
})
}, 100)
}
}
const imgUrl = `${imageFile.ossUrl}?${new Date().getTime()}`
hasImgReady: true,
});
}, 100);
},
};
const imgUrl = `${imageFile.ossUrl}?${new Date().getTime()}`;
if (!this.state.photoclip) {
const _photoclip = new PhotoClip('#headPicModal', options)
_photoclip.load(imgUrl)
const _photoclip = new PhotoClip('#headPicModal', options);
_photoclip.load(imgUrl);
this.setState({
photoclip: _photoclip
})
photoclip: _photoclip,
});
} else {
this.state.photoclip.clear()
this.state.photoclip.load(imgUrl)
this.state.photoclip.clear();
this.state.photoclip.load(imgUrl);
}
}, 200)
}, 200);
}
)
}
);
};
//获取resourceId
getSignature = (blob, fileName) => {
......@@ -501,30 +501,30 @@ class AddVideoCourse extends React.Component {
{
coverClicpPath: signInfo.fileUrl,
coverId: signInfo.resourceId,
visible: false
visible: false,
},
() => this.updateCover()
)
})
}
);
});
};
updateCover = () => {
const { coverClicpPath, coverId } = this.state
const { coverClicpPath, coverId } = this.state;
this.setState({
showSelectCoverModal: false,
coverUrl: coverClicpPath,
coverId: coverId
})
}
coverId: coverId,
});
};
// base64转换成blob
convertBase64UrlToBlob = (urlData) => {
const bytes = window.atob(urlData.split(',')[1])
const ab = new ArrayBuffer(bytes.length)
const ia = new Uint8Array(ab)
const bytes = window.atob(urlData.split(',')[1]);
const ab = new ArrayBuffer(bytes.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i)
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], { type: 'image/png' })
}
return new Blob([ab], { type: 'image/png' });
};
render() {
const {
pageType,
......@@ -552,13 +552,13 @@ class AddVideoCourse extends React.Component {
cutImageBlob,
introduce,
loadintroduce,
id
} = this.state
id,
} = this.state;
// 已选择的上课学员数量
const hasSelectedStu = studentList.length
const hasSelectedStu = studentList.length;
const courseWareIcon = FileVerifyMap[videoType] ? FileTypeIcon[FileVerifyMap[videoType].type] : FileTypeIcon[videoType]
const courseWareIcon = FileVerifyMap[videoType] ? FileTypeIcon[FileVerifyMap[videoType].type] : FileTypeIcon[videoType];
return (
<div className='page add-video-course-page'>
......@@ -578,7 +578,7 @@ class AddVideoCourse extends React.Component {
maxLength={40}
style={{ width: 240 }}
onChange={(e) => {
this.handleChangeForm('courseName', e.target.value)
this.handleChangeForm('courseName', e.target.value);
}}
/>
</div>
......@@ -601,8 +601,8 @@ class AddVideoCourse extends React.Component {
<Button
onClick={() => {
this.setState({
showSelectFileModal: true
})
showSelectFileModal: true,
});
}}>{`${pageType === 'add' && !scheduleVideoId ? '选择' : '更换'}视频`}</Button>
<span className='tips'>视频数量限制1个,大小不超过2G</span>
......@@ -627,7 +627,7 @@ class AddVideoCourse extends React.Component {
<div className='opt-btns'>
<Button
onClick={() => {
this.setState({ showSelectCoverModal: true })
this.setState({ showSelectCoverModal: true });
}}>{`${pageType === 'add' && !scheduleVideoId && !coverUrl ? '上传' : '修改'}封面`}</Button>
<div className='tips'>建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。</div>
</div>
......@@ -676,7 +676,7 @@ class AddVideoCourse extends React.Component {
shelfState,
whetherVisitorsJoin,
introduce,
loadintroduce
loadintroduce,
}}
onChange={this.handleChangeForm}
/>
......@@ -684,7 +684,7 @@ class AddVideoCourse extends React.Component {
</div>
</div>
<div className="footer shrink-footer">
<div className='footer shrink-footer'>
<Button onClick={this.handleGoBack}>取消</Button>
<Button onClick={this.handleShowPreviewModal}>预览</Button>
<Button type='primary' onClick={_.debounce(() => this.handleSubmit(), 3000, true)}>
......@@ -700,14 +700,14 @@ class AddVideoCourse extends React.Component {
accept='video/mp4'
confirm={{
title: '文件过大,无法上传',
content: '为保障学员的观看体验,上传的视频大小不能超过2G'
content: '为保障学员的观看体验,上传的视频大小不能超过2G',
}}
tooltip={'格式支持mp4,大小不超过2G'}
isOpen={showSelectFileModal}
diskList={diskList}
addVideo={true}
onClose={() => {
this.setState({ showSelectFileModal: false })
this.setState({ showSelectFileModal: false });
}}
onSelect={this.handleSelectVideo}
/>
......@@ -722,7 +722,7 @@ class AddVideoCourse extends React.Component {
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectCoverModal}
onClose={() => {
this.setState({ showSelectCoverModal: false })
this.setState({ showSelectCoverModal: false });
}}
onSelect={this.handleSelectCover}
/>
......@@ -734,14 +734,14 @@ class AddVideoCourse extends React.Component {
maskClosable={false}
closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
onCancel={() => {
this.setState({ visible: false })
this.setState({ visible: false });
}}
zIndex={10001}
footer={[
<Button
key='back'
onClick={() => {
this.setState({ visible: false })
this.setState({ visible: false });
}}>
重新上传
</Button>,
......@@ -751,13 +751,13 @@ class AddVideoCourse extends React.Component {
disabled={!hasImgReady}
onClick={() => {
if (!cutFlag) {
cutFlag = true
this.refs.hiddenBtn.click()
cutFlag = true;
this.refs.hiddenBtn.click();
}
this.getSignature(cutImageBlob)
this.getSignature(cutImageBlob);
}}>
确定
</Button>
</Button>,
]}>
<div className='clip-box'>
<div
......@@ -766,7 +766,7 @@ class AddVideoCourse extends React.Component {
style={{
width: '500px',
height: '430px',
marginBottom: 0
marginBottom: 0,
}}></div>
<div id='clipBtn' style={{ display: 'none' }} ref='hiddenBtn'></div>
<div className='preview-img'>
......@@ -784,8 +784,8 @@ class AddVideoCourse extends React.Component {
</Modal>
{this.state.previewCourseModal}
</div>
)
);
}
}
export default AddVideoCourse
export default AddVideoCourse;
......@@ -450,7 +450,7 @@ class VideoCourseList extends React.Component {
},
() => {
this.props.onChange();
},
}
);
};
render() {
......
......@@ -139,6 +139,7 @@
background: #fff;
width: ~'calc(50% - 8px)';
padding: 16px;
overflow: hidden;
.study-title {
font-size: 14px;
color: #333;
......
......@@ -2,207 +2,207 @@
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-12 14:49:40
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-05-30 18:36:45
* @LastEditors: wufan
* @LastEditTime: 2021-05-30 20:37:42
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react"
import { Table, Modal, message, Tooltip, Switch, Dropdown, Button } from "antd"
import { Route, withRouter } from "react-router-dom"
import { PageControl } from "@/components"
import { LIVE_SHARE_MAP } from "@/common/constants/academic/cloudClass"
import { appId, shareUrl, LIVE_SHARE } from "@/domains/course-domain/constants"
import ScanFileModal from "../../resource-disk/modal/ScanFileModal"
import WatchData from "./WatchData"
import KnowledgeAPI from "@/data-source/knowledge/request-api"
import ENUM from "../ENUM.js"
import "./KnowledgeBaseList.less"
import React from 'react';
import { Table, Modal, message, Tooltip, Switch, Dropdown, Button } from 'antd';
import { Route, withRouter } from 'react-router-dom';
import { PageControl } from '@/components';
import { LIVE_SHARE_MAP } from '@/common/constants/academic/cloudClass';
import { appId, shareUrl, LIVE_SHARE } from '@/domains/course-domain/constants';
import ScanFileModal from '../../resource-disk/modal/ScanFileModal';
import WatchData from './WatchData';
import KnowledgeAPI from '@/data-source/knowledge/request-api';
import ENUM from '../ENUM.js';
import './KnowledgeBaseList.less';
const DEFAULT_SIZE_UNIT = 1000 * 1000 // 将B转换成M
const { confirm } = Modal
const ENV = process.env.DEPLOY_ENV || "dev"
const DEFAULT_SIZE_UNIT = 1000 * 1000; // 将B转换成M
const { confirm } = Modal;
const ENV = process.env.DEPLOY_ENV || 'dev';
class KnowledgeBaseList extends React.Component {
constructor(props) {
super(props)
super(props);
this.state = {
id: "",
scanFileModal: null
}
id: '',
scanFileModal: null,
};
}
handleAdminName = (adminArray) => {
let adminStr = ""
let adminStr = '';
adminArray.map((item, index) => {
if (index < adminArray.length - 1) {
adminStr = adminStr + item.adminName + "、"
adminStr = adminStr + item.adminName + '、';
} else {
adminStr = adminStr + item.adminName
adminStr = adminStr + item.adminName;
}
})
return adminStr
}
});
return adminStr;
};
handleUp = (index, record) => {
if (index === 0 && this.props.query.current === 1) {
return
return;
}
const params = {
direction: "UP",
direction: 'UP',
id: record.id,
storeId: record.storeId
}
storeId: record.storeId,
};
KnowledgeAPI.moveKnowledge(params).then((res) => {
if (res.success) {
message.success("更新成功")
this.props.onChange()
message.success('更新成功');
this.props.onChange();
}
})
}
});
};
handleDown = (record, index) => {
const { query, totalCount } = this.props
const { current, size } = query
const { query, totalCount } = this.props;
const { current, size } = query;
if (totalCount === size * (current - 1) + index + 1) {
return
return;
}
const params = {
direction: "DOWN",
direction: 'DOWN',
id: record.id,
storeId: record.storeId
}
storeId: record.storeId,
};
KnowledgeAPI.moveKnowledge(params).then((res) => {
if (res.success) {
message.success("更新成功")
this.props.onChange()
message.success('更新成功');
this.props.onChange();
}
})
}
});
};
getBlob = (url) => {
return new Promise((resolve) => {
const xhr = new XMLHttpRequest()
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true)
xhr.responseType = "blob"
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response)
resolve(xhr.response);
}
}
xhr.send()
})
}
};
xhr.send();
});
};
saveAs = (blob, filename) => {
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, filename)
navigator.msSaveBlob(blob, filename);
} else {
const link = document.createElement("a")
const body = document.querySelector("body")
const link = document.createElement('a');
const body = document.querySelector('body');
// 创建对象url
link.href = window.URL.createObjectURL(blob)
link.download = filename
link.href = window.URL.createObjectURL(blob);
link.download = filename;
body.appendChild(link)
body.appendChild(link);
link.click()
body.removeChild(link)
link.click();
body.removeChild(link);
// 通过调用 URL.createObjectURL() 创建的 URL 对象
window.URL.revokeObjectURL(link.href)
window.URL.revokeObjectURL(link.href);
}
}
};
// 下载文件
handleDownload = (folder) => {
this.getBlob(folder.ossUrl).then((blob) => {
this.saveAs(blob, folder.folderName)
})
}
this.saveAs(blob, folder.folderName);
});
};
// 预览文件
handleScanFile = (folder) => {
console.log(folder)
const { folderFormat, folderSize, ossUrl } = folder
console.log(folder);
const { folderFormat, folderSize, ossUrl } = folder;
switch (folderFormat) {
case "PDF":
window.open(ossUrl, "_blank")
break
case "WORD":
case "DOCX":
case "DOC":
case "EXCEL":
case "PPT":
case "PPTX":
case "PDF":
case 'PDF':
window.open(ossUrl, '_blank');
break;
case 'WORD':
case 'DOCX':
case 'DOC':
case 'EXCEL':
case 'PPT':
case 'PPTX':
case 'PDF':
if (
((folderFormat === "PPT" || folderFormat === "PPTX" || folderFormat === "DOCX" || folderFormat === "WORD" || folderFormat === "DOC") &&
((folderFormat === 'PPT' || folderFormat === 'PPTX' || folderFormat === 'DOCX' || folderFormat === 'WORD' || folderFormat === 'DOC') &&
folderSize > 10 * DEFAULT_SIZE_UNIT) ||
(folderFormat === "EXCEL" && folderSize > 5 * DEFAULT_SIZE_UNIT)
(folderFormat === 'EXCEL' && folderSize > 5 * DEFAULT_SIZE_UNIT)
) {
Modal.confirm({
title: "抱歉,不能在线预览",
content: "由于文件较大,不支持在线预览,请下载后再查看",
title: '抱歉,不能在线预览',
content: '由于文件较大,不支持在线预览,请下载后再查看',
// icon: <Icon type="question-circle" theme="filled" style={{ color: '#FF8534' }}></Icon>,
cancelText: "取消",
okText: "下载",
cancelText: '取消',
okText: '下载',
onOk: () => {
this.handleDownload(folder)
}
})
break
this.handleDownload(folder);
},
});
break;
}
const prefixUrl = "https://view.officeapps.live.com/op/view.aspx?src="
const scanUrl = `${prefixUrl}${encodeURIComponent(ossUrl)}`
window.open(scanUrl, "_blank")
break
const prefixUrl = 'https://view.officeapps.live.com/op/view.aspx?src=';
const scanUrl = `${prefixUrl}${encodeURIComponent(ossUrl)}`;
window.open(scanUrl, '_blank');
break;
default:
const scanFileModal = (
<ScanFileModal
fileType={folderFormat}
item={folder}
close={() => {
this.setState({ scanFileModal: null })
this.setState({ scanFileModal: null });
}}
/>
)
this.setState({ scanFileModal })
break
);
this.setState({ scanFileModal });
break;
}
}
};
// 请求表头
parseColumns = () => {
const { query, totalCount } = this.props
const { current, size } = query
const { query, totalCount } = this.props;
const { current, size } = query;
const columns = [
{
title: "课程名称",
key: "name",
dataIndex: "name",
title: '课程名称',
key: 'name',
dataIndex: 'name',
width: 391,
fixed: "left",
fixed: 'left',
render: (val, record) => {
const { coverUrl, mediaCourseUrl, courseDivision } = record.source
let hasCover = false
const type = record.type
const { coverUrl, mediaCourseUrl, courseDivision } = record.source;
let hasCover = false;
const type = record.type;
return (
<div>
{type === "LIVE" && (
{type === 'LIVE' && (
<div className='record__item'>
{record.source &&
record.source.courseMediaVOS.map((item, index) => {
if (item.contentType === "COVER") {
hasCover = true
return <img className='course-cover' key={index} src={item.mediaUrl} />
if (item.contentType === 'COVER') {
hasCover = true;
return <img className='course-cover' key={index} src={item.mediaUrl} />;
}
})}
{!hasCover && <img className='course-cover' src={"https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png"} />}
{!hasCover && <img className='course-cover' src={'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'} />}
<div>
{val.length > 17 ? (
<Tooltip title={val}>
......@@ -213,13 +213,13 @@ class KnowledgeBaseList extends React.Component {
)}
<div>
<span className='course-time'>
{formatDate("YYYY-MM-DD H:i", parseInt(record.source.startTime))}~{formatDate("H:i", parseInt(record.source.endTime))}
{formatDate('YYYY-MM-DD H:i', parseInt(record.source.startTime))}~{formatDate('H:i', parseInt(record.source.endTime))}
</span>
<span
className='course-status'
style={{
color: ENUM.courseStateShow[record.source.courseState].color,
border: `1px solid ${ENUM.courseStateShow[record.source.courseState].color}`
border: `1px solid ${ENUM.courseStateShow[record.source.courseState].color}`,
}}>
{ENUM.courseStateShow[record.source.courseState].title}
</span>
......@@ -228,10 +228,10 @@ class KnowledgeBaseList extends React.Component {
<i
className='icon iconfont'
style={{
marginLeft: "5px",
cursor: "pointer",
color: "#FF4F4F",
fontSize: "14px"
marginLeft: '5px',
cursor: 'pointer',
color: '#FF4F4F',
fontSize: '14px',
}}>
&#xe61d;
</i>
......@@ -257,9 +257,9 @@ class KnowledgeBaseList extends React.Component {
{record.source.admins.map((item, index) => {
return (
<span>
{item.adminName} {index < record.source.admins.length - 1 && <span></span>}{" "}
{item.adminName} {index < record.source.admins.length - 1 && <span></span>}{' '}
</span>
)
);
})}
</span>
</Tooltip>
......@@ -269,9 +269,9 @@ class KnowledgeBaseList extends React.Component {
{record.source.admins.map((item, index) => {
return (
<span key={index}>
{item.adminName} {index < record.source.admins.length - 1 && <span></span>}{" "}
{item.adminName} {index < record.source.admins.length - 1 && <span></span>}{' '}
</span>
)
);
})}
</span>
)}
......@@ -282,7 +282,7 @@ class KnowledgeBaseList extends React.Component {
</div>
)}
{type === "VOICE" && (
{type === 'VOICE' && (
<div className='record__item'>
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
<img
......@@ -290,9 +290,9 @@ class KnowledgeBaseList extends React.Component {
src={
coverUrl
? coverUrl
: courseDivision !== "EXTERNAL"
: courseDivision !== 'EXTERNAL'
? `${mediaCourseUrl}?x-oss-process=video/snapshot,t_0,m_fast`
: "https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png"
: 'https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png'
}
alt=''
/>
......@@ -306,9 +306,9 @@ class KnowledgeBaseList extends React.Component {
</div>
)}
{type === "PICTURE" && (
{type === 'PICTURE' && (
<div className='record__item'>
<img className='course-cover' src={coverUrl || "https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png"} />
<img className='course-cover' src={coverUrl || 'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png'} />
{val.length > 25 ? (
<Tooltip title={val}>
<div className='course-name clamp'>{val}</div>
......@@ -319,11 +319,11 @@ class KnowledgeBaseList extends React.Component {
</div>
)}
{type === "FOLDER" && (
{type === 'FOLDER' && (
<div
className='record__item'
onClick={() => {
this.handleScanFile(record.source)
this.handleScanFile(record.source);
}}>
<div className={`folder-type ${record.source && record.source.folderFormat}`} />
{val.length > 25 ? (
......@@ -336,24 +336,24 @@ class KnowledgeBaseList extends React.Component {
</div>
)}
</div>
)
}
);
},
},
{
title: "课程类型",
key: "type",
dataIndex: "type",
align: "center",
title: '课程类型',
key: 'type',
dataIndex: 'type',
align: 'center',
// width: 100,
render: (val, record) => {
return <div className=''>{val ? ENUM.CourseTypeEnum[val] : "-"}</div>
}
return <div className=''>{val ? ENUM.CourseTypeEnum[val] : '-'}</div>;
},
},
{
title: "创建人",
key: "createName",
dataIndex: "createName",
align: "center",
title: '创建人',
key: 'createName',
dataIndex: 'createName',
align: 'center',
render: (val) => {
return (
<div>
......@@ -363,37 +363,37 @@ class KnowledgeBaseList extends React.Component {
</Tooltip>
)}
</div>
)
}
);
},
},
{
title: "观看学员数",
key: "watchUserCount",
dataIndex: "watchUserCount",
align: "right",
title: '观看学员数',
key: 'watchUserCount',
dataIndex: 'watchUserCount',
align: 'right',
render: (val, item) => {
return val ? (
<div className='operate' style={{ display: "block" }} onClick={() => this.handleLinkToClassData(item)}>
<div className='operate' style={{ display: 'block' }} onClick={() => this.handleLinkToClassData(item)}>
<span className='operate__item'>{val}</span>
</div>
) : (
0
)
}
);
},
},
{
title: "",
width: 48
title: '',
width: 48,
},
{
title: "操作",
key: "operate",
dataIndex: "operate",
title: '操作',
key: 'operate',
dataIndex: 'operate',
width: 160,
fixed: "right",
fixed: 'right',
render: (val, record, index) => {
console.log(this.props.categoryId)
return this.props.categoryId === "0" ? (
console.log(this.props.categoryId);
return this.props.categoryId === '0' ? (
<div className='operate'>
<div className='operate__item' onClick={() => this.handleDelete(record)}>
移出
......@@ -401,12 +401,12 @@ class KnowledgeBaseList extends React.Component {
</div>
) : (
<div className='operate'>
<div className={index === 0 && current === 1 ? "operate__item disable" : "operate__item"} onClick={() => this.handleUp(index, record)}>
<div className={index === 0 && current === 1 ? 'operate__item disable' : 'operate__item'} onClick={() => this.handleUp(index, record)}>
上移
</div>
<span className='operate__item split'> | </span>
<div
className={totalCount === size * (current - 1) + index + 1 ? "operate__item disable" : "operate__item"}
className={totalCount === size * (current - 1) + index + 1 ? 'operate__item disable' : 'operate__item'}
onClick={() => this.handleDown(record, index)}>
下移
</div>
......@@ -415,66 +415,66 @@ class KnowledgeBaseList extends React.Component {
移出
</div>
</div>
)
}
}
]
return columns
}
);
},
},
];
return columns;
};
handleDelete = (record) => {
return confirm({
title: "移出知识",
content: "确定将分类中此知识移出吗?",
title: '移出知识',
content: '确定将分类中此知识移出吗?',
icon: <span className='icon iconfont default-confirm-icon'>&#xe839; </span>,
okText: "删除",
okType: "danger",
cancelText: "取消",
okText: '删除',
okType: 'danger',
cancelText: '取消',
width: 440,
height: 188,
onOk: () => {
this.deleteConfirm(record)
}
})
}
this.deleteConfirm(record);
},
});
};
// 前往上课数据页面
handleLinkToClassData = (item) => {
const { match } = this.props
console.log(item)
localStorage.setItem("WatchData_CourseName", item.name)
const { match } = this.props;
console.log(item);
localStorage.setItem('WatchData_CourseName', item.name);
window.RCHistory.push({
// pathname: `${match.url}/course-data?type=${item.courseType}&id=${item.liveCourseId}`,
pathname: `${match.url}/course-data?type=${item.type}&id=${item.id}`
})
}
pathname: `${match.url}/course-data?type=${item.type}&id=${item.id}`,
});
};
deleteConfirm = (item) => {
const params = {
id: item.id,
storeId: item.storeId
}
storeId: item.storeId,
};
KnowledgeAPI.delKnowledge(params).then((res) => {
if (res.success) {
message.success("移出成功")
this.props.onChange()
this.props.updateCategoryTree()
message.success('移出成功');
this.props.onChange();
this.props.updateCategoryTree();
}
})
}
});
};
onShowSizeChange = (current, size) => {
if (current == size) {
return
return;
}
let _query = this.props.query
_query.size = size
this.props.onChange(_query)
}
let _query = this.props.query;
_query.size = size;
this.props.onChange(_query);
};
render() {
const { dataSource = [], totalCount, query, match } = this.props
const { current, size } = query
const { dataSource = [], totalCount, query, match } = this.props;
const { current, size } = query;
return (
<div className='knowledge-base-list'>
<Table
......@@ -495,8 +495,8 @@ class KnowledgeBaseList extends React.Component {
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = { ...query, current: page + 1 }
this.props.onChange(_query)
const _query = { ...query, current: page + 1 };
this.props.onChange(_query);
}}
onShowSizeChange={this.onShowSizeChange}
/>
......@@ -507,8 +507,8 @@ class KnowledgeBaseList extends React.Component {
{this.state.scanFileModal}
</div>
)
);
}
}
export default withRouter(KnowledgeBaseList)
export default withRouter(KnowledgeBaseList);
import React from 'react';
import React from 'react'
import KnowledgeBaseFilter from './components/KnowledgeBaseFilter';
import KnowledgeBaseOpt from './components/KnowledgeBaseOpt';
import KnowledgeBaseList from './components/KnowledgeBaseList';
import Classification from './components/Classification';
import KnowledgeBaseFilter from './components/KnowledgeBaseFilter'
import KnowledgeBaseOpt from './components/KnowledgeBaseOpt'
import KnowledgeBaseList from './components/KnowledgeBaseList'
import Classification from './components/Classification'
import KnowledgeAPI from '@/data-source/knowledge/request-api'
import User from '@/common/js/user'
import KnowledgeAPI from '@/data-source/knowledge/request-api';
import User from '@/common/js/user';
export default class KnowledgeBase extends React.Component {
constructor(props) {
super(props)
super(props);
this.state = {
query: {
size: 10,
......@@ -23,51 +22,51 @@ export default class KnowledgeBase extends React.Component {
totalCount: 0, // 知识库数据总条数
categoryId: '0',
updateCategoryFlag: false,
}
};
}
componentWillMount() {
// 获取知识库列表
this.handleFetchScheduleList()
this.handleFetchScheduleList();
// this.getCategoryTree()
}
getSelectedCategoryId = (categoryId) => {
this.setState({
categoryId,
})
this.handleFetchScheduleList({ categoryId, current: 1 })
}
});
this.handleFetchScheduleList({ categoryId, current: 1 });
};
// 更新分类树
updateCategoryTree = () => {
this.setState({
updateCategoryFlag: !this.state.updateCategoryFlag,
})
}
});
};
// 获取知识库列表
handleFetchScheduleList = (_query = {}, flag = true) => {
const query = {
...this.state.query,
..._query,
}
};
// 更新请求参数
this.setState({ query })
this.setState({ query });
flag &&
KnowledgeAPI.queryPageKnowledgeForManager(query).then((res) => {
// KnowledgeAPI.videoSchedulePage(query).then((res) => {
const { result = {} } = res || {}
const { records = [], total = 0 } = result
const { result = {} } = res || {};
const { records = [], total = 0 } = result;
this.setState({
dataSource: records,
totalCount: Number(total),
})
})
}
});
});
};
render() {
const { dataSource, totalCount, query, categoryId, updateCategoryFlag } = this.state
const { dataSource, totalCount, query, categoryId, updateCategoryFlag } = this.state;
return (
<div className='page'>
<div className='content-header'>知识库</div>
......@@ -77,11 +76,8 @@ export default class KnowledgeBase extends React.Component {
<div className='left' style={{ width: 245 }}>
<Classification updateCategoryFlag={updateCategoryFlag} categoryId={categoryId} getSelectedCategoryId={this.getSelectedCategoryId} />
</div>
<div
className="liner"
style={{ backgroundColor: "rgb(238, 238, 238)", width: 0.5, margin: "1px 16px 1px 2px" }}
></div>
<div className="right" style={{ width: "calc(100% - 265px)" }}>
<div className='liner' style={{ backgroundColor: 'rgb(238, 238, 238)', width: 0.5, margin: '1px 16px 1px 2px' }}></div>
<div className='right' style={{ width: 'calc(100% - 265px)' }}>
<KnowledgeBaseFilter onChange={this.handleFetchScheduleList} />
{/* 操作模块 */}
......@@ -101,6 +97,6 @@ export default class KnowledgeBase extends React.Component {
</div>
</div>
</div>
)
);
}
}
......@@ -3,7 +3,7 @@
* @Author: zangsuyun
* @Date: 2021-03-13 09:54:26
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-05-31 18:23:28
* @LastEditTime: 2021-06-01 10:26:46
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -258,7 +258,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchLiveList();
},
}
);
};
......@@ -272,7 +272,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchVideoList();
},
}
);
};
......@@ -286,7 +286,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchPictureList();
},
}
);
};
......@@ -593,7 +593,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchVideoList();
},
}
);
};
......@@ -615,7 +615,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchLiveList();
},
}
);
};
......@@ -629,7 +629,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchPictureList();
},
}
);
};
handAddCourse = () => {
......@@ -696,7 +696,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchVideoList();
},
}
);
};
......@@ -858,7 +858,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchLiveList();
},
}
);
}}
onShowSizeChange={this.onShowLiveSizeChange}
......@@ -893,6 +893,7 @@ class AddCourse extends React.Component {
<TreeSelect
treeNodeFilterProp='categoryName'
showSearch
value={videoQuery[videoCourseDivision].categoryId || null}
style={{ minWidth: 'calc(100% - 75px)' }}
value={videoQuery[videoCourseDivision].categoryId || null}
dropdownMatchSelectWidth={false}
......@@ -950,7 +951,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchVideoList();
},
}
);
}}
onShowSizeChange={this.onShowVideoSizeChange}
......@@ -1030,7 +1031,7 @@ class AddCourse extends React.Component {
},
() => {
this.handleFetchPictureList();
},
}
);
}}
onShowSizeChange={this.onShowPictureSizeChange}
......
......@@ -71,13 +71,13 @@
}
.courseware {
font-size: 14px;
color: #2966FF;
color: #2966ff;
line-height: 20px;
text-align: right;
cursor: pointer;
}
.quota-icon {
color: #2966FF;
color: #2966ff;
cursor: pointer;
}
.operate {
......@@ -85,7 +85,7 @@
align-items: center;
flex-wrap: wrap;
.operate__item {
color: #2966FF;
color: #2966ff;
cursor: pointer;
&.split {
margin: 0 8px;
......@@ -94,7 +94,7 @@
}
}
.operate-text {
color: #2966FF;
color: #2966ff;
cursor: pointer;
}
.course-start-end {
......@@ -127,8 +127,8 @@
.add-course-modal {
.ant-tabs-nav .ant-tabs-tab-active {
// border: 1px solid #2966FF;
color: #2966FF;
}
color: #2966ff;
}
.ant-modal-content tr > td {
padding: 12px 8px !important;
}
......
......@@ -2,7 +2,11 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39
* @LastEditors: wufan
<<<<<<< HEAD
* @LastEditTime: 2021-05-30 17:40:39
=======
* @LastEditTime: 2021-05-30 20:39:16
>>>>>>> hotfix/pangguoming/20210601/plan_list_add_cover
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51
* @LastEditors: wufan
* @LastEditTime: 2021-05-13 16:36:26
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-01 15:20:33
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from 'react';
import { Button,Input,Switch,Radio,Row,Col,Modal,message,Tooltip} from 'antd';
import { Button, Input, Switch, Radio, Row, Col, Modal, message, Tooltip } from 'antd';
import { withRouter } from 'react-router-dom';
import SelectOperatorModal from '../modal/SelectOperatorModal';
import { ImgCutModalNew } from '@/components';
import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal';
import Upload from '@/core/upload';
// import PhotoClip from 'photoclip'
import './BasicInfo.less';
const { TextArea } = Input;
const defaultCover = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
const defaultCover = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png';
let cutFlag = false;
let timer = null
class BasicInfo extends React.Component{
class BasicInfo extends React.Component {
constructor(props) {
super(props);
this.state = {
operatorModalVisible: false,
showSelectFileModal:false,
cutImageBlob: null
showSelectFileModal: false,
cutImageBlob: null,
};
}
handleShowSelectOperatorModal = () =>{
handleShowSelectOperatorModal = () => {
this.setState({
operatorModalVisible:true
})
}
handleCloseSelectOperatorMOdal = ()=>{
operatorModalVisible: true,
});
};
handleCloseSelectOperatorMOdal = () => {
this.setState({
operatorModalVisible:false
})
}
handleConfirmSelectOperator = (selectOperatorList)=> {
if(selectOperatorList.length === 0){
message.warning('请选择运营师')
operatorModalVisible: false,
});
};
handleConfirmSelectOperator = (selectOperatorList) => {
if (selectOperatorList.length === 0) {
message.warning('请选择运营师');
return;
}
this.props.onChange('selectOperatorList',selectOperatorList);
this.props.onChange('selectOperatorList', selectOperatorList);
this.setState({
operatorModalVisible:false
})
}
enableStateChange = ()=> {
if(this.props.data.enableState==="NO"){
this.props.onChange('enableState','YES')
}else{
this.props.onChange('enableState','NO')
operatorModalVisible: false,
});
};
enableStateChange = () => {
if (this.props.data.enableState === 'NO') {
this.props.onChange('enableState', 'YES');
} else {
this.props.onChange('enableState', 'NO');
}
}
};
// 使用默认封面图
handleResetCoverUrl = ()=> {
const { data: { coverUrl } } = this.props;
handleResetCoverUrl = () => {
const {
data: { coverUrl },
} = this.props;
const isDefaultCover = coverUrl === defaultCover;
// 如果已经是默认图的话,不做任何任何处理
if (isDefaultCover) return;
message.success('已替换为默认图');
this.props.onChange('coverUrl',defaultCover);
setTimeout(()=>{
this.props.onChange('coverUrl', defaultCover);
setTimeout(() => {
this.props.onChange('coverId', null);
},1000)
}
handleSelectCover = (file)=> {
}, 1000);
};
handleSelectCover = (file) => {
this.uploadImage(file);
}
};
//上传图片
uploadImage = (imageFile) => {
const { folderName } = imageFile;
const fileName = window.random_string(16) + folderName.slice(folderName.lastIndexOf("."));
const self = this;
this.setState(
{
......@@ -87,57 +83,55 @@ class BasicInfo extends React.Component{
},
() => {
setTimeout(() => {
const okBtnDom = document.querySelector("#headPicModal");
const okBtnDom = document.querySelector('#headPicModal');
const options = {
size: [500, 282],
ok: okBtnDom,
maxZoom: 3,
style: {
jpgFillColor: "transparent",
jpgFillColor: 'transparent',
},
done: function (dataUrl) {
clearTimeout(self.timer);
self.timer = setTimeout(() => {
if ((self.state.rotate != this.rotate()) || (self.state.scale != this.scale())) {
console.log(this.scale(), 'scale')
const _dataUrl = this.clip()
if (self.state.rotate !== this.rotate() || self.state.scale !== this.scale()) {
console.log(this.scale(), 'scale');
const _dataUrl = this.clip();
const cutImageBlob = self.convertBase64UrlToBlob(_dataUrl);
self.setState({
cutImageBlob,
dataUrl: _dataUrl,
rotate: this.rotate(),
scale: this.scale()
})
scale: this.scale(),
});
}
}, 500)
}, 500);
const cutImageBlob = self.convertBase64UrlToBlob(dataUrl);
self.setState({
cutImageBlob,
dataUrl
})
dataUrl,
});
setTimeout(() => {
cutFlag = false;
}, 2000);
},
fail: (failInfo) => {
message.error("图片上传失败了,请重新上传");
message.error('图片上传失败了,请重新上传');
},
loadComplete: function (img) {
setTimeout(() => {
const _dataUrl = this.clip()
const _dataUrl = this.clip();
self.setState({
dataUrl: _dataUrl,
hasImgReady: true
})
}, 100)
hasImgReady: true,
});
}, 100);
},
};
const imgUrl = `${imageFile.ossUrl}?${new Date().getTime()}`
const imgUrl = `${imageFile.ossUrl}?${new Date().getTime()}`;
if (!this.state.photoclip) {
const _photoclip = new PhotoClip("#headPicModal", options);
const _photoclip = new PhotoClip('#headPicModal', options);
_photoclip.load(imgUrl);
this.setState({
photoclip: _photoclip,
......@@ -146,7 +140,6 @@ class BasicInfo extends React.Component{
this.state.photoclip.clear();
this.state.photoclip.load(imgUrl);
}
}, 200);
}
);
......@@ -154,290 +147,319 @@ class BasicInfo extends React.Component{
//获取resourceId
getSignature = (blob, fileName) => {
Upload.uploadBlobToOSS(blob, 'cover' + (new Date()).valueOf(),null,'signInfo').then((signInfo) => {
this.setState({
coverClicpPath:signInfo.fileUrl,
coverId:signInfo.resourceId,
visible: false
},()=>this.updateCover())
Upload.uploadBlobToOSS(blob, 'cover' + new Date().valueOf(), null, 'signInfo').then((signInfo) => {
this.setState(
{
coverClicpPath: signInfo.fileUrl,
coverId: signInfo.resourceId,
visible: false,
},
() => this.updateCover()
);
});
};
updateCover = () =>{
const {coverClicpPath,coverId} = this.state
updateCover = () => {
const { coverClicpPath, coverId } = this.state;
this.setState({
showSelectFileModal: false
})
showSelectFileModal: false,
});
this.props.onChange('coverUrl', coverClicpPath);
setTimeout(()=>{
setTimeout(() => {
this.props.onChange('coverId', coverId);
},1000)
}
// base64转换成blob
}, 1000);
};
// base64转换成blob
convertBase64UrlToBlob = (urlData) => {
const bytes = window.atob(urlData.split(",")[1]);
const bytes = window.atob(urlData.split(',')[1]);
const ab = new ArrayBuffer(bytes.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], { type: "image/png" });
return new Blob([ab], { type: 'image/png' });
};
limitNumber = value => {
limitNumber = (value) => {
if (typeof value === 'string') {
return !isNaN(Number(value)) ? value.replace(/^(0+)|[^\d]/g, '') : ''
return !isNaN(Number(value)) ? value.replace(/^(0+)|[^\d]/g, '') : '';
} else if (typeof value === 'number') {
return !isNaN(value) ? String(value).replace(/^(0+)|[^\d]/g, '') : ''
return !isNaN(value) ? String(value).replace(/^(0+)|[^\d]/g, '') : '';
} else {
return ''
return '';
}
}
percentCompleteBlur = (e,field) =>{
};
percentCompleteBlur = (e, field) => {
let _percentCompleteLive;
const { value } = e.target;
if(value > 100){
if (value > 100) {
_percentCompleteLive = 100;
}else{
if(value < 0){
} else {
if (value < 0) {
_percentCompleteLive = 0;
}else{
} else {
_percentCompleteLive = value;
}
}
this.props.onChange(field,_percentCompleteLive)
}
render(){
const { operatorModalVisible ,showSelectFileModal,visible,hasImgReady,cutImageBlob} = this.state;
const { data} = this.props;
const { planName,coverUrl,instro,enableState,operateType,selectOperatorList,percentCompleteLive,percentCompleteVideo,percentCompletePicture} = data;
this.props.onChange(field, _percentCompleteLive);
};
render() {
const { operatorModalVisible, showSelectFileModal, visible, hasImgReady, cutImageBlob } = this.state;
const { data } = this.props;
const { planName, coverUrl, instro, enableState, operateType, selectOperatorList, percentCompleteLive, percentCompleteVideo, percentCompletePicture } =
data;
// 当前是否使用的是默认图片
const isDefaultCover = coverUrl === defaultCover;
return (
<div className="plan-basic-info">
<div className="plan-name">
<span className="label"><span className="require">*</span>培训计划名称:</span>
<Input
value={planName}
placeholder="请输入培训计划名称(20字以内)"
maxLength={20}
style={{ width: 240 }}
onChange={(e)=>this.props.onChange('planName', e.target.value)}
/>
</div>
<div className="cover">
<span className="label">封面图:</span>
<div className="cover__wrap">
<div className="img-content">
{ isDefaultCover &&
<span className="tag">默认图</span>
}
<img src={coverUrl} width="690"/>
</div>
<div className="opt-btns">
<Button onClick={() => {
<div className='plan-basic-info'>
<div className='plan-name'>
<span className='label'>
<span className='require'>*</span>培训计划名称:
</span>
<Input
value={planName}
placeholder='请输入培训计划名称(20字以内)'
maxLength={20}
style={{ width: 240 }}
onChange={(e) => this.props.onChange('planName', e.target.value)}
/>
</div>
<div className='cover'>
<span className='label'>封面图:</span>
<div className='cover__wrap'>
<div className='img-content'>
{isDefaultCover && <span className='tag'>默认图</span>}
<img src={coverUrl} width='690' alt='' />
</div>
<div className='opt-btns'>
<Button
onClick={() => {
this.setState({
showSelectFileModal:true
})
}}>上传图片</Button>
<span
className={`default-btn ${isDefaultCover ? 'disabled' : ''}`}
onClick={this.handleResetCoverUrl}
>使用默认图</span>
<div className="tips">建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。</div>
</div>
showSelectFileModal: true,
});
}}>
上传图片
</Button>
<span className={`default-btn ${isDefaultCover ? 'disabled' : ''}`} onClick={this.handleResetCoverUrl}>
使用默认图
</span>
<div className='tips'>建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。</div>
</div>
</div>
<div className="introduction">
<span className="label">简介:</span>
<TextArea
placeholder="请输入培训计划简介"
maxLength={200}
style={{ width: '552px',height:'110px'}}
className="instro-textarea"
value={instro}
onChange={(e)=>this.props.onChange('instro', e.target.value)}
</div>
<div className='introduction'>
<span className='label'>简介:</span>
<TextArea
placeholder='请输入培训计划简介'
maxLength={200}
style={{ width: '552px', height: '110px' }}
className='instro-textarea'
value={instro}
onChange={(e) => this.props.onChange('instro', e.target.value)}
/>
</div>
<div className='wether-use'>
<span className='label'>是否启用:</span>
<div className='content'>
<div>
<Switch
checked={enableState === 'YES' ? true : false}
onChange={() => {
this.enableStateChange();
}}
/>
</div>
<div className="wether-use">
<span className="label">是否启用:</span>
<div className="content">
<div>
<Switch checked={enableState==="YES"? true:false} onChange={()=> {this.enableStateChange()}}/>
</div>
<div>
<div className="instro-text">
<div>开启:此培训计划可以分享给学员进行学习</div>
<div>关闭:此培训计划暂不可分享给学员进行学习,后续可开启</div>
</div>
</div>
</div>
</div>
<div className="view-range" >
<span className="label">
<span className="require">*</span>
可见范围
<Tooltip
title="学院管理员、管理员默认都可见">
<span className="iconfont">&#xe61d;</span>
</Tooltip></span>
<div className="content">
<Radio.Group value={operateType} onChange={(e) => { this.props.onChange('operateType', e.target.value) }}>
<Row style={{ marginBottom: '5px' }}>
<Col span={24}>
<Radio value="All_Operate">
所有运营师
<span className="playback__text">后续新增的运营师都有权限可见</span>
</Radio>
</Col>
</Row>
<Row>
<Col span={24}>
<Radio value="Assign_Operate">
指定运营师
<span className="playback__text">仅被选择的运营师有权限可见</span>
</Radio>
</Col>
</Row>
</Radio.Group>
{operateType==="Assign_Operate" &&
<div className="choose-business">
<Button onClick={()=>{this.handleShowSelectOperatorModal()}}>选择运营师</Button>
<span>已选择<span>{selectOperatorList.length}</span>名运营师</span>
</div>
}
<div>
<div className='instro-text'>
<div>开启:此培训计划可以分享给学员进行学习</div>
<div>关闭:此培训计划暂不可分享给学员进行学习,后续可开启</div>
</div>
</div>
</div>
<div className="done-standard">
<span className="label standard-label"><span className="require">*</span>完成标准:</span>
<div>
<div className="live-standard-info">
<span className="icon iconfont">&#xe865;</span>
<span className="instro">直播课单个课程,学员学习进度达到
<Input
width="40"
value={percentCompleteLive}
onChange={(e) => { this.props.onChange('percentCompleteLive', e.target.value.replace(/\D/g,'')) }}
onBlur={(e)=>this.percentCompleteBlur(e,'percentCompleteLive')}
className="input-box"
/>%,即视为"已完成"学习
</span>
</div>
<div className="live-standard-info">
<span className="icon iconfont">&#xe864;</span>
<span className="instro">视频课单个课程,学员学习进度达到
<Input
width="40"
value={percentCompleteVideo}
onChange={(e) => { this.props.onChange('percentCompleteVideo', e.target.value.replace(/\D/g,'')) }}
onBlur={(e)=>this.percentCompleteBlur(e,'percentCompleteVideo')}
className="input-box"
/>
%,即视为"已完成"学习
</span>
</div>
<div className="live-standard-info">
<span className="icon iconfont">&#xe601;</span>
<span className="instro">图文课单个课程,学员学习进度达到
<Input
width="40"
value={percentCompletePicture}
onChange={(e) => { this.props.onChange('percentCompletePicture', e.target.value.replace(/\D/g,'')) }}
onBlur={(e)=>this.percentCompleteBlur(e,'percentCompletePicture')}
className="input-box"
/>
%,即视为"已完成"学习
</span>
</div>
</div>
</div>
<div className='view-range'>
<span className='label'>
<span className='require'>*</span>
可见范围
<Tooltip title='学院管理员、管理员默认都可见'>
<span className='iconfont'>&#xe61d;</span>
</Tooltip>
</span>
<div className='content'>
<Radio.Group
value={operateType}
onChange={(e) => {
this.props.onChange('operateType', e.target.value);
}}>
<Row style={{ marginBottom: '5px' }}>
<Col span={24}>
<Radio value='All_Operate'>
所有运营师
<span className='playback__text'>后续新增的运营师都有权限可见</span>
</Radio>
</Col>
</Row>
<Row>
<Col span={24}>
<Radio value='Assign_Operate'>
指定运营师
<span className='playback__text'>仅被选择的运营师有权限可见</span>
</Radio>
</Col>
</Row>
</Radio.Group>
{operateType === 'Assign_Operate' && (
<div className='choose-business'>
<Button
onClick={() => {
this.handleShowSelectOperatorModal();
}}>
选择运营师
</Button>
<span>
已选择<span>{selectOperatorList.length}</span>名运营师
</span>
</div>
)}
</div>
{ operatorModalVisible &&
<SelectOperatorModal
visible={operatorModalVisible}
onClose={this.handleCloseSelectOperatorMOdal}
selectOperatorList={selectOperatorList}
onSelect={this.handleConfirmSelectOperator}
/>
}
{showSelectFileModal &&
<SelectPrepareFileModal
key="basic"
operateType="select"
multiple={false}
accept="image/jpeg,image/png,image/jpg"
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectFileModal}
onClose={() => {
this.setState({
showSelectFileModal:false
})
}}
onSelect={this.handleSelectCover}
/>
}
<Modal
title="设置图片"
width={1080}
visible={visible}
maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
onCancel={() => {
this.setState({ visible: false });
</div>
<div className='done-standard'>
<span className='label standard-label'>
<span className='require'>*</span>完成标准:
</span>
<div>
<div className='live-standard-info'>
<span className='icon iconfont'>&#xe865;</span>
<span className='instro'>
直播课单个课程,学员学习进度达到
<Input
width='40'
value={percentCompleteLive}
onChange={(e) => {
this.props.onChange('percentCompleteLive', e.target.value.replace(/\D/g, ''));
}}
onBlur={(e) => this.percentCompleteBlur(e, 'percentCompleteLive')}
className='input-box'
/>
%,即视为"已完成"学习
</span>
</div>
<div className='live-standard-info'>
<span className='icon iconfont'>&#xe864;</span>
<span className='instro'>
视频课单个课程,学员学习进度达到
<Input
width='40'
value={percentCompleteVideo}
onChange={(e) => {
this.props.onChange('percentCompleteVideo', e.target.value.replace(/\D/g, ''));
}}
onBlur={(e) => this.percentCompleteBlur(e, 'percentCompleteVideo')}
className='input-box'
/>
%,即视为"已完成"学习
</span>
</div>
<div className='live-standard-info'>
<span className='icon iconfont'>&#xe601;</span>
<span className='instro'>
图文课单个课程,学员学习进度达到
<Input
width='40'
value={percentCompletePicture}
onChange={(e) => {
this.props.onChange('percentCompletePicture', e.target.value.replace(/\D/g, ''));
}}
onBlur={(e) => this.percentCompleteBlur(e, 'percentCompletePicture')}
className='input-box'
/>
%,即视为"已完成"学习
</span>
</div>
</div>
</div>
{operatorModalVisible && (
<SelectOperatorModal
visible={operatorModalVisible}
onClose={this.handleCloseSelectOperatorMOdal}
selectOperatorList={selectOperatorList}
onSelect={this.handleConfirmSelectOperator}
/>
)}
{showSelectFileModal && (
<SelectPrepareFileModal
key='basic'
operateType='select'
multiple={false}
accept='image/jpeg,image/png,image/jpg'
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectFileModal}
onClose={() => {
this.setState({
showSelectFileModal: false,
});
}}
zIndex={10001}
footer={[
<Button
key="back"
onClick={() => {
this.setState({ visible: false });
}}
>
重新上传
</Button>,
<Button
key="submit"
type="primary"
disabled={!hasImgReady}
onClick={() => {
if (!cutFlag) {
cutFlag = true;
this.refs.hiddenBtn.click();
}
this.getSignature(cutImageBlob);
}}
>
确定
</Button>,
]}
>
<div className="clip-box">
<div
id="headPicModal"
ref="headPicModal"
style={{
width: "500px",
height: "430px",
marginBottom: 0,
}}
></div>
<div id="clipBtn" style={{ display: "none" }} ref="hiddenBtn"></div>
<div className="preview-img">
<div className="title">效果预览</div>
<div id="preview-url-box" style={{width:500,height:282}}>
<img src={this.state.dataUrl} style={{ width: '100%' }} alt="" />
</div>
<div className="tip-box">
<div className="tip">温馨提示</div>
<div className="tip">①预览效果图时可能存在延迟,单击左侧图片刷新即可</div>
<div className="tip">②设置图片时双击可旋转图片,滚动可放大或缩小图片</div>
</div>
onSelect={this.handleSelectCover}
/>
)}
<Modal
title='设置图片'
width={1080}
visible={visible}
maskClosable={false}
closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
onCancel={() => {
this.setState({ visible: false });
}}
zIndex={10001}
footer={[
<Button
key='back'
onClick={() => {
this.setState({ visible: false });
}}>
重新上传
</Button>,
<Button
key='submit'
type='primary'
disabled={!hasImgReady}
onClick={() => {
if (!cutFlag) {
cutFlag = true;
this.refs.hiddenBtn.click();
}
this.getSignature(cutImageBlob);
}}>
确定
</Button>,
]}>
<div className='clip-box'>
<div
id='headPicModal'
ref='headPicModal'
style={{
width: '500px',
height: '430px',
marginBottom: 0,
}}></div>
<div id='clipBtn' style={{ display: 'none' }} ref='hiddenBtn'></div>
<div className='preview-img'>
<div className='title'>效果预览</div>
<div id='preview-url-box' style={{ width: 500, height: 282 }}>
<img src={this.state.dataUrl} style={{ width: '100%' }} alt='' />
</div>
<div className='tip-box'>
<div className='tip'>温馨提示</div>
<div className='tip'>①预览效果图时可能存在延迟,单击左侧图片刷新即可</div>
<div className='tip'>②设置图片时双击可旋转图片,滚动可放大或缩小图片</div>
</div>
</div>
</Modal>
</div>
</Modal>
</div>
);
}
}
export default withRouter(BasicInfo)
export default withRouter(BasicInfo);
......@@ -134,6 +134,7 @@ class EmployeeShareData extends React.Component {
)
}
},
//产品暂时性隐藏
// {
// title: '手机号',
// key: 'storeUserPhone',
......
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:46:46
* @LastEditors: wufan
* @LastEditTime: 2021-05-14 18:12:50
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-01 11:45:34
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { useState, useRef, useEffect } from 'react';
import { Table, Modal, message , Tooltip,Switch,Dropdown} from 'antd';
import React, { useState } from 'react';
import { Table, Modal, message, Tooltip, Switch, Dropdown } from 'antd';
import { withRouter } from 'react-router-dom';
import { PageControl } from "@/components";
import PlanService from "@/domains/plan-domain/planService";
import { PageControl } from '@/components';
import PlanService from '@/domains/plan-domain/planService';
import SharePlanModal from '../modal/SharePlanModal';
import {LIVE_SHARE} from '@/domains/course-domain/constants';
import { LIVE_SHARE } from '@/domains/course-domain/constants';
import User from '@/common/js/user';
import './PlanList.less';
const { confirm } = Modal;
const userRole = User.getUserRole();
function PlanList(props) {
const [sharePlanModal, setSharePlanModal] = useState(null);
function parseColumns(){
const columns = [
{
title: '培训计划',
key: 'planName',
dataIndex: 'planName',
width:'18%',
render: (val, record) => {
return (
<div className="plan-name">
{val}
</div>
)
}
},
{
title: '课程总数量',
key: 'courseNum',
dataIndex: 'courseNum',
width: 110,
render: (val, record) => {
return (
<div className="course-number">
{val}
</div>
)
}
},
{
title: '当前状态',
width: '10%',
dataIndex: "status",
render: (val, item, index) => {
return (
<Switch checked={item.enableState==="NO"?false:true} onChange={()=>changeEnableState(item)} disabled={(User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager")?false:true}/>
)
},
},
{
title: '创建人',
key: 'createName',
dataIndex: 'createName',
width: '10%',
render: (val) => {
return (
<div className="create-name">
{val}
</div>
)
}
},
{
title: '创建时间',
width: "12.5%",
key: 'created',
dataIndex: 'created',
sorter: true,
render: (val) => {
return formatDate('YYYY-MM-DD H:i', val)
}
},
{
title: '更新时间',
width: "10%",
key: 'updated',
dataIndex: 'updated',
sorter: true,
render: (val) => {
return formatDate('YYYY-MM-DD H:i', val)
}
},
{
title: '参培人数',
width:76,
key: 'cultureCustomerNum',
dataIndex: 'cultureCustomerNum',
sorter: true,
render: (val) => {
return (
<div className="join-number">
{val}
</div>
)
}
},
{
title: '操作',
key: 'operate',
dataIndex: 'operate',
fixed: 'right',
width: 176,
render: (val, record) => {
return (
<div className="operate">
<div className="operate__item" onClick={()=>toLearningDataPage(record)}>学习数据</div>
{record.enableState==="YES" &&
<>
<span className="operate__item split"> | </span>
<div className="operate__item" onClick={() => {handleShowShareModal(record); }}>分享</div>
</>
}
{(User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager") &&
<>
<span className="operate__item split"> | </span>
<Dropdown overlay={renderMoreOperate(record)}>
<span className="more-operate">
<span className="operate-text">更多</span>
<span
className="iconfont icon"
style={{ color: "#2966FF" }}
>
&#xe824;
</span>
</span>
</Dropdown>
</>
}
</div>
)
}
}
];
return columns;
}
function renderMoreOperate(item){
return (
<div className="live-course-more-menu">
<div className="operate__item"
onClick={()=>toEditPlanPage(item)}
>编辑</div>
<div
className="operate__item" onClick={()=>handleDelete(item)}
>删除</div>
const [sharePlanModal, setSharePlanModal] = useState(null);
function parseColumns() {
const columns = [
{
title: '培训计划',
key: 'planName',
dataIndex: 'planName',
width: '18%',
render: (val, record) => {
return (
<div className='plan_name_item'>
<img className='plan-cover' src={record.coverUrl || 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png'} alt='' />
<Choose>
<When condition={record.planName.length > 25}>
<Tooltip title={record.planName}>
<div className='plan-name'>{val}</div>
</Tooltip>
</When>
<Otherwise>
<div className='plan-name'>{val}</div>
</Otherwise>
</Choose>
</div>
)
}
function handleChangeTable(pagination, filters, sorter){
const { columnKey, order } = sorter;
const { query } = props;
let _columnKey;
let _order;
);
},
},
{
title: '课程总数量',
key: 'courseNum',
dataIndex: 'courseNum',
width: 110,
render: (val, record) => {
return <div className='course-number'>{val}</div>;
},
},
{
title: '当前状态',
width: '10%',
dataIndex: 'status',
render: (val, item, index) => {
return (
<Switch
checked={item.enableState === 'NO' ? false : true}
onChange={() => changeEnableState(item)}
disabled={User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager' ? false : true}
/>
);
},
},
{
title: '创建人',
key: 'createName',
dataIndex: 'createName',
width: '10%',
render: (val) => {
return <div className='create-name'>{val}</div>;
},
},
{
title: '创建时间',
width: '12.5%',
key: 'created',
dataIndex: 'created',
sorter: true,
render: (val) => {
return window.formatDate('YYYY-MM-DD H:i', val);
},
},
{
title: '更新时间',
width: '10%',
key: 'updated',
dataIndex: 'updated',
sorter: true,
render: (val) => {
return window.formatDate('YYYY-MM-DD H:i', val);
},
},
{
title: '参培人数',
width: 76,
key: 'cultureCustomerNum',
dataIndex: 'cultureCustomerNum',
sorter: true,
render: (val) => {
return <div className='join-number'>{val}</div>;
},
},
{
title: '操作',
key: 'operate',
dataIndex: 'operate',
fixed: 'right',
width: 176,
render: (val, record) => {
return (
<div className='operate'>
<div className='operate__item' onClick={() => toLearningDataPage(record)}>
学习数据
</div>
{record.enableState === 'YES' && (
<>
<span className='operate__item split'> | </span>
<div
className='operate__item'
onClick={() => {
handleShowShareModal(record);
}}>
分享
</div>
</>
)}
{(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && (
<>
<span className='operate__item split'> | </span>
<Dropdown overlay={renderMoreOperate(record)}>
<span className='more-operate'>
<span className='operate-text'>更多</span>
<span className='iconfont icon' style={{ color: '#2966FF' }}>
&#xe824;
</span>
</span>
</Dropdown>
</>
)}
</div>
);
},
},
];
return columns;
}
function renderMoreOperate(item) {
return (
<div className='live-course-more-menu'>
<div className='operate__item' onClick={() => toEditPlanPage(item)}>
编辑
</div>
<div className='operate__item' onClick={() => handleDelete(item)}>
删除
</div>
</div>
);
}
// 按创建时间升序排序
if (columnKey === 'created' && order === 'ascend') {_columnKey="CREATED"; _order = 'SORT_ASC'; }
// 按创建时间降序排序
if (columnKey === 'created' && order === 'descend') { _columnKey="CREATED"; _order = 'SORT_DESC';}
// 按更新时间升序排序
if (columnKey === 'updated' && order === 'ascend') { _columnKey="UPDATED"; _order = 'SORT_ASC'; }
// 按更新时间降序排序
if (columnKey === 'updated' && order === 'descend') { _columnKey="UPDATED"; _order = 'SORT_DESC'; }
// 按更新时间升序排序
if (columnKey === 'cultureCustomerNum' && order === 'ascend') { _columnKey="CUSTOMER_NUM"; _order = 'SORT_ASC'; }
// 按更新时间降序排序
if (columnKey === 'cultureCustomerNum' && order === 'descend') { _columnKey="CUSTOMER_NUM"; _order = 'SORT_DESC'; }
const _query = {
...query,
sortMap:{}
};
_query.sortMap[_columnKey]=_order;
props.onChange(_query);
function handleChangeTable(pagination, filters, sorter) {
const { columnKey, order } = sorter;
const { query } = props;
let _columnKey;
let _order;
// 按创建时间升序排序
if (columnKey === 'created' && order === 'ascend') {
_columnKey = 'CREATED';
_order = 'SORT_ASC';
}
// 显示分享弹窗
function handleShowShareModal(item) {
const htmlUrl = `${LIVE_SHARE}training_plan_detail/${item.planId}?id=${User.getStoreId()}&storeUserId=${User.getStoreUserId()}`;
const longUrl = htmlUrl
const shareData = { ...item, longUrl };
const sharePlanModal = (
<SharePlanModal
data={shareData}
type="liveClass"
close={() => {
setSharePlanModal(null)
}}
/>
)
setSharePlanModal(sharePlanModal)
// 按创建时间降序排序
if (columnKey === 'created' && order === 'descend') {
_columnKey = 'CREATED';
_order = 'SORT_DESC';
}
//改变上架状态
function changeEnableState(item){
let _enableState = item.enableState
if(_enableState==='NO'){
_enableState = "YES";
item.enableState = "YES"
}else{
_enableState = "NO"
item.enableState = "NO"
}
const params={
"planId": item.planId,
"enableState":_enableState
}
PlanService.updateStateTrainingPlan(params).then((res)=>{
if(res.success){
if(_enableState === "YES"){
message.success("已启用此计划");
}else{
message.success("已禁用此计划");
}
props.onChange();
}
})
}
function toEditPlanPage(item){
window.RCHistory.push({
pathname: `/create-plan?type=edit&id=${item.planId}`,
})
// 按更新时间升序排序
if (columnKey === 'updated' && order === 'ascend') {
_columnKey = 'UPDATED';
_order = 'SORT_ASC';
}
function toLearningDataPage(item){
window.RCHistory.push({
pathname: `/learning-data?id=${item.planId}`,
})
// 按更新时间降序排序
if (columnKey === 'updated' && order === 'descend') {
_columnKey = 'UPDATED';
_order = 'SORT_DESC';
}
function handleDelete(record){
return confirm({
title: '你确定要删除吗?',
content: '删除后,此培训计划的学员将无法继续学习,所有学习数据将同步删除不可恢复',
icon: <span className="icon iconfont default-confirm-icon">&#xe839; </span>,
okText: '删除',
okType: 'danger',
cancelText: '取消',
width:440,
height:188,
onOk: () => {
if(record.enableState === "YES"){
Modal.warning({
title: '无法删除',
content: '培训计划启用中,无法直接删除',
});
}else{
deleteConfirm(record);
}
}
})
// 按更新时间升序排序
if (columnKey === 'cultureCustomerNum' && order === 'ascend') {
_columnKey = 'CUSTOMER_NUM';
_order = 'SORT_ASC';
}
function deleteConfirm(item){
const params={
"planId": item.planId,
}
PlanService.deleteTrainingPlan(params).then((res)=>{
if(res.success){
message.success("删除成功");
props.onChange();
}
})
// 按更新时间降序排序
if (columnKey === 'cultureCustomerNum' && order === 'descend') {
_columnKey = 'CUSTOMER_NUM';
_order = 'SORT_DESC';
}
const _query = {
...query,
sortMap: {},
};
_query.sortMap[_columnKey] = _order;
props.onChange(_query);
}
// 显示分享弹窗
function handleShowShareModal(item) {
const htmlUrl = `${LIVE_SHARE}training_plan_detail/${item.planId}?id=${User.getStoreId()}&storeUserId=${User.getStoreUserId()}`;
const longUrl = htmlUrl;
const shareData = { ...item, longUrl };
const sharePlanModal = (
<SharePlanModal
data={shareData}
type='liveClass'
close={() => {
setSharePlanModal(null);
}}
/>
);
setSharePlanModal(sharePlanModal);
}
//改变上架状态
function changeEnableState(item) {
let _enableState = item.enableState;
if (_enableState === 'NO') {
_enableState = 'YES';
item.enableState = 'YES';
} else {
_enableState = 'NO';
item.enableState = 'NO';
}
function onShowSizeChange(current, size){
if (current === size) {
return
const params = {
planId: item.planId,
enableState: _enableState,
};
PlanService.updateStateTrainingPlan(params).then((res) => {
if (res.success) {
if (_enableState === 'YES') {
message.success('已启用此计划');
} else {
message.success('已禁用此计划');
}
props.onChange();
}
});
}
function toEditPlanPage(item) {
window.RCHistory.push({
pathname: `/create-plan?type=edit&id=${item.planId}`,
});
}
function toLearningDataPage(item) {
window.RCHistory.push({
pathname: `/learning-data?id=${item.planId}`,
});
}
function handleDelete(record) {
return confirm({
title: '你确定要删除吗?',
content: '删除后,此培训计划的学员将无法继续学习,所有学习数据将同步删除不可恢复',
icon: <span className='icon iconfont default-confirm-icon'>&#xe839; </span>,
okText: '删除',
okType: 'danger',
cancelText: '取消',
width: 440,
height: 188,
onOk: () => {
if (record.enableState === 'YES') {
Modal.warning({
title: '无法删除',
content: '培训计划启用中,无法直接删除',
});
} else {
deleteConfirm(record);
}
let _query = props.query
_query.size = size;
props.onChange(_query)
},
});
}
function deleteConfirm(item) {
const params = {
planId: item.planId,
};
PlanService.deleteTrainingPlan(params).then((res) => {
if (res.success) {
message.success('删除成功');
props.onChange();
}
});
}
function onShowSizeChange(current, size) {
if (current === size) {
return;
}
return (
<div className="plan-list">
<Table
rowKey={record => record.id}
showSorterTooltip={false}
dataSource={props.planListData}
columns={ parseColumns() }
pagination={false}
onChange={handleChangeTable}
bordered
size="middle"
scroll={{ x: 1400}}
className="plan-list-table"
/>
<div className="box-footer">
<PageControl
current={props.query.current - 1}
pageSize={props.query.size}
total={props.totalCount}
toPage={(page) => {
const _query = {...props.query, current: page + 1};
props.onChange(_query)
}}
onShowSizeChange={onShowSizeChange}
/>
</div>
{sharePlanModal }
</div>
)
let _query = props.query;
_query.size = size;
props.onChange(_query);
}
export default withRouter(PlanList);
\ No newline at end of file
return (
<div className='plan-list'>
<Table
rowKey={(record) => record.id}
showSorterTooltip={false}
dataSource={props.planListData}
columns={parseColumns()}
pagination={false}
onChange={handleChangeTable}
bordered
size='middle'
scroll={{ x: 1400 }}
className='plan-list-table'
/>
<div className='box-footer'>
<PageControl
current={props.query.current - 1}
pageSize={props.query.size}
total={props.totalCount}
toPage={(page) => {
const _query = { ...props.query, current: page + 1 };
props.onChange(_query);
}}
onShowSizeChange={onShowSizeChange}
/>
</div>
{sharePlanModal}
</div>
);
}
export default withRouter(PlanList);
.plan-list{
margin-top:12px;
.course-number{
text-align:right;
margin-right:45px;
.plan-list {
margin-top: 12px;
.course-number {
text-align: right;
margin-right: 45px;
}
.plan-list-table {
thead.ant-table-thead {
tr {
th {
padding: 10px 12px;
}
}
}
.plan-list-table{
tbody {
tr{
&:nth-child(even){
background: transparent !important;
td{
background:#FFF !important;
}
tbody {
tr {
td.ant-table-cell {
padding: 16px 12px;
color: #333;
}
&:nth-child(even) {
background: transparent;
td {
background: #fff;
}
&:nth-child(odd){
background: #FAFAFA !important;
td{
background: #FAFAFA !important;
}
}
&:nth-child(odd) {
background: #fafafa;
td {
background: #fafafa;
}
&:hover{
td{
background:#F3f6fa !important;
}
}
&:hover {
td {
background: #f3f6fa;
}
}
}
}
.plan-name{
text-overflow: -o-ellipsis-lastline;
}
.plan_name_item {
display: flex;
align-items: center;
.plan-cover {
width: 106px;
height: 60px;
border-radius: 2px;
margin-right: 8px;
}
.plan-name {
width: 188px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
height: 40px;
}
.operate-text {
color: #2966FF;
}
.operate-text {
color: #2966ff;
cursor: pointer;
}
.operate {
display: flex;
&__item {
color: #2966ff;
cursor: pointer;
}
.operate {
display: flex;
&__item {
color: #2966FF;
cursor: pointer;
&.split {
margin: 0 8px;
color: #BFBFBF;
}
&.split {
margin: 0 8px;
color: #bfbfbf;
}
}
.join-number{
text-align:right;
margin-right:12px;
}
.more-operate{
line-height:20px;
}
}
\ No newline at end of file
}
.join-number {
text-align: right;
margin-right: 12px;
}
.more-operate {
line-height: 20px;
}
}
import React from "react"
import _ from "underscore"
import { Table, Radio, Tabs, Modal, Input, message, Button, Tooltip } from "antd"
import React from 'react';
import _ from 'underscore';
import { Table, Radio, Tabs, Modal, Input, message, Button, Tooltip } from 'antd';
import { PageControl } from "@/components"
import { PageControl } from '@/components';
import CourseService from "@/domains/course-domain/CourseService"
import User from "@/common/js/user"
import Service from "@/common/js/service"
import dealTimeDuration from "../../course-manage/utils/dealTimeDuration"
import CourseService from '@/domains/course-domain/CourseService';
import User from '@/common/js/user';
import Service from '@/common/js/service';
import dealTimeDuration from '../../course-manage/utils/dealTimeDuration';
import "./relatedCourseModal.less"
import './relatedCourseModal.less';
const { Search } = Input
const { TabPane } = Tabs
const { Search } = Input;
const { TabPane } = Tabs;
const courseStateShow = {
UN_START: {
code: 1,
title: "待开课",
color: "#FFB129"
title: '待开课',
color: '#FFB129',
},
STARTING: {
code: 2,
title: "上课中",
color: "#238FFF"
title: '上课中',
color: '#238FFF',
},
FINISH: {
code: 3,
title: "已完成",
color: "#3BBDAA"
title: '已完成',
color: '#3BBDAA',
},
EXPIRED: {
code: 4,
title: "未成功开课",
color: "#999"
}
}
title: '未成功开课',
color: '#999',
},
};
class SelectOperatorModal extends React.Component {
constructor(props) {
super(props)
super(props);
this.state = {
liveDataSource: [],
liveSize: 10,
liveQuery: {
current: 1
current: 1,
},
liveTotalCount: 0,
selectLive: [], //弹窗内已选择的直播课程
currentCourseListData: [],
currentLiveCourseListData: [], //页面中已关联的直播课程
videoCourseDivision: "internal",
videoCourseDivision: 'internal',
videoDataSource: {
external: [],
internal: []
internal: [],
},
videoSize: {
external: 10,
internal: 10
internal: 10,
},
videoSearchName: {
external: "",
internal: ""
external: '',
internal: '',
},
videoSearchDefalt: "",
videoSearchDefalt: '',
videoQuery: {
external: {
current: 1
current: 1,
},
internal: {
current: 1
}
current: 1,
},
},
videoTotalCount: {
external: 0,
internal: 0
internal: 0,
},
selectVideo: {
external: [],
internal: []
internal: [],
}, //弹窗内已选择的视频课程
currentVideoCourseListData: {
external: [],
internal: []
internal: [],
}, //页面中已关联的视频课程
pictureDataSource: [],
pictureSize: 10,
pictureQuery: {
current: 1
current: 1,
},
pictureTotalCount: 0,
selectPicture: [], //弹窗内已选择的视频课程
currentPictureCourseListData: [], //页面中已关联的视频课程
activeKey: "video",
currentTaskCourseData: this.props.data[this.props.selectedTaskIndex].courseList || []
}
activeKey: 'video',
currentTaskCourseData: this.props.data[this.props.selectedTaskIndex].courseList || [],
};
}
componentDidMount() {
this.handleFetchLiveDataList()
this.handleFetchVideoDataList()
this.handleFetchPictureDataList()
this.handleFetchLiveDataList();
this.handleFetchVideoDataList();
this.handleFetchPictureDataList();
}
// 获取直播课列表
handleFetchLiveDataList = () => {
const { liveQuery, liveSize } = this.state
const _data = [...this.props.data]
let currentLiveCourseListData = []
const { liveQuery, liveSize } = this.state;
const _data = [...this.props.data];
let currentLiveCourseListData = [];
_data.map((item) => {
item.courseList.map((childItem, childIndex) => {
if (childItem.courseType === "LIVE") {
currentLiveCourseListData.push(childItem.courseId)
if (childItem.courseType === 'LIVE') {
currentLiveCourseListData.push(childItem.courseId);
}
return childItem
})
return item
})
return childItem;
});
return item;
});
const params = {
...liveQuery,
size: liveSize,
excludeCourseIdList: currentLiveCourseListData
}
excludeCourseIdList: currentLiveCourseListData,
};
CourseService.getLiveCloudCourseBasePage(params).then((res) => {
const { result = {} } = res
const { records = [], total = 0 } = result
const { result = {} } = res;
const { records = [], total = 0 } = result;
this.setState({
liveDataSource: records,
liveTotalCount: Number(total),
currentLiveCourseListData
})
})
}
currentLiveCourseListData,
});
});
};
// 获取视频课列表
handleFetchVideoDataList = () => {
const { videoQuery, videoSize, videoDataSource, videoTotalCount, videoCourseDivision } = this.state
const { videoQuery, videoSize, videoDataSource, videoTotalCount, videoCourseDivision } = this.state;
const _data = [...this.props.data]
let currentVideoCourseListData = []
const _data = [...this.props.data];
let currentVideoCourseListData = [];
_data.map((item, index) => {
item.courseList.map((childItem, childIndex) => {
if (childItem.courseType === "VOICE") {
currentVideoCourseListData.push(childItem.courseId)
if (childItem.courseType === 'VOICE') {
currentVideoCourseListData.push(childItem.courseId);
}
return childItem
})
return item
})
return childItem;
});
return item;
});
const params = {
...videoQuery[videoCourseDivision],
size: videoSize[videoCourseDivision],
courseDivision: videoCourseDivision === "internal" ? "INTERNAL" : "EXTERNAL",
excludeCourseIdList: currentVideoCourseListData
}
courseDivision: videoCourseDivision === 'internal' ? 'INTERNAL' : 'EXTERNAL',
excludeCourseIdList: currentVideoCourseListData,
};
CourseService.videoScheduleBasePage(params).then((res) => {
const { result = {} } = res
console.log("result", result)
const { result = {} } = res;
console.log('result', result);
const { records = [], total = 0 } = result
const { records = [], total = 0 } = result;
this.setState({
videoDataSource: {
...videoDataSource,
[videoCourseDivision]: records
[videoCourseDivision]: records,
},
videoTotalCount: {
...videoTotalCount,
[videoCourseDivision]: Number(total)
[videoCourseDivision]: Number(total),
},
currentVideoCourseListData
})
})
}
currentVideoCourseListData,
});
});
};
// 获取图文课列表
handleFetchPictureDataList = () => {
const { pictureQuery, pictureSize } = this.state
const _data = [...this.props.data]
let currentPictureCourseListData = []
const { pictureQuery, pictureSize } = this.state;
const _data = [...this.props.data];
let currentPictureCourseListData = [];
_data.map((item, index) => {
item.courseList.map((childItem, childIndex) => {
if (childItem.courseType === "PICTURE") {
currentPictureCourseListData.push(childItem.courseId)
if (childItem.courseType === 'PICTURE') {
currentPictureCourseListData.push(childItem.courseId);
}
return childItem
})
return item
})
return childItem;
});
return item;
});
const params = {
...pictureQuery,
size: pictureSize,
courseType: "PICTURE",
courseType: 'PICTURE',
storeId: User.getStoreId(),
excludeCourseIdList: currentPictureCourseListData
}
excludeCourseIdList: currentPictureCourseListData,
};
Service.Hades("public/hades/mediaCoursePage", params).then((res) => {
const { result = {} } = res
const { records = [], total = 0 } = result
Service.Hades('public/hades/mediaCoursePage', params).then((res) => {
const { result = {} } = res;
const { records = [], total = 0 } = result;
this.setState({
pictureDataSource: records,
pictureTotalCount: Number(total),
currentPictureCourseListData
})
})
}
currentPictureCourseListData,
});
});
};
handleChangVideoCourseName = (value) => {
const { videoQuery, videoCourseDivision, videoSearchName } = this.state
videoQuery[videoCourseDivision].courseName = value
videoQuery[videoCourseDivision].current = 1
const { videoQuery, videoCourseDivision, videoSearchName } = this.state;
videoQuery[videoCourseDivision].courseName = value;
videoQuery[videoCourseDivision].current = 1;
this.setState({
...videoQuery,
videoSearchDefalt: value,
videoSearchName: {
...videoSearchName,
[videoCourseDivision]: value
}
})
}
[videoCourseDivision]: value,
},
});
};
handleChangLiveCourseName = (value) => {
const { liveQuery } = this.state
liveQuery.courseName = value
liveQuery.current = 1
const { liveQuery } = this.state;
liveQuery.courseName = value;
liveQuery.current = 1;
this.setState({
liveQuery
})
}
liveQuery,
});
};
handleChangPictureCourseName = (value) => {
const { pictureQuery } = this.state
pictureQuery.courseName = value
pictureQuery.current = 1
const { pictureQuery } = this.state;
pictureQuery.courseName = value;
pictureQuery.current = 1;
this.setState({
pictureQuery
})
}
pictureQuery,
});
};
onShowLiveSizeChange = (current, size) => {
if (current === size) {
return
return;
}
this.setState(
{
liveSize: size
liveSize: size,
},
() => {
this.handleFetchLiveDataList()
this.handleFetchLiveDataList();
}
)
}
);
};
onShowVideoSizeChange = (current, size) => {
if (current === size) {
return
return;
}
this.setState(
{
videoSize: size
videoSize: size,
},
() => {
this.handleFetchLiveDataList()
this.handleFetchLiveDataList();
}
)
}
);
};
onShowPictureSizeChange = (current, size) => {
if (current === size) {
return
return;
}
this.setState(
{
pictureSize: size
pictureSize: size,
},
() => {
this.handleFetchPictureDataList()
this.handleFetchPictureDataList();
}
)
}
);
};
// 请求表头
parseLiveColumns = () => {
......@@ -291,28 +291,28 @@ class SelectOperatorModal extends React.Component {
<span>
<span>课程信息</span>
<Tooltip title='仅显示未关联课程,已关联课程不支持重复选择'>
<i className='icon iconfont' style={{ marginLeft: "5px", cursor: "pointer", color: "#bfbfbf", fontSize: "14px", fontWeight: "400" }}>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: '400' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: "course",
dataIndex: "course",
width: "40%",
key: 'course',
dataIndex: 'course',
width: '40%',
render: (val, record) => {
let hasCover = false
let hasCover = false;
return (
<div className='course-info'>
{record.courseMediaVOS.map((item) => {
if (item.contentType === "COVER") {
hasCover = true
return <img className='course-cover' src={item.mediaUrl} alt='' />
if (item.contentType === 'COVER') {
hasCover = true;
return <img className='course-cover' src={item.mediaUrl} alt='' />;
}
return null
return null;
})}
<If condition={!hasCover}>
<img className='course-cover' src={"https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"} alt='' />
<img className='course-cover' src={'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'} alt='' />
</If>
<div>
......@@ -324,35 +324,35 @@ class SelectOperatorModal extends React.Component {
</span>
</div>
</div>
)
}
);
},
},
{
title: "上课时间",
key: "courseTime",
dataIndex: "courseTime",
width: "40%",
title: '上课时间',
key: 'courseTime',
dataIndex: 'courseTime',
width: '40%',
render: (val, record) => {
return (
<div>
<div>{formatDate("YYYY-MM-DD", record.startTime)}</div>
<div>{formatDate('YYYY-MM-DD', record.startTime)}</div>
<div>
{formatDate("H:i", record.startTime)}~{formatDate("H:i", record.endTime)}
{formatDate('H:i', record.startTime)}~{formatDate('H:i', record.endTime)}
</div>
</div>
)
}
);
},
},
{
title: "学院展示",
key: "shelfState",
dataIndex: "shelfState",
width: "20%",
title: '学院展示',
key: 'shelfState',
dataIndex: 'shelfState',
width: '20%',
render: (val, record) => {
return (
<span>
<Choose>
<When condition={record.shelfState === "YES"}>
<When condition={record.shelfState === 'YES'}>
<span>开启</span>
</When>
<Otherwise>
......@@ -360,33 +360,46 @@ class SelectOperatorModal extends React.Component {
</Otherwise>
</Choose>
</span>
)
}
}
]
return columns
}
);
},
},
];
return columns;
};
// 请求表头
parseVideoColumns = () => {
const { videoCourseDivision } = this.state
const { videoCourseDivision } = this.state;
const columns = [
{
title: (
<span>
<span>课程信息</span>
<Tooltip title='仅显示未关联课程,已关联课程不支持重复选择'>
<i className='icon iconfont' style={{ marginLeft: "5px", cursor: "pointer", color: "#bfbfbf", fontSize: "14px", fontWeight: "400" }}>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: '400' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: "course",
dataIndex: "course",
width: "40%",
key: 'course',
dataIndex: 'course',
width: '40%',
title: (
<span>
<span>课程信息</span>
<Tooltip title='仅显示未关联课程,已关联课程不支持重复选择'>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: '400' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: 'course',
dataIndex: 'course',
width: '60%',
render: (val, record) => {
const { coverUrl, scheduleVideoUrl } = record
const { coverUrl, scheduleVideoUrl } = record;
return (
<div className='course-info'>
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
......@@ -394,48 +407,48 @@ class SelectOperatorModal extends React.Component {
className='course-cover'
src={
coverUrl ||
(videoCourseDivision === "internal"
(videoCourseDivision === 'internal'
? `${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast`
: "https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png")
: 'https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png')
}
alt=''
/>
<div className='course-name'>{record.courseName}</div>
</div>
)
}
);
},
},
{
title: "课程时长",
key: "courseTime",
dataIndex: "courseTime",
width: "20%",
title: '课程时长',
key: 'courseTime',
dataIndex: 'courseTime',
width: '20%',
render: (val, record) => {
return <span className='course-status'>{dealTimeDuration(record.videoDuration)}</span>
}
return <span className='course-status'>{dealTimeDuration(record.videoDuration)}</span>;
},
},
{
title: "学院展示",
key: "shelfState",
dataIndex: "shelfState",
width: "20%",
title: '学院展示',
key: 'shelfState',
dataIndex: 'shelfState',
width: '20%',
render: (val, record) => {
return (
<Choose>
<When condition={record.shelfState === "YES"}>
<When condition={record.shelfState === 'YES'}>
<span>开启</span>
</When>
<Otherwise>
<span>关闭</span>
</Otherwise>
</Choose>
)
}
}
]
return columns
}
);
},
},
];
return columns;
};
// 请求表头
parsePictureColumns = () => {
......@@ -445,201 +458,201 @@ class SelectOperatorModal extends React.Component {
<span>
<span>课程信息</span>
<Tooltip title='仅显示未关联课程,已关联课程不支持重复选择'>
<i className='icon iconfont' style={{ marginLeft: "5px", cursor: "pointer", color: "#bfbfbf", fontSize: "14px", fontWeight: "400" }}>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: '400' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: "course",
dataIndex: "course",
width: "55%",
key: 'course',
dataIndex: 'course',
width: '55%',
render: (val, record) => {
const { coverUrl } = record
const { coverUrl } = record;
return (
<div className='course-info'>
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
<img className='course-cover' src={coverUrl || "https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"} alt='' />
<img className='course-cover' src={coverUrl || 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'} alt='' />
<div className='course-name'>{record.courseName}</div>
</div>
)
}
);
},
},
{
title: "更新时间",
key: "updated",
dataIndex: "updated",
width: "25%",
title: '更新时间',
key: 'updated',
dataIndex: 'updated',
width: '25%',
render: (val, record) => {
return <span className='course-status'>{formatDate("YYYY-MM-DD", record.updated)}</span>
}
return <span className='course-status'>{formatDate('YYYY-MM-DD', record.updated)}</span>;
},
},
{
title: "学院展示",
key: "shelfState",
dataIndex: "shelfState",
width: "20%",
title: '学院展示',
key: 'shelfState',
dataIndex: 'shelfState',
width: '20%',
render: (val, record) => {
return <span>{record.shelfState === "YES" ? "开启" : "关闭"}</span>
}
}
]
return columns
}
return <span>{record.shelfState === 'YES' ? '开启' : '关闭'}</span>;
},
},
];
return columns;
};
selectLiveList = (record, selected) => {
const { selectVideo, currentTaskCourseData, selectLive, selectPicture } = this.state
let _list = []
const { selectVideo, currentTaskCourseData, selectLive, selectPicture } = this.state;
let _list = [];
if (selected || !_.find(selectLive, (item) => item.liveCourseId === record.liveCourseId)) {
_list = _.uniq(selectLive.concat([record]), false, (item) => item.liveCourseId)
_list = _.uniq(selectLive.concat([record]), false, (item) => item.liveCourseId);
} else {
_list = _.reject(selectLive, (item) => item.liveCourseId === record.liveCourseId)
_list = _.reject(selectLive, (item) => item.liveCourseId === record.liveCourseId);
}
if (_list.length + currentTaskCourseData.length + selectVideo.length + selectPicture.length > 20) {
message.warning("无法继续选择,一个任务最多关联20个课程")
return
message.warning('无法继续选择,一个任务最多关联20个课程');
return;
}
this.setState({ selectLive: _list })
}
this.setState({ selectLive: _list });
};
selectVideoList = (record, selected) => {
const { selectVideo, currentTaskCourseData, selectLive, selectPicture, videoCourseDivision } = this.state
const { selectVideo, currentTaskCourseData, selectLive, selectPicture, videoCourseDivision } = this.state;
let { [videoCourseDivision]: selectList } = selectVideo
let { [videoCourseDivision]: selectList } = selectVideo;
let _list = []
let _list = [];
if (selected || !_.find(selectList, (item) => item.id === record.id)) {
_list = _.uniq(selectList.concat([record]), false, (item) => item.id)
_list = _.uniq(selectList.concat([record]), false, (item) => item.id);
} else {
_list = _.reject(selectList, (item) => item.id === record.id)
_list = _.reject(selectList, (item) => item.id === record.id);
}
if (_list.length + currentTaskCourseData.length + selectLive.length + selectPicture.length > 20) {
message.warning("无法继续选择,一个任务最多关联20个课程")
return
message.warning('无法继续选择,一个任务最多关联20个课程');
return;
}
this.setState({
selectVideo: {
...selectVideo,
[videoCourseDivision]: _list
}
})
}
[videoCourseDivision]: _list,
},
});
};
selectPictureList = (record, selected) => {
const { selectVideo, currentTaskCourseData, selectLive, selectPicture } = this.state
let _list = []
const { selectVideo, currentTaskCourseData, selectLive, selectPicture } = this.state;
let _list = [];
if (selected || !_.find(selectPicture, (item) => item.id === record.id)) {
_list = _.uniq(selectPicture.concat([record]), false, (item) => item.id)
_list = _.uniq(selectPicture.concat([record]), false, (item) => item.id);
} else {
_list = _.reject(selectPicture, (item) => item.id === record.id)
_list = _.reject(selectPicture, (item) => item.id === record.id);
}
if (_list.length + currentTaskCourseData.length + selectLive.length + selectVideo.length > 20) {
message.warning("无法继续选择,一个任务最多关联20个课程")
return
message.warning('无法继续选择,一个任务最多关联20个课程');
return;
}
this.setState({ selectPicture: _list })
}
this.setState({ selectPicture: _list });
};
clearSelectCourse = () => {
this.setState({
selectLive: [],
selectVideo: {
internal: [],
external: []
external: [],
},
selectPicture: []
})
}
selectPicture: [],
});
};
handleSelectVideo = (selectVideo) => {
return selectVideo.map((item) => {
let _item = {}
_item.courseId = item.id
_item.courseType = "VOICE"
_item.courseName = item.courseName
let _item = {};
_item.courseId = item.id;
_item.courseType = 'VOICE';
_item.courseName = item.courseName;
return _item
})
}
return _item;
});
};
handleSelectLive = (selectLive) => {
return selectLive.map((item, index) => {
let _item = {}
_item.courseId = item.liveCourseId
_item.courseType = "LIVE"
_item.courseName = item.courseName
_item.courseState = item.courseState
return _item
})
}
let _item = {};
_item.courseId = item.liveCourseId;
_item.courseType = 'LIVE';
_item.courseName = item.courseName;
_item.courseState = item.courseState;
return _item;
});
};
videoCourseDivisionChange = (e) => {
const { videoSearchName } = this.state
const { videoSearchName } = this.state;
this.setState(
{
videoCourseDivision: e.target.value,
videoSearchDefalt: videoSearchName[e.target.value]
videoSearchDefalt: videoSearchName[e.target.value],
},
() => {
this.handleFetchVideoDataList()
this.handleFetchVideoDataList();
}
)
}
);
};
handleSelectPicture = (selectPicture) => {
return selectPicture.map((item, index) => {
let _item = {}
_item.courseId = item.id
_item.courseType = "PICTURE"
_item.courseName = item.courseName
return _item
})
}
let _item = {};
_item.courseId = item.id;
_item.courseType = 'PICTURE';
_item.courseName = item.courseName;
return _item;
});
};
renderFooter = () => {
const { activeKey } = this.state
let href = ""
const { activeKey } = this.state;
let href = '';
switch (activeKey) {
case "live":
case 'live':
href = (
<a
target='_blank'
rel='noopener noreferrer'
className='link-create-course'
href={window.location.origin + window.location.pathname + "#/create-live-course?type=add"}
href={window.location.origin + window.location.pathname + '#/create-live-course?type=add'}
onClick={this.props.onClose}>
没有找到需要的直播课?<span>去创建</span>
</a>
)
break
case "video":
);
break;
case 'video':
href = (
<a
target='_blank'
rel='noopener noreferrer'
className='link-create-course'
href={window.location.origin + window.location.pathname + "#/create-video-course?type=add"}
href={window.location.origin + window.location.pathname + '#/create-video-course?type=add'}
onClick={this.props.onClose}>
没有找到需要的视频课?<span>去创建</span>
</a>
)
break
case "picture":
);
break;
case 'picture':
href = (
<a
target='_blank'
rel='noopener noreferrer'
className='link-create-course'
href={window.location.origin + window.location.pathname + "#/create-graphics-course?type=add"}
href={window.location.origin + window.location.pathname + '#/create-graphics-course?type=add'}
onClick={this.props.onClose}>
没有找到需要的图文课?<span>去创建</span>
</a>
)
break
);
break;
default:
break
break;
}
return href
}
return href;
};
render() {
const { visible } = this.props
const { visible } = this.props;
const {
liveDataSource,
liveSize,
......@@ -659,8 +672,8 @@ class SelectOperatorModal extends React.Component {
pictureQuery,
pictureTotalCount,
videoCourseDivision
} = this.state
videoCourseDivision,
} = this.state;
return (
<Modal
title='关联课程'
......@@ -676,7 +689,7 @@ class SelectOperatorModal extends React.Component {
this.renderFooter(),
<Button
onClick={() => {
this.props.onClose()
this.props.onClose();
}}>
取消
</Button>,
......@@ -687,18 +700,18 @@ class SelectOperatorModal extends React.Component {
...this.handleSelectVideo(selectVideo.internal),
...this.handleSelectVideo(selectVideo.external),
...this.handleSelectLive(selectLive),
...this.handleSelectPicture(selectPicture)
...this.handleSelectPicture(selectPicture),
])
}>
确定
</Button>
</Button>,
]}>
<div>
<Tabs
type='line'
defaultActiveKey='live'
onChange={(activeKey) => {
this.setState({ activeKey: activeKey })
this.setState({ activeKey: activeKey });
}}>
<TabPane tab='直播课' key='live'>
<div className='search-container'>
......@@ -707,10 +720,10 @@ class SelectOperatorModal extends React.Component {
placeholder='搜索课程名称'
style={{ width: 200 }}
onChange={(e) => {
this.handleChangLiveCourseName(e.target.value)
this.handleChangLiveCourseName(e.target.value);
}}
onSearch={() => {
this.handleFetchLiveDataList()
this.handleFetchLiveDataList();
}}
/>
</div>
......@@ -741,25 +754,25 @@ class SelectOperatorModal extends React.Component {
pagination={false}
bordered
rowSelection={{
type: "checkbox",
selectedRowKeys: _.pluck(selectLive, "liveCourseId"),
type: 'checkbox',
selectedRowKeys: _.pluck(selectLive, 'liveCourseId'),
onSelect: (record, selected) => {
this.selectLiveList(record, selected)
this.selectLiveList(record, selected);
},
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = []
let _list = [];
if (selected) {
_list = _.uniq(selectLive.concat(changeRows), false, (item) => item.liveCourseId)
_list = _.uniq(selectLive.concat(changeRows), false, (item) => item.liveCourseId);
} else {
_list = _.reject(selectLive, (item) => _.find(changeRows, (data) => data.liveCourseId === item.liveCourseId))
_list = _.reject(selectLive, (item) => _.find(changeRows, (data) => data.liveCourseId === item.liveCourseId));
}
if (_list.length + currentTaskCourseData.length + selectVideo.length + selectPicture.length > 20) {
message.warning("无法继续选择,一个任务最多关联20个课程")
const extraLength = _list.length + currentTaskCourseData.length + selectVideo.length + selectPicture.length - 20
_list.splice(_list.length - extraLength, extraLength)
message.warning('无法继续选择,一个任务最多关联20个课程');
const extraLength = _list.length + currentTaskCourseData.length + selectVideo.length + selectPicture.length - 20;
_list.splice(_list.length - extraLength, extraLength);
}
this.setState({ selectLive: _list })
}
this.setState({ selectLive: _list });
},
}}
/>
{liveDataSource.length > 0 && (
......@@ -770,15 +783,15 @@ class SelectOperatorModal extends React.Component {
size='small'
total={liveTotalCount}
toPage={(page) => {
const _query = { ...liveQuery, current: page + 1 }
const _query = { ...liveQuery, current: page + 1 };
this.setState(
{
liveQuery: _query
liveQuery: _query,
},
() => {
this.handleFetchLiveDataList()
this.handleFetchLiveDataList();
}
)
);
}}
onShowSizeChange={this.onShowLiveSizeChange}
/>
......@@ -799,10 +812,10 @@ class SelectOperatorModal extends React.Component {
placeholder='搜索课程名称'
style={{ width: 200 }}
onChange={(e) => {
this.handleChangVideoCourseName(e.target.value)
this.handleChangVideoCourseName(e.target.value);
}}
onSearch={() => {
this.handleFetchVideoDataList()
this.handleFetchVideoDataList();
}}
/>
</div>
......@@ -832,30 +845,30 @@ class SelectOperatorModal extends React.Component {
pagination={false}
bordered
rowSelection={{
type: "checkbox",
selectedRowKeys: _.pluck(selectVideo[videoCourseDivision], "id"),
type: 'checkbox',
selectedRowKeys: _.pluck(selectVideo[videoCourseDivision], 'id'),
onSelect: (record, selected) => {
this.selectVideoList(record, selected)
this.selectVideoList(record, selected);
},
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = []
let _list = [];
if (selected) {
_list = _.uniq(selectVideo[videoCourseDivision].concat(changeRows), false, (item) => item.id)
_list = _.uniq(selectVideo[videoCourseDivision].concat(changeRows), false, (item) => item.id);
} else {
_list = _.reject(selectVideo[videoCourseDivision], (item) => _.find(changeRows, (data) => data.id === item.id))
_list = _.reject(selectVideo[videoCourseDivision], (item) => _.find(changeRows, (data) => data.id === item.id));
}
if (_list.length + currentTaskCourseData.length + selectLive.length + selectPicture.length > 20) {
message.warning("无法继续选择,一个任务最多关联20个课程")
const extraLength = _list.length + currentTaskCourseData.length + selectLive.length + selectPicture.length - 20
_list.splice(_list.length - extraLength, extraLength)
message.warning('无法继续选择,一个任务最多关联20个课程');
const extraLength = _list.length + currentTaskCourseData.length + selectLive.length + selectPicture.length - 20;
_list.splice(_list.length - extraLength, extraLength);
}
this.setState({
selectVideo: {
...selectVideo,
[videoCourseDivision]: _list
}
})
}
[videoCourseDivision]: _list,
},
});
},
}}
/>
{videoDataSource[videoCourseDivision].length > 0 && (
......@@ -866,19 +879,19 @@ class SelectOperatorModal extends React.Component {
size='small'
total={videoTotalCount[videoCourseDivision]}
toPage={(page) => {
const _query = { ...videoQuery[videoCourseDivision], current: page + 1 }
const _query = { ...videoQuery[videoCourseDivision], current: page + 1 };
this.setState(
{
videoQuery: {
...videoQuery,
[videoCourseDivision]: _query
}
[videoCourseDivision]: _query,
},
},
() => {
this.handleFetchVideoDataList()
this.handleFetchVideoDataList();
}
)
);
}}
onShowSizeChange={this.onShowVideoSizeChange}
/>
......@@ -893,10 +906,10 @@ class SelectOperatorModal extends React.Component {
placeholder='搜索课程名称'
style={{ width: 200 }}
onChange={(e) => {
this.handleChangPictureCourseName(e.target.value)
this.handleChangPictureCourseName(e.target.value);
}}
onSearch={() => {
this.handleFetchPictureDataList()
this.handleFetchPictureDataList();
}}
/>
</div>
......@@ -927,25 +940,25 @@ class SelectOperatorModal extends React.Component {
pagination={false}
bordered
rowSelection={{
type: "checkbox",
selectedRowKeys: _.pluck(selectPicture, "id"),
type: 'checkbox',
selectedRowKeys: _.pluck(selectPicture, 'id'),
onSelect: (record, selected) => {
this.selectPictureList(record, selected)
this.selectPictureList(record, selected);
},
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = []
let _list = [];
if (selected) {
_list = _.uniq(selectPicture.concat(changeRows), false, (item) => item.id)
_list = _.uniq(selectPicture.concat(changeRows), false, (item) => item.id);
} else {
_list = _.reject(selectPicture, (item) => _.find(changeRows, (data) => data.id === item.id))
_list = _.reject(selectPicture, (item) => _.find(changeRows, (data) => data.id === item.id));
}
if (_list.length + currentTaskCourseData.length + selectVideo.length + selectLive.length > 20) {
message.warning("无法继续选择,一个任务最多关联20个课程")
const extraLength = _list.length + currentTaskCourseData.length + selectVideo.length + selectLive.length - 20
_list.splice(_list.length - extraLength, extraLength)
message.warning('无法继续选择,一个任务最多关联20个课程');
const extraLength = _list.length + currentTaskCourseData.length + selectVideo.length + selectLive.length - 20;
_list.splice(_list.length - extraLength, extraLength);
}
this.setState({ selectPicture: _list })
}
this.setState({ selectPicture: _list });
},
}}
/>
{pictureDataSource.length > 0 && (
......@@ -956,15 +969,15 @@ class SelectOperatorModal extends React.Component {
size='small'
total={pictureTotalCount}
toPage={(page) => {
const _query = { ...pictureQuery, current: page + 1 }
const _query = { ...pictureQuery, current: page + 1 };
this.setState(
{
pictureQuery: _query
pictureQuery: _query,
},
() => {
this.handleFetchPictureDataList()
this.handleFetchPictureDataList();
}
)
);
}}
onShowSizeChange={this.onShowPictureSizeChange}
/>
......@@ -975,8 +988,8 @@ class SelectOperatorModal extends React.Component {
</Tabs>
</div>
</Modal>
)
);
}
}
export default SelectOperatorModal
export default SelectOperatorModal;
......@@ -12,7 +12,47 @@
text-align: left;
display: inline-block;
span {
color: #5289fa;
color: #2966ff;
}
}
.search-container {
margin-bottom: 16px;
}
.select-area {
margin-bottom: 12px;
display: flex;
justify-content: space-between;
.select-box {
display: inline-box;
width: 186px;
background: #e9efff;
border-radius: 4px;
padding: 6px 16px;
margin-right: 8px;
display: flex;
justify-content: space-between;
.tip-icon {
color: #2966ff;
font-size: 14px;
margin-right: 4px;
}
.select-num {
color: #666666;
font-size: 14px;
}
.clear-btn {
text-align: right;
color: #2966ff;
font-size: 14px;
}
}
.related-box {
padding: 6px 16px;
background: #e9efff;
border-radius: 4px;
flex: 1;
color: #666666;
font-size: 14px;
}
}
.search-container {
......
......@@ -9,42 +9,40 @@
color: #999999;
line-height: 20px;
}
.rwm{
position: relative;
width: 210px;
height: 210px;
text-align: center;
display: inline-block;
margin-top: 24px;
border: 1px solid #e8e8e8;
border-radius: 2px;
padding:15px;
.error{
position: absolute;
width: 200px;
height: 200px;
background: rgba(255, 255, 255, 0.95);
display: flex;
align-items:center;
justify-content:center;
left:5px;
top:5px;
div{
margin: 0 10px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
}
.ope{
cursor: pointer;
color:rgba(82, 137, 250, 1);
}
}
.rwm {
position: relative;
width: 210px;
height: 210px;
text-align: center;
display: inline-block;
margin-top: 24px;
border: 1px solid #e8e8e8;
border-radius: 2px;
padding: 15px;
.error {
position: absolute;
width: 200px;
height: 200px;
background: rgba(255, 255, 255, 0.95);
display: flex;
align-items: center;
justify-content: center;
left: 5px;
top: 5px;
div {
margin: 0 10px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
}
.ope {
cursor: pointer;
color: rgba(82, 137, 250, 1);
}
}
}
.ant-tabs-tab-active {
.ant-tabs-tab-btn {
......
......@@ -129,6 +129,7 @@ function ExaminationManager(props: any) {
{
title: "创建时间",
dataIndex: "examCreateTime",
align:fixStr.right,
sorter: true,
sortOrder: field === "examCreateTime" ? order : sortStatus.type,
render: (text: any, record: any) => <span>{moment(text).format("YYYY-MM-DD HH:mm")}</span>,
......
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