Commit 136034ff by yuananting

feat:新建培训任务相关接口联调

parent 11f4ee76
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-06 17:35:35 * @Date: 2021-08-06 17:35:35
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 14:23:07 * @LastEditTime: 2021-08-10 15:28:07
* @Description: 任务中心接口 * @Description: 任务中心接口
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -13,6 +13,10 @@ export function getTrainingTaskPage(params: object) { ...@@ -13,6 +13,10 @@ export function getTrainingTaskPage(params: object) {
return Service.Hades('public/hades/getTrainingTaskPage', params); return Service.Hades('public/hades/getTrainingTaskPage', params);
} }
export function getStoreTaskNum(params: object) {
return Service.Hades('public/hades/getStoreTaskNum', params);
}
export function createTrainingExam(params: object) { export function createTrainingExam(params: object) {
return Service.Hades('public/hades/createTrainingExam', params); return Service.Hades('public/hades/createTrainingExam', params);
} }
...@@ -20,3 +24,19 @@ export function createTrainingExam(params: object) { ...@@ -20,3 +24,19 @@ export function createTrainingExam(params: object) {
export function createTrainingTask(params: object) { export function createTrainingTask(params: object) {
return Service.Hades('public/hades/createTrainingTask', params); return Service.Hades('public/hades/createTrainingTask', params);
} }
export function updateIssueStateTraining(params: object) {
return Service.Hades('public/hades/updateIssueStateTraining', params);
}
export function deleteTrainingTask(params: object) {
return Service.Hades('public/hades/deleteTrainingTask', params);
}
export function getTrainingTaskDetail(params: object) {
return Service.Hades('public/hades/getTrainingTaskDetail', params);
}
export function updateTrainingTask(params: object) {
return Service.Hades('public/hades/updateTrainingTask', params);
}
...@@ -2,12 +2,21 @@ ...@@ -2,12 +2,21 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-06 17:32:41 * @Date: 2021-08-06 17:32:41
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 14:23:33 * @LastEditTime: 2021-08-10 15:28:39
* @Description: 任务中心-培训任务接口 * @Description: 任务中心-培训任务接口
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import { getTrainingTaskPage, createTrainingExam, createTrainingTask } from '@/data-source/taskCenter/request-apis'; import {
getTrainingTaskPage,
getStoreTaskNum,
createTrainingExam,
createTrainingTask,
updateIssueStateTraining,
deleteTrainingTask,
getTrainingTaskDetail,
updateTrainingTask,
} from '@/data-source/taskCenter/request-apis';
export default class TaskCenterService { export default class TaskCenterService {
// 获取培训任务列表 // 获取培训任务列表
...@@ -15,6 +24,11 @@ export default class TaskCenterService { ...@@ -15,6 +24,11 @@ export default class TaskCenterService {
return getTrainingTaskPage(params); return getTrainingTaskPage(params);
} }
// 获取学院任务数量
static getStoreTaskNum(params: any) {
return getStoreTaskNum(params);
}
// 培训任务创建考试 // 培训任务创建考试
static createTrainingExam(params: any) { static createTrainingExam(params: any) {
return createTrainingExam(params); return createTrainingExam(params);
...@@ -24,4 +38,24 @@ export default class TaskCenterService { ...@@ -24,4 +38,24 @@ export default class TaskCenterService {
static createTrainingTask(params: any) { static createTrainingTask(params: any) {
return createTrainingTask(params); return createTrainingTask(params);
} }
// 发布/取消发布培训任务
static updateIssueStateTraining(params: any) {
return updateIssueStateTraining(params);
}
// 删除培训任务
static deleteTrainingTask(params: any) {
return deleteTrainingTask(params);
}
// 获取培训任务详情
static getTrainingTaskDetail(params: any) {
return getTrainingTaskDetail(params);
}
// 修改培训任务
static updateTrainingTask(params: any) {
return updateTrainingTask(params);
}
} }
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react';
import { Select, Tooltip, Carousel, Popover } from 'antd' import { Select, Tooltip, Carousel, Popover } from 'antd';
import DataSet from '@antv/data-set' import DataSet from '@antv/data-set';
import { Chart as G2Chart } from '@antv/g2' import { Chart as G2Chart } from '@antv/g2';
import { G2, Chart, Geom, Axis, Tooltip as G2Tooltip, Coord, Label, Legend, View, Guide, Shape, Facet, Util } from 'bizcharts' import { G2, Chart, Geom, Axis, Tooltip as G2Tooltip, Coord, Label, Legend, View, Guide, Shape, Facet, Util } from 'bizcharts';
import moment from 'moment' import moment from 'moment';
import Service from '@/common/js/service' import Service from '@/common/js/service';
import User from '@/common/js/user' import User from '@/common/js/user';
import HomeTip from './HomeTip' import HomeTip from './HomeTip';
import './Home.less' import './Home.less';
const Option = Select.Option const Option = Select.Option;
class Home extends React.Component { class Home extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props);
this.state = { this.state = {
scheduleType: 'LIVE', scheduleType: 'LIVE',
list: [], list: [],
...@@ -34,54 +34,54 @@ class Home extends React.Component { ...@@ -34,54 +34,54 @@ class Home extends React.Component {
incWeekVisitCustomerNum: 0, incWeekVisitCustomerNum: 0,
courseNum: 0, //课程总数 courseNum: 0, //课程总数
inCourseNum: 0, //本月新增课程总数 inCourseNum: 0, //本月新增课程总数
} };
this._chart = null this._chart = null;
} }
componentDidMount() { componentDidMount() {
this.getPanelInfo() this.getPanelInfo();
this.getStudyInfo() this.getStudyInfo();
this.getHotCourse() this.getHotCourse();
this.getTrainingInfo() this.getTrainingInfo();
} }
getTrainingInfo() { getTrainingInfo() {
Service.Hades('public/hades/planOverview', { storeId: User.getStoreId() }).then((res) => { Service.Hades('public/hades/planOverview', { storeId: User.getStoreId() }).then((res) => {
if (res.success) { if (res.success) {
this.setState(res.result) this.setState(res.result);
} }
}) });
} }
getHotCourse() { getHotCourse() {
const { timeRange, scheduleType } = this.state const { timeRange, scheduleType } = this.state;
const data = { const data = {
hotNum: 5, hotNum: 5,
scheduleType, scheduleType,
storeId: User.getStoreId(), storeId: User.getStoreId(),
timeRange, timeRange,
} };
Service.Hades('public/courseCloud/hotCourse', data).then((res) => { Service.Hades('public/courseCloud/hotCourse', data).then((res) => {
if (res.success) { if (res.success) {
this.setState({ this.setState({
list: res.result, list: res.result,
}) });
} }
}) });
} }
getStudyInfo() { getStudyInfo() {
const { studyTimeRange } = this.state const { studyTimeRange } = this.state;
Service.Hades('public/hades/studyInfo', { storeId: User.getStoreId(), timeRange: studyTimeRange }).then((res) => { Service.Hades('public/hades/studyInfo', { storeId: User.getStoreId(), timeRange: studyTimeRange }).then((res) => {
if (res.success) { if (res.success) {
const dataList = res.result.map((item) => ({ const dataList = res.result.map((item) => ({
time: moment(item.dateline).format('MM-DD'), time: moment(item.dateline).format('MM-DD'),
studyNum: item.studyNum, studyNum: item.studyNum,
studyTime: Math.round(item.studyTime / 6) / 10, studyTime: Math.round(item.studyTime / 6) / 10,
})) }));
this.createChart(dataList) this.createChart(dataList);
} }
}) });
} }
getPanelInfo() { getPanelInfo() {
...@@ -106,22 +106,22 @@ class Home extends React.Component { ...@@ -106,22 +106,22 @@ class Home extends React.Component {
incWeekVisitCustomerNum: res.result.incWeekVisitCustomerNum, incWeekVisitCustomerNum: res.result.incWeekVisitCustomerNum,
courseNum: res.result.videoCourseNum + res.result.liveCourseNum + res.result.pictureCourseNum + res.result.offlineCourseNum, courseNum: res.result.videoCourseNum + res.result.liveCourseNum + res.result.pictureCourseNum + res.result.offlineCourseNum,
inCourseNum: res.result.incLiveCourseNum + res.result.incVideoCourseNum + res.result.incPictureCourseNum + res.result.incOfflineCourseNum, inCourseNum: res.result.incLiveCourseNum + res.result.incVideoCourseNum + res.result.incPictureCourseNum + res.result.incOfflineCourseNum,
}) });
} }
}) });
} }
showNumber(index) { showNumber(index) {
switch (index) { switch (index) {
case 0: case 0:
return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png' return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png';
case 1: case 1:
return 'https://image.xiaomaiketang.com/xm/Qfib4mnGJT.png' return 'https://image.xiaomaiketang.com/xm/Qfib4mnGJT.png';
case 2: case 2:
return 'https://image.xiaomaiketang.com/xm/8jKXHyrDaG.png' return 'https://image.xiaomaiketang.com/xm/8jKXHyrDaG.png';
default: default:
return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png' return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png';
} }
} }
...@@ -132,28 +132,28 @@ class Home extends React.Component { ...@@ -132,28 +132,28 @@ class Home extends React.Component {
forceFit: true, forceFit: true,
height: 290, height: 290,
padding: [48, 64], padding: [48, 64],
}) });
} }
this._chart.clear() this._chart.clear();
this._chart.source(data, { this._chart.source(data, {
studyTime: { studyTime: {
formatter: (val) => { formatter: (val) => {
return val return val;
}, },
tickCount: 5, tickCount: 5,
}, },
time: { time: {
formatter: (val) => { formatter: (val) => {
return `${val}` return `${val}`;
}, },
}, },
studyNum: { studyNum: {
formatter: (val) => { formatter: (val) => {
return val return val;
}, },
tickCount: 5, tickCount: 5,
}, },
}) });
this._chart.axis('time', { this._chart.axis('time', {
label: { label: {
offset: 20, offset: 20,
...@@ -168,7 +168,7 @@ class Home extends React.Component { ...@@ -168,7 +168,7 @@ class Home extends React.Component {
tickLine: { tickLine: {
stroke: '#E8E8E8', stroke: '#E8E8E8',
}, },
}) });
this._chart.axis('submitCount', { this._chart.axis('submitCount', {
label: { label: {
textStyle: { textStyle: {
...@@ -176,7 +176,7 @@ class Home extends React.Component { ...@@ -176,7 +176,7 @@ class Home extends React.Component {
fontSize: 14, fontSize: 14,
}, },
}, },
}) });
this._chart.axis('studyTime', { this._chart.axis('studyTime', {
label: { label: {
textStyle: { textStyle: {
...@@ -184,7 +184,7 @@ class Home extends React.Component { ...@@ -184,7 +184,7 @@ class Home extends React.Component {
fontSize: 14, fontSize: 14,
}, },
}, },
}) });
this._chart this._chart
.line() .line()
.position('time*studyNum') .position('time*studyNum')
...@@ -193,8 +193,8 @@ class Home extends React.Component { ...@@ -193,8 +193,8 @@ class Home extends React.Component {
return { return {
name: '学习人数', name: '学习人数',
value: studyNum + '人', value: studyNum + '人',
} };
}) });
this._chart this._chart
.line() .line()
.position('time*studyTime') .position('time*studyTime')
...@@ -203,10 +203,10 @@ class Home extends React.Component { ...@@ -203,10 +203,10 @@ class Home extends React.Component {
return { return {
name: '人均学习时长', name: '人均学习时长',
value: studyTime + '分钟', value: studyTime + '分钟',
} };
}) });
this._chart.legend(false) this._chart.legend(false);
this._chart.tooltip({ this._chart.tooltip({
containerTpl: containerTpl:
'<div class="g2-tooltip" style="background: #fff !important;">' + '<div class="g2-tooltip" style="background: #fff !important;">' +
...@@ -214,9 +214,9 @@ class Home extends React.Component { ...@@ -214,9 +214,9 @@ class Home extends React.Component {
'<ul class="g2-tooltip-list"></ul></div>', // tooltip 容器模板 '<ul class="g2-tooltip-list"></ul></div>', // tooltip 容器模板
itemTpl: itemTpl:
'<li data-index={index}><span style="background-color:{color};width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:8px;"></span>{name}<span style="display: inline-block; float: right; margin-left: 30px;">{value}</span></li>', // tooltip 每项记录的默认模板 '<li data-index={index}><span style="background-color:{color};width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:8px;"></span>{name}<span style="display: inline-block; float: right; margin-left: 30px;">{value}</span></li>', // tooltip 每项记录的默认模板
}) });
this._chart.render() this._chart.render();
} };
render() { render() {
const { const {
...@@ -245,7 +245,7 @@ class Home extends React.Component { ...@@ -245,7 +245,7 @@ class Home extends React.Component {
offlineCourseNum, offlineCourseNum,
weekVisitCustomerNum, weekVisitCustomerNum,
incWeekVisitCustomerNum, incWeekVisitCustomerNum,
} = this.state } = this.state;
const data = [ const data = [
{ {
item: '已完成培训', item: '已完成培训',
...@@ -255,26 +255,26 @@ class Home extends React.Component { ...@@ -255,26 +255,26 @@ class Home extends React.Component {
item: '未完成培训', item: '未完成培训',
count: unfinishedNum, count: unfinishedNum,
}, },
] ];
const { DataView } = DataSet const { DataView } = DataSet;
const { Html } = Guide const { Html } = Guide;
const sum = data[0].count + data[1].count const sum = data[0].count + data[1].count;
const dv = new DataView() const dv = new DataView();
sum && sum &&
dv.source(data).transform({ dv.source(data).transform({
type: 'percent', type: 'percent',
field: 'count', field: 'count',
dimension: 'item', dimension: 'item',
as: 'percent', as: 'percent',
}) });
const cols = { const cols = {
percent: { percent: {
formatter: (val) => { formatter: (val) => {
val = val * 100 + '%' val = val * 100 + '%';
return val return val;
}, },
}, },
} };
return ( return (
<div className='home-page'> <div className='home-page'>
<HomeTip /> <HomeTip />
...@@ -357,7 +357,7 @@ class Home extends React.Component { ...@@ -357,7 +357,7 @@ class Home extends React.Component {
<div className='data-item'> <div className='data-item'>
<div className='header'> <div className='header'>
<img className='header-icon' src='https://image.xiaomaiketang.com/xm/jZf3GNY5tY.png' alt='' /> <img className='header-icon' src='https://image.xiaomaiketang.com/xm/jZf3GNY5tY.png' alt='' />
<span className='header-word'>培训计划总数 (个)</span> <span className='header-word'>培训任务总数 (个)</span>
</div> </div>
<div className='data-number'>{trainingPlanNum}</div> <div className='data-number'>{trainingPlanNum}</div>
<div className='data-footer'> <div className='data-footer'>
...@@ -416,7 +416,7 @@ class Home extends React.Component { ...@@ -416,7 +416,7 @@ class Home extends React.Component {
style={{ width: 88 }} style={{ width: 88 }}
value={timeRange} value={timeRange}
onChange={(value) => { onChange={(value) => {
this.setState({ timeRange: value }, () => this.getHotCourse()) this.setState({ timeRange: value }, () => this.getHotCourse());
}}> }}>
<Option value='7'>近7天</Option> <Option value='7'>近7天</Option>
<Option value='15'>近15天</Option> <Option value='15'>近15天</Option>
...@@ -459,8 +459,8 @@ class Home extends React.Component { ...@@ -459,8 +459,8 @@ class Home extends React.Component {
</div> </div>
<div className='study-item'> <div className='study-item'>
<div className='study-title'> <div className='study-title'>
培训计划完成情况 培训任务完成情况
<Tooltip overlayClassName='data-plan-tooltip' title='若某人加入多个培训计划,则需完成所有已加入的培训计划后,才视为已完成培训'> <Tooltip overlayClassName='data-plan-tooltip' title='若某人加入多个培训任务,则需完成所有已加入的培训任务后,才视为已完成培训'>
<span className='iconfont icon'>&#xe61d;</span> <span className='iconfont icon'>&#xe61d;</span>
</Tooltip> </Tooltip>
<span className='tip'>(本月)</span> <span className='tip'>(本月)</span>
...@@ -479,7 +479,7 @@ class Home extends React.Component { ...@@ -479,7 +479,7 @@ class Home extends React.Component {
<Axis name='percent' /> <Axis name='percent' />
<G2Tooltip <G2Tooltip
showTitle={false} showTitle={false}
itemTpl='<li><span style="background-color:{color};" class="g2-tooltip-marker"></span>{name}: {value}</li>' itemTpl='<li><span style="background-color:{color};" class="g2-tooltip-marker"></span><span style="margin-right:16px;">{percent}</span><span>{num}</span></li>'
/> />
<Guide> <Guide>
<Html <Html
...@@ -492,15 +492,15 @@ class Home extends React.Component { ...@@ -492,15 +492,15 @@ class Home extends React.Component {
<Geom <Geom
type='intervalStack' type='intervalStack'
position='percent' position='percent'
color={['item', ['#FFBB54', '#2966FF']]} color={['item', ['#14CCA7', '#2966FF']]}
tooltip={[ tooltip={[
'item*percent', 'item*percent',
(item, percent) => { (item, percent) => {
percent = Math.round(percent * 100) + '%' percent = Math.round(percent * 100) + '%';
return { return {
name: item, num: item === '未完成培训' ? unfinishedNum + '人' : completeNum + '人',
value: percent, percent: percent,
} };
}, },
]} ]}
style={{ style={{
...@@ -526,15 +526,15 @@ class Home extends React.Component { ...@@ -526,15 +526,15 @@ class Home extends React.Component {
</Otherwise> </Otherwise>
</Choose> </Choose>
<div className='circle-tip unfinished'> <div className='circle-tip finished'>
<div className='spot'></div> <div className='spot'></div>
<div className='number'>{unfinishedNum}</div> {/* <div className='number'>{completeNum}人</div> */}
<div className='word'>完成培训</div> <div className='word'>完成培训</div>
</div> </div>
<div className='circle-tip finished'> <div className='circle-tip unfinished'>
<div className='spot'></div> <div className='spot'></div>
<div className='number'>{completeNum}</div> {/* <div className='number'>{unfinishedNum}人</div> */}
<div className='word'>完成培训</div> <div className='word'>完成培训</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -554,7 +554,7 @@ class Home extends React.Component { ...@@ -554,7 +554,7 @@ class Home extends React.Component {
style={{ width: 88 }} style={{ width: 88 }}
value={studyTimeRange} value={studyTimeRange}
onChange={(value) => { onChange={(value) => {
this.setState({ studyTimeRange: value }, () => this.getStudyInfo()) this.setState({ studyTimeRange: value }, () => this.getStudyInfo());
}}> }}>
<Option value='7'>近7天</Option> <Option value='7'>近7天</Option>
<Option value='15'>近15天</Option> <Option value='15'>近15天</Option>
...@@ -582,8 +582,8 @@ class Home extends React.Component { ...@@ -582,8 +582,8 @@ class Home extends React.Component {
</div> </div>
</div> </div>
</div> </div>
) );
} }
} }
export default Home export default Home;
...@@ -278,18 +278,19 @@ ...@@ -278,18 +278,19 @@
} }
.circle-tip { .circle-tip {
position: absolute; position: absolute;
left: 70%;
padding-left: 16px; padding-left: 16px;
&.unfinished { &.unfinished {
top: 152px; bottom: 2%;
left: 37%;
.spot { .spot {
background: #2966ff; background: #2966ff;
} }
} }
&.finished { &.finished {
top: 232px; bottom: 2%;
left: 14%;
.spot { .spot {
background: #ffbb54; background: #14cca7;
} }
} }
.spot { .spot {
...@@ -297,7 +298,7 @@ ...@@ -297,7 +298,7 @@
width: 8px; width: 8px;
height: 8px; height: 8px;
border-radius: 4px; border-radius: 4px;
top: 20px; top: 8px;
left: 0; left: 0;
} }
.number { .number {
......
...@@ -6,66 +6,66 @@ ...@@ -6,66 +6,66 @@
* @Description: 大班直播分享弹窗 * @Description: 大班直播分享弹窗
*/ */
import React from 'react' import React from 'react';
import { Modal, Button, message } from 'antd' import { Modal, Button, message } from 'antd';
import domtoimage from 'dom-to-image' import domtoimage from 'dom-to-image';
import qrcode from '@/libs/qrcode/qrcode.js' import qrcode from '@/libs/qrcode/qrcode.js';
import User from '@/common/js/user' import User from '@/common/js/user';
import $ from 'jquery' import $ from 'jquery';
import CourseService from '@/domains/course-domain/CourseService' import CourseService from '@/domains/course-domain/CourseService';
import './SharePlanModal.less' import './SharePlanModal.less';
const DEFAULT_COVER = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png' const DEFAULT_COVER = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png';
class ShareLiveModal extends React.Component { class ShareLiveModal extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props);
this.state = { this.state = {
shareUrl: '', shareUrl: '',
} };
} }
componentDidMount() { componentDidMount() {
// 获取短链接 // 获取短链接
this.handleConvertShortUrl() this.handleConvertShortUrl();
} }
handleConvertShortUrl = () => { handleConvertShortUrl = () => {
const { longUrl } = this.props.data const { longUrl } = this.props.data;
// 发请求 // 发请求
CourseService.getQrcode({ CourseService.getQrcode({
urls: [longUrl], urls: [longUrl],
}).then((res) => { }).then((res) => {
const { result = [] } = res const { result = [] } = res;
this.setState( this.setState(
{ {
shareUrl: result[0].shortUrl, shareUrl: result[0].shortUrl,
}, },
() => { () => {
const qrcodeWrapDom = document.querySelector('#qrcodeWrap') const qrcodeWrapDom = document.querySelector('#qrcodeWrap');
const qrcodeNode = new qrcode({ const qrcodeNode = new qrcode({
text: this.state.shareUrl, text: this.state.shareUrl,
size: 98, size: 98,
}) });
qrcodeWrapDom.appendChild(qrcodeNode) qrcodeWrapDom.appendChild(qrcodeNode);
const qrcodeWrapDomDownload = document.querySelector('#qrcodeWrap-dowload') const qrcodeWrapDomDownload = document.querySelector('#qrcodeWrap-dowload');
const qrcodeNodeDownLoad = new qrcode({ const qrcodeNodeDownLoad = new qrcode({
text: this.state.shareUrl, text: this.state.shareUrl,
size: 196, size: 196,
}) });
qrcodeWrapDomDownload.appendChild(qrcodeNodeDownLoad) qrcodeWrapDomDownload.appendChild(qrcodeNodeDownLoad);
}
)
})
} }
);
});
};
componentWillUnmount() { componentWillUnmount() {
// 页面销毁之前清空定时器 // 页面销毁之前清空定时器
clearTimeout(this.timer) clearTimeout(this.timer);
} }
// 下载海报 // 下载海报
...@@ -77,29 +77,29 @@ class ShareLiveModal extends React.Component { ...@@ -77,29 +77,29 @@ class ShareLiveModal extends React.Component {
}, },
() => { () => {
this.setState({ time: new Date().valueOf() }, () => { this.setState({ time: new Date().valueOf() }, () => {
let node = document.getElementById('poster-dowload') let node = document.getElementById('poster-dowload');
domtoimage.toPng(node).then((imgData) => { domtoimage.toPng(node).then((imgData) => {
const download = document.createElement('a') const download = document.createElement('a');
const { planName } = this.props.data const { planName } = this.props.data;
$(download).attr('href', imgData).attr('download', `${planName}.png`).get(0).click() $(download).attr('href', imgData).attr('download', `${planName}.png`).get(0).click();
}) });
}) });
}
)
} }
);
};
// 复制分享链接 // 复制分享链接
handleCopy = () => { handleCopy = () => {
const textContent = document.getElementById('shareUrl').innerText const textContent = document.getElementById('shareUrl').innerText;
window.copyText(textContent) window.copyText(textContent);
message.success('复制成功!') message.success('复制成功!');
} };
render() { render() {
const { data } = this.props const { data } = this.props;
const { planName, coverUrl = DEFAULT_COVER } = data const { planName, coverUrl = DEFAULT_COVER } = data;
const { shareUrl, showImg, time } = this.state const { shareUrl, showImg, time } = this.state;
return ( return (
<Modal <Modal
title={'分享培训计划'} title={'分享培训计划'}
...@@ -185,8 +185,8 @@ class ShareLiveModal extends React.Component { ...@@ -185,8 +185,8 @@ class ShareLiveModal extends React.Component {
</div> </div>
</div> </div>
</Modal> </Modal>
) );
} }
} }
export default ShareLiveModal export default ShareLiveModal;
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-07-29 13:57:03 * @Date: 2021-07-29 13:57:03
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 17:39:56 * @LastEditTime: 2021-08-11 12:46:17
* @Description: 任务中心-培训任务-新建页面 * @Description: 任务中心-培训任务-新建页面
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import { Button, message, Modal, Space } from 'antd'; import { Button, message, Modal, Space } from 'antd';
import ShowTips from '@/components/ShowTips'; import ShowTips from '@/components/ShowTips';
import Breadcrumbs from '@/components/Breadcrumbs'; import Breadcrumbs from '@/components/Breadcrumbs';
...@@ -18,14 +18,15 @@ import _ from 'underscore'; ...@@ -18,14 +18,15 @@ import _ from 'underscore';
import './AddTrainTask.less'; import './AddTrainTask.less';
import Upload from '@/core/upload'; import Upload from '@/core/upload';
import { randomString } from '@/domains/basic-domain/utils'; import { randomString } from '@/domains/basic-domain/utils';
import TaskCenterService from '@/domains/task-center-domain/TaskCenterService';
import Bus from '@/core/bus';
const defaultCover = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png'; const defaultCover = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png';
const DEFAULT_BASIC_INFO = { const DEFAULT_BASIC_INFO = {
taskName: '1', // 培训任务名称 taskName: '', // 培训任务名称
coverUrl: defaultCover, coverUrl: defaultCover,
coverId: null, coverId: null,
trainingStageList: [], // 培训内容
helpStoreUserIds: [], // 指定协同者id helpStoreUserIds: [], // 指定协同者id
timeType: 'FOREVER', // 培训时间,默认永久有效 timeType: 'FOREVER', // 培训时间,默认永久有效
startTime: null, // 固定时间段-开始时间 startTime: null, // 固定时间段-开始时间
...@@ -51,17 +52,85 @@ const DEFAULT_FINISH_STANDARD = { ...@@ -51,17 +52,85 @@ const DEFAULT_FINISH_STANDARD = {
function AddTrainTask() { function AddTrainTask() {
const type = getParameterByName('type'); const type = getParameterByName('type');
const taskId = getParameterByName('taskId');
const taskState = getParameterByName('taskState');
const [activeStep, setActiveStep] = useState('BASIC_INFO'); const [activeStep, setActiveStep] = useState('BASIC_INFO');
const [basicInfo, setBasicInfo] = useState(DEFAULT_BASIC_INFO); const [basicInfo, setBasicInfo] = useState(DEFAULT_BASIC_INFO);
const [stageList, setStageList] = useState(DEFAULT_STAGE_LIST); const [stageList, setStageList] = useState(DEFAULT_STAGE_LIST);
const [finishStandard, setFinishStandard] = useState(DEFAULT_FINISH_STANDARD); // 完成百分比 const [finishStandard, setFinishStandard] = useState(DEFAULT_FINISH_STANDARD); // 完成百分比
const [startCheck, setStartCheck] = useState(false); // 是否启动校验 const [startCheck, setStartCheck] = useState(false); // 是否启动校验
const basicInfoRef = useRef(null);
useEffect(() => {
basicInfoRef.current = basicInfo;
}, [basicInfo]);
useEffect(() => {
if (type === 'edit') {
TaskCenterService.getTrainingTaskDetail({
taskId,
}).then((res) => {
const {
result: {
taskName,
courseMediaVOS,
helpStoreUsers,
timeType,
startTime,
endTime,
learnType,
assignList,
percentCompleteLive,
percentCompletePicture,
percentCompleteVideo,
trainingStageList,
},
} = res;
const _helpStoreUserIds = helpStoreUsers.map((item) => {
item.nickName = item.storeUserName;
item.userId = item.storeUserId;
return item;
});
// useEffect(() => { const coverInfo = courseMediaVOS.filter((item) => item.contentType === 'COVER')[0];
const coverUrl = coverInfo ? coverInfo.mediaUrl : defaultCover;
const coverId = coverInfo ? coverInfo.mediaContent : null;
// }, [basicInfo]); const ITEM_BASIC_INFO = {
console.log('basicInfo=====>', basicInfo); taskName,
coverUrl,
coverId,
helpStoreUserIds: _helpStoreUserIds,
timeType,
startTime,
endTime,
learnType,
assignList,
// introduce: null, // 培训目的
};
const ITEM_FINISH_STANDARD = {
percentCompleteLive,
percentCompletePicture,
percentCompleteVideo,
};
const _stageList = trainingStageList.map((item) => {
item.contentList = item.contentVOList;
item.type = 'text';
return item;
});
setBasicInfo(ITEM_BASIC_INFO);
setFinishStandard(ITEM_FINISH_STANDARD);
setStageList(_stageList);
});
}
}, []);
// 渲染底部操作按钮
function renderFooter() { function renderFooter() {
return ( return (
<Choose> <Choose>
...@@ -90,34 +159,55 @@ function AddTrainTask() { ...@@ -90,34 +159,55 @@ function AddTrainTask() {
); );
} }
// 确认保存新建
function submitRemote(introduceId, issue) { function submitRemote(introduceId, issue) {
const { endTime, helpStoreUserIds, learnType, startTime, taskName, timeType, coverId, coverUrl } = basicInfo; const { endTime, helpStoreUserIds, learnType, startTime, taskName, timeType, coverId, coverUrl } = basicInfo;
const { percentCompleteLive, percentCompletePicture, percentCompleteVideo } = finishStandard; const { percentCompleteLive, percentCompletePicture, percentCompleteVideo } = finishStandard;
const commonParams = { const _stageList = stageList.map((item, index) => {
assignList: [ delete item.contentVOList;
// 指派对象 delete item.check;
delete item.type;
delete item.liveFailure;
item.sequence = index + 1;
return item;
});
const _helpStoreUserIds = helpStoreUserIds.map((item) => {
return item.userId;
});
const assignList = [
{ {
assignId: '', assignId: '1379762403510968321',
assignName: '', assignType: 'CUSTOM',
assignType: '',
}, },
], ];
// const _assignList = assignList((item) => {
// if (item.depType === 'DEP_CUSTOM') {
// // item.
// }
// });
// console.log(assignList);
createId: User.getUserId(), const commonParams = {
assignList,
createId: User.getStoreUserId(),
endTime, endTime,
helpStoreUserIds, // 协同者集合 helpStoreUserIds: _helpStoreUserIds, // 协同者集合
issueState: issue, // 是否发布 issueState: issue, // 是否发布
learnType, // 学习模式 learnType, // 学习模式
scheduleMediaRequests: [ scheduleMediaRequests: coverId
? [
{ {
contentType: 'COVER', contentType: 'COVER',
mediaContent: coverId, mediaContent: coverId,
mediaType: 'PICTURE', mediaType: 'PICTURE',
mediaUrl: coverUrl, mediaUrl: coverUrl,
}, },
], ]
: [],
startTime, startTime,
storeId: User.getStoreId(), storeId: User.getStoreId(),
taskName, taskName,
...@@ -126,17 +216,60 @@ function AddTrainTask() { ...@@ -126,17 +216,60 @@ function AddTrainTask() {
percentCompletePicture, percentCompletePicture,
percentCompleteVideo, percentCompleteVideo,
introduceId, introduceId,
trainingStageList: _stageList,
}; };
console.log('commonParams:', commonParams); // if (type === 'edit' && timeType === 'FOREVER') {
// delete commonParams.startTime;
// delete commonParams.endTime;
// }
if (type === 'edit') {
TaskCenterService.updateTrainingTask({ ...commonParams, id: taskId }).then((res) => {
message.success('保存成功');
RCHistory.goBack();
});
} else {
TaskCenterService.createTrainingTask(commonParams).then((res) => {
message.success('保存成功');
RCHistory.goBack();
});
}
Bus.trigger('getTrainingTaskPage');
Bus.trigger('getStoreTaskNum');
} }
// 保存
function handleSubmit(issue) { function handleSubmit(issue) {
setStartCheck(true); setStartCheck(true);
const { taskName, assignList } = basicInfo;
const { percentCompleteLive, percentCompleteVideo, percentCompletePicture } = finishStandard;
console.log(percentCompleteLive, percentCompleteVideo, percentCompletePicture);
if (!taskName) {
return message.warning('请输入培训任务名称');
}
// if (assignList.length === 0) {
// return message.warning('请选择指派对象');
// }
if (stageList.length === 0) { if (stageList.length === 0) {
return message.warning('请添加阶段'); return message.warning('请添加阶段');
} }
const stageNameEmpty = stageList.filter((item) => !item.stageName);
if (stageNameEmpty.length > 0) {
return message.warning('请输入阶段名称');
}
const stageNameArr = stageList.map((item) => item.stageName);
const stageNameSet = new Set(stageNameArr);
if (stageNameSet.size !== stageNameArr.length) {
return message.warning('阶段名称不能重复');
}
if (percentCompleteLive === '' || percentCompleteVideo === '' || percentCompletePicture === '') {
return message.warning('请输入完成标准');
}
Upload.uploadTextToOSS( Upload.uploadTextToOSS(
basicInfo.introduce, basicInfo.introduce,
`${randomString()}.txt`, `${randomString()}.txt`,
...@@ -147,39 +280,37 @@ function AddTrainTask() { ...@@ -147,39 +280,37 @@ function AddTrainTask() {
); );
} }
// 返回、取消
function handleGoBack() { function handleGoBack() {
window.RCHistory.goBack(); window.RCHistory.goBack();
} }
function handleChangeBasicInfo(field, value) { function handleChangeBasicInfo(field, value) {
console.log('handleChangeBasicInfo====>', basicInfo, field, value);
if (field === 'coverUrl') { if (field === 'coverUrl') {
setBasicInfo({ setBasicInfo({
...basicInfo, ...basicInfoRef.current,
coverUrl: value.fileUrl, coverUrl: value.fileUrl,
coverId: value.resourceId, coverId: value.resourceId,
}); });
} else if (field === 'trainDate') { } else if (field === 'trainDate') {
// 固定培训时间,设置起始 // 固定培训时间,设置起始
setBasicInfo({ setBasicInfo({
...basicInfo, ...basicInfoRef.current,
startTime: value && value[0]?.valueOf(), startTime: value && value[0]?.valueOf(),
endTime: value && value[1]?.valueOf(), endTime: value && value[1]?.valueOf(),
}); });
} else if (field === 'timeType' && value === 'FOREVER') { } else if (field === 'timeType' && value === 'FOREVER') {
setBasicInfo({ setBasicInfo({
...basicInfo, ...basicInfoRef.current,
[field]: value, [field]: value,
startTime: null, startTime: null,
endTime: null, endTime: null,
}); });
} else { } else {
let a = { setBasicInfo({
...basicInfo, ...basicInfoRef.current,
[field]: value, [field]: value,
}; });
console.log('a====>', a);
setBasicInfo(a);
} }
} }
...@@ -187,10 +318,7 @@ function AddTrainTask() { ...@@ -187,10 +318,7 @@ function AddTrainTask() {
if (field === 'stageList') { if (field === 'stageList') {
setStageList(value); setStageList(value);
} else { } else {
setFinishStandard({ setFinishStandard(value);
...finishStandard,
[field]: value,
});
} }
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-07-28 11:25:58 * @Date: 2021-07-28 11:25:58
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 11:41:40 * @LastEditTime: 2021-08-10 15:10:44
* @Description: 任务中心-培训任务 * @Description: 任务中心-培训任务
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -13,6 +13,8 @@ import TrainList from './components/TrainList'; ...@@ -13,6 +13,8 @@ import TrainList from './components/TrainList';
import TaskCenterService from '@/domains/task-center-domain/TaskCenterService'; import TaskCenterService from '@/domains/task-center-domain/TaskCenterService';
import DataCenter from '../data-center/Index'; import DataCenter from '../data-center/Index';
import User from '@/common/js/user'; import User from '@/common/js/user';
import Bus from '@/core/bus';
function TrainTaskPage(props) { function TrainTaskPage(props) {
const [trainListData, setTrainListData] = useState([]); // 培训任务列表 const [trainListData, setTrainListData] = useState([]); // 培训任务列表
const [query, setQuery] = useState({ const [query, setQuery] = useState({
...@@ -28,12 +30,33 @@ function TrainTaskPage(props) { ...@@ -28,12 +30,33 @@ function TrainTaskPage(props) {
taskName: '', taskName: '',
}); });
const [totalCount, setTotalCount] = useState(0); // 总数 const [totalCount, setTotalCount] = useState(0); // 总数
const [storeTaskNum, setStoreTaskNum] = useState({});
const { match } = props; const { match } = props;
useEffect(() => { useEffect(() => {
getTrainingTaskPage(); getTrainingTaskPage();
}, [query]); }, [query]);
useEffect(() => {
getStoreTaskNum();
initPageData();
return () => {
removePageData();
};
}, []);
useEffect(() => {}, []);
const initPageData = () => {
Bus.bind('getTrainingTaskPage', getTrainingTaskPage);
Bus.bind('getStoreTaskNum', getStoreTaskNum);
};
const removePageData = () => {
Bus.unbind('getTrainingTaskPage', getTrainingTaskPage);
Bus.unbind('getStoreTaskNum', getStoreTaskNum);
};
// 获取计划列表 // 获取计划列表
function getTrainingTaskPage() { function getTrainingTaskPage() {
let _query = _.clone(query); let _query = _.clone(query);
...@@ -49,6 +72,13 @@ function TrainTaskPage(props) { ...@@ -49,6 +72,13 @@ function TrainTaskPage(props) {
}); });
} }
// 获取学院任务数量
function getStoreTaskNum() {
TaskCenterService.getStoreTaskNum({ storeId: User.getStoreId() }).then((res) => {
setStoreTaskNum(res.result);
});
}
// 搜索条件修改 // 搜索条件修改
function queryChange(_query) { function queryChange(_query) {
setQuery({ ...query, ..._query }); setQuery({ ...query, ..._query });
...@@ -59,7 +89,7 @@ function TrainTaskPage(props) { ...@@ -59,7 +89,7 @@ function TrainTaskPage(props) {
<div className='content-header'>培训任务</div> <div className='content-header'>培训任务</div>
<div className='box'> <div className='box'>
<TrainFilter onChange={queryChange} /> <TrainFilter onChange={queryChange} />
<TrainList trainListData={trainListData} query={query} totalCount={totalCount} onChange={queryChange} /> <TrainList trainListData={trainListData} storeTaskNum={storeTaskNum} query={query} totalCount={totalCount} onChange={queryChange} />
</div> </div>
<Route path={`${match.url}/data`} component={DataCenter} /> <Route path={`${match.url}/data`} component={DataCenter} />
</div> </div>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-07-29 14:32:24 * @Date: 2021-07-29 14:32:24
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 17:46:08 * @LastEditTime: 2021-08-11 10:20:33
* @Description: 任务中心-培训任务-新建-基本信息 * @Description: 任务中心-培训任务-新建-基本信息
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -24,6 +24,9 @@ const { RangePicker } = DatePicker; ...@@ -24,6 +24,9 @@ const { RangePicker } = DatePicker;
const FormItem = Form.Item; const FormItem = Form.Item;
function BasicInfo(props) { function BasicInfo(props) {
const taskState = getParameterByName('taskState');
const type = getParameterByName('type');
const { basicInfo, startCheck } = props; const { basicInfo, startCheck } = props;
const { taskName, coverUrl, helpStoreUserIds, timeType, startTime, endTime, learnType, assignList, introduce } = basicInfo; const { taskName, coverUrl, helpStoreUserIds, timeType, startTime, endTime, learnType, assignList, introduce } = basicInfo;
const [imageFile, setImageFile] = useState(null); // 需要被截取的图片 const [imageFile, setImageFile] = useState(null); // 需要被截取的图片
...@@ -94,18 +97,21 @@ function BasicInfo(props) { ...@@ -94,18 +97,21 @@ function BasicInfo(props) {
} }
function confirmAddCollaborator(data) { function confirmAddCollaborator(data) {
const helpStoreUserIds = data.map((item) => item.userId); props.onChange('helpStoreUserIds', data);
props.onChange('helpStoreUserIds', helpStoreUserIds); }
function confirmAddAssignor(data) {
props.onChange('assignList', data);
} }
function removeSelectedCollaborator(tag, index) { function removeSelectedCollaborator(tag) {
const _helpStoreUserIds = helpStoreUserIds.filter((item) => item !== tag); const _helpStoreUserIds = helpStoreUserIds.filter((item) => item.userId !== tag);
props.onChange('helpStoreUserIds', _helpStoreUserIds); props.onChange('helpStoreUserIds', _helpStoreUserIds);
} }
function test(data) {
console.log(data); function removeCheckedAssignor(tag) {
props.onChange('introduce', data); const _assignList = assignList.filter((item) => item.id !== tag.id);
// props.onChange('introduce', data); props.onChange('assignList', _assignList);
} }
return ( return (
...@@ -148,6 +154,7 @@ function BasicInfo(props) { ...@@ -148,6 +154,7 @@ function BasicInfo(props) {
<div className='duration__wrap'> <div className='duration__wrap'>
<Radio.Group <Radio.Group
value={timeType} value={timeType}
disabled={taskState === 'STARTING'}
onChange={(e) => { onChange={(e) => {
props.onChange('timeType', e.target.value); props.onChange('timeType', e.target.value);
}}> }}>
...@@ -172,6 +179,7 @@ function BasicInfo(props) { ...@@ -172,6 +179,7 @@ function BasicInfo(props) {
}} }}
disabledDate={disabledDate} disabledDate={disabledDate}
disabledTime={disabledRangeTime} disabledTime={disabledRangeTime}
disabled={[type === 'edit' && taskState === 'STARTING', false]}
value={[startTime ? moment(Number(startTime)) : null, endTime ? moment(Number(endTime)) : null]} value={[startTime ? moment(Number(startTime)) : null, endTime ? moment(Number(endTime)) : null]}
format='YYYY-MM-DD HH:mm' format='YYYY-MM-DD HH:mm'
onChange={(date) => { onChange={(date) => {
...@@ -188,7 +196,7 @@ function BasicInfo(props) { ...@@ -188,7 +196,7 @@ function BasicInfo(props) {
</FormItem> </FormItem>
<FormItem label='学习模式' required extra={<div className='learning-model-tips'>提示:任务开始后学习模式将不允许更换</div>}> <FormItem label='学习模式' required extra={<div className='learning-model-tips'>提示:任务开始后学习模式将不允许更换</div>}>
<div className='learning-model__wrap'> <div className='learning-model__wrap'>
<Radio.Group value={learnType} onChange={(e) => props.onChange('learnType', e.target.value)}> <Radio.Group value={learnType} disabled={taskState === 'STARTING'} onChange={(e) => props.onChange('learnType', e.target.value)}>
<Space direction='vertical' size={16}> <Space direction='vertical' size={16}>
<Radio value='FREEDOM'>自由学习</Radio> <Radio value='FREEDOM'>自由学习</Radio>
<Radio value='BREAKTHROUGH_LEARNING'> <Radio value='BREAKTHROUGH_LEARNING'>
...@@ -214,7 +222,7 @@ function BasicInfo(props) { ...@@ -214,7 +222,7 @@ function BasicInfo(props) {
<FormItem <FormItem
label={ label={
<span> <span>
闯关学习 指派对象
<Tooltip title='选择员工协同完成任务指派和督学工作'> <Tooltip title='选择员工协同完成任务指派和督学工作'>
<i <i
className='icon iconfont' className='icon iconfont'
...@@ -230,7 +238,10 @@ function BasicInfo(props) { ...@@ -230,7 +238,10 @@ function BasicInfo(props) {
</Tooltip> </Tooltip>
</span> </span>
} }
required> required
// validateStatus={startCheck && assignList.length === 0 ? 'error' : ''}
// help={startCheck && assignList.length === 0 && '请选择培训时间'}>
>
<Button <Button
style={{ display: 'block' }} style={{ display: 'block' }}
onClick={() => { onClick={() => {
...@@ -238,14 +249,18 @@ function BasicInfo(props) { ...@@ -238,14 +249,18 @@ function BasicInfo(props) {
}}> }}>
添加指派对象 添加指派对象
</Button> </Button>
{assignList > 0 && ( {/* {assignList.length > 0 && (
<Space size={'12'} direction={'vertical'} className='select-obj'> <Space size={'12'} direction={'vertical'} className='select-obj'>
{assignList.length > 0 && ( {assignList.length > 0 && (
<div className='obj-type-container'> <div className='obj-type-container'>
<div className='type-title'>已选组织:</div> <div className='type-title'>已选组织:</div>
<div className='tag-box'> <div className='tag-box'>
{_.map(assignList, (item) => { {_.map(assignList, (tag) => {
return <Tag closable>{item.name}</Tag>; return (
<Tag key={tag.id} onClose={() => removeCheckedAssignor(tag)} closable>
{tag.name}
</Tag>
);
})} })}
</div> </div>
</div> </div>
...@@ -254,14 +269,18 @@ function BasicInfo(props) { ...@@ -254,14 +269,18 @@ function BasicInfo(props) {
<div className='obj-type-container'> <div className='obj-type-container'>
<div className='type-title'>已选学员:</div> <div className='type-title'>已选学员:</div>
<div className='tag-box'> <div className='tag-box'>
{_.map(assignList, (item) => { {_.map(assignList, (tag) => {
return <Tag closable>{item.name}</Tag>; return (
<Tag key={tag.id} onClose={() => removeCheckedAssignor(tag)} closable>
{tag.name}
</Tag>
);
})} })}
</div> </div>
</div> </div>
)} )}
</Space> </Space>
)} )} */}
</FormItem> </FormItem>
<FormItem <FormItem
label={ label={
...@@ -291,9 +310,9 @@ function BasicInfo(props) { ...@@ -291,9 +310,9 @@ function BasicInfo(props) {
</Button> </Button>
{helpStoreUserIds.length > 0 && ( {helpStoreUserIds.length > 0 && (
<div className='select-obj'> <div className='select-obj'>
{_.map(helpStoreUserIds, (tag, index) => { {_.map(helpStoreUserIds, (tag) => {
return ( return (
<Tag key={tag.id} onClose={() => removeSelectedCollaborator(tag, index)} closable> <Tag key={tag.userId} onClose={() => removeSelectedCollaborator(tag)} closable>
<WWOpenDataCom type='userName' openid={tag.nickName} /> <WWOpenDataCom type='userName' openid={tag.nickName} />
</Tag> </Tag>
); );
...@@ -310,8 +329,8 @@ function BasicInfo(props) { ...@@ -310,8 +329,8 @@ function BasicInfo(props) {
detail={{ detail={{
content: introduce, content: introduce,
}} }}
onChange={(val, length) => { onChange={(val) => {
test(val); props.onChange('introduce', val);
}} }}
/> />
</FormItem> </FormItem>
...@@ -343,14 +362,13 @@ function BasicInfo(props) { ...@@ -343,14 +362,13 @@ function BasicInfo(props) {
)} )}
{assignorModalVisible && ( {assignorModalVisible && (
<ChooseAssignorModal <ChooseAssignorModal
currentAssignorList={assignList}
visible={assignorModalVisible} visible={assignorModalVisible}
type='CUSTOMER' onClose={() => {
treeDepType={'DEP_CHAT'} setAssignorModalVisible(false);
close={() => {
// closeChooseMembersModal();
}} }}
onConfirm={() => { onConfirm={(data) => {
// confirmAddCustomer(); confirmAddAssignor(data);
}} }}
/> />
)} )}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-01 17:28:30 * @Date: 2021-08-01 17:28:30
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 14:25:18 * @LastEditTime: 2021-08-11 11:27:09
* @Description: 新建培训任务-关联课程抽屉 * @Description: 新建培训任务-关联课程抽屉
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -83,7 +83,7 @@ class RelatedCourseDrawer extends Component { ...@@ -83,7 +83,7 @@ class RelatedCourseDrawer extends Component {
currentPictureCourseListData: [], //页面中已关联的线上课程 currentPictureCourseListData: [], //页面中已关联的线上课程
activeKey: 'live', activeKey: 'live',
currentTaskCourseData: [], currentTaskContentData: props.data[props.selectedStageIndex].contentList || [],
}; };
} }
...@@ -97,11 +97,12 @@ class RelatedCourseDrawer extends Component { ...@@ -97,11 +97,12 @@ class RelatedCourseDrawer extends Component {
handleFetchLiveDataList = () => { handleFetchLiveDataList = () => {
const { liveQuery, liveSize } = this.state; const { liveQuery, liveSize } = this.state;
const _data = [...this.props.data]; const _data = [...this.props.data];
console.log('data=========>', _data);
let currentLiveCourseListData = []; let currentLiveCourseListData = [];
_data.map((item) => { _data.map((item) => {
item.contentList.map((childItem, childIndex) => { item.contentList.map((childItem, childIndex) => {
if (childItem.courseType === 'LIVE') { if (childItem.courseType === 'LIVE') {
currentLiveCourseListData.push(childItem.courseId); currentLiveCourseListData.push(childItem.contentId);
} }
return childItem; return childItem;
}); });
...@@ -379,14 +380,14 @@ class RelatedCourseDrawer extends Component { ...@@ -379,14 +380,14 @@ class RelatedCourseDrawer extends Component {
}; };
selectLiveList = (record, selected) => { selectLiveList = (record, selected) => {
const { selectVideo, currentTaskCourseData, selectLive, selectPicture } = this.state; const { selectVideo, currentTaskContentData, selectLive, selectPicture } = this.state;
let _list = []; let _list = [];
if (selected || !_.find(selectLive, (item) => item.liveCourseId === record.liveCourseId)) { 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 { } else {
_list = _.reject(selectLive, (item) => item.liveCourseId === record.liveCourseId); _list = _.reject(selectLive, (item) => item.liveCourseId === record.liveCourseId);
} }
if (_list.length + currentTaskCourseData.length + selectVideo.internal.length + selectVideo.external.length + selectPicture.length > 20) { if (_list.length + currentTaskContentData.length + selectVideo.internal.length + selectVideo.external.length + selectPicture.length > 20) {
message.warning('无法继续选择,一个任务最多关联20个课程'); message.warning('无法继续选择,一个任务最多关联20个课程');
return; return;
} }
...@@ -394,7 +395,7 @@ class RelatedCourseDrawer extends Component { ...@@ -394,7 +395,7 @@ class RelatedCourseDrawer extends Component {
}; };
selectVideoList = (record, selected) => { selectVideoList = (record, selected) => {
const { selectVideo, currentTaskCourseData, selectLive, selectPicture, videoCourseDivision } = this.state; const { selectVideo, currentTaskContentData, selectLive, selectPicture, videoCourseDivision } = this.state;
let { [videoCourseDivision]: selectList } = selectVideo; let { [videoCourseDivision]: selectList } = selectVideo;
let otherVideoCourseDivision = videoCourseDivision === 'internal' ? 'external' : 'internal'; let otherVideoCourseDivision = videoCourseDivision === 'internal' ? 'external' : 'internal';
...@@ -404,7 +405,7 @@ class RelatedCourseDrawer extends Component { ...@@ -404,7 +405,7 @@ class RelatedCourseDrawer extends Component {
} else { } else {
_list = _.reject(selectList, (item) => item.id === record.id); _list = _.reject(selectList, (item) => item.id === record.id);
} }
if (_list.length + selectVideo[otherVideoCourseDivision]?.length + currentTaskCourseData.length + selectLive.length + selectPicture.length > 20) { if (_list.length + selectVideo[otherVideoCourseDivision]?.length + currentTaskContentData.length + selectLive.length + selectPicture.length > 20) {
message.warning('无法继续选择,一个任务最多关联20个课程'); message.warning('无法继续选择,一个任务最多关联20个课程');
return; return;
} }
...@@ -417,14 +418,14 @@ class RelatedCourseDrawer extends Component { ...@@ -417,14 +418,14 @@ class RelatedCourseDrawer extends Component {
}; };
selectPictureList = (record, selected) => { selectPictureList = (record, selected) => {
const { selectVideo, currentTaskCourseData, selectLive, selectPicture } = this.state; const { selectVideo, currentTaskContentData, selectLive, selectPicture } = this.state;
let _list = []; let _list = [];
if (selected || !_.find(selectPicture, (item) => item.id === record.id)) { 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 { } 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.internal.length + selectVideo.external.length > 20) { if (_list.length + currentTaskContentData.length + selectLive.length + selectVideo.internal.length + selectVideo.external.length > 20) {
message.warning('无法继续选择,一个任务最多关联20个课程'); message.warning('无法继续选择,一个任务最多关联20个课程');
return; return;
} }
...@@ -485,7 +486,8 @@ class RelatedCourseDrawer extends Component { ...@@ -485,7 +486,8 @@ class RelatedCourseDrawer extends Component {
return _item; return _item;
}); });
}; };
renderFooter = () => {
renderTipFooter = () => {
const { activeKey } = this.state; const { activeKey } = this.state;
let href = ''; let href = '';
switch (activeKey) { switch (activeKey) {
...@@ -544,13 +546,14 @@ class RelatedCourseDrawer extends Component { ...@@ -544,13 +546,14 @@ class RelatedCourseDrawer extends Component {
videoSearchDefalt, videoSearchDefalt,
videoTotalCount, videoTotalCount,
selectVideo, selectVideo,
currentTaskCourseData, currentTaskContentData,
selectPicture, selectPicture,
pictureDataSource, pictureDataSource,
pictureSize, pictureSize,
pictureQuery, pictureQuery,
pictureTotalCount, pictureTotalCount,
videoCourseDivision, videoCourseDivision,
activeKey,
} = this.state; } = this.state;
return ( return (
...@@ -600,7 +603,7 @@ class RelatedCourseDrawer extends Component { ...@@ -600,7 +603,7 @@ class RelatedCourseDrawer extends Component {
</div> </div>
</div> </div>
<div className='related-box'> <div className='related-box'>
该任务已关联{currentTaskCourseData.length}个课程,可继续选择{20 - currentTaskCourseData.length} 该任务已关联{currentTaskContentData.length}个课程,可继续选择{20 - currentTaskContentData.length}
</div> </div>
</div> </div>
<div> <div>
...@@ -627,10 +630,13 @@ class RelatedCourseDrawer extends Component { ...@@ -627,10 +630,13 @@ class RelatedCourseDrawer extends Component {
} else { } 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.internal.length + selectVideo.external.length + selectPicture.length > 20) { if (
_list.length + currentTaskContentData.length + selectVideo.internal.length + selectVideo.external.length + selectPicture.length >
20
) {
message.warning('无法继续选择,一个任务最多关联20个课程'); message.warning('无法继续选择,一个任务最多关联20个课程');
const extraLength = const extraLength =
_list.length + currentTaskCourseData.length + selectVideo.internal.length + selectVideo.external.length + +selectPicture.length - 20; _list.length + currentTaskContentData.length + selectVideo.internal.length + selectVideo.external.length + +selectPicture.length - 20;
_list.splice(_list.length - extraLength, extraLength); _list.splice(_list.length - extraLength, extraLength);
} }
this.setState({ selectLive: _list }); this.setState({ selectLive: _list });
...@@ -696,7 +702,7 @@ class RelatedCourseDrawer extends Component { ...@@ -696,7 +702,7 @@ class RelatedCourseDrawer extends Component {
</div> </div>
</div> </div>
<div className='related-box'> <div className='related-box'>
该任务已关联{currentTaskCourseData.length}个课程,可继续选择{20 - currentTaskCourseData.length} 该任务已关联{currentTaskContentData.length}个课程,可继续选择{20 - currentTaskContentData.length}
</div> </div>
</div> </div>
<div> <div>
...@@ -725,14 +731,18 @@ class RelatedCourseDrawer extends Component { ...@@ -725,14 +731,18 @@ class RelatedCourseDrawer extends Component {
_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 ( if (
_list.length + selectVideo[otherVideoCourseDivision]?.length + currentTaskCourseData.length + selectLive.length + selectPicture.length > _list.length +
selectVideo[otherVideoCourseDivision]?.length +
currentTaskContentData.length +
selectLive.length +
selectPicture.length >
20 20
) { ) {
message.warning('无法继续选择,一个任务最多关联20个课程'); message.warning('无法继续选择,一个任务最多关联20个课程');
const extraLength = const extraLength =
_list.length + _list.length +
selectVideo[otherVideoCourseDivision]?.length + selectVideo[otherVideoCourseDivision]?.length +
currentTaskCourseData.length + currentTaskContentData.length +
selectLive.length + selectLive.length +
selectPicture.length - selectPicture.length -
20; 20;
...@@ -806,7 +816,7 @@ class RelatedCourseDrawer extends Component { ...@@ -806,7 +816,7 @@ class RelatedCourseDrawer extends Component {
</div> </div>
</div> </div>
<div className='related-box'> <div className='related-box'>
该任务已关联{currentTaskCourseData.length}个课程,可继续选择{20 - currentTaskCourseData.length} 该任务已关联{currentTaskContentData.length}个课程,可继续选择{20 - currentTaskContentData.length}
</div> </div>
</div> </div>
<div> <div>
...@@ -833,10 +843,10 @@ class RelatedCourseDrawer extends Component { ...@@ -833,10 +843,10 @@ class RelatedCourseDrawer extends Component {
} else { } 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.internal.length + selectVideo.external.length + selectLive.length > 20) { if (_list.length + currentTaskContentData.length + selectVideo.internal.length + selectVideo.external.length + selectLive.length > 20) {
message.warning('无法继续选择,一个任务最多关联20个课程'); message.warning('无法继续选择,一个任务最多关联20个课程');
const extraLength = const extraLength =
_list.length + currentTaskCourseData.length + selectVideo.internal.length + selectVideo.external.length + selectLive.length - 20; _list.length + currentTaskContentData.length + selectVideo.internal.length + selectVideo.external.length + selectLive.length - 20;
_list.splice(_list.length - extraLength, extraLength); _list.splice(_list.length - extraLength, extraLength);
} }
this.setState({ selectPicture: _list }); this.setState({ selectPicture: _list });
...@@ -870,6 +880,7 @@ class RelatedCourseDrawer extends Component { ...@@ -870,6 +880,7 @@ class RelatedCourseDrawer extends Component {
</Tabs> </Tabs>
</div> </div>
<div className='footer shrink-footer'> <div className='footer shrink-footer'>
{!(activeKey === 'video' && videoCourseDivision === 'external') && this.renderTipFooter()}
<Button onClick={this.props.onClose}>取消</Button> <Button onClick={this.props.onClose}>取消</Button>
<Button <Button
type='primary' type='primary'
......
...@@ -125,12 +125,11 @@ ...@@ -125,12 +125,11 @@
position: fixed; position: fixed;
right: 0; right: 0;
bottom: 0; bottom: 0;
height: 50px;
width: 720px; width: 720px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
padding-right: 24px; padding: 16px 24px;
background: #fff; background: #fff;
border-top: 1px solid #e8e8e8; border-top: 1px solid #e8e8e8;
z-index: 9999; z-index: 9999;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-03 17:05:32 * @Date: 2021-08-03 17:05:32
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 14:36:05 * @LastEditTime: 2021-08-11 11:49:11
* @Description: 新建培训任务-关联考试抽屉 * @Description: 新建培训任务-关联考试抽屉
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -20,7 +20,6 @@ import Bus from '@/core/bus'; ...@@ -20,7 +20,6 @@ import Bus from '@/core/bus';
function RelatedExamDrawer(props) { function RelatedExamDrawer(props) {
const [showPaperModal, setShowPaperModal] = useState(false); const [showPaperModal, setShowPaperModal] = useState(false);
const [paperInfo, setPaperInfo] = useState({}); const [paperInfo, setPaperInfo] = useState({});
const [basicInfo, setBasicInfo] = useState(props.basicInfo);
const [answerAnalysis, setAnswerAnalysis] = useState('RIGHT_OR_WRONG'); // 答案与解析-默认仅显示对错 const [answerAnalysis, setAnswerAnalysis] = useState('RIGHT_OR_WRONG'); // 答案与解析-默认仅显示对错
const [examDesc, setExamDesc] = useState(''); // 考试说明 const [examDesc, setExamDesc] = useState(''); // 考试说明
const [examDuration, setExamDuration] = useState(null); // 考试时长 const [examDuration, setExamDuration] = useState(null); // 考试时长
...@@ -36,6 +35,8 @@ function RelatedExamDrawer(props) { ...@@ -36,6 +35,8 @@ function RelatedExamDrawer(props) {
const [check, setCheck] = useState(false); const [check, setCheck] = useState(false);
const [examTotal, setExamTotal] = useState(0); const [examTotal, setExamTotal] = useState(0);
const [samePaper, setSamePaper] = useState(false);
const request = useRef(false); const request = useRef(false);
useEffect(() => { useEffect(() => {
...@@ -55,11 +56,6 @@ function RelatedExamDrawer(props) { ...@@ -55,11 +56,6 @@ function RelatedExamDrawer(props) {
setExamTotal(paperInfo.singleChoiceCnt + paperInfo.multiChoiceCnt + paperInfo.judgeCnt + paperInfo.gapFillingCnt + paperInfo.indefiniteChoiceCnt || 0); setExamTotal(paperInfo.singleChoiceCnt + paperInfo.multiChoiceCnt + paperInfo.judgeCnt + paperInfo.gapFillingCnt + paperInfo.indefiniteChoiceCnt || 0);
}, [paperInfo.paperId, passRate]); }, [paperInfo.paperId, passRate]);
function disabledDate(current) {
// Can not select days before today and today
return current && current < moment().startOf('day');
}
function handleSave() { function handleSave() {
if (request.current) { if (request.current) {
return; return;
...@@ -75,23 +71,28 @@ function RelatedExamDrawer(props) { ...@@ -75,23 +71,28 @@ function RelatedExamDrawer(props) {
resultShow, resultShow,
resultContent, resultContent,
answerAnalysis, answerAnalysis,
examEndTime: basicInfo.endTime, examEndTime: props.basicInfo.endTime || null,
examStartTime: basicInfo.startTime || new Date().valueOf(), // 新建(永久)取当前时间,固定取培训开始,编辑取培训创建的时间 examStartTime: props.basicInfo.startTime || new Date().valueOf(),
passScore, passScore,
source: 0, source: 0,
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
userId: User.getStoreUserId(), userId: User.getStoreUserId(),
}; };
console.log('sfkajsdfiohasiudfhaiusdfhiaus', params); console.log('新建入参==============>', params);
if ( if (
!paperId || !paperId ||
samePaper ||
!examName || !examName ||
examName.length > 40 || examName.length > 40 ||
!passRate || !passRate ||
!examDuration || !examDuration ||
editorTextLength > 1000 || editorTextLength > 1000 ||
(basicInfo.timeType === 'VALIDITY' && basicInfo.startTime && basicInfo.endTime && basicInfo.startTime + examDuration * 60 * 1000 > basicInfo.endTime) (props.basicInfo.timeType === 'VALIDITY' &&
props.basicInfo.startTime &&
props.basicInfo.endTime &&
props.basicInfo.startTime + examDuration * 60 * 1000 > props.basicInfo.endTime)
) { ) {
return; return;
} }
...@@ -102,7 +103,7 @@ function RelatedExamDrawer(props) { ...@@ -102,7 +103,7 @@ function RelatedExamDrawer(props) {
}, 2000); }, 2000);
TaskCenterService.createTrainingExam(params).then((res) => { TaskCenterService.createTrainingExam(params).then((res) => {
console.log(res); props.onSave(res.result);
}); });
} }
...@@ -110,7 +111,11 @@ function RelatedExamDrawer(props) { ...@@ -110,7 +111,11 @@ function RelatedExamDrawer(props) {
<Drawer title='添加考试' width={720} maskClosable={false} closable={true} onClose={props.onClose} visible={true} mask className='related-exam-drawer'> <Drawer title='添加考试' width={720} maskClosable={false} closable={true} onClose={props.onClose} visible={true} mask className='related-exam-drawer'>
<Form labelCol={{ span: 4 }} wrapperCol={{ span: 20 }} layout='horizontal'> <Form labelCol={{ span: 4 }} wrapperCol={{ span: 20 }} layout='horizontal'>
<div className='module-title'>基本信息</div> <div className='module-title'>基本信息</div>
<Form.Item label='选择试卷' validateStatus={check && !paperId ? 'error' : ''} help={check && !paperId && '请选择试卷'} required> <Form.Item
label='选择试卷'
validateStatus={(check && !paperId) || samePaper ? 'error' : ''}
help={(check && !paperId && '请选择试卷') || (samePaper && '已存在相同试卷')}
required>
<Button <Button
onClick={() => { onClick={() => {
setShowPaperModal(true); setShowPaperModal(true);
...@@ -199,20 +204,20 @@ function RelatedExamDrawer(props) { ...@@ -199,20 +204,20 @@ function RelatedExamDrawer(props) {
validateStatus={ validateStatus={
check && check &&
(!examDuration || (!examDuration ||
(basicInfo.timeType === 'VALIDITY' && (props.basicInfo.timeType === 'VALIDITY' &&
basicInfo.startTime && props.basicInfo.startTime &&
basicInfo.endTime && props.basicInfo.endTime &&
basicInfo.startTime + examDuration * 60 * 1000 > basicInfo.endTime)) props.basicInfo.startTime + examDuration * 60 * 1000 > props.basicInfo.endTime))
? 'error' ? 'error'
: '' : ''
} }
help={ help={
check && check &&
((!examDuration && '请输入考试时长') || ((!examDuration && '请输入考试时长') ||
(basicInfo.timeType === 'VALIDITY' && (props.basicInfo.timeType === 'VALIDITY' &&
basicInfo.startTime && props.basicInfo.startTime &&
basicInfo.endTime && props.basicInfo.endTime &&
basicInfo.startTime + examDuration * 60 * 1000 > basicInfo.endTime && props.basicInfo.startTime + examDuration * 60 * 1000 > props.basicInfo.endTime &&
'考试时长不得超过培训有效期时长')) '考试时长不得超过培训有效期时长'))
} }
required> required>
...@@ -300,6 +305,17 @@ function RelatedExamDrawer(props) { ...@@ -300,6 +305,17 @@ function RelatedExamDrawer(props) {
{showPaperModal && ( {showPaperModal && (
<SelectPaperModal <SelectPaperModal
onSelect={(info) => { onSelect={(info) => {
const contentList = props.stageList.map((item) => {
return item.contentList;
});
const existedPaperId = contentList.flat().filter((item) => {
return item.paperId === info.paperId;
});
if (existedPaperId.length > 0) {
setSamePaper(true);
} else {
setSamePaper(false);
}
setPaperInfo(info); setPaperInfo(info);
}} }}
paperInfo={paperInfo} paperInfo={paperInfo}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-07-30 16:33:58 * @Date: 2021-07-30 16:33:58
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 13:56:24 * @LastEditTime: 2021-08-11 13:33:44
* @Description: 任务中心-培训任务-新建-培训内容 * @Description: 任务中心-培训任务-新建-培训内容
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -64,85 +64,7 @@ class TrainContent extends Component { ...@@ -64,85 +64,7 @@ class TrainContent extends Component {
}; };
} }
componentDidMount() { componentDidMount() {}
// if (type === 'edit') {
// this.getPlanDetail();
// this.getPlanCustomerState();
// }
// Bus.bind('editorLimit', (editorTextLength) => {
// setEditorTextLength(editorTextLength);
// });
}
getPlanDetail = () => {
PlanService.getTrainingPlanDetail({
planId: id,
}).then((res) => {
const {
planId,
planName,
enableState,
operateType,
operateIds,
percentCompleteLive,
percentCompleteVideo,
percentCompletePicture,
courseMediaVOS,
trainingTaskList,
} = res.result;
let coverId;
let coverUrl;
let instro;
let hasIntro = false;
courseMediaVOS.map((item) => {
switch (item.contentType) {
case 'COVER':
coverId = item.mediaContent;
coverUrl = item.mediaUrl;
break;
case 'INTRO':
hasIntro = true;
instro = item.mediaContent;
break;
default:
break;
}
return item;
});
let _selectOperatorList = [];
if (operateIds) {
_selectOperatorList = operateIds.map((item, index) => {
let _item = {};
_item.id = item;
return _item;
});
}
setTaskList(trainingTaskList);
setBasicData({
planId,
planName,
coverUrl: coverUrl || defaultCover,
coverId,
enableState,
selectOperatorList: _selectOperatorList,
instro,
operateType,
percentCompleteLive,
percentCompleteVideo,
percentCompletePicture,
});
setHasGetDetail(true);
});
};
getPlanCustomerState = () => {
PlanService.getTrainingCourseAutoCancel({
planId: id,
}).then((res) => {
const expiredCourseList = res.result;
this.setState({ expiredCourseList });
});
};
setTrianTypeOption = (index) => { setTrianTypeOption = (index) => {
return ( return (
...@@ -196,8 +118,7 @@ class TrainContent extends Component { ...@@ -196,8 +118,7 @@ class TrainContent extends Component {
} }
}; };
handleRenameStageName = (e, item) => { handleRenameStageName = (value, item) => {
const { value } = e.target;
const { stageList } = this.state; const { stageList } = this.state;
item.stageName = value; item.stageName = value;
item.check = true; item.check = true;
...@@ -211,9 +132,15 @@ class TrainContent extends Component { ...@@ -211,9 +132,15 @@ class TrainContent extends Component {
); );
}; };
handleStageNameBlur = (e, item) => { handleStageNameBlur = (e, item, currentIndex) => {
const { value } = e.target; const { value } = e.target;
const { stageList } = this.state; const { stageList } = this.state;
const sameStageName = stageList.filter((item, index) => {
return item.stageName === value && index !== currentIndex;
});
if (sameStageName.length > 0) {
return;
}
let input = /^[\s]*$/; let input = /^[\s]*$/;
if (value && !input.test(value)) { if (value && !input.test(value)) {
item.type = 'text'; item.type = 'text';
...@@ -271,6 +198,36 @@ class TrainContent extends Component { ...@@ -271,6 +198,36 @@ class TrainContent extends Component {
); );
}; };
handleDeleteCourse = (parentIndex, index) => {
return confirm({
title: '删除学习内容',
content: '确定删除该学习内容吗?',
icon: <span className='icon iconfont default-confirm-icon'>&#xe839; </span>,
okText: '删除',
okType: 'danger',
cancelText: '取消',
onOk: () => {
this.handleConfirmDeleteCourse(parentIndex, index);
},
});
};
handleConfirmDeleteCourse = (parentIndex, index) => {
const { stageList } = this.state;
const _stageList = [...stageList];
const selectData = [..._stageList[parentIndex].contentList];
selectData.splice(index, 1);
_stageList[parentIndex].contentList = selectData;
this.setState(
{
stageList: _stageList,
},
() => {
this.props.onChange(_stageList);
}
);
};
renderStageInfo = (item, index) => { renderStageInfo = (item, index) => {
const { startCheck } = this.props; const { startCheck } = this.props;
return ( return (
...@@ -291,10 +248,10 @@ class TrainContent extends Component { ...@@ -291,10 +248,10 @@ class TrainContent extends Component {
maxLength={20} maxLength={20}
value={item.stageName} value={item.stageName}
onChange={(e) => { onChange={(e) => {
this.handleRenameStageName(e, item); this.handleRenameStageName(e.target.value, item);
}} }}
onBlur={(e) => { onBlur={(e) => {
this.handleStageNameBlur(e, item); this.handleStageNameBlur(e, item, index);
}} }}
/> />
</Form.Item> </Form.Item>
...@@ -356,16 +313,16 @@ class TrainContent extends Component { ...@@ -356,16 +313,16 @@ class TrainContent extends Component {
}; };
renderContentItem = (record, index, parentIndex) => { renderContentItem = (record, index, parentIndex) => {
const { courseState, courseName, courseType, courseChapterNum } = record; const { courseState, contentName, contentType, courseType, courseChapterNum } = record;
return ( return (
<div className='sort-content-item'> <div className='sort-content-item'>
<div className='content-info'> <div className='content-info'>
<img className='type-option-icon' src={ENUM.LearningContentIcon[courseType]} /> <img className='type-option-icon' src={ENUM.LearningContentIcon[courseType || contentType]} />
<span className='content-name'> <span className='content-name'>
{parentIndex + 1}.{index + 1} {courseName} {parentIndex + 1}.{index + 1} {contentName}
</span> </span>
{courseState === 'EXPIRED' && <span className='icon iconfont tip'>&#xe834;</span>} {courseState === 'EXPIRED' && <span className='icon iconfont tip'>&#xe834;</span>}
{courseType === 'LIVE' && <span className='extra-info'>{courseStateShow[record.courseState].title}</span>} {courseType === 'LIVE' && <span className='extra-info'>{courseStateShow[courseState].title}</span>}
{courseType === 'VOICE' && <span className='extra-info'>(共{courseChapterNum || 1}小节)</span>} {courseType === 'VOICE' && <span className='extra-info'>(共{courseChapterNum || 1}小节)</span>}
</div> </div>
<div className='content-operate'> <div className='content-operate'>
...@@ -388,9 +345,7 @@ class TrainContent extends Component { ...@@ -388,9 +345,7 @@ class TrainContent extends Component {
const { stageList } = this.state; const { stageList } = this.state;
const stageObj = { const stageObj = {
stageName: '', stageName: '',
index: stageList.length,
type: 'input', type: 'input',
open: true,
contentList: [], contentList: [],
check: false, check: false,
}; };
...@@ -422,7 +377,17 @@ class TrainContent extends Component { ...@@ -422,7 +377,17 @@ class TrainContent extends Component {
const { stageList } = this.state; const { stageList } = this.state;
const _stageList = [...stageList]; const _stageList = [...stageList];
const selectData = [..._stageList[selectedStageIndex].contentList]; const selectData = [..._stageList[selectedStageIndex].contentList];
const _selectData = [...selectData, ...selectList]; let _selectList = [];
selectList.forEach((item) => {
_selectList.push({
contentId: item.courseId,
contentName: item.courseName,
contentType: 'COURSE',
courseType: item.courseType,
courseState: item.courseState,
});
});
const _selectData = [...selectData, ..._selectList];
_stageList[selectedStageIndex].contentList = _selectData; _stageList[selectedStageIndex].contentList = _selectData;
this.setState( this.setState(
{ {
...@@ -430,24 +395,34 @@ class TrainContent extends Component { ...@@ -430,24 +395,34 @@ class TrainContent extends Component {
stageList: _stageList, stageList: _stageList,
}, },
() => { () => {
console.log('_stageList=============>', _stageList);
this.props.onChange('stageList', _stageList); this.props.onChange('stageList', _stageList);
} }
); );
}; };
percentCompleteBlur = (e, field) => { confirmCreateExam = (examInfo) => {
let _percentCompleteLive; const { selectedStageIndex } = this.state;
const { value } = e.target; const { stageList } = this.state;
if (value > 100) { const _stageList = [...stageList];
_percentCompleteLive = 100; const selectData = [..._stageList[selectedStageIndex].contentList];
} else { const _examInfo = {
if (value < 0) { contentId: examInfo.examId,
_percentCompleteLive = 0; contentName: examInfo.examName,
} else { contentType: 'EXAM',
_percentCompleteLive = value; paperId: examInfo.paperId,
} };
selectData.push(_examInfo);
_stageList[selectedStageIndex].contentList = selectData;
this.setState(
{
showExamDrawer: false,
stageList: _stageList,
},
() => {
this.props.onChange('stageList', _stageList);
} }
this.props.onChange(field, _percentCompleteLive); );
}; };
changePercentComplete = (e, field) => { changePercentComplete = (e, field) => {
...@@ -477,7 +452,8 @@ class TrainContent extends Component { ...@@ -477,7 +452,8 @@ class TrainContent extends Component {
}; };
render() { render() {
const { stageList, showCourseDrawer, showExamDrawer, expiredCourseList, showStandardDetail, finishStandard, basicInfo } = this.state; const { stageList, showCourseDrawer, showExamDrawer, expiredCourseList, showStandardDetail, finishStandard, basicInfo, selectedStageIndex } = this.state;
console.log('finishStandard==================>', finishStandard);
const { percentCompleteLive, percentCompleteVideo, percentCompletePicture } = finishStandard; const { percentCompleteLive, percentCompleteVideo, percentCompletePicture } = finishStandard;
const { startCheck } = this.props; const { startCheck } = this.props;
...@@ -495,23 +471,30 @@ class TrainContent extends Component { ...@@ -495,23 +471,30 @@ class TrainContent extends Component {
+ 添加阶段 + 添加阶段
</div> </div>
)} )}
{showCourseDrawer && <RelatedCourseDrawer data={stageList} onClose={this.onCloseCourseDrawer} onSelect={this.confirmSelectCourse} />} {showCourseDrawer && (
{showExamDrawer && <RelatedExamDrawer basicInfo={basicInfo} onClose={this.onCloseExamDrawer} />} <RelatedCourseDrawer
data={stageList}
selectedStageIndex={selectedStageIndex}
onClose={this.onCloseCourseDrawer}
onSelect={this.confirmSelectCourse}
/>
)}
{showExamDrawer && <RelatedExamDrawer basicInfo={basicInfo} stageList={stageList} onClose={this.onCloseExamDrawer} onSave={this.confirmCreateExam} />}
</div> </div>
{window.getParameterByName('type') === 'edit' && expiredCourseList.length > 0 && (
<div className='expired-info__wrap'> <div className='expired-info__wrap'>
<div className='module-title'>失效课程</div> <div className='module-title'>失效课程</div>
<ExpiredCourseList expiredCourseList={expiredCourseList} /> <ExpiredCourseList expiredCourseList={expiredCourseList} />
</div> </div>
)}
<div className='finish-standard__warp'> <div className='finish-standard__warp'>
<div className='module-title'> <div
高级设置 className='module-title'
<span
className={`icon iconfont ${showStandardDetail && 'rotate-arrow'}`}
onClick={() => { onClick={() => {
this.setState({ showStandardDetail: !showStandardDetail }); this.setState({ showStandardDetail: !showStandardDetail });
}}> }}>
&#xe614; 高级设置
</span> <span className={`icon iconfont ${showStandardDetail && 'rotate-arrow'}`}>&#xe614;</span>
</div> </div>
{showStandardDetail && ( {showStandardDetail && (
<div className='detail-container'> <div className='detail-container'>
...@@ -523,7 +506,9 @@ class TrainContent extends Component { ...@@ -523,7 +506,9 @@ class TrainContent extends Component {
</span> </span>
<span> <span>
直播课单个课程,学员学习进度达到 直播课单个课程,学员学习进度达到
<FormItem validateStatus={startCheck && !percentCompleteLive ? 'error' : ''} help={startCheck && !percentCompleteLive && '请输入完成标准'}> <FormItem
validateStatus={startCheck && percentCompleteLive === '' ? 'error' : ''}
help={startCheck && percentCompleteLive === '' && '请输入完成标准'}>
<Input <Input
value={percentCompleteLive} value={percentCompleteLive}
onChange={(e) => { onChange={(e) => {
...@@ -540,8 +525,8 @@ class TrainContent extends Component { ...@@ -540,8 +525,8 @@ class TrainContent extends Component {
<span> <span>
线上课单个课节,学员学习进度达到 线上课单个课节,学员学习进度达到
<FormItem <FormItem
validateStatus={startCheck && !percentCompleteVideo ? 'error' : ''} validateStatus={startCheck && percentCompleteVideo === '' ? 'error' : ''}
help={startCheck && !percentCompleteVideo && '请输入完成标准'}> help={startCheck && percentCompleteVideo === '' && '请输入完成标准'}>
<Input <Input
value={percentCompleteVideo} value={percentCompleteVideo}
onChange={(e) => { onChange={(e) => {
...@@ -558,8 +543,8 @@ class TrainContent extends Component { ...@@ -558,8 +543,8 @@ class TrainContent extends Component {
<span> <span>
图文课单个课程,学员学习进度达到 图文课单个课程,学员学习进度达到
<FormItem <FormItem
validateStatus={startCheck && !percentCompletePicture ? 'error' : ''} validateStatus={startCheck && percentCompletePicture === '' ? 'error' : ''}
help={startCheck && !percentCompletePicture && '请输入完成标准'}> help={startCheck && percentCompletePicture === '' && '请输入完成标准'}>
<Input <Input
value={percentCompletePicture} value={percentCompletePicture}
onChange={(e) => { onChange={(e) => {
......
...@@ -23,18 +23,19 @@ ...@@ -23,18 +23,19 @@
} }
.finish-standard__warp { .finish-standard__warp {
margin-top: 24px; margin-top: 24px;
.module-title { .module-title {
height: 22px; height: 22px;
font-size: 16px; font-size: 16px;
color: #333333; color: #333333;
line-height: 22px; line-height: 22px;
cursor: pointer;
.icon { .icon {
font-size: 12px; font-size: 12px;
margin-left: 8px; margin-left: 8px;
color: #5e606a; color: #5e606a;
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
cursor: pointer;
} }
.rotate-arrow { .rotate-arrow {
transform: (rotate(180deg)); transform: (rotate(180deg));
......
...@@ -2,17 +2,21 @@ ...@@ -2,17 +2,21 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-07-28 14:56:52 * @Date: 2021-07-28 14:56:52
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 11:13:14 * @LastEditTime: 2021-08-11 11:01:49
* @Description: 描述一下咯 * @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Route, withRouter } from 'react-router-dom'; import { Route, withRouter } from 'react-router-dom';
import { Tooltip, Checkbox, Dropdown, Radio, Button, Space, Badge } from 'antd'; import { Tooltip, Checkbox, Dropdown, Radio, Button, Space, Modal, message } from 'antd';
import './TrainList.less'; import './TrainList.less';
import { XMTable, PageControl } from '@/components'; import { XMTable, PageControl } from '@/components';
import User from '@/common/js/user'; import User from '@/common/js/user';
import ENUM from '../../enum'; import ENUM from '../../enum';
import TaskCenterService from '@/domains/task-center-domain/TaskCenterService';
import ShareTrainTaskModal from '../modal/ShareTrainTaskModal';
import { LIVE_SHARE } from '@/domains/course-domain/constants';
import Bus from '@/core/bus';
function TrainList(props) { function TrainList(props) {
const { const {
...@@ -21,14 +25,110 @@ function TrainList(props) { ...@@ -21,14 +25,110 @@ function TrainList(props) {
match, match,
} = props; } = props;
const [shareTrainTaskModal, setShareTrainTaskModal] = useState(null);
// 发布或取消发布培训任务
function updateIssueStateTrain(taskId, issueState) {
Modal.confirm({
title: '提示',
content:
issueState === 'YES'
? '发布后,被指派学员将任务列表中看到该任务,确定要发布?'
: '取消发布后,任务对学员暂不可见,可能会影响正在学习学员,确定要取消?',
okText: '确定',
cancelText: '取消',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
TaskCenterService.updateIssueStateTraining({
taskId,
issueState,
}).then((res) => {
message.success(issueState === 'YES' ? '发布成功' : '取消发布成功');
Bus.trigger('getTrainingTaskPage');
Bus.trigger('getStoreTaskNum');
});
},
});
}
// 删除培训任务
function deleteTrainTask(taskId) {
Modal.confirm({
title: '你确定要删除吗?',
content: '删除后,此培训任务的用户将无法继续学习,所有学习数据将同步删除不可恢复',
okText: '确定',
cancelText: '取消',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
TaskCenterService.deleteTrainingTask({
taskId,
}).then((res) => {
message.success('删除成功');
Bus.trigger('getTrainingTaskPage');
Bus.trigger('getStoreTaskNum');
});
},
});
}
// 编辑培训任务-跳转新建/编辑页
function editTrainingTask(item) {
window.RCHistory.push({
pathname: `/create-train-task?type=edit&taskId=${item.taskId}&taskState=${item.taskState}`,
});
}
// 显示分享弹窗
function handleShowShareModal(item) {
const htmlUrl = `${LIVE_SHARE}training_task_detail/${item.taskId}?id=${User.getStoreId()}&storeUserId=${User.getStoreUserId()}`;
const longUrl = htmlUrl;
const shareData = { ...item, longUrl };
const shareTrainTaskModal = (
<ShareTrainTaskModal
data={shareData}
type='liveClass'
close={() => {
setShareTrainTaskModal(null);
}}
/>
);
setShareTrainTaskModal(shareTrainTaskModal);
}
function renderMoreOperate(item) { function renderMoreOperate(item) {
const isUnableIssue = item.issueState === 'YES'; // 已发布
const isUnableAbleEdit = item.issueState === 'YES' || item.taskState === 'FINISH'; // 已发布或已结束
const isUnableShare = item.issueState === 'NO' || item.taskState === 'FINISH'; //未发布或已结束
return ( return (
<div className='live-course-more-menu'> <div className='live-course-more-menu'>
<div className='operate__item'>取消发布</div> {!isUnableIssue && (
<div className='operate__item'>编辑</div> <div className='operate__item' onClick={() => updateIssueStateTrain(item.taskId, 'YES')}>
<div className='operate__item'>分享</div> 发布
<div className='operate__item'>审批作业</div> </div>
<div className='operate__item'>删除 </div> )}
{isUnableIssue && (
<div className='operate__item' onClick={() => updateIssueStateTrain(item.taskId, 'NO')}>
取消发布
</div>
)}
<div
className={`operate__item ${isUnableAbleEdit && 'disabled'} `}
onClick={() => {
editTrainingTask(item);
}}>
编辑
</div>
<div className={`operate__item ${isUnableShare && 'disabled'} `} onClick={() => handleShowShareModal(item)}>
分享
</div>
{/* <div className='operate__item'>审批作业</div> */}
<div
className='operate__item'
onClick={() => {
deleteTrainTask(item.taskId);
}}>
删除
</div>
</div> </div>
); );
} }
...@@ -132,7 +232,7 @@ function TrainList(props) { ...@@ -132,7 +232,7 @@ function TrainList(props) {
}, },
{ {
title: '培训时间', title: '培训时间',
width: '14%', width: '12.5%',
key: 'trainTime', key: 'trainTime',
dataIndex: 'trainTime', dataIndex: 'trainTime',
render: (val, record) => { render: (val, record) => {
...@@ -140,7 +240,7 @@ function TrainList(props) { ...@@ -140,7 +240,7 @@ function TrainList(props) {
return <span>不限时</span>; return <span>不限时</span>;
} }
return ( return (
<span style={{ whiteSpace: 'nowrap' }}> <span>
{window.formatDate('YYYY-MM-DD H:i', record.startTime)}~{window.formatDate('YYYY-MM-DD H:i', record.endTime)} {window.formatDate('YYYY-MM-DD H:i', record.startTime)}~{window.formatDate('YYYY-MM-DD H:i', record.endTime)}
</span> </span>
); );
...@@ -194,9 +294,9 @@ function TrainList(props) { ...@@ -194,9 +294,9 @@ function TrainList(props) {
</div> </div>
<span className='split'> | </span> <span className='split'> | </span>
<div <div
className='operate__item' className={`operate__item ${record.taskState === 'FINISH' && 'disabled'} `}
onClick={() => { onClick={() => {
handleShowShareModal(record); // handleShowShareModal(record);
}}> }}>
指派 指派
</div> </div>
...@@ -305,12 +405,12 @@ function TrainList(props) { ...@@ -305,12 +405,12 @@ function TrainList(props) {
onChange={(e) => { onChange={(e) => {
handleChangeQuery('issueState', e.target.value); handleChangeQuery('issueState', e.target.value);
}}> }}>
<Radio.Button value='ALL'>全部(2)</Radio.Button> <Radio.Button value='ALL'>全部({props.storeTaskNum.allNum})</Radio.Button>
<Radio.Button value='YES'>已发布(2)</Radio.Button> <Radio.Button value='YES'>已发布({props.storeTaskNum.issueNum})</Radio.Button>
<Radio.Button value='NO'>未发布(10)</Radio.Button> <Radio.Button value='NO'>未发布({props.storeTaskNum.notIssueNum})</Radio.Button>
</Radio.Group> </Radio.Group>
<Checkbox style={{ lineHeight: '32px' }} value={myAssist} onChange={(e) => handleChangeQuery('myAssist', e.target.checked)}> <Checkbox style={{ lineHeight: '32px' }} value={myAssist} onChange={(e) => handleChangeQuery('myAssist', e.target.checked)}>
只看我协同的 ({10}) 只看我协同的 ({props.storeTaskNum.myAssistNum})
</Checkbox> </Checkbox>
</Space> </Space>
</div> </div>
...@@ -342,6 +442,7 @@ function TrainList(props) { ...@@ -342,6 +442,7 @@ function TrainList(props) {
/> />
</div> </div>
</div> </div>
{shareTrainTaskModal}
</div> </div>
); );
} }
......
...@@ -109,3 +109,9 @@ ...@@ -109,3 +109,9 @@
} }
} }
} }
.disabled {
color: #ccc !important;
cursor: not-allowed !important;
pointer-events: none !important;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-05 17:09:36 * @Date: 2021-08-05 17:09:36
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-06 17:23:31 * @LastEditTime: 2021-08-10 20:21:36
* @Description: 新建培训任务-选择指派对象 * @Description: 新建培训任务-选择指派对象
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -21,6 +21,7 @@ import StoreService from '@/domains/store-domain/storeService'; ...@@ -21,6 +21,7 @@ import StoreService from '@/domains/store-domain/storeService';
// import SearchUser from '../components/SearchUser'; // import SearchUser from '../components/SearchUser';
import WWOpenDataCom from '@/components/WWOpenDataCom'; import WWOpenDataCom from '@/components/WWOpenDataCom';
import './ChooseAssignorModal.less'; import './ChooseAssignorModal.less';
import Item from 'antd/lib/list/Item';
// import _ from 'underscore'; // import _ from 'underscore';
const { Search } = Input; const { Search } = Input;
...@@ -30,6 +31,8 @@ const { DirectoryTree } = Tree; ...@@ -30,6 +31,8 @@ const { DirectoryTree } = Tree;
function ChooseAssignorModal(props) { function ChooseAssignorModal(props) {
const [structureData, setStructureData] = useState([]); const [structureData, setStructureData] = useState([]);
const [activeKey, setActiveKey] = useState('departMentTab'); const [activeKey, setActiveKey] = useState('departMentTab');
const [checkedAssignorList, setCheckedAssignorList] = useState(props.currentAssignorList || []); // 勾选的指派对象
const [checkedAssignorKeys, setCheckedAssignorKeys] = useState(props.currentAssignorList.map((item) => item.id) || []);
useEffect(() => { useEffect(() => {
getStructureData(); getStructureData();
...@@ -53,6 +56,9 @@ function ChooseAssignorModal(props) { ...@@ -53,6 +56,9 @@ function ChooseAssignorModal(props) {
function handleStructureData(dataArray) { function handleStructureData(dataArray) {
const _dataArray = dataArray.map((item, index) => { const _dataArray = dataArray.map((item, index) => {
item.key = item.id; item.key = item.id;
if (item.depLevel === 0) {
item.disableCheckbox = true;
}
if (item.sonDepartmentVOList) { if (item.sonDepartmentVOList) {
item.children = item.sonDepartmentVOList; item.children = item.sonDepartmentVOList;
handleStructureData(item.sonDepartmentVOList); handleStructureData(item.sonDepartmentVOList);
...@@ -62,17 +68,40 @@ function ChooseAssignorModal(props) { ...@@ -62,17 +68,40 @@ function ChooseAssignorModal(props) {
return _dataArray; return _dataArray;
} }
function onSelectAssignor(value) {} function onCheckAssignor(key, e) {
const { node, checked } = e;
let _checkedAssignorList = [...checkedAssignorList];
if (checked) {
_checkedAssignorList.push(node);
} else {
_checkedAssignorList = checkedAssignorList.filter((item) => item.id !== node.id);
}
const _checkedAssignorKeys = _checkedAssignorList.map((item) => item.id);
setCheckedAssignorKeys(_checkedAssignorKeys);
setCheckedAssignorList(_checkedAssignorList);
}
function removeCheckedAssignor(item) {
const _checkedAssignorList = checkedAssignorList.filter((innerItem) => innerItem.id !== item.id);
const _checkedAssignorKeys = _checkedAssignorList.map((item) => item.id);
setCheckedAssignorKeys(_checkedAssignorKeys);
setCheckedAssignorList(_checkedAssignorList);
}
function clearCheckedAssignor() {
setCheckedAssignorKeys([]);
setCheckedAssignorList([]);
}
return ( return (
<Modal <Modal
className='choose-assignor-modal' className='choose-assignor-modal'
title='添加指派对象' title='添加指派对象'
visible={true} visible={true}
// onCancel={props.onClose} onCancel={props.onClose}
onOk={() => { onOk={() => {
// props.onConfirm(seletedAssignorList); props.onConfirm(checkedAssignorList);
// props.onClose(); props.onClose();
}} }}
width={680} width={680}
maskClosable={false}> maskClosable={false}>
...@@ -97,8 +126,8 @@ function ChooseAssignorModal(props) { ...@@ -97,8 +126,8 @@ function ChooseAssignorModal(props) {
checkable checkable
showIcon={false} showIcon={false}
treeData={structureData} treeData={structureData}
// selectedKeys={selectedKeys} checkedKeys={checkedAssignorKeys}
onSelect={onSelectAssignor} onCheck={(key, e) => onCheckAssignor(key, e)}
titleRender={(nodeData) => { titleRender={(nodeData) => {
return ( return (
<div className='node-title-div'> <div className='node-title-div'>
...@@ -124,11 +153,27 @@ function ChooseAssignorModal(props) { ...@@ -124,11 +153,27 @@ function ChooseAssignorModal(props) {
<div className='right-list'> <div className='right-list'>
<div className='header-line'> <div className='header-line'>
<span className='tip-text'>已选择</span> <span className='tip-text'>已选择</span>
<span className='clear-btn' onClick={() => {}}> <span className='clear-btn' onClick={clearCheckedAssignor}>
清空 清空
</span> </span>
</div> </div>
<div className='data-body'></div> <div className='data-body'>
{checkedAssignorList.map((item, index) => {
return (
<div className='selected-item'>
<span className='item-name'>
<span className='icon iconfont avatar-icon'>&#xe84a;</span>
<Tooltip title={item.name}>
<span className='name-text'>{item.name}</span>
</Tooltip>
</span>
<span className='icon iconfont clear-icon' onClick={() => removeCheckedAssignor(item)}>
&#xe717;
</span>
</div>
);
})}
</div>
</div> </div>
</div> </div>
</Modal> </Modal>
......
...@@ -89,7 +89,7 @@ ...@@ -89,7 +89,7 @@
padding: 12px 12px 12px 16px; padding: 12px 12px 12px 16px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.user-name { .item-name {
width: 80%; width: 80%;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
......
...@@ -207,10 +207,10 @@ function ChooseCollaboratorModal(props) { ...@@ -207,10 +207,10 @@ function ChooseCollaboratorModal(props) {
{seletedCollaboratorList.map((item, index) => { {seletedCollaboratorList.map((item, index) => {
return ( return (
<div className='selected-item'> <div className='selected-item'>
<span className='user-name'> <span className='item-name'>
<span className='icon iconfont avatar-icon'>&#xe84a;</span> <span className='icon iconfont avatar-icon'>&#xe84a;</span>
<Tooltip title={<WWOpenDataCom type='userName' openid={item.nickName} />}> <Tooltip title={<WWOpenDataCom type='userName' openid={item.nickName} />}>
<span className='user-name'> <span className='name-text'>
<WWOpenDataCom type='userName' openid={item.nickName} /> <WWOpenDataCom type='userName' openid={item.nickName} />
</span> </span>
</Tooltip> </Tooltip>
......
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
padding: 12px 12px 12px 16px; padding: 12px 12px 12px 16px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.user-name { .item-name {
width: 80%; width: 80%;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
......
/*
* @Author: 吴文洁
* @Date: 2020-07-20 19:12:49
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-20 20:25:13
* @Description: 大班直播分享弹窗
*/
import React from 'react';
import { Modal, Button, message } from 'antd';
import domtoimage from 'dom-to-image';
import qrcode from '@/libs/qrcode/qrcode.js';
import User from '@/common/js/user';
import $ from 'jquery';
import CourseService from '@/domains/course-domain/CourseService';
import './ShareTrainTaskModal.less';
const DEFAULT_COVER = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png';
class ShareTrainTaskModal extends React.Component {
constructor(props) {
super(props);
this.state = {
shareUrl: '',
};
}
componentDidMount() {
// 获取短链接
this.handleConvertShortUrl();
}
handleConvertShortUrl = () => {
const { longUrl } = this.props.data;
// 发请求
CourseService.getQrcode({
urls: [longUrl],
}).then((res) => {
const { result = [] } = res;
this.setState(
{
shareUrl: result[0].shortUrl,
},
() => {
const qrcodeWrapDom = document.querySelector('#qrcodeWrap');
const qrcodeNode = new qrcode({
text: this.state.shareUrl,
size: 98,
});
qrcodeWrapDom.appendChild(qrcodeNode);
const qrcodeWrapDomDownload = document.querySelector('#qrcodeWrap-dowload');
const qrcodeNodeDownLoad = new qrcode({
text: this.state.shareUrl,
size: 196,
});
qrcodeWrapDomDownload.appendChild(qrcodeNodeDownLoad);
}
);
});
};
componentWillUnmount() {
// 页面销毁之前清空定时器
clearTimeout(this.timer);
}
// 下载海报
handleDownloadPoster = () => {
this.setState(
{
showImg: true,
time: new Date().valueOf(),
},
() => {
this.setState({ time: new Date().valueOf() }, () => {
let node = document.getElementById('poster-dowload');
domtoimage.toPng(node).then((imgData) => {
const download = document.createElement('a');
const { planName } = this.props.data;
$(download).attr('href', imgData).attr('download', `${planName}.png`).get(0).click();
});
});
}
);
};
// 复制分享链接
handleCopy = () => {
const textContent = document.getElementById('shareUrl').innerText;
window.copyText(textContent);
message.success('复制成功!');
};
render() {
const { data } = this.props;
const { planName, coverUrl = DEFAULT_COVER } = data;
const { shareUrl, showImg, time } = this.state;
return (
<Modal
title={'分享培训任务'}
width={680}
visible={true}
footer={null}
maskClosable={false}
closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
className='share-task-modal'
onCancel={this.props.close}>
<div className='left'>
<div id='poster'>
<div className='store-name'>
<span className='text'>{User.getStoreName()}</span>
</div>
<div className='course-name-title'>邀请你参与培训:</div>
<div className='live-couse-name'>{planName}</div>
<Choose>
<When condition={showImg}>
<img crossOrigin='*' src={coverUrl + `?=${time}`} className='course-cover' alt='' />
</When>
<Otherwise>
<img src={coverUrl + `?=${time}`} className='course-cover' alt='' />
</Otherwise>
</Choose>
<div className='qrcode-wrap'>
<div className='qrcode-wrap__left'>
<div className='text'>长按识别二维码进入观看</div>
<img className='finger' src='https://image.xiaomaiketang.com/xm/thpkWDwJsC.png' alt='' />
</div>
<div className='qrcode-wrap__right' id='qrcodeWrap'></div>
</div>
</div>
<div id='poster-dowload'>
<div className='store-name'>
<span className='text'>{User.getStoreName()}</span>
</div>
<div className='course-name-title'>邀请你参与培训:</div>
<div className='live-couse-name'>{planName}</div>
<Choose>
<When condition={showImg}>
<img crossOrigin='*' src={coverUrl + `?=${time}`} className='course-cover' alt='' />
</When>
<Otherwise>
<img src={coverUrl + `?=${time}`} className='course-cover' alt='' />
</Otherwise>
</Choose>
<div className='qrcode-wrap'>
<div className='qrcode-wrap__left'>
<div className='text'>长按识别二维码进入观看</div>
<img className='finger' src='https://image.xiaomaiketang.com/xm/thpkWDwJsC.png' alt='' />
</div>
<div className='qrcode-wrap__right' id='qrcodeWrap-dowload'></div>
</div>
</div>
</div>
<div className='right'>
<div className='share-poster right__item'>
<div className='title'>① 海报分享</div>
<div className='sub-title'>学员可通过微信扫描海报二维码,查看培训计划</div>
<div className='content' onClick={this.handleDownloadPoster}>
下载海报
</div>
</div>
<div className='share-url right__item'>
<div className='title'>② 链接分享</div>
<div className='sub-title'>学员可通过微信或浏览器打开以下链接,查看培训计划</div>
<div className='content url-content'>
<div className='share-url' id='shareUrl'>
{shareUrl}
</div>
<Button type='primary' onClick={this.handleCopy}>
复制
</Button>
</div>
</div>
</div>
</Modal>
);
}
}
export default ShareTrainTaskModal;
.share-task-modal {
.ant-modal-body {
display: flex;
height: 510px !important;
overflow: hidden !important;
.left {
width: 303px;
margin: 0 32px 0 16px;
box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.05);
border-radius: 12px;
#poster {
background: #fff;
margin: 0;
padding: 20px;
margin-bottom: 140px;
.course-name-title {
font-size: 14px;
color: #333;
line-height: 20px;
margin-bottom: 4px;
}
.live-couse-name {
font-size: 16px;
color: #333333;
font-weight: 600;
}
.course-name {
color: #333;
font-size: 16px;
font-weight: 600;
line-height: 20px;
}
.course-cover {
width: 263px;
height: 143px;
border-radius: 6px;
margin-top: 8px;
}
.qrcode-wrap {
padding: 0 16px;
display: flex;
align-items: center;
margin: 24px 0 16px 0;
&__left {
width: 98px;
text-align: center;
margin-right: 22px;
.text {
line-height: 20px;
}
.finger {
width: 40px;
height: 40px;
margin-top: 8px;
}
}
&__right {
width: 110px;
height: 110px;
padding: 6px;
}
}
.store-name {
// padding: 8px 16px;
display: flex;
align-items: center;
margin-bottom: 8px;
.text {
font-size: 12px;
color: #999;
font-size: 14px;
line-height: 20px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
}
}
#poster-dowload {
background: #fff;
margin: 0;
padding: 40px;
width: 606px;
.course-name-title {
font-size: 28px;
color: #333;
line-height: 40px;
margin-bottom: 8px;
}
.live-couse-name {
font-size: 32px;
color: #333333;
font-weight: 600;
}
.course-name {
color: #333;
font-size: 32px;
font-weight: 600;
line-height: 40px;
}
.course-cover {
width: 526px;
height: 286px;
border-radius: 6px;
margin-top: 16px;
}
.qrcode-wrap {
padding: 0 32px;
display: flex;
align-items: center;
margin: 48px 0 32px 0;
&__left {
width: 196px;
text-align: center;
margin-right: 44px;
.text {
line-height: 40px;
}
.finger {
width: 80px;
height: 80px;
margin-top: 16px;
}
}
&__right {
width: 220px;
height: 220px;
padding: 12px;
}
}
.store-name {
// padding: 8px 16px;
display: flex;
align-items: center;
margin-bottom: 16px;
.text {
font-size: 12px;
color: #999;
font-size: 28px;
line-height: 40px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
}
}
}
.right {
.title {
color: #333;
font-weight: 500;
}
.sub-title {
color: #999;
margin-top: 16px;
}
.content {
display: flex;
align-items: center;
margin-top: 8px;
.share-url {
width: 212px;
overflow: hidden;
height: 28px;
line-height: 28px;
border-radius: 4px 0 0 4px;
padding-left: 12px;
white-space: nowrap;
color: #999999;
background: #efefef;
}
.ant-btn {
margin-left: -2px;
}
}
.url-content {
position: relative;
&:after {
content: '';
width: 12px;
height: 22px;
background: #efefef;
position: absolute;
right: 71px;
}
}
.share-poster {
margin-bottom: 40px;
.content {
color: #2966ff;
cursor: pointer;
}
}
}
}
}
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