Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xiaomai-cloud-class-web
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xiaomai-cloud-class
xiaomai-cloud-class-web
Commits
a4d52d69
Commit
a4d52d69
authored
Aug 04, 2021
by
yuananting
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:添加新建培训任务校验
parent
4f7e0407
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
458 additions
and
296 deletions
+458
-296
src/modules/task-center/train-task/AddTrainTask.jsx
+65
-25
src/modules/task-center/train-task/components/BasicInfo.jsx
+169
-117
src/modules/task-center/train-task/components/BasicInfo.less
+4
-0
src/modules/task-center/train-task/components/RelatedCourseDrawer.jsx
+4
-4
src/modules/task-center/train-task/components/RelatedExamDrawer.jsx
+26
-60
src/modules/task-center/train-task/components/RelatedExamDrawer.less
+3
-0
src/modules/task-center/train-task/components/TrainContent.jsx
+178
-88
src/modules/task-center/train-task/components/TrainContent.less
+9
-2
No files found.
src/modules/task-center/train-task/AddTrainTask.jsx
View file @
a4d52d69
...
@@ -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-0
2 17:25:17
* @LastEditTime: 2021-08-0
4 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
)
{
if
(
field
===
'trainDate'
)
{
// 固定培训时间,设置起始
setBasicInfo
({
...
basicInfo
,
startTime
:
value
&&
value
[
0
]?.
valueOf
(),
endTime
:
value
&&
value
[
1
]?.
valueOf
(),
});
}
else
{
setBasicInfo
({
setBasicInfo
({
...
basicInfo
,
...
basicInfo
,
[
field
]:
value
,
[
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
>
...
...
src/modules/task-center/train-task/components/BasicInfo.jsx
View file @
a4d52d69
...
@@ -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-0
2 17:50:51
* @LastEditTime: 2021-08-0
4 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=
{
plan
Name
}
value=
{
task
Name
}
placeholder=
'请输入培训任务名称(20字以内)'
placeholder=
'请输入培训任务名称(20字以内)'
maxLength=
{
20
}
maxLength=
{
20
}
style=
{
{
width
:
300
}
}
style=
{
{
width
:
300
}
}
// onChange={(e) => this.props.onChange('plan
Name', e.target.value)}
onChange=
{
(
e
)
=>
props
.
onChange
(
'task
Name'
,
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,15 +135,18 @@ function BasicInfo(props) {
...
@@ -148,15 +135,18 @@ 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
(
'duration
Type'
,
e
.
target
.
value
)
}
>
<
Radio
.
Group
value=
{
timeType
}
onChange=
{
(
e
)
=>
props
.
onChange
(
'time
Type'
,
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'
>
固定时间段
固定时间段
{
duration
Type
===
'FIXED_DURATION'
&&
(
{
time
Type
===
'FIXED_DURATION'
&&
(
<
div
className=
'picker-box'
>
<
div
className=
'picker-box'
>
<
FormItem
validateStatus=
{
startCheck
&&
!
startTime
&&
!
endTime
?
'error'
:
''
}
help=
{
startCheck
&&
!
startTime
&&
!
endTime
&&
'请选择培训时间'
}
>
<
RangePicker
<
RangePicker
style=
{
{
width
:
320
}
}
style=
{
{
width
:
320
}
}
showTime=
{
{
defaultValue
:
[
moment
().
add
(
10
,
'minutes'
),
moment
().
add
(
10
,
'minutes'
)]
}
}
showTime=
{
{
defaultValue
:
[
moment
().
add
(
10
,
'minutes'
),
moment
().
add
(
10
,
'minutes'
)]
}
}
...
@@ -165,15 +155,15 @@ function BasicInfo(props) {
...
@@ -165,15 +155,15 @@ function BasicInfo(props) {
近
1
个月
:
[
moment
().
add
(
10
,
'minute'
),
moment
().
add
(
1
,
'month'
).
endOf
(
'day'
)],
近
1
个月
:
[
moment
().
add
(
10
,
'minute'
),
moment
().
add
(
1
,
'month'
).
endOf
(
'day'
)],
近
3
个月
:
[
moment
().
add
(
10
,
'minute'
),
moment
().
add
(
3
,
'month'
).
endOf
(
'day'
)],
近
3
个月
:
[
moment
().
add
(
10
,
'minute'
),
moment
().
add
(
3
,
'month'
).
endOf
(
'day'
)],
}
}
}
}
//
disabledDate=
{
disabledDate
}
disabledDate=
{
disabledDate
}
// value=
{[
examStartTime
?
moment
(
Number
(
examStartTime
))
:
null
,
examEndTime
?
moment
(
Number
(
examEndTime
))
:
null
]
}
disabledTime=
{
disabledRangeTime
}
// disabledTime=
{
disabledRangeTime
}
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
)
=>
{
// setStartTime(date && date[0]?.valueOf()
);
props
.
onChange
(
'trainDate'
,
date
);
// setExamEndTime(date && date[1]?.valueOf());
}
}
/
/
}
}
/
>
{
' '
}
/
>
</
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'
,
}
}
>

</
i
>
</
Tooltip
>
</
span
>
}
required
>
<
Button
style=
{
{
display
:
'block'
}
}
>
添加指派对象
</
Button
>
<
Button
style=
{
{
display
:
'block'
}
}
>
添加指派对象
</
Button
>
{
assignList
1
.
length
+
assignList2
.
length
>
0
&&
(
{
assignList
>
0
&&
(
<
Space
size=
{
'12'
}
direction=
{
'vertical'
}
className=
'select-obj'
>
<
Space
size=
{
'12'
}
direction=
{
'vertical'
}
className=
'select-obj'
>
{
assignList
1
.
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
1
,
(
item
)
=>
{
{
_
.
map
(
assignList
,
(
item
)
=>
{
return
<
Tag
closable
>
{
item
.
name
}
</
Tag
>;
return
<
Tag
closable
>
{
item
.
name
}
</
Tag
>;
})
}
})
}
</
div
>
</
div
>
</
div
>
</
div
>
)
}
)
}
{
assignList
2
.
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
2
,
(
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'
,
}
}
>

</
i
>
</
Tooltip
>
</
span
>
}
>
<
Button
style=
{
{
display
:
'block'
}
}
>
添加协同者
</
Button
>
<
Button
style=
{
{
display
:
'block'
}
}
>
添加协同者
</
Button
>
{
helpStoreUsers
.
length
>
0
&&
(
{
helpStoreUser
Id
s
.
length
>
0
&&
(
<
div
className=
'select-obj'
>
<
div
className=
'select-obj'
>
{
_
.
map
(
helpStoreUsers
,
(
item
)
=>
{
{
_
.
map
(
helpStoreUser
Id
s
,
(
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
>
);
);
}
}
...
...
src/modules/task-center/train-task/components/BasicInfo.less
View file @
a4d52d69
...
@@ -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;
}
}
}
}
}
}
}
...
...
src/modules/task-center/train-task/components/RelatedCourseDrawer.jsx
View file @
a4d52d69
...
@@ -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-0
2 14:26:43
* @LastEditTime: 2021-08-0
4 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
.
co
urse
List
.
map
((
childItem
,
childIndex
)
=>
{
item
.
co
ntent
List
.
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
.
co
urse
List
.
map
((
childItem
,
childIndex
)
=>
{
item
.
co
ntent
List
.
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
.
co
urse
List
.
map
((
childItem
,
childIndex
)
=>
{
item
.
co
ntent
List
.
map
((
childItem
,
childIndex
)
=>
{
if
(
childItem
.
courseType
===
'PICTURE'
)
{
if
(
childItem
.
courseType
===
'PICTURE'
)
{
currentPictureCourseListData
.
push
(
childItem
.
courseId
);
currentPictureCourseListData
.
push
(
childItem
.
courseId
);
}
}
...
...
src/modules/task-center/train-task/components/RelatedExamDrawer.jsx
View file @
a4d52d69
...
@@ -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-0
3 20:02:27
* @LastEditTime: 2021-08-0
4 10:40:11
* @Description: 新建培训任务-关联考试抽屉
* @Description: 新建培训任务-关联考试抽屉
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
import
React
,
{
useState
,
useRef
}
from
'react'
;
import
React
,
{
useState
,
use
Effect
,
use
Ref
}
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'
>

</
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
>
...
...
src/modules/task-center/train-task/components/RelatedExamDrawer.less
View file @
a4d52d69
...
@@ -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;
}
}
}
}
}
}
}
src/modules/task-center/train-task/components/TrainContent.jsx
View file @
a4d52d69
...
@@ -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-0
3 18:32:02
* @LastEditTime: 2021-08-0
4 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
Sortable
Task
Container
=
sortableContainer
((
props
)
=>
<
div
{
...
props
}
></
div
>);
const
Sortable
Stage
Container
=
sortableContainer
((
props
)
=>
<
div
{
...
props
}
></
div
>);
const
Sortable
TaskItem
=
sortableElement
((
props
)
=>
<
div
{
...
props
}
>
{
props
.
task
item
}
</
div
>);
const
Sortable
StageItem
=
sortableElement
((
props
)
=>
<
div
{
...
props
}
>
{
props
.
stage
item
}
</
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
,
selected
Task
Index
:
0
,
selected
Stage
Index
:
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
>
);
);
};
};
on
Task
SortEnd
=
({
oldIndex
,
newIndex
})
=>
{
on
Stage
SortEnd
=
({
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
].
course
List
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
);
_
stageList
[
parentIndex
].
contentList
=
arrayMove
([].
concat
(
stageList
[
parentIndex
].
content
List
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
);
this
.
setState
(
this
.
setState
(
{
{
dataSource
:
_dataSource
,
stageList
:
_stageList
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
_dataSource
);
this
.
props
.
onChange
(
'stageList'
,
_stageList
);
}
}
);
);
}
}
};
};
handleRename
Task
Name
=
(
e
,
item
)
=>
{
handleRename
Stage
Name
=
(
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
false
;
};
// 移除阶段
handleDeleteStage
=
(
index
)
=>
{
return
confirm
({
title
:
'删除阶段'
,
content
:
'删除该阶段会连同课程、作业、考试一起删除,删除后不可恢复,是否仍要删除?'
,
icon
:
<
span
className=
'icon iconfont default-confirm-icon'
>

</
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
);
}
}
return
Promise
.
resolve
(
);
);
};
};
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
.
task
Name
}
</
span
>
<
span
className=
'info-text'
>
{
item
.
stage
Name
}
</
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'
>

