Commit a4d52d69 by yuananting

feat:添加新建培训任务校验

parent 4f7e0407
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @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-02 17:25:17 * @LastEditTime: 2021-08-04 17:47:51
* @Description: 任务中心-培训任务-新建页面 * @Description: 任务中心-培训任务-新建页面
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -21,35 +21,48 @@ import './AddTrainTask.less'; ...@@ -21,35 +21,48 @@ import './AddTrainTask.less';
import Bus from '@/core/bus'; import Bus from '@/core/bus';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const defaultCover = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png';
const DEFAULT_BASIC_INFO = { const DEFAULT_BASIC_INFO = {
planName: '', taskName: '', // 培训任务名称
coverUrl: defaultCover, // createId: User.getStoreUserId(), // 创建人id
coverId: null, // storeId: User.getStoreId(), // 学院id
durationType: 'NEVER_EXPIRES', // issueState: 'YES', // 是否发布此计划(底部按钮区分)
learnType: 'FREEDOM', // scheduleMediaRequests: [], // 封面图-(简介待定)
enableState: 'YES', coverUrl: '',
selectOperatorList: [], trainingStageList: [], // 培训内容
instro: '', helpStoreUserIds: [], // 指定协同者id
operateType: 'All_Operate', timeType: 'VALIDITY', // 培训时间,默认永久有效
percentCompleteLive: 80, startTime: null, // 固定时间段-开始时间
percentCompleteVideo: 80, endTime: null, // 固定时间段-结束时间
percentCompletePicture: 100, learnType: 'FREEDOM', // 学习模式,默认自由学习
assignList: [], // 指派列表-assignId assignType
instro: null, // 培训目的
}; };
const DEFAULT_TASK_LIST = [ const DEFAULT_STAGE_LIST = [
{ {
taskName: '阶段一', stageName: '阶段一',
courseList: [], contentList: [],
check: false,
}, },
]; ];
const DEFAULT_FINISH_STANDARD = {
percentCompleteLive: 80,
percentCompleteVideo: 80, // 线上课完成百分比
percentCompletePicture: 80, // 图文课完成百分比
};
function AddTrainTask() { function AddTrainTask() {
const type = getParameterByName('type'); const type = getParameterByName('type');
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 [taskList, setTaskList] = useState(DEFAULT_TASK_LIST); const [stageList, setStageList] = useState(DEFAULT_STAGE_LIST);
const [finishStandard, setFinishStandard] = useState(DEFAULT_FINISH_STANDARD); // 完成百分比
const [startCheck, setStartCheck] = useState(false); // 是否启动校验
useEffect(() => {
console.log('basicInfo:', basicInfo);
}, [basicInfo]);
function renderFooter() { function renderFooter() {
return ( return (
...@@ -57,7 +70,7 @@ function AddTrainTask() { ...@@ -57,7 +70,7 @@ function AddTrainTask() {
<When condition={activeStep === 'BASIC_INFO'}> <When condition={activeStep === 'BASIC_INFO'}>
<div className='footer shrink-footer'> <div className='footer shrink-footer'>
<Button onClick={handleGoBack}>取消</Button> <Button onClick={handleGoBack}>取消</Button>
<Button onClick={() => console.log('提交')}>保存</Button> <Button onClick={handleSubmit}>保存</Button>
<Button type='primary' onClick={() => console.log('下一步')}> <Button type='primary' onClick={() => console.log('下一步')}>
下一步 下一步
</Button> </Button>
...@@ -68,7 +81,7 @@ function AddTrainTask() { ...@@ -68,7 +81,7 @@ function AddTrainTask() {
<div className='footer shrink-footer'> <div className='footer shrink-footer'>
<Button onClick={handleGoBack}>取消</Button> <Button onClick={handleGoBack}>取消</Button>
<Button onClick={() => console.log('上一步')}>上一步</Button> <Button onClick={() => console.log('上一步')}>上一步</Button>
<Button onClick={() => console.log('提交')}>保存</Button> <Button onClick={handleSubmit}>保存</Button>
<Button type='primary' onClick={() => console.log('提交')}> <Button type='primary' onClick={() => console.log('提交')}>
保存并发布 保存并发布
</Button> </Button>
...@@ -79,19 +92,44 @@ function AddTrainTask() { ...@@ -79,19 +92,44 @@ function AddTrainTask() {
); );
} }
function handleSubmit() {
setStartCheck(true);
if (stageList.length === 0) {
return message.warning('请添加阶段');
}
}
function handleGoBack() { function handleGoBack() {
window.RCHistory.goBack(); window.RCHistory.goBack();
} }
function handleChangeBasicInfo(field, value) { function handleChangeBasicInfo(field, value) {
setBasicInfo({ if (field === 'trainDate') {
...basicInfo, // 固定培训时间,设置起始
[field]: value, setBasicInfo({
}); ...basicInfo,
startTime: value && value[0]?.valueOf(),
endTime: value && value[1]?.valueOf(),
});
} else {
setBasicInfo({
...basicInfo,
[field]: value,
startTime: null,
endTime: null,
});
}
} }
function handleChangeTaskInfo(value) { function handleChangeStageInfo(field, value) {
setTaskList(value); if (field === 'stageList') {
setStageList(value);
} else {
setFinishStandard({
...finishStandard,
[field]: value,
});
}
} }
return ( return (
...@@ -118,8 +156,10 @@ function AddTrainTask() { ...@@ -118,8 +156,10 @@ function AddTrainTask() {
</span> </span>
</span> </span>
</div> </div>
{activeStep === 'BASIC_INFO' && <BasicInfo data={basicInfo} onChange={handleChangeBasicInfo} />} {activeStep === 'BASIC_INFO' && <BasicInfo basicInfo={basicInfo} startCheck={startCheck} onChange={handleChangeBasicInfo} />}
{activeStep === 'TRAIN_CONTENT' && <TrainContent data={taskList} onChange={handleChangeTaskInfo} />} {activeStep === 'TRAIN_CONTENT' && (
<TrainContent stageList={stageList} startCheck={startCheck} finishStandard={finishStandard} onChange={handleChangeStageInfo} />
)}
</div> </div>
{renderFooter()} {renderFooter()}
</div> </div>
......
...@@ -2,126 +2,115 @@ ...@@ -2,126 +2,115 @@
* @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-02 17:50:51 * @LastEditTime: 2021-08-04 17:25:40
* @Description: 任务中心-培训任务-新建-基本信息 * @Description: 任务中心-培训任务-新建-基本信息
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React from 'react'; import React, { useEffect, useState } from 'react';
import { Form, Button, Input, Space, DatePicker, Radio, Tag, Col, message, Tooltip } from 'antd'; import { Form, Button, Input, Space, DatePicker, Radio, Tag, message, Tooltip } from 'antd';
import { PlusOutlined } from '@ant-design/icons'; import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal';
import { withRouter } from 'react-router-dom';
// import SelectOperatorModal from '../modal/SelectOperatorModal';
// import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal';
import Upload from '@/core/upload'; import Upload from '@/core/upload';
import GraphicsEditor from '@/modules/course-manage/components/GraphicsEditor'; import GraphicsEditor from '@/modules/course-manage/components/GraphicsEditor';
// import ImgClipModal from '@/components/ImgClipModal'; import ImgClipModal from '@/components/ImgClipModal';
import moment from 'moment'; import moment from 'moment';
import './BasicInfo.less'; import './BasicInfo.less';
const { TextArea } = Input;
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
const FormItem = Form.Item; const FormItem = Form.Item;
function BasicInfo(props) { function BasicInfo(props) {
const { data } = props; const { basicInfo, startCheck } = props;
const { const { taskName, coverUrl, helpStoreUserIds, timeType, startTime, endTime, learnType, assignList, instro } = basicInfo;
planName, const [imageFile, setImageFile] = useState(null); // 需要被截取的图片
coverUrl, const [showSelectFileModal, setShowSelectFileModal] = useState(false);
durationType, const [imgClipVisible, setImgClipVisible] = useState(false);
learnType, const [coverClicpPath, setCoverClicpPath] = useState(null);
instro, const [coverId, setCoverId] = useState(null);
endTime, // 当前是否使用的是默认图片
enableState, const defaultCover = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png';
operateType, const isDefaultCover = coverUrl === defaultCover;
selectOperatorList,
percentCompleteLive,
percentCompleteVideo,
percentCompletePicture,
} = data;
const isDefaultCover = true;
const helpStoreUsers = [];
const assignList1 = [ useEffect(() => {
{ updateCover();
id: 1, }, [coverId]);
name: 'yat',
},
{
id: 2,
name: '而已',
},
{
id: 3,
name: '一条鱼',
},
];
const assignList2 = [
{
id: 1,
name: 'yat',
},
{
id: 2,
name: 'ya发发送到发送到发送到撒旦法撒旦法师t',
},
{
id: 3,
name: '1111111111111111111111111111111111111111111111111111111',
},
{
id: 4,
name: 'fsaf',
},
{
id: 5,
name: '示范法as',
},
{
id: 6,
name: '示范法as水电费',
},
{
id: 7,
name: '千多',
},
{
id: 8,
name: 'y阿萨at',
},
{
id: 9,
name: '发顺丰',
},
{
id: 10,
name: 'iuyti第三方感受到',
},
];
// 使用默认封面图 // 使用默认封面图
function handleResetCoverUrl() { function handleResetCoverUrl() {
// const isDefaultCover = coverUrl === defaultCover; message.success('已替换为默认图');
// // 如果已经是默认图的话,不做任何任何处理 props.onChange('coverUrl', defaultCover);
// if (isDefaultCover) return; }
// message.success('已替换为默认图');
// this.props.onChange('coverUrl', defaultCover); // 从云盘选择封面
// setTimeout(() => { function handleSelectCover(file) {
// this.props.onChange('coverId', null); setImgClipVisible(true);
// }, 1000); setImageFile(file);
}
function getSignature(blob, fileName) {
Upload.uploadBlobToOSS(blob, 'cover' + new Date().valueOf(), null, 'signInfo').then((signInfo) => {
setCoverClicpPath(signInfo.fileUrl);
setCoverId(signInfo.resourceId);
setImgClipVisible(false);
});
}
function updateCover() {
setShowSelectFileModal(false);
props.onChange('coverUrl', coverClicpPath || coverUrl || defaultCover);
}
// 禁选日期
function disabledDate(current) {
return current && current < moment().startOf('day');
}
// 禁选时间
function disabledRangeTime(date, type) {
if (moment(date).isSame(moment(), 'day')) {
return {
disabledHours: () => {
const hours = [];
for (let i = 0; i < moment().hour(); i++) {
hours.push(i);
}
return hours;
},
disabledMinutes: () => {
const currentMinute = moment().minute();
const currentHour = moment(date).hour();
const minutes = [];
if (currentHour === moment().hour()) {
for (let i = 0; i < currentMinute; i++) {
minutes.push(i);
}
}
return minutes;
},
};
}
return {
disabledHours: () => [],
disabledMinutes: () => [],
disabledSeconds: () => [],
};
} }
return ( return (
<div className='basic-info__form'> <div className='basic-info__form'>
<Form> <Form>
<FormItem label='培训任务名称' required> <FormItem
label='培训任务名称'
required
validateStatus={startCheck && (!taskName || taskName.length > 20) ? 'error' : ''}
help={startCheck && ((!taskName && '请输入培训任务名称') || (taskName.length > 20 && '任务名称最多20字'))}>
<Input <Input
value={planName} value={taskName}
placeholder='请输入培训任务名称(20字以内)' placeholder='请输入培训任务名称(20字以内)'
maxLength={20} maxLength={20}
style={{ width: 300 }} style={{ width: 300 }}
// onChange={(e) => this.props.onChange('planName', e.target.value)} onChange={(e) => props.onChange('taskName', e.target.value)}
/> />
</FormItem> </FormItem>
<FormItem label='封面图'> <FormItem label='封面图'>
...@@ -129,9 +118,7 @@ function BasicInfo(props) { ...@@ -129,9 +118,7 @@ function BasicInfo(props) {
<div className='opt-box'> <div className='opt-box'>
<Button <Button
onClick={() => { onClick={() => {
this.setState({ setShowSelectFileModal(true);
showSelectFileModal: true,
});
}}> }}>
上传封面 上传封面
</Button> </Button>
...@@ -148,32 +135,35 @@ function BasicInfo(props) { ...@@ -148,32 +135,35 @@ function BasicInfo(props) {
</FormItem> </FormItem>
<FormItem label='培训时间'> <FormItem label='培训时间'>
<div className='duration__wrap'> <div className='duration__wrap'>
<Radio.Group value={durationType} onChange={(e) => props.onChange('durationType', e.target.value)}> <Radio.Group value={timeType} onChange={(e) => props.onChange('timeType', e.target.value)}>
<Space direction='vertical' size={16}> <Space direction='vertical' size={16}>
<Radio value='NEVER_EXPIRES'> <Radio value='VALIDITY'>
永久有效<span className='tips'>设置为“永久有效”,发布后任务开始生效,取消发布后失效</span> 永久有效<span className='tips'>设置为“永久有效”,发布后任务开始生效,取消发布后失效</span>
</Radio> </Radio>
<Radio value='FIXED_DURATION'> <Radio value='FIXED_DURATION'>
固定时间段 固定时间段
{durationType === 'FIXED_DURATION' && ( {timeType === 'FIXED_DURATION' && (
<div className='picker-box'> <div className='picker-box'>
<RangePicker <FormItem
style={{ width: 320 }} validateStatus={startCheck && !startTime && !endTime ? 'error' : ''}
showTime={{ defaultValue: [moment().add(10, 'minutes'), moment().add(10, 'minutes')] }} help={startCheck && !startTime && !endTime && '请选择培训时间'}>
ranges={{ <RangePicker
7: [moment().add(10, 'minute'), moment().add(6, 'day').endOf('day')], style={{ width: 320 }}
1个月: [moment().add(10, 'minute'), moment().add(1, 'month').endOf('day')], showTime={{ defaultValue: [moment().add(10, 'minutes'), moment().add(10, 'minutes')] }}
3个月: [moment().add(10, 'minute'), moment().add(3, 'month').endOf('day')], ranges={{
}} 7: [moment().add(10, 'minute'), moment().add(6, 'day').endOf('day')],
// disabledDate={disabledDate} 1个月: [moment().add(10, 'minute'), moment().add(1, 'month').endOf('day')],
// value={[examStartTime ? moment(Number(examStartTime)) : null, examEndTime ? moment(Number(examEndTime)) : null]} 3个月: [moment().add(10, 'minute'), moment().add(3, 'month').endOf('day')],
// disabledTime={disabledRangeTime} }}
format='YYYY-MM-DD HH:mm' disabledDate={disabledDate}
// onChange={(date) => { disabledTime={disabledRangeTime}
// setStartTime(date && date[0]?.valueOf()); value={[startTime ? moment(Number(startTime)) : null, endTime ? moment(Number(endTime)) : null]}
// setExamEndTime(date && date[1]?.valueOf()); format='YYYY-MM-DD HH:mm'
// }} onChange={(date) => {
/> props.onChange('trainDate', date);
}}
/>{' '}
</FormItem>
</div> </div>
)} )}
</Radio> </Radio>
...@@ -206,25 +196,44 @@ function BasicInfo(props) { ...@@ -206,25 +196,44 @@ function BasicInfo(props) {
</Radio.Group> </Radio.Group>
</div> </div>
</FormItem> </FormItem>
<FormItem label='指派学员' required> <FormItem
label={
<span>
闯关学习
<Tooltip title='选择员工协同完成任务指派和督学工作'>
<i
className='icon iconfont'
style={{
marginLeft: '5px',
cursor: 'pointer',
color: '#bfbfbf',
fontSize: '14px',
fontWeight: 'normal',
}}>
&#xe61d;
</i>
</Tooltip>
</span>
}
required>
<Button style={{ display: 'block' }}>添加指派对象</Button> <Button style={{ display: 'block' }}>添加指派对象</Button>
{assignList1.length + assignList2.length > 0 && ( {assignList > 0 && (
<Space size={'12'} direction={'vertical'} className='select-obj'> <Space size={'12'} direction={'vertical'} className='select-obj'>
{assignList1.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(assignList1, (item) => { {_.map(assignList, (item) => {
return <Tag closable>{item.name}</Tag>; return <Tag closable>{item.name}</Tag>;
})} })}
</div> </div>
</div> </div>
)} )}
{assignList2.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(assignList2, (item) => { {_.map(assignList, (item) => {
return <Tag closable>{item.name}</Tag>; return <Tag closable>{item.name}</Tag>;
})} })}
</div> </div>
...@@ -233,11 +242,29 @@ function BasicInfo(props) { ...@@ -233,11 +242,29 @@ function BasicInfo(props) {
</Space> </Space>
)} )}
</FormItem> </FormItem>
<FormItem label='协同人员'> <FormItem
label={
<span>
协同人员
<Tooltip title='选择需要培训的人员'>
<i
className='icon iconfont'
style={{
marginLeft: '5px',
cursor: 'pointer',
color: '#bfbfbf',
fontSize: '14px',
fontWeight: 'normal',
}}>
&#xe61d;
</i>
</Tooltip>
</span>
}>
<Button style={{ display: 'block' }}>添加协同者</Button> <Button style={{ display: 'block' }}>添加协同者</Button>
{helpStoreUsers.length > 0 && ( {helpStoreUserIds.length > 0 && (
<div className='select-obj'> <div className='select-obj'>
{_.map(helpStoreUsers, (item) => { {_.map(helpStoreUserIds, (item) => {
return <Tag closable>{item.name}</Tag>; return <Tag closable>{item.name}</Tag>;
})} })}
</div> </div>
...@@ -253,11 +280,36 @@ function BasicInfo(props) { ...@@ -253,11 +280,36 @@ function BasicInfo(props) {
content: instro, content: instro,
}} }}
onChange={(val) => { onChange={(val) => {
// this.changeIntro(val); // changeIntro(val);
}} }}
/> />
</FormItem> </FormItem>
</Form> </Form>
{showSelectFileModal && (
<SelectPrepareFileModal
key='basic'
operateType='select'
multiple={false}
accept='image/jpeg,image/png,image/jpg'
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectFileModal}
onClose={() => {
setShowSelectFileModal(false);
}}
onSelect={handleSelectCover}
/>
)}
{imgClipVisible && (
<ImgClipModal
visible={imgClipVisible}
imgUrl={imageFile.ossUrl}
onConfirm={getSignature}
onClose={() => {
setImgClipVisible(false);
}}
/>
)}
</div> </div>
); );
} }
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
&.disabled { &.disabled {
color: #ccc; color: #ccc;
cursor: not-allowed; cursor: not-allowed;
pointer-events: none;
} }
} }
.tips { .tips {
...@@ -57,6 +58,9 @@ ...@@ -57,6 +58,9 @@
.picker-box { .picker-box {
display: inline-block; display: inline-block;
margin-left: 16px; margin-left: 16px;
.ant-form-item {
margin-bottom: 0 !important;
}
} }
} }
} }
......
...@@ -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-02 14:26:43 * @LastEditTime: 2021-08-04 16:13:46
* @Description: 新建培训任务-关联课程抽屉 * @Description: 新建培训任务-关联课程抽屉
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -99,7 +99,7 @@ class RelatedCourseDrawer extends Component { ...@@ -99,7 +99,7 @@ class RelatedCourseDrawer extends Component {
const _data = [...this.props.data]; const _data = [...this.props.data];
let currentLiveCourseListData = []; let currentLiveCourseListData = [];
_data.map((item) => { _data.map((item) => {
item.courseList.map((childItem, childIndex) => { item.contentList.map((childItem, childIndex) => {
if (childItem.courseType === 'LIVE') { if (childItem.courseType === 'LIVE') {
currentLiveCourseListData.push(childItem.courseId); currentLiveCourseListData.push(childItem.courseId);
} }
...@@ -130,7 +130,7 @@ class RelatedCourseDrawer extends Component { ...@@ -130,7 +130,7 @@ class RelatedCourseDrawer extends Component {
const _data = [...this.props.data]; const _data = [...this.props.data];
let currentVideoCourseListData = []; let currentVideoCourseListData = [];
_data.map((item, index) => { _data.map((item, index) => {
item.courseList.map((childItem, childIndex) => { item.contentList.map((childItem, childIndex) => {
if (childItem.courseType === 'VOICE') { if (childItem.courseType === 'VOICE') {
currentVideoCourseListData.push(childItem.courseId); currentVideoCourseListData.push(childItem.courseId);
} }
...@@ -168,7 +168,7 @@ class RelatedCourseDrawer extends Component { ...@@ -168,7 +168,7 @@ class RelatedCourseDrawer extends Component {
const _data = [...this.props.data]; const _data = [...this.props.data];
let currentPictureCourseListData = []; let currentPictureCourseListData = [];
_data.map((item, index) => { _data.map((item, index) => {
item.courseList.map((childItem, childIndex) => { item.contentList.map((childItem, childIndex) => {
if (childItem.courseType === 'PICTURE') { if (childItem.courseType === 'PICTURE') {
currentPictureCourseListData.push(childItem.courseId); currentPictureCourseListData.push(childItem.courseId);
} }
......
...@@ -2,17 +2,18 @@ ...@@ -2,17 +2,18 @@
* @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-03 20:02:27 * @LastEditTime: 2021-08-04 10:40:11
* @Description: 新建培训任务-关联考试抽屉 * @Description: 新建培训任务-关联考试抽屉
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { useState, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Drawer, Form, Input, Button, Tooltip, Switch, Radio, InputNumber } from 'antd'; import { Drawer, Form, Input, Button, Tooltip, Switch, Radio, InputNumber, message } from 'antd';
import GraphicsEditor from '@/modules/course-manage/components/GraphicsEditor'; import GraphicsEditor from '@/modules/course-manage/components/GraphicsEditor';
import moment from 'moment'; import moment from 'moment';
import './RelatedExamDrawer.less'; import './RelatedExamDrawer.less';
import SelectPaperModal from '@/modules/teach-tool/examination-manager/SelectPaperModal'; import SelectPaperModal from '@/modules/teach-tool/examination-manager/SelectPaperModal';
import User from '@/common/js/user';
function RelatedExamDrawer(props) { function RelatedExamDrawer(props) {
const paperInfoInit = { passScore: 60 }; const paperInfoInit = { passScore: 60 };
...@@ -32,8 +33,6 @@ function RelatedExamDrawer(props) { ...@@ -32,8 +33,6 @@ function RelatedExamDrawer(props) {
const [passScore, setPassScore] = useState(100); const [passScore, setPassScore] = useState(100);
const [desclen, setDescLen] = useState(0); const [desclen, setDescLen] = useState(0);
const [check, setCheck] = useState(false); const [check, setCheck] = useState(false);
const [getData, setGetData] = useState(false);
const [preview, setPreview] = useState(false);
const [examTotal, setExamTotal] = useState(0); const [examTotal, setExamTotal] = useState(0);
const [examList, setExamList] = useState([]); const [examList, setExamList] = useState([]);
const request = useRef(false); const request = useRef(false);
...@@ -41,52 +40,22 @@ function RelatedExamDrawer(props) { ...@@ -41,52 +40,22 @@ function RelatedExamDrawer(props) {
const [examDuration, setExamDuration] = useState(undefined); const [examDuration, setExamDuration] = useState(undefined);
useEffect(() => {
setPaperId(paperInfo.paperId);
setPassRate(paperInfo.passRate);
setExamName(paperInfo.paperName);
}, [paperInfo.paperId]);
useEffect(() => {
setPassScore(Math.round(((paperInfo.totalScore || 0) * (passRate || 0)) / 100));
setExamTotal(paperInfo.singleChoiceCnt + paperInfo.multiChoiceCnt + paperInfo.judgeCnt + paperInfo.gapFillingCnt + paperInfo.indefiniteChoiceCnt || 0);
}, [paperInfo.paperId, passRate]);
function disabledDate(current) { function disabledDate(current) {
// Can not select days before today and today // Can not select days before today and today
return current && current < moment().startOf('day'); return current && current < moment().startOf('day');
} }
function queryExamList() {
let param = {
current: 1,
size: 9999,
order: 'EXAM_START_TIME_DESC',
userId: User.getStoreUserId(),
tenantId: User.getStoreId(),
source: 0,
};
Service.Hades('public/hades/queryExamPageList', param).then((res) => {
const { result = {} } = res;
setExamList(result.records || []);
});
}
function queryExamDetail() {
Service.Hades('public/hades/queryExamDetail', {
examId: match.params.id,
tenantId: User.getStoreId(),
userId: User.getStoreUserId(),
source: 0,
}).then((res) => {
const { result } = res;
setPaperInfo(result.examPaper);
setPaperId(result.examPaper.paperId);
setStartTime(props.type === 'edit' ? result.examStartTime : '');
setExamEndTime(props.type === 'edit' ? result.examEndTime : '');
setExamName(props.type === 'edit' ? result.examName : `${result.examName}(复制)`);
setPassRate(result.passRate * 100);
setNeedPhone(result.needPhone);
setExamDesc(result.examDesc);
setExamDuration(result.examDuration / 60 / 1000);
setAnswerAnalysis(result.answerAnalysis);
setNeedOptionDisorder(result.needOptionDisorder);
setPassScore(result.passScore);
setResultContent(result.resultContent);
setResultShow(result.resultShow);
setGetData(true);
});
}
function handleSave() { function handleSave() {
if (request.current) { if (request.current) {
return; return;
...@@ -222,19 +191,6 @@ function RelatedExamDrawer(props) { ...@@ -222,19 +191,6 @@ function RelatedExamDrawer(props) {
}; };
} }
function handleGoBack() {
Modal.confirm({
title: '确定要返回吗?',
content: '返回后,本次编辑的内容将不被保存',
okText: '确认返回',
cancelText: '留在本页',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
window.RCHistory.push('/examination-manage-index');
},
});
}
// 校验考试名称是否存在 // 校验考试名称是否存在
function checkExist(examName) { function checkExist(examName) {
var result = null; var result = null;
...@@ -385,6 +341,16 @@ function RelatedExamDrawer(props) { ...@@ -385,6 +341,16 @@ function RelatedExamDrawer(props) {
</div> </div>
</div> </div>
</Form.Item> </Form.Item>
<Form.Item label='考试结果查看' required>
<Radio.Group
onChange={(e) => {
setResultShow(e.target.value);
}}
value={resultShow}>
<Radio value={'IMMEDIATELY'}>交卷后立即显示考试结果</Radio>
<Radio value={'AFTER_EXAM_END'}>到达考试截止日期才显示结果</Radio>
</Radio.Group>
</Form.Item>
<Form.Item label='考试结果内容' required> <Form.Item label='考试结果内容' required>
<Radio.Group <Radio.Group
...@@ -412,7 +378,7 @@ function RelatedExamDrawer(props) { ...@@ -412,7 +378,7 @@ function RelatedExamDrawer(props) {
</Form> </Form>
<div className='footer shrink-footer'> <div className='footer shrink-footer'>
<Button onClick={props.onClose}>取消</Button> <Button onClick={props.onClose}>取消</Button>
<Button type='primary' onClick={() => console.log('提交')}> <Button type='primary' onClick={handleSave}>
确定 确定
</Button> </Button>
</div> </div>
......
...@@ -68,6 +68,9 @@ ...@@ -68,6 +68,9 @@
.graphics-editor-container { .graphics-editor-container {
width: 550px; width: 550px;
height: 130px; height: 130px;
.editor-warning {
top: 130px !important;
}
} }
} }
} }
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
* @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-03 18:32:02 * @LastEditTime: 2021-08-04 19:27:08
* @Description: 任务中心-培训任务-新建-培训内容 * @Description: 任务中心-培训任务-新建-培训内容
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Form, Input, Collapse, Dropdown, Menu } from 'antd'; import { Form, Input, Collapse, Dropdown, Menu, Modal } from 'antd';
import { sortableContainer, sortableElement, sortableHandle } from 'react-sortable-hoc'; import { sortableContainer, sortableElement, sortableHandle } from 'react-sortable-hoc';
import arrayMove from 'array-move'; import arrayMove from 'array-move';
import './TrainContent.less'; import './TrainContent.less';
...@@ -16,11 +16,13 @@ import RelatedCourseDrawer from './RelatedCourseDrawer'; ...@@ -16,11 +16,13 @@ import RelatedCourseDrawer from './RelatedCourseDrawer';
import RelatedExamDrawer from './RelatedExamDrawer'; import RelatedExamDrawer from './RelatedExamDrawer';
import ExpiredCourseList from './ExpiredCourseList'; import ExpiredCourseList from './ExpiredCourseList';
import ENUM from '../../enum'; import ENUM from '../../enum';
import FormItem from 'antd/lib/form/FormItem';
const { Panel } = Collapse; const { Panel } = Collapse;
const { confirm } = Modal;
const SortableTaskContainer = sortableContainer((props) => <div {...props}></div>); const SortableStageContainer = sortableContainer((props) => <div {...props}></div>);
const SortableTaskItem = sortableElement((props) => <div {...props}>{props.taskitem}</div>); const SortableStageItem = sortableElement((props) => <div {...props}>{props.stageitem}</div>);
const SortableContentContainer = sortableContainer((props) => <div {...props}></div>); const SortableContentContainer = sortableContainer((props) => <div {...props}></div>);
const SortableContentItem = sortableElement((props) => <div {...props}>{props.contentitem}</div>); const SortableContentItem = sortableElement((props) => <div {...props}>{props.contentitem}</div>);
...@@ -62,10 +64,11 @@ class TrainContent extends Component { ...@@ -62,10 +64,11 @@ class TrainContent extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
dataSource: props.data, stageList: props.stageList,
finishStandard: props.finishStandard,
showCourseDrawer: false, showCourseDrawer: false,
showExamDrawer: false, showExamDrawer: false,
selectedTaskIndex: 0, selectedStageIndex: 0,
expiredCourseList: [], // 失效课程 expiredCourseList: [], // 失效课程
showStandardDetail: false, // 是否展开高级设置 showStandardDetail: false, // 是否展开高级设置
}; };
...@@ -151,97 +154,135 @@ class TrainContent extends Component { ...@@ -151,97 +154,135 @@ class TrainContent extends Component {
}); });
}; };
setTrianTypeOption = () => { setTrianTypeOption = (index) => {
return ( return (
<Menu> <Menu>
<Menu.Item key='course' onClick={() => this.setState({ showCourseDrawer: true })}> <Menu.Item key='course' onClick={() => this.setState({ showCourseDrawer: true, selectedStageIndex: index })}>
<img className='type-option-icon' src={ENUM.LearningContentIcon['COURSE']} /> <img className='type-option-icon' src={ENUM.LearningContentIcon['COURSE']} />
<span className='type-option-text'>课程</span> <span className='type-option-text'>课程</span>
</Menu.Item> </Menu.Item>
<Menu.Item key='exam' onClick={() => this.setState({ showExamDrawer: true })}> <Menu.Item key='exam' onClick={() => this.setState({ showExamDrawer: true, selectedStageIndex: index })}>
<img className='type-option-icon' src={ENUM.LearningContentIcon['EXAM']} /> <img className='type-option-icon' src={ENUM.LearningContentIcon['EXAM']} />
<span className='type-option-text'>考试</span> <span className='type-option-text'>考试</span>
</Menu.Item> </Menu.Item>
<Menu.Item key='homework'> {/* <Menu.Item key='homework'>
<img className='type-option-icon' src={ENUM.LearningContentIcon['HOMEWORK']} /> <img className='type-option-icon' src={ENUM.LearningContentIcon['HOMEWORK']} />
<span className='type-option-text'>实操作业</span> <span className='type-option-text'>实操作业</span>
</Menu.Item> </Menu.Item> */}
</Menu> </Menu>
); );
}; };
onTaskSortEnd = ({ oldIndex, newIndex }) => { onStageSortEnd = ({ oldIndex, newIndex }) => {
const { dataSource } = this.state; const { stageList } = this.state;
if (oldIndex !== newIndex) { if (oldIndex !== newIndex) {
const newData = arrayMove([].concat(dataSource), oldIndex, newIndex).filter((el) => !!el); const _stageList = arrayMove([].concat(stageList), oldIndex, newIndex).filter((el) => !!el);
this.setState( this.setState(
{ {
dataSource: newData, stageList: _stageList,
}, },
() => { () => {
this.props.onChange(newData); this.props.onChange('stageList', _stageList);
} }
); );
} }
}; };
onContentSortEnd = ({ oldIndex, newIndex }, parentIndex) => { onContentSortEnd = ({ oldIndex, newIndex }, parentIndex) => {
const { dataSource } = this.state; const { stageList } = this.state;
const _dataSource = [...dataSource]; const _stageList = [...stageList];
if (oldIndex !== newIndex) { if (oldIndex !== newIndex) {
_dataSource[parentIndex].courseList = arrayMove([].concat(dataSource[parentIndex].courseList), oldIndex, newIndex).filter((el) => !!el); _stageList[parentIndex].contentList = arrayMove([].concat(stageList[parentIndex].contentList), oldIndex, newIndex).filter((el) => !!el);
this.setState( this.setState(
{ {
dataSource: _dataSource, stageList: _stageList,
}, },
() => { () => {
this.props.onChange(_dataSource); this.props.onChange('stageList', _stageList);
} }
); );
} }
}; };
handleRenameTaskName = (e, item) => { handleRenameStageName = (e, item) => {
const { value } = e.target; const { value } = e.target;
const { dataSource } = this.state; const { stageList } = this.state;
item.taskName = value; item.stageName = value;
item.check = true;
this.setState( this.setState(
{ {
dataSource, stageList,
}, },
() => { () => {
this.props.onChange(dataSource); this.props.onChange('stageList', stageList);
} }
); );
}; };
handleTaskNameBlur = (e, item) => {
handleStageNameBlur = (e, item) => {
const { value } = e.target; const { value } = e.target;
const { dataSource } = this.state; const { stageList } = this.state;
let input = /^[\s]*$/; let input = /^[\s]*$/;
if (value && !input.test(value)) { if (value && !input.test(value)) {
item.type = 'text'; item.type = 'text';
this.setState( this.setState(
{ {
dataSource, stageList,
}, },
() => { () => {
this.props.onChange(dataSource); this.props.onChange('stageList', stageList);
} }
); );
} }
}; };
handleValidatorTaskName = (rule, value) => { handleValidatorStageName = (value, currentIndex) => {
const { stageList } = this.state;
const sameStageName = stageList.filter((item, index) => {
return item.stageName === value && index !== currentIndex;
});
let input = /^[\s]*$/; let input = /^[\s]*$/;
if (input.test(value) || !value) { if (input.test(value) || !value) {
return Promise.reject(new Error('请输入任务名称')); return '请输入阶段名称';
} else if (sameStageName.length > 0) {
return '阶段名称已存在';
} }
return Promise.resolve(); return false;
};
// 移除阶段
handleDeleteStage = (index) => {
return confirm({
title: '删除阶段',
content: '删除该阶段会连同课程、作业、考试一起删除,删除后不可恢复,是否仍要删除?',
icon: <span className='icon iconfont default-confirm-icon'>&#xe839; </span>,
okText: '删除',
okType: 'danger',
cancelText: '取消',
onOk: () => {
this.handleConfirmDeleteStage(index);
},
});
};
handleConfirmDeleteStage = (index) => {
const { stageList } = this.state;
const _stageList = [...stageList];
_stageList.splice(index, 1);
this.setState(
{
stageList: _stageList,
},
() => {
this.props.onChange('stageList', _stageList);
}
);
}; };
renderStageInfo = (item, index) => { renderStageInfo = (item, index) => {
const { startCheck } = this.props;
return ( return (
<div className='sort-stage-item'> <div className='sort-stage-item'>
<div className='item-info'> <div className='item-info'>
...@@ -250,33 +291,27 @@ class TrainContent extends Component { ...@@ -250,33 +291,27 @@ class TrainContent extends Component {
<When condition={item.type === 'input'}> <When condition={item.type === 'input'}>
<Form> <Form>
<Form.Item <Form.Item
initialValue={item.taskName} initialValue={item.stageName}
validateTrigger={['onChange', 'onBlur']} validateStatus={(item.check || startCheck) && this.handleValidatorStageName(item.stageName, index) ? 'error' : ''}
name={['stageName']} help={(item.check || startCheck) && this.handleValidatorStageName(item.stageName, index)}>
rules={[
{
validator: (rule, value) => this.handleValidatorTaskName(rule, value),
},
]}>
<Input <Input
className='info-input' className='info-input'
style={{ width: 300 }} style={{ width: 300 }}
placeholder='请输入阶段名称' placeholder='请输入阶段名称'
maxLength={20} maxLength={20}
value={item.stageName}
onChange={(e) => { onChange={(e) => {
this.handleRenameTaskName(e, item); this.handleRenameStageName(e, item);
e.stopPropagation();
}} }}
onBlur={(e) => { onBlur={(e) => {
this.handleTaskNameBlur(e, item); this.handleStageNameBlur(e, item);
e.stopPropagation();
}} }}
/> />
</Form.Item> </Form.Item>
</Form> </Form>
</When> </When>
<Otherwise> <Otherwise>
<span className='info-text'>{item.taskName}</span> <span className='info-text'>{item.stageName}</span>
</Otherwise> </Otherwise>
</Choose> </Choose>
</div> </div>
...@@ -284,9 +319,11 @@ class TrainContent extends Component { ...@@ -284,9 +319,11 @@ class TrainContent extends Component {
<span <span
className='operate__item' className='operate__item'
onClick={(e) => { onClick={(e) => {
const { dataSource } = this.state; if (item.type === 'input') return;
const { stageList } = this.state;
item.type = 'input'; item.type = 'input';
this.setState({ dataSource }); item.check = true;
this.setState({ stageList });
e.stopPropagation(); e.stopPropagation();
}}> }}>
<span className='icon iconfont'>&#xe6f5;</span> <span className='icon iconfont'>&#xe6f5;</span>
...@@ -296,7 +333,7 @@ class TrainContent extends Component { ...@@ -296,7 +333,7 @@ class TrainContent extends Component {
className='operate__item' className='operate__item'
style={{ marginLeft: 16 }} style={{ marginLeft: 16 }}
onClick={(e) => { onClick={(e) => {
this.handleDeleteTask(index); this.handleDeleteStage(index);
e.stopPropagation(); e.stopPropagation();
}}> }}>
<span className='icon iconfont'>&#xe6f6;</span> <span className='icon iconfont'>&#xe6f6;</span>
...@@ -313,19 +350,15 @@ class TrainContent extends Component { ...@@ -313,19 +350,15 @@ class TrainContent extends Component {
<Collapse ghost> <Collapse ghost>
<Panel header={this.renderStageInfo(item, index)} key={index}> <Panel header={this.renderStageInfo(item, index)} key={index}>
<SortableContentContainer useDragHandle disableAutoscroll helperClass='row-dragging' onSortEnd={(item) => this.onContentSortEnd(item, index)}> <SortableContentContainer useDragHandle disableAutoscroll helperClass='row-dragging' onSortEnd={(item) => this.onContentSortEnd(item, index)}>
{item.courseList.map((contentItem, contentIndex) => ( {item.contentList.map((contentItem, contentIndex) => (
<SortableContentItem <SortableContentItem
contentitem={this.renderContentItem(contentItem, contentIndex, index)} contentitem={this.renderContentItem(contentItem, contentIndex, index)}
index={contentIndex} index={contentIndex}
key={contentIndex}></SortableContentItem> key={contentIndex}></SortableContentItem>
))} ))}
</SortableContentContainer> </SortableContentContainer>
<Dropdown <Dropdown overlay={this.setTrianTypeOption(index)}>
overlay={this.setTrianTypeOption()} <span className={`add-content-btn ${item.contentList.length === 20 && 'disabled'}`}>+ 添加学习内容</span>
onClick={() => {
// this.showRelatedCourseModal(index);
}}>
<span className='add-content-btn'>+ 添加学习内容</span>
</Dropdown> </Dropdown>
</Panel> </Panel>
</Collapse> </Collapse>
...@@ -362,21 +395,22 @@ class TrainContent extends Component { ...@@ -362,21 +395,22 @@ class TrainContent extends Component {
// 添加阶段 // 添加阶段
addStage = () => { addStage = () => {
const { dataSource } = this.state; const { stageList } = this.state;
const taskObj = { const stageObj = {
taskName: '', stageName: '',
index: dataSource.length, index: stageList.length,
type: 'input', type: 'input',
open: true, open: true,
courseList: [], contentList: [],
check: false,
}; };
const newData = [...dataSource, taskObj]; const _stageList = [...stageList, stageObj];
this.setState( this.setState(
{ {
dataSource: newData, stageList: _stageList,
}, },
() => { () => {
this.props.onChange(newData); this.props.onChange('stageList', _stageList);
} }
); );
}; };
...@@ -394,37 +428,84 @@ class TrainContent extends Component { ...@@ -394,37 +428,84 @@ class TrainContent extends Component {
}; };
confirmSelectCourse = (selectList) => { confirmSelectCourse = (selectList) => {
const { selectedTaskIndex } = this.state; const { selectedStageIndex } = this.state;
const { dataSource } = this.state; const { stageList } = this.state;
const newData = [...dataSource]; const _stageList = [...stageList];
const selectData = [...newData[selectedTaskIndex].courseList]; const selectData = [..._stageList[selectedStageIndex].contentList];
const _selectData = [...selectData, ...selectList]; const _selectData = [...selectData, ...selectList];
newData[selectedTaskIndex].courseList = _selectData; _stageList[selectedStageIndex].contentList = _selectData;
this.setState( this.setState(
{ {
showCourseDrawer: false, showCourseDrawer: false,
dataSource: newData, stageList: _stageList,
}, },
() => { () => {
this.props.onChange(newData); this.props.onChange('stageList', _stageList);
}
);
};
percentCompleteBlur = (e, field) => {
let _percentCompleteLive;
const { value } = e.target;
if (value > 100) {
_percentCompleteLive = 100;
} else {
if (value < 0) {
_percentCompleteLive = 0;
} else {
_percentCompleteLive = value;
}
}
this.props.onChange(field, _percentCompleteLive);
};
changePercentComplete = (e, field) => {
const { finishStandard } = this.state;
let _percentComplete = 0;
const value = e.target.value.replace(/\D/g, '');
if (value > 100) {
_percentComplete = 100;
} else {
if (value < 0) {
_percentComplete = 0;
} else {
_percentComplete = value;
}
}
this.setState(
{
finishStandard: {
...finishStandard,
[field]: _percentComplete,
},
},
() => {
this.props.onChange('finishStandard', this.state.finishStandard);
} }
); );
}; };
render() { render() {
const { dataSource, showCourseDrawer, showExamDrawer, expiredCourseList, showStandardDetail } = this.state; const { stageList, showCourseDrawer, showExamDrawer, expiredCourseList, showStandardDetail, finishStandard } = this.state;
const { percentCompleteLive, percentCompleteVideo, percentCompletePicture } = finishStandard;
const { startCheck } = this.props;
return ( return (
<div className='train-content-page'> <div className='train-content-page'>
<div className='train-content__warp'> <div className='train-content__warp'>
<SortableTaskContainer useDragHandle disableAutoscroll helperClass='row-dragging' onSortEnd={this.onTaskSortEnd}> <SortableStageContainer useDragHandle disableAutoscroll helperClass='row-dragging' onSortEnd={this.onStageSortEnd}>
{dataSource.map((item, index) => ( {stageList.map((item, index) => (
<SortableTaskItem taskitem={this.renderStageItem(item, index)} index={index} key={index}></SortableTaskItem> <SortableStageItem stageitem={this.renderStageItem(item, index)} index={index} key={index}></SortableStageItem>
))} ))}
</SortableTaskContainer> </SortableStageContainer>
<div className='add-stage-btn' onClick={() => this.addStage()}> {stageList.length < 10 && (
+ 添加阶段 <div className='add-stage-btn' onClick={() => this.addStage()}>
</div> + 添加阶段
{showCourseDrawer && <RelatedCourseDrawer data={dataSource} onClose={this.onCloseCourseDrawer} onSelect={this.confirmSelectCourse} />} </div>
)}
{showCourseDrawer && <RelatedCourseDrawer data={stageList} onClose={this.onCloseCourseDrawer} onSelect={this.confirmSelectCourse} />}
{showExamDrawer && <RelatedExamDrawer onClose={this.onCloseExamDrawer} />} {showExamDrawer && <RelatedExamDrawer onClose={this.onCloseExamDrawer} />}
</div> </div>
<div className='expired-info__wrap'> <div className='expired-info__wrap'>
...@@ -445,19 +526,22 @@ class TrainContent extends Component { ...@@ -445,19 +526,22 @@ class TrainContent extends Component {
{showStandardDetail && ( {showStandardDetail && (
<div className='detail-container'> <div className='detail-container'>
<div className='title-text'>完成标准:</div> <div className='title-text'>完成标准:</div>
<div className='detail-box'> <Form className='detail-box'>
<div className='item-info'> <div className='item-info'>
<img src={ENUM.LearningContentIcon['LIVE']} /> <span>
<img src={ENUM.LearningContentIcon['LIVE']} />
</span>
<span> <span>
直播课单个课程,学员学习进度达到 直播课单个课程,学员学习进度达到
<Input <FormItem validateStatus={startCheck && !percentCompleteLive ? 'error' : ''} help={startCheck && !percentCompleteLive && '请输入完成标准'}>
// value={percentCompleteLive} <Input
onChange={(e) => { value={percentCompleteLive}
// this.props.onChange('percentCompleteLive', e.target.value.replace(/\D/g, '')); onChange={(e) => {
}} this.changePercentComplete(e, 'percentCompleteLive');
// onBlur={(e) => this.percentCompleteBlur(e, 'percentCompleteLive')} }}
className='input-box' className='input-box'
/> />
</FormItem>
%,即视为"已完成"学习 %,即视为"已完成"学习
</span> </span>
</div> </div>
...@@ -465,14 +549,17 @@ class TrainContent extends Component { ...@@ -465,14 +549,17 @@ class TrainContent extends Component {
<img src={ENUM.LearningContentIcon['VOICE']} /> <img src={ENUM.LearningContentIcon['VOICE']} />
<span> <span>
线上课单个课节,学员学习进度达到 线上课单个课节,学员学习进度达到
<Input <FormItem
// value={percentCompleteVideo} validateStatus={startCheck && !percentCompleteVideo ? 'error' : ''}
onChange={(e) => { help={startCheck && !percentCompleteVideo && '请输入完成标准'}>
// this.props.onChange('percentCompleteVideo', e.target.value.replace(/\D/g, '')); <Input
}} value={percentCompleteVideo}
// onBlur={(e) => this.percentCompleteBlur(e, 'percentCompleteVideo')} onChange={(e) => {
className='input-box' this.changePercentComplete(e, 'percentCompleteVideo');
/> }}
className='input-box'
/>
</FormItem>
%,即课节视为"已完成"学习 %,即课节视为"已完成"学习
</span> </span>
</div> </div>
...@@ -480,18 +567,21 @@ class TrainContent extends Component { ...@@ -480,18 +567,21 @@ class TrainContent extends Component {
<img src={ENUM.LearningContentIcon['PICTURE']} /> <img src={ENUM.LearningContentIcon['PICTURE']} />
<span> <span>
图文课单个课程,学员学习进度达到 图文课单个课程,学员学习进度达到
<Input <FormItem
// value={percentCompletePicture} validateStatus={startCheck && !percentCompletePicture ? 'error' : ''}
onChange={(e) => { help={startCheck && !percentCompletePicture && '请输入完成标准'}>
// this.props.onChange('percentCompletePicture', e.target.value.replace(/\D/g, '')); <Input
}} value={percentCompletePicture}
// onBlur={(e) => this.percentCompleteBlur(e, 'percentCompletePicture')} onChange={(e) => {
className='input-box' this.changePercentComplete(e, 'percentCompletePicture');
/> }}
className='input-box'
/>
</FormItem>
%,即视为"已完成"学习 %,即视为"已完成"学习
</span> </span>
</div> </div>
</div> </Form>
</div> </div>
)} )}
</div> </div>
......
...@@ -53,8 +53,10 @@ ...@@ -53,8 +53,10 @@
color: #333333; color: #333333;
vertical-align: middle; vertical-align: middle;
margin-bottom: 20px; margin-bottom: 20px;
* { .ant-form-item {
vertical-align: middle; display: inline-block;
margin-bottom: 0 !important;
vertical-align: baseline;
} }
img { img {
width: 20px; width: 20px;
...@@ -185,6 +187,11 @@ ...@@ -185,6 +187,11 @@
padding: 16px; padding: 16px;
cursor: pointer; cursor: pointer;
display: inline-block; display: inline-block;
&.disabled {
color: #ccc;
cursor: not-allowed;
pointer-events: none;
}
} }
.ant-collapse-content { .ant-collapse-content {
......
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