</
span
>
<
span
className=
'icon iconfont'
>

</
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
.
handleDelete
Task
(
index
);
this
.
handleDelete
Stage
(
index
);
e
.
stopPropagation
();
e
.
stopPropagation
();
}
}
>
}
}
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'icon iconfont'
>

</
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
.
co
urse
List
.
map
((
contentItem
,
contentIndex
)
=>
(
{
item
.
co
ntent
List
.
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
task
Obj
=
{
const
stage
Obj
=
{
task
Name
:
''
,
stage
Name
:
''
,
index
:
dataSource
.
length
,
index
:
stageList
.
length
,
type
:
'input'
,
type
:
'input'
,
open
:
true
,
open
:
true
,
courseList
:
[],
contentList
:
[],
check
:
false
,
};
};
const
newData
=
[...
dataSource
,
task
Obj
];
const
_stageList
=
[...
stageList
,
stage
Obj
];
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
{
selected
Task
Index
}
=
this
.
state
;
const
{
selected
Stage
Index
}
=
this
.
state
;
const
{
dataSource
}
=
this
.
state
;
const
{
stageList
}
=
this
.
state
;
const
newData
=
[...
dataSource
];
const
_stageList
=
[...
stageList
];
const
selectData
=
[...
newData
[
selectedTaskIndex
].
course
List
];
const
selectData
=
[...
_stageList
[
selectedStageIndex
].
content
List
];
const
_selectData
=
[...
selectData
,
...
selectList
];
const
_selectData
=
[...
selectData
,
...
selectList
];
newData
[
selectedTaskIndex
].
course
List
=
_selectData
;
_stageList
[
selectedStageIndex
].
content
List
=
_selectData
;
this
.
setState
(
this
.
setState
(
{
{
showCourseDrawer
:
false
,
showCourseDrawer
:
false
,
dataSource
:
newData
,
stageList
:
_stageList
,
},
()
=>
{
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
(
newData
);
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'
>
<
Sortable
TaskContainer
useDragHandle
disableAutoscroll
helperClass=
'row-dragging'
onSortEnd=
{
this
.
onTask
SortEnd
}
>
<
Sortable
StageContainer
useDragHandle
disableAutoscroll
helperClass=
'row-dragging'
onSortEnd=
{
this
.
onStage
SortEnd
}
>
{
dataSource
.
map
((
item
,
index
)
=>
(
{
stageList
.
map
((
item
,
index
)
=>
(
<
Sortable
TaskItem
taskitem=
{
this
.
renderStageItem
(
item
,
index
)
}
index=
{
index
}
key=
{
index
}
></
SortableTask
Item
>
<
Sortable
StageItem
stageitem=
{
this
.
renderStageItem
(
item
,
index
)
}
index=
{
index
}
key=
{
index
}
></
SortableStage
Item
>
))
}
))
}
</
SortableTaskContainer
>
</
SortableStageContainer
>
{
stageList
.
length
<
10
&&
(
<
div
className=
'add-stage-btn'
onClick=
{
()
=>
this
.
addStage
()
}
>
<
div
className=
'add-stage-btn'
onClick=
{
()
=>
this
.
addStage
()
}
>
+ 添加阶段
+ 添加阶段
</
div
>
</
div
>
{
showCourseDrawer
&&
<
RelatedCourseDrawer
data=
{
dataSource
}
onClose=
{
this
.
onCloseCourseDrawer
}
onSelect=
{
this
.
confirmSelectCourse
}
/>
}
)
}
{
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'
>
<
span
>
<
img
src=
{
ENUM
.
LearningContentIcon
[
'LIVE'
]
}
/>
<
img
src=
{
ENUM
.
LearningContentIcon
[
'LIVE'
]
}
/>
</
span
>
<
span
>
<
span
>
直播课单个课程,学员学习进度达到
直播课单个课程,学员学习进度达到
<
FormItem
validateStatus=
{
startCheck
&&
!
percentCompleteLive
?
'error'
:
''
}
help=
{
startCheck
&&
!
percentCompleteLive
&&
'请输入完成标准'
}
>
<
Input
<
Input
//
value=
{
percentCompleteLive
}
value=
{
percentCompleteLive
}
onChange=
{
(
e
)
=>
{
onChange=
{
(
e
)
=>
{
// this.props.onChange('percentCompleteLive', e.target.value.replace(/\D/g, '')
);
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
>
线上课单个课节,学员学习进度达到
线上课单个课节,学员学习进度达到
<
FormItem
validateStatus=
{
startCheck
&&
!
percentCompleteVideo
?
'error'
:
''
}
help=
{
startCheck
&&
!
percentCompleteVideo
&&
'请输入完成标准'
}
>
<
Input
<
Input
//
value=
{
percentCompleteVideo
}
value=
{
percentCompleteVideo
}
onChange=
{
(
e
)
=>
{
onChange=
{
(
e
)
=>
{
// this.props.onChange('percentCompleteVideo', e.target.value.replace(/\D/g, '')
);
this
.
changePercentComplete
(
e
,
'percentCompleteVideo'
);
}
}
}
}
// onBlur=
{(
e
)
=
>
this.percentCompleteBlur(e, 'percentCompleteVideo')}
className=
'input-box'
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
>
图文课单个课程,学员学习进度达到
图文课单个课程,学员学习进度达到
<
FormItem
validateStatus=
{
startCheck
&&
!
percentCompletePicture
?
'error'
:
''
}
help=
{
startCheck
&&
!
percentCompletePicture
&&
'请输入完成标准'
}
>
<
Input
<
Input
//
value=
{
percentCompletePicture
}
value=
{
percentCompletePicture
}
onChange=
{
(
e
)
=>
{
onChange=
{
(
e
)
=>
{
// this.props.onChange('percentCompletePicture', e.target.value.replace(/\D/g, '')
);
this
.
changePercentComplete
(
e
,
'percentCompletePicture'
);
}
}
}
}
// onBlur=
{(
e
)
=
>
this.percentCompleteBlur(e, 'percentCompletePicture')}
className=
'input-box'
className=
'input-box'
/>
/>
</
FormItem
>
%,即视为"已完成"学习
%,即视为"已完成"学习
</
span
>
</
span
>
</
div
>
</
div
>
</
div
>
</
Form
>
</
div
>
</
div
>
)
}
)
}
</
div
>
</
div
>
...
...
src/modules/task-center/train-task/components/TrainContent.less
View file @
a4d52d69
...
@@ -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 {
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment