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
9ce18f7d
Commit
9ce18f7d
authored
Jul 18, 2021
by
yuananting
Browse files
Options
Browse Files
Download
Plain Diff
fix:解决合并代码的冲突
parents
9e46dec4
5aef17a1
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
707 additions
and
674 deletions
+707
-674
src/modules/course-manage/modal/PreviewCourseModal.jsx
+2
-2
src/modules/course-manage/offline-course/AddOfflineCourse.jsx
+4
-9
src/modules/course-manage/video-course/AddVideoCourse.jsx
+25
-21
src/modules/course-manage/video-course/AddVideoCourse.less
+31
-2
src/modules/course-manage/video-course/VideoCourseDetail.tsx
+2
-2
src/modules/course-manage/video-course/components/AddVideoIntro.jsx
+32
-32
src/modules/course-manage/video-course/components/ChapterList.jsx
+5
-1
src/modules/course-manage/video-course/components/ChapterList.less
+9
-3
src/modules/course-manage/video-course/components/VideoCourseList.jsx
+10
-10
src/modules/knowledge-base/components/KnowledgeBaseList.jsx
+2
-2
src/modules/plan-manage/AddPlan.jsx
+6
-2
src/modules/plan-manage/components/BasicInfo.jsx
+8
-8
src/modules/plan-manage/components/BasicInfo.less
+1
-0
src/modules/plan-manage/components/PlanList.jsx
+2
-3
src/modules/plan-manage/components/PlanList.less
+0
-1
src/modules/plan-manage/modal/relatedCourseModal.jsx
+20
-7
src/modules/prepare-lesson/modal/SelectPrepareFileModal.jsx
+22
-10
src/modules/root/Header.jsx
+3
-3
src/modules/root/Header.less
+1
-1
src/modules/root/Menu.less
+10
-3
src/modules/teach-tool/examination-manager/AddExam.tsx
+512
-552
No files found.
src/modules/course-manage/modal/PreviewCourseModal.jsx
View file @
9ce18f7d
/*
* @Author: 吴文洁
* @Date: 2020-07-23 14:54:16
* @LastEditors:
Please set LastEditors
* @LastEditTime: 2021-07-1
4 18:19:22
* @LastEditors:
yuananting
* @LastEditTime: 2021-07-1
8 16:53:35
* @Description: 大班直播课预览弹窗
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
...
...
src/modules/course-manage/offline-course/AddOfflineCourse.jsx
View file @
9ce18f7d
...
...
@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: yuananting
* @LastEditTime: 2021-07-1
5 12:08:28
* @LastEditTime: 2021-07-1
8 16:54:11
* @Description: 线下课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -10,7 +10,6 @@
import
React
from
'react'
;
import
{
Button
,
Input
,
Radio
,
message
,
Modal
,
TreeSelect
,
Select
,
Switch
,
TimePicker
,
InputNumber
,
Tooltip
}
from
'antd'
;
import
$
from
'jquery'
;
import
Bus
from
'@/core/bus'
;
import
RangePicker
from
'@/modules/common/DateRangePicker'
;
import
ShowTips
from
'@/components/ShowTips'
;
import
Breadcrumbs
from
'@/components/Breadcrumbs'
;
...
...
@@ -27,6 +26,7 @@ import GraphicsEditor from '../components/GraphicsEditor';
import
MultipleDatePicker
from
'@/components/MultipleDatePicker'
;
import
ImgClipModal
from
'@/components/ImgClipModal'
;
import
'./AddOfflineCourse.less'
;
import
Bus
from
'@/core/bus'
;
const
{
Option
}
=
Select
;
const
defaultCoverUrl
=
'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
;
...
...
@@ -342,8 +342,7 @@ class AddOfflineCourse extends React.Component {
visible
:
true
,
imageFile
:
file
});
}
};
//获取resourceId
getSignature
=
(
blob
,
fileName
)
=>
{
...
...
@@ -626,11 +625,7 @@ class AddOfflineCourse extends React.Component {
});
}
changeIntro
=
(
value
,
textLength
)
=>
{
// const isMore = textLength > 1000;
// if (isMore) {
// message.warning('内容过长,不能超过1000字');
// }
changeIntro
=
(
value
)
=>
{
this
.
setState
({
introduce
:
value
});
};
...
...
src/modules/course-manage/video-course/AddVideoCourse.jsx
View file @
9ce18f7d
...
...
@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: yuananting
* @LastEditTime: 2021-07-1
5 12:04:40
* @LastEditTime: 2021-07-1
8 16:54:33
* @Description: 线上课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -45,7 +45,14 @@ const defaultScheduleMedia = [
]
const
whetherVisitorsJoin
=
'NO'
let
cutFlag
=
false
let
cutFlag
=
false
;
const
SUPPORT_WORD_PDF
=
[
"application/msword"
,
"application/wps-writer"
,
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
,
"application/pdf"
,
"application/wps-office.pdf"
];
class
AddVideoCourse
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
...
...
@@ -87,7 +94,6 @@ class AddVideoCourse extends React.Component {
],
// 课节列表
// videoType: "MP4",
mediaNameAlias
:
''
,
// 任一视频重命名的名称(气泡框)
popConfirmVisible
:
false
,
selectTypeList
:[
'MP4'
],
accept
:
'video/mp4'
}
...
...
@@ -318,10 +324,11 @@ class AddVideoCourse extends React.Component {
return
;
}
selectedFileList
.
map
((
file
,
index
)
=>
{
console
.
log
(
''
)
const
{
ossUrl
,
resourceId
,
folderName
,
folderFormat
,
folderSize
}
=
file
;
const
_mediaName
=
folderName
.
replace
(
`.
${
_
.
last
(
folderName
.
split
(
'.'
)).
toLowerCase
()}
`
,
''
)
console
.
log
(
'folderFormat'
,
folderFormat
);
if
(
folderFormat
===
'MP4'
){
if
(
folderFormat
===
'MP4'
||
folderFormat
===
'video/mp4'
){
const
videoDom
=
document
.
createElement
(
'video'
)
videoDom
.
src
=
ossUrl
videoDom
.
onloadedmetadata
=
()
=>
{
...
...
@@ -329,26 +336,17 @@ class AddVideoCourse extends React.Component {
mediaContent
:
resourceId
,
contentType
:
'SCHEDULE'
,
mediaType
:
"VIDEO"
,
mediaName
:
folderName
.
replace
(
'.mp4'
,
''
)
,
mediaName
:
_mediaName
,
videoDuration
:
videoDom
.
duration
,
resourceId
,
mediaUrl
:
ossUrl
,
sort
:
_courseChapterList
.
length
})
this
.
setState
({
// size: folderSize,
// videoName: folderName,
// videoType: folderFormat,
courseChapterList
:
_courseChapterList
})
}
}
else
{
let
_mediaName
=
folderName
;
if
(
folderFormat
===
'PDF'
){
_mediaName
=
folderName
.
replace
(
'.pdf'
,
''
)
}
else
{
_mediaName
=
folderName
.
replace
(
'.doc'
,
''
)
&&
folderName
.
replace
(
'.docx'
,
''
)
}
}
else
if
(
folderFormat
===
"WORD"
||
folderFormat
===
"PDF"
||
SUPPORT_WORD_PDF
.
indexOf
(
folderFormat
)
>-
1
){
const
suffix
=
_
.
last
(
folderName
.
split
(
'.'
)).
toUpperCase
();
_courseChapterList
.
push
({
mediaContent
:
resourceId
,
...
...
@@ -556,7 +554,6 @@ class AddVideoCourse extends React.Component {
chapterNameValidateStatus
:
''
,
chapterNameHelpMsg
:
''
,
mediaNameAlias
:
''
,
popConfirmVisible
:
false
})
});
...
...
@@ -684,6 +681,14 @@ class AddVideoCourse extends React.Component {
})
}
}
renderToolTipTitle
=
()
=>
{
return
(<
div
>
<
p
>
视频支持mp4格式,大小不超过2G;
</
p
>
<
p
>
文件支持PDF、docx、doc格式,大小不超过100M
</
p
>
</
div
>)
}
render
()
{
const
{
pageType
,
...
...
@@ -706,7 +711,6 @@ class AddVideoCourse extends React.Component {
id
,
courseChapterList
,
imageFile
,
popConfirmVisible
,
selectTypeList
,
accept
}
=
this
.
state
...
...
@@ -738,7 +742,7 @@ class AddVideoCourse extends React.Component {
<
div
className=
'upload-video mt16'
>
<
div
className=
'content flex'
>
<
span
className=
'label required'
>
上传课节:
</
span
>
<
span
className=
'label required
upload-chapter
'
>
上传课节:
</
span
>
</
div
>
<
div
className=
'sub-content'
>
<
div
className=
"btn-wrap"
>
...
...
@@ -761,7 +765,7 @@ class AddVideoCourse extends React.Component {
</
div
>
<
div
className=
'tips'
>
课节数量限制20个,文件规格说明
<
Tooltip
title=
"视频支持mp4格式,大小不超过2G;文件支持PDF、docx、doc格式,大小不超过100M
"
>
<
Tooltip
title=
{
this
.
renderToolTipTitle
()
}
overlayClassName=
"my-chapter-tooltip
"
>
<
i
className=
'icon iconfont'
style=
{
{
cursor
:
'pointer'
,
color
:
'#bfbfbf'
,
fontSize
:
'14px'
}
}
>

</
i
>
</
Tooltip
>
</
div
>
...
...
@@ -821,7 +825,7 @@ class AddVideoCourse extends React.Component {
</
If
>
<
div
className=
'cover-url flex mt16'
>
<
div
className=
'label'
>
封面图:
</
div
>
<
div
className=
'label
cover
'
>
封面图:
</
div
>
<
div
className=
'cover-url__wrap'
>
<
div
className=
'opt-btns'
>
<
div
>
...
...
src/modules/course-manage/video-course/AddVideoCourse.less
View file @
9ce18f7d
...
...
@@ -32,6 +32,12 @@
display:inline-block;
text-align:right;
width:85px;
&.upload-chapter {
margin-top: 6px;
}
&.cover {
margin-top: 2px;
}
}
.required {
position: relative;
...
...
@@ -172,10 +178,9 @@
}
.course-chapter-list {
max-height: 245px;
min-height: 130px;
overflow-y: auto ;
border-radius: 4px;
padding: 16px;
padding: 1
2px 16px 16px 1
6px;
.course-ware {
display: flex;
align-items: center;
...
...
@@ -257,4 +262,27 @@
.ant-form-item-explain {
min-height: 0;
}
}
.course-chapter-title-popover {
.tag-title {
color: #333333;
margin-bottom: 8px;
width: 318px;
}
.chapter-btns {
margin-top: 16px;
display: flex;
justify-content: flex-end;
.confirm {
margin-left: 8px;
}
}
.ant-form-item {
margin-bottom: 0 !important;
}
}
.my-chapter-tooltip {
max-width: 600px!important;
}
\ No newline at end of file
src/modules/course-manage/video-course/VideoCourseDetail.tsx
View file @
9ce18f7d
/*
* @Author: wufan
* @Date: 2020-04-28 18:05:30
* @LastEditors:
Please set LastEditors
* @LastEditTime: 2021-07-1
3 15:26:1
1
* @LastEditors:
yuananting
* @LastEditTime: 2021-07-1
5 14:04:2
1
* @Description: 线上课课程课节详情
*/
...
...
src/modules/course-manage/video-course/components/AddVideoIntro.jsx
View file @
9ce18f7d
...
...
@@ -111,53 +111,53 @@ class AddVideoIntro extends React.Component {
<
span
className=
'label'
>
观看设置:
</
span
>
<
div
className=
'content'
>
<
div
>
<
Switch
checked=
{
whetherVisitorsJoin
===
'NO'
?
true
:
false
}
onChange=
{
this
.
whetherVisitorsJoinChange
}
/>
</
div
>
<
Switch
checked=
{
whetherVisitorsJoin
===
"NO"
?
true
:
false
}
onChange=
{
this
.
whetherVisitorsJoinChange
}
/>
</
div
>
<
div
>
<
div
className=
'desc'
>
<
Choose
>
<
When
condition=
{
whetherVisitorsJoin
===
'NO'
}
>
<
div
>
已开启,学员需绑定手机号才可观看
</
div
>
</
When
>
<
Otherwise
>
<
div
>
已关闭,学员无需绑定手机号即可观看
</
div
>
</
Otherwise
>
</
Choose
>
<
div
className=
"desc"
>
<
Choose
>
<
When
condition=
{
whetherVisitorsJoin
===
"NO"
}
>
<
div
>
已开启,学员需绑定手机号才可观看
</
div
>
</
When
>
<
Otherwise
>
<
div
>
已关闭,学员无需绑定手机号即可观看
</
div
>
</
Otherwise
>
</
Choose
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className=
'store-show'
>
<
span
className=
'label'
>
学院展示:
</
span
>
<
div
className=
'content'
>
<
Row
>
<
Col
span=
{
3
}
>
<
Switch
checked=
{
shelfState
===
'YES'
?
true
:
false
}
onChange=
{
this
.
shelfStateChange
}
/>
</
Col
>
<
Col
span=
{
21
}
>
<
div
className=
'desc'
>
<
Choose
>
<
When
condition=
{
shelfState
===
'YES'
}
>
<
div
className=
"store-show"
>
<
span
className=
"label"
>
学院展示:
</
span
>
<
div
className=
"content"
>
<
Row
>
<
Col
span=
{
3
}
>
<
Switch
checked=
{
shelfState
===
"YES"
?
true
:
false
}
onChange=
{
this
.
shelfStateChange
}
/>
</
Col
>
<
Col
span=
{
21
}
>
<
div
className=
"desc"
>
<
Choose
>
<
When
condition=
{
shelfState
===
"YES"
}
>
<
div
>
已开启,课程将在该学院的学员课程列表中显示
</
div
>
</
When
>
<
Otherwise
>
</
When
>
<
Otherwise
>
<
div
>
已关闭,课程将在该学院的学员课程列表中隐藏
</
div
>
</
Otherwise
>
</
Choose
>
</
Otherwise
>
</
Choose
>
</
div
>
</
Col
>
</
Row
>
</
div
>
</
div
>
<
div
className=
'introduce'
>
<
span
className=
'label'
>
课程简介:
</
span
>
<
div
className=
'content'
>
<
div
className=
'intro-list'
>
<
div
className=
'intro-list__item introduce-editor'
>
<
div
className=
"introduce"
>
<
span
className=
"label"
>
课程简介:
</
span
>
<
div
className=
"content"
>
<
div
className=
"intro-list"
>
<
div
className=
"intro-list__item introduce-editor"
>
{
(
!
id
||
loadintroduce
)
&&
(
<
GraphicsEditor
maxLimit=
{
1000
}
id=
'intro'
id=
"intro"
isIntro=
{
true
}
detail=
{
{
content
:
introduce
,
...
...
src/modules/course-manage/video-course/components/ChapterList.jsx
View file @
9ce18f7d
import
React
from
'react'
;
import
'./ChapterList.less'
;
import
{
FileTypeIcon
}
from
'@/common/constants/academic/lessonEnum'
const
FileTypeIconMap
=
FileTypeIcon
;
function
ChapterList
(
props
){
const
{
courseChapterList
}
=
props
;
...
...
@@ -9,7 +12,8 @@ function ChapterList(props){
{
_
.
map
(
courseChapterList
,(
item
,
index
)
=>
{
return
<
div
className=
'course-ware'
>
<
div
className=
'course-ware__index'
>
{
index
<
9
?
`0${index + 1 } `
:
`${index + 1 } `
}
</
div
>
<
img
className=
'course-ware__img'
src=
{
FileTypeIconMap
[
item
.
mediaType
]
}
alt=
''
/>
<
div
className=
'course-ware__index'
>
{
index
<
9
?
`0${index + 1 }`
:
`${index + 1 }`
}
</
div
>
<
div
className=
"course-ware__detail"
>
<
div
className=
'course-ware__detail__name'
>
{
item
.
mediaName
}
</
div
>
{
item
.
mediaType
===
'VIDEO'
&&
...
...
src/modules/course-manage/video-course/components/ChapterList.less
View file @
9ce18f7d
...
...
@@ -14,18 +14,24 @@
font-weight: 500;
color: #999999;
line-height: 18px;
white-space: nowrap;
margin-left: 8px;
margin-right: 6px;
line-height: 20px;
}
&__img {
width: 20px;
height: 20px;
}
&__detail {
display: flex;
flex-direction: column;
width: calc(~'100% - 18px');
&__name {
width: 267px;
font-size: 13px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 2
1
px;
line-height: 2
0
px;
margin-bottom: 4px;
}
&__duration {
...
...
src/modules/course-manage/video-course/components/VideoCourseList.jsx
View file @
9ce18f7d
import
React
from
'react'
;
import
{
Modal
,
message
,
Tooltip
,
Switch
,
Dropdown
}
from
'antd'
;
import
_
from
'underscore'
;
import
{
PageControl
}
from
'@/components'
;
import
{
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
;
import
React
from
"react"
import
{
Modal
,
message
,
Tooltip
,
Switch
,
Dropdown
}
from
"antd"
import
_
from
"underscore"
import
{
PageControl
}
from
"@/components"
import
{
LIVE_SHARE
}
from
"@/domains/course-domain/constants"
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
ShareLiveModal
from
'@/modules/course-manage/modal/ShareLiveModal'
;
import
CourseService
from
'@/domains/course-domain/CourseService'
;
import
RelatedPlanModal
from
'../../modal/RelatedPlanModal'
;
import
User
from
'@/common/js/user'
;
import
ShareLiveModal
from
"@/modules/course-manage/modal/ShareLiveModal"
import
CourseService
from
"@/domains/course-domain/CourseService"
import
RelatedPlanModal
from
"../../modal/RelatedPlanModal"
import
User
from
"@/common/js/user"
import
VideoCourseDetail
from
'../VideoCourseDetail'
;
import
WatchData
from
'./WatchData'
;
import
WatchData
from
"./WatchData"
;
import
{
XMTable
}
from
'@/components'
;
import
college
from
'@/common/lottie/college'
;
import
'./VideoCourseList.less'
;
...
...
src/modules/knowledge-base/components/KnowledgeBaseList.jsx
View file @
9ce18f7d
...
...
@@ -2,8 +2,8 @@
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-12 14:49:40
* @LastEditors:
Please set LastEditors
* @LastEditTime: 2021-07-1
3 15:28:04
* @LastEditors:
yuananting
* @LastEditTime: 2021-07-1
8 16:58:23
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
src/modules/plan-manage/AddPlan.jsx
View file @
9ce18f7d
...
...
@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39
* @LastEditors: yuananting
* @LastEditTime: 2021-07-
08 10:52:05
* @LastEditTime: 2021-07-
18 16:06:17
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -65,6 +65,7 @@ function AddPlan() {
planId
:
id
,
}).
then
((
res
)
=>
{
const
{
planId
,
planName
,
enableState
,
operateType
,
...
...
@@ -78,6 +79,7 @@ function AddPlan() {
let
coverId
;
let
coverUrl
;
let
instro
;
let
hasIntro
=
false
;
courseMediaVOS
.
map
((
item
)
=>
{
switch
(
item
.
contentType
)
{
case
'COVER'
:
...
...
@@ -85,6 +87,7 @@ function AddPlan() {
coverUrl
=
item
.
mediaUrl
;
break
;
case
'INTRO'
:
hasIntro
=
true
;
instro
=
item
.
mediaContent
;
break
;
default
:
...
...
@@ -102,6 +105,7 @@ function AddPlan() {
}
setTaskList
(
trainingTaskList
);
setBasicData
({
planId
,
planName
,
coverUrl
:
coverUrl
||
defaultCover
,
coverId
,
...
...
@@ -282,7 +286,7 @@ function AddPlan() {
<
div
className=
'add-plan-page__form'
>
<
div
className=
'basic-info__wrap'
>
<
div
className=
'title'
>
基本信息
</
div
>
<
BasicInfo
data=
{
basicData
}
onChange=
{
handleChangeBasicInfo
}
/>
<
BasicInfo
data=
{
{
...
basicData
,
id
}
}
onChange=
{
handleChangeBasicInfo
}
/>
</
div
>
<
div
className=
'basic-info__wrap'
>
<
div
className=
'title'
>
培训任务
</
div
>
...
...
src/modules/plan-manage/components/BasicInfo.jsx
View file @
9ce18f7d
/*
* @Author: yuananting
* @Date: 2021-07-05 10:48:08
* @LastEditors:
Please set LastEditors
* @LastEditTime: 2021-07-
09 11:51:46
* @LastEditors:
yuananting
* @LastEditTime: 2021-07-
18 16:58:40
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...
...
@@ -22,7 +22,7 @@ import SelectOperatorModal from '../modal/SelectOperatorModal';
import
SelectPrepareFileModal
from
'@/modules/prepare-lesson/modal/SelectPrepareFileModal'
;
import
Upload
from
'@/core/upload'
;
import
GraphicsEditor
from
'@/modules/course-manage/components/GraphicsEditor'
;
import
ImgClipModal
from
'@/components/ImgClipModal'
;
import
ImgClipModal
from
'@/components/ImgClipModal'
import
'./BasicInfo.less'
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png'
;
...
...
@@ -133,13 +133,13 @@ class BasicInfo extends React.Component {
};
changeIntro
=
(
value
)
=>
{
this
.
props
.
onChange
(
'in
troduce
'
,
value
);
this
.
props
.
onChange
(
'in
stro
'
,
value
);
};
render
()
{
const
{
operatorModalVisible
,
showSelectFileModal
,
visible
,
imageFile
}
=
this
.
state
;
const
{
data
}
=
this
.
props
;
const
{
planName
,
coverUrl
,
in
troduce
,
enableState
,
operateType
,
selectOperatorList
,
percentCompleteLive
,
percentCompleteVideo
,
percentCompletePicture
}
=
const
{
planName
,
coverUrl
,
in
stro
,
enableState
,
operateType
,
selectOperatorList
,
percentCompleteLive
,
percentCompleteVideo
,
percentCompletePicture
,
planId
,
id
}
=
data
;
// 当前是否使用的是默认图片
const
isDefaultCover
=
coverUrl
===
defaultCover
;
...
...
@@ -182,17 +182,17 @@ class BasicInfo extends React.Component {
</
div
>
<
div
className=
'introduction'
>
<
span
className=
'label'
>
简介:
</
span
>
<
GraphicsEditor
{
(
!
id
||
planId
)
&&
(
<
GraphicsEditor
id=
'intro'
isIntro=
{
true
}
maxLimit=
{
1000
}
detail=
{
{
content
:
in
troduce
,
content
:
in
stro
,
}
}
onChange=
{
(
val
)
=>
{
this
.
changeIntro
(
val
);
}
}
/>
/>
)
}
</
div
>
<
div
className=
'wether-use'
>
<
span
className=
'label'
>
是否启用:
</
span
>
...
...
src/modules/plan-manage/components/BasicInfo.less
View file @
9ce18f7d
...
...
@@ -89,6 +89,7 @@
}
.choose-business {
margin-top: 12px;
margin-left: 24px;
.ant-btn {
margin-right: 12px;
}
...
...
src/modules/plan-manage/components/PlanList.jsx
View file @
9ce18f7d
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:46:46
* @LastEditors:
fusanqias
ng
* @LastEditTime: 2021-0
6-15 14:37:20
* @LastEditors:
yuananti
ng
* @LastEditTime: 2021-0
7-18 16:58:52
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -52,7 +52,6 @@ function PlanList(props) {
title
:
'课程总数量'
,
key
:
'courseNum'
,
dataIndex
:
'courseNum'
,
width
:
110
,
render
:
(
val
,
record
)
=>
{
return
<
div
className=
'course-number'
>
{
val
}
</
div
>;
},
...
...
src/modules/plan-manage/components/PlanList.less
View file @
9ce18f7d
.plan-list {
margin-top: 12px;
.course-number {
text-align: right;
margin-right: 45px;
}
...
...
src/modules/plan-manage/modal/relatedCourseModal.jsx
View file @
9ce18f7d
/*
* @Author: yuananting
* @Date: 2021-07-05 10:50:10
* @LastEditors:
yuananting
* @LastEditTime: 2021-07-1
3 19:55:29
* @LastEditors:
Please set LastEditors
* @LastEditTime: 2021-07-1
8 10:47:02
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
;
import
_
from
'underscore'
;
import
{
Table
,
Radio
,
Tabs
,
Modal
,
Input
,
message
,
Button
,
Tooltip
}
from
'antd'
;
import
{
Radio
,
Tabs
,
Modal
,
Input
,
message
,
Button
,
Tooltip
}
from
'antd'
;
import
{
PageControl
}
from
'@/components'
;
import
{
PageControl
,
XMTable
}
from
'@/components'
;
import
college
from
'@/common/lottie/college'
;
import
CourseService
from
'@/domains/course-domain/CourseService'
;
import
User
from
'@/common/js/user'
;
...
...
@@ -732,7 +733,11 @@ class SelectOperatorModal extends React.Component {
</
div
>
</
div
>
<
div
>
<
Table
<
XMTable
renderEmpty=
{
{
image
:
college
,
description
:
'暂无数据'
,
}
}
rowKey=
{
(
record
)
=>
record
.
liveCourseId
}
dataSource=
{
liveDataSource
}
columns=
{
this
.
parseLiveColumns
()
}
...
...
@@ -824,7 +829,11 @@ class SelectOperatorModal extends React.Component {
</
div
>
</
div
>
<
div
>
<
Table
<
XMTable
renderEmpty=
{
{
image
:
college
,
description
:
'暂无数据'
,
}
}
rowKey=
{
(
record
)
=>
record
.
id
}
dataSource=
{
videoDataSource
[
videoCourseDivision
]
}
columns=
{
this
.
parseVideoColumns
()
}
...
...
@@ -929,7 +938,11 @@ class SelectOperatorModal extends React.Component {
</
div
>
</
div
>
<
div
>
<
Table
<
XMTable
renderEmpty=
{
{
image
:
college
,
description
:
'暂无数据'
,
}
}
rowKey=
{
(
record
)
=>
record
.
id
}
dataSource=
{
pictureDataSource
}
columns=
{
this
.
parsePictureColumns
()
}
...
...
src/modules/prepare-lesson/modal/SelectPrepareFileModal.jsx
View file @
9ce18f7d
...
...
@@ -290,7 +290,8 @@ class SelectPrepareFileModal extends React.Component {
const
{
fileListRef
}
=
this
.
refs
;
// const hasReachBottom = fileListRef.scrollTop + fileListRef.clientHeight === fileListRef.scrollHeight;
const
hasReachBottom
=
fileListRef
.
scrollTop
+
fileListRef
.
clientHeight
>
fileListRef
.
scrollHeight
-
1
;
const
hasReachBottom
=
fileListRef
.
scrollTop
+
fileListRef
.
clientHeight
>
fileListRef
.
scrollHeight
-
10
;
console
.
log
(
"fileListRef.scrollTop + fileListRef.clientHeight"
,
hasReachBottom
,
fileListRef
.
scrollTop
,
fileListRef
.
clientHeight
,
fileListRef
.
scrollHeight
)
if
(
!
hasReachBottom
||
!
hasMore
)
return
;
const
currentFolder
=
folderPathList
[
folderPathList
.
length
-
1
];
...
...
@@ -325,14 +326,16 @@ class SelectPrepareFileModal extends React.Component {
// 上传文件
handleUpload
=
(
event
)
=>
{
const
{
selectType
}
=
this
.
props
;
const
{
selectType
,
accept
}
=
this
.
props
;
const
fileList
=
event
.
target
.
files
;
// 判断文件的大小是否超出了限制
const
nonCompliantFileList
=
[];
const
_fileList
=
[...
fileList
];
const
_accept
=
accept
.
split
(
','
);
console
.
log
(
"_fileList"
,
_fileList
);
console
.
log
(
'accept'
,
_accept
);
_fileList
.
map
((
file
,
index
)
=>
{
console
.
log
(
'file'
,
file
);
let
{
size
,
type
,
name
}
=
file
;
if
(
!
type
)
{
type
=
getFileTypeByName
(
name
);
...
...
@@ -341,6 +344,11 @@ class SelectPrepareFileModal extends React.Component {
nonCompliantFileList
.
push
(
file
);
_fileList
.
splice
(
index
,
1
);
}
console
.
log
(
'type'
,
type
);
//mac的企业微信环境下加accept不起作用,所以需要我们在选择完成后做一层限制
// if(accept && _accept.indexOf("."+_.last(name.split('.')).toLowerCase()) === -1){
// _fileList.splice(index, 1);
// }
file
.
key
=
count
++
;
});
console
.
log
(
"nonCompliantFileList"
,
nonCompliantFileList
);
...
...
@@ -573,8 +581,9 @@ class SelectPrepareFileModal extends React.Component {
}
</
div
>
{
!
_
.
isEmpty
(
folderList
)
?
<
div
>
<
Choose
>
<
When
condition=
{
!
_
.
isEmpty
(
folderList
)
}
>
<
div
>
<
div
className=
"file-list"
onScrollCapture=
{
()
=>
this
.
handleScrollEvent
()
}
style=
{
{
height
:
'320px'
,
overflowY
:
'auto'
}
}
...
...
@@ -611,8 +620,7 @@ class SelectPrepareFileModal extends React.Component {
// 文件禁止点击的情况(移动、直播场景下文件为Excel、文件已经被关联了、文件不合法)
const
disabled
=
hiddenVideo
||
(
!
isFolder
&&
operateType
===
'move'
)
||
(
scene
===
'liveCourse'
&&
folder
.
folderFormat
===
'EXCEL'
)
||
!!
hasRelation
||
(
!
isFolder
&&
!
FILE_SUFFIX_LIST
.
includes
(
suffix
));
// console.log('currentFile',currentFile);
// console.log('folder',folder);
let
currentFileCheck
=
false
;
if
(
currentFile
){
currentFileCheck
=
(
currentFile
.
id
===
folder
.
id
)
...
...
@@ -660,12 +668,16 @@ class SelectPrepareFileModal extends React.Component {
})
}
</
div
>
</
div
>
:
<
LottieIcon
</
div
>
</
When
>
<
Otherwise
>
<
LottieIcon
title=
{
<
span
className=
"desc"
>
这个文件夹是空的
</
span
>
}
type=
"college"
size=
{
150
}
/>
</
Otherwise
>
</
Choose
>
}
<
UploadProgressModal
...
...
src/modules/root/Header.jsx
View file @
9ce18f7d
/*
* @Author: 吴文洁
* @Date: 2019-09-10 18:26:03
* @LastEditors:
yuananting
* @LastEditTime: 2021-07-
06 14:37:49
* @LastEditors:
Please set LastEditors
* @LastEditTime: 2021-07-
14 14:14:16
* @Description:
*/
import
React
,
{
useRef
,
useContext
,
useEffect
,
useState
}
from
'react'
;
...
...
@@ -344,7 +344,7 @@ function Header(props) {
<
div
className=
'h5-url'
>
<
div
className=
'name'
>
手机端学院
</
div
>
<
div
id=
'h5-qrcode'
></
div
>
<
div
className=
'tip'
>
微信扫码,打开
学院
</
div
>
<
div
className=
'tip'
>
企业员工扫码登录
学院
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/modules/root/Header.less
View file @
9ce18f7d
...
...
@@ -378,7 +378,7 @@
.name,
.tip {
width: 70px;
font-size: 1
4
px;
font-size: 1
3
px;
color: #333333;
line-height: 52px;
margin: 0 auto;
...
...
src/modules/root/Menu.less
View file @
9ce18f7d
...
...
@@ -120,7 +120,7 @@
.ant-menu-item {
padding-left: 46px !important;
&:hover {
color:
@active-color
!important;
color:
#333
!important;
}
}
}
...
...
@@ -131,17 +131,20 @@
.ant-menu-item-selected {
color: @active-color;
font-weight: 500;
&:hover {
color: @active-color!important;
}
.listType {
background: @active-color;
}
}
.ant-menu-submenu-arrow {
right:
22px
;
right:
10px!important
;
color: @active-color;
}
}
.ant-menu-submenu-arrow {
right:
22px
;
right:
10px!important
;
color: #5e606a;
}
}
...
...
@@ -277,6 +280,10 @@
left: 74px;
}
}
.ant-menu-inline .ant-menu-item, .ant-menu-inline .ant-menu-submenu-title {
width: calc(100% - 15px)!important;
}
.ant-menu-submenu:hover {
// background: rgba(41, 102, 255, .05) !important;
&.ant-menu-submenu-title:hover {
...
...
src/modules/teach-tool/examination-manager/AddExam.tsx
View file @
9ce18f7d
import
React
,
{
useState
,
useRef
,
useEffect
}
from
'react'
;
import
Breadcrumbs
from
'@/components/Breadcrumbs'
;
import
{
Form
,
Input
,
Button
,
InputNumber
,
DatePicker
,
Switch
,
Radio
,
message
,
Modal
,
Tooltip
}
from
'antd'
;
import
{
withRouter
}
from
'react-router-dom'
;
import
User
from
'@/common/js/user'
;
import
moment
from
'moment'
;
import
Service
from
'@/common/js/service'
;
import
_
from
'underscore'
;
import
React
,
{
useState
,
useRef
,
useEffect
,
useContext
}
from
'react'
import
Breadcrumbs
from
"@/components/Breadcrumbs"
;
import
{
Form
,
Alert
,
Input
,
Button
,
InputNumber
,
DatePicker
,
Switch
,
Radio
,
message
,
Modal
,
Tooltip
}
from
'antd'
;
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
User
from
"@/common/js/user"
;
import
moment
from
'moment'
import
Service
from
"@/common/js/service"
;
import
_
from
'underscore'
import
GraphicsEditor
from
'../../course-manage/components/GraphicsEditor'
;
import
SelectPaperModal
from
'./SelectPaperModal'
;
import
PreviewModal
from
'./PreviewModal'
;
import
ShowTips
from
'@/components/ShowTips'
;
import
SelectPaperModal
from
'./SelectPaperModal'
import
PreviewModal
from
'./PreviewModal'
import
ShowTips
from
"@/components/ShowTips"
;
import
'./AddExam.less'
;
const
{
RangePicker
}
=
DatePicker
;
function
AddExam
(
props
:
any
)
{
const
paperInfoInit
:
any
=
{
passScore
:
60
};
const
[
showModal
,
setShowModal
]
=
useState
(
false
);
const
[
paperInfo
,
setPaperInfo
]
=
useState
(
paperInfoInit
);
const
[
paperId
,
setPaperId
]
=
useState
(
''
);
const
[
passRate
,
setPassRate
]
=
useState
(
60
);
//及格线
const
[
examStartTime
,
setStartTime
]
=
useState
(
''
);
const
[
examEndTime
,
setExamEndTime
]
=
useState
(
''
);
const
[
examName
,
setExamName
]
=
useState
(
''
);
const
[
needPhone
,
setNeedPhone
]
=
useState
(
'DO_NOT_NEED_PHONE_VERIFY'
);
const
[
needOptionDisorder
,
setNeedOptionDisorder
]
=
useState
(
'OPTION_SORT'
);
const
[
resultContent
,
setResultContent
]
=
useState
(
'PASS_AND_SCORE'
);
const
[
answerAnalysis
,
setAnswerAnalysis
]
=
useState
(
'RIGHT_OR_WRONG'
);
const
[
resultShow
,
setResultShow
]
=
useState
(
'IMMEDIATELY'
);
const
[
examDesc
,
setExamDesc
]
=
useState
(
''
);
const
[
passScore
,
setPassScore
]
=
useState
(
100
);
const
[
desclen
,
setDescLen
]
=
useState
(
0
);
const
[
check
,
setCheck
]
=
useState
(
false
);
const
[
getData
,
setGetData
]
=
useState
(
false
);
const
[
preview
,
setPreview
]
=
useState
(
false
);
const
[
examTotal
,
setExamTotal
]
=
useState
(
0
);
const
[
examList
,
setExamList
]
=
useState
([]);
const
request
=
useRef
(
false
);
const
{
match
}
=
props
;
const
[
examDuration
,
setExamDuration
]
=
useState
(
undefined
);
useEffect
(()
=>
{
queryExamList
();
switch
(
props
.
type
)
{
case
'copy'
:
// 考试列表-复制考试进入
case
'edit'
:
// 考试列表-编辑考试进入
queryExamDetail
();
break
;
case
'organizeExam'
:
// 试卷列表-组织考试进入
case
'newPaperToAddExam'
:
// 组卷页面-新建保存试卷并组织考试
case
'editPaperToAddExam'
:
// 组卷页面-编辑保存试卷并组织考试
setGetData
(
true
);
setPaperInfo
(
props
.
paperInfo
);
setExamName
(
props
.
paperInfo
?.
paperName
);
break
;
}
},
[
props
.
paperInfo
,
props
.
type
,
queryExamDetail
]);
useEffect
(()
=>
{
setPaperId
(
paperInfo
.
paperId
);
setPassRate
(
paperInfo
.
passRate
);
},
[
paperInfo
.
paperId
,
paperInfo
.
passRate
]);
useEffect
(()
=>
{
setPassScore
(
Math
.
round
((((
paperInfo
.
totalScore
||
0
)
*
(
passRate
||
0
))
as
any
)
/
100
));
setExamTotal
(
paperInfo
.
singleChoiceCnt
+
paperInfo
.
multiChoiceCnt
+
paperInfo
.
judgeCnt
+
paperInfo
.
gapFillingCnt
+
paperInfo
.
indefiniteChoiceCnt
||
0
);
},
[
paperInfo
.
gapFillingCnt
,
paperInfo
.
indefiniteChoiceCnt
,
paperInfo
.
judgeCnt
,
paperInfo
.
multiChoiceCnt
,
paperInfo
.
paperId
,
paperInfo
.
singleChoiceCnt
,
paperInfo
.
totalScore
,
passRate
,
]);
function
disabledDate
(
current
:
any
)
{
// Can not select days before today and today
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
)
=>
{
console
.
log
(
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
)
as
any
);
setAnswerAnalysis
(
result
.
answerAnalysis
);
setNeedOptionDisorder
(
result
.
needOptionDisorder
);
setPassScore
(
result
.
passScore
);
setResultContent
(
result
.
resultContent
);
setResultShow
(
result
.
resultShow
);
setGetData
(
true
);
});
}
function
handleSave
()
{
if
(
request
.
current
)
{
return
;
}
setCheck
(
true
);
const
param
=
{
paperId
,
startTime
:
examStartTime
,
endTime
:
examEndTime
,
examName
,
passRate
:
passRate
/
100
,
examStartTime
,
examEndTime
,
examDesc
,
needPhone
,
needOptionDisorder
,
resultContent
,
answerAnalysis
,
resultShow
,
examDuration
:
(
examDuration
||
0
)
*
60
*
1000
,
passScore
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
source
:
0
,
examId
:
''
,
};
if
(
!
param
.
examName
)
{
message
.
warning
(
'请输入考试名称'
);
return
;
}
if
(
param
.
examName
&&
param
.
examName
.
length
>
40
)
{
message
.
warning
(
'考试名称最多40字'
);
return
;
}
if
(
checkExist
(
param
.
examName
))
{
message
.
warning
(
'此考试名称已存在'
);
return
;
}
if
(
!
paperId
)
{
message
.
warning
(
'请选择试卷'
);
return
;
}
if
(
!
passRate
)
{
message
.
warning
(
'请输入及格线'
);
return
;
}
const
paperInfoInit
:
any
=
{
passScore
:
60
};
const
[
showModal
,
setShowModal
]
=
useState
(
false
);
const
[
paperInfo
,
setPaperInfo
]
=
useState
(
paperInfoInit
);
const
[
paperId
,
setPaperId
]
=
useState
(
''
);
const
[
passRate
,
setPassRate
]
=
useState
(
60
);
//及格线
const
[
examStartTime
,
setStartTime
]
=
useState
(
''
);
const
[
examEndTime
,
setExamEndTime
]
=
useState
(
''
);
const
[
examName
,
setExamName
]
=
useState
(
''
);
const
[
needPhone
,
setNeedPhone
]
=
useState
(
'DO_NOT_NEED_PHONE_VERIFY'
);
const
[
needOptionDisorder
,
setNeedOptionDisorder
]
=
useState
(
'OPTION_SORT'
);
const
[
resultContent
,
setResultContent
]
=
useState
(
'PASS_AND_SCORE'
);
const
[
answerAnalysis
,
setAnswerAnalysis
]
=
useState
(
'RIGHT_OR_WRONG'
);
const
[
resultShow
,
setResultShow
]
=
useState
(
'IMMEDIATELY'
);
const
[
examDesc
,
setExamDesc
]
=
useState
(
''
);
const
[
passScore
,
setPassScore
]
=
useState
(
100
);
const
[
desclen
,
setDescLen
]
=
useState
(
0
);
const
[
check
,
setCheck
]
=
useState
(
false
);
const
[
getData
,
setGetData
]
=
useState
(
false
);
const
[
preview
,
setPreview
]
=
useState
(
false
);
const
[
examTotal
,
setExamTotal
]
=
useState
(
0
);
const
[
examList
,
setExamList
]
=
useState
([]);
const
request
=
useRef
(
false
);
const
{
match
}
=
props
;
const
[
examDuration
,
setExamDuration
]
=
useState
(
undefined
);
useEffect
(()
=>
{
queryExamList
();
switch
(
props
.
type
)
{
case
"copy"
:
// 考试列表-复制考试进入
case
"edit"
:
// 考试列表-编辑考试进入
queryExamDetail
();
break
;
case
"organizeExam"
:
// 试卷列表-组织考试进入
case
"newPaperToAddExam"
:
// 组卷页面-新建保存试卷并组织考试
case
"editPaperToAddExam"
:
// 组卷页面-编辑保存试卷并组织考试
setGetData
(
true
);
setPaperInfo
(
props
.
paperInfo
);
setExamName
(
props
.
paperInfo
?.
paperName
)
break
;
}
},
[])
if
(
!
examStartTime
||
!
examEndTime
)
{
message
.
warning
(
'请选择考试起止时间'
);
return
;
}
useEffect
(()
=>
{
setPaperId
(
paperInfo
.
paperId
)
setPassRate
(
paperInfo
.
passRate
)
if
(
Number
(
examStartTime
)
<
moment
().
valueOf
())
{
message
.
warning
(
'开始时间不能早于现在'
);
return
;
}
},
[
paperInfo
.
paperId
])
if
(
!
examDuration
)
{
message
.
warning
(
'请输入考试时长'
);
return
;
}
useEffect
(()
=>
{
setPassScore
(
Math
.
round
((
paperInfo
.
totalScore
||
0
)
*
(
passRate
||
0
)
as
any
/
100
))
setExamTotal
(
paperInfo
.
singleChoiceCnt
+
paperInfo
.
multiChoiceCnt
+
paperInfo
.
judgeCnt
+
paperInfo
.
gapFillingCnt
+
paperInfo
.
indefiniteChoiceCnt
||
0
)
}
,
[
paperInfo
.
paperId
,
passRate
])
if
(
examStartTime
+
(
examDuration
as
any
)
*
60
*
1000
>
examEndTime
)
{
message
.
warning
(
'考试时长不得超过考试有效期时长'
);
return
;
function
disabledDate
(
current
:
any
)
{
// Can not select days before today and today
return
current
&&
current
<
moment
().
startOf
(
'day'
)
;
}
if
(
desclen
>
1000
)
{
message
.
warning
(
'内容过长,不能超过1000字'
);
return
;
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
=>
{
console
.
log
(
res
)
const
{
result
=
{}
}
=
res
;
setExamList
(
result
.
records
)
})
}
request
.
current
=
true
;
setTimeout
(()
=>
{
request
.
current
=
false
;
},
2000
);
if
(
props
.
type
===
'edit'
)
{
param
.
examId
=
match
.
params
.
id
;
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
as
any
)
setAnswerAnalysis
(
result
.
answerAnalysis
)
setNeedOptionDisorder
(
result
.
needOptionDisorder
)
setPassScore
(
result
.
passScore
)
setResultContent
(
result
.
resultContent
)
setResultShow
(
result
.
resultShow
)
setGetData
(
true
)
})
}
Service
.
Hades
(
props
.
type
===
'edit'
?
'public/hades/editExam'
:
'public/hades/createExam'
,
param
).
then
((
res
)
=>
{
message
.
success
(
props
.
type
===
'edit'
?
'编辑成功'
:
'创建成功'
);
switch
(
props
.
type
)
{
case
'organizeExam'
:
// 试卷列表-组织考试进入
case
'newPaperToAddExam'
:
// 组卷保存组织考试
case
'editPaperToAddExam'
:
window
.
RCHistory
.
push
(
'/examination-manage-index'
);
break
;
case
'add'
:
case
'edit'
:
// 考试列表-新建或编辑
case
'copy'
:
// 考试列表-新建或编辑
props
.
freshList
();
props
.
history
.
goBack
();
break
;
}
});
}
function
disabledRangeTime
(
date
:
any
,
type
:
any
)
{
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
:
()
=>
[],
};
}
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
:
any
)
{
var
result
:
any
=
null
;
examList
.
forEach
((
item
:
any
)
=>
{
if
(
result
!=
null
)
{
return
result
;
}
if
(
props
.
type
===
'edit'
)
{
if
(
item
.
examName
===
examName
&&
item
.
examId
!==
match
.
params
.
id
)
{
result
=
item
;
function
handleSave
()
{
if
(
request
.
current
)
{
return
}
}
else
{
if
(
item
.
examName
===
examName
)
{
result
=
item
;
}
}
});
return
result
;
}
let
title
=
''
;
switch
(
props
.
type
)
{
case
'add'
:
case
'organizeExam'
:
case
'newPaperToAddExam'
:
case
'editPaperToAddExam'
:
title
=
'新建考试'
;
break
;
case
'edit'
:
title
=
'编辑考试'
;
break
;
case
'copy'
:
title
=
'复制考试'
;
break
;
default
:
break
;
}
return
(
<
div
className=
'page examPage'
>
<
Breadcrumbs
navList=
{
title
}
goBack=
{
handleGoBack
}
/>
<
div
className=
'box'
>
<
div
className=
'show-tips'
>
<
ShowTips
message=
'请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利'
/>
</
div
>
{
' '
}
<
div
className=
'form'
>
<
div
className=
'title'
>
基本信息
</
div
>
<
Form
labelCol=
{
{
span
:
3
}
}
wrapperCol=
{
{
span
:
14
}
}
layout=
'horizontal'
>
<
Form
.
Item
label=
'考试名称'
validateStatus=
{
check
&&
(
!
examName
||
examName
.
length
>
40
||
checkExist
(
examName
))
?
'error'
:
''
}
help=
{
check
&&
(
!
examName
?
'请输入考试名称'
:
examName
.
length
>
40
?
'考试名称最多40字'
:
checkExist
(
examName
)
&&
'此考试名称已存在'
)
}
required
>
<
Input
placeholder=
'请输入考试名称(40字以内)'
maxLength=
{
40
}
value=
{
examName
}
onChange=
{
(
e
)
=>
{
setExamName
(
e
.
target
.
value
);
}
}
style=
{
{
width
:
320
}
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'选择试卷'
validateStatus=
{
check
&&
!
paperId
?
'error'
:
''
}
help=
{
check
&&
!
paperId
&&
'请选择试卷'
}
required
>
<
Button
onClick=
{
()
=>
{
setShowModal
(
true
);
}
}
>
{
paperInfo
.
paperId
?
'重新选择'
:
'选择试卷'
}
</
Button
>
{
paperInfo
.
paperId
&&
(
<
div
className=
'paperTitle'
>
<
img
src=
'https://image.xiaomaiketang.com/xm/pY5imEhjzw.png'
alt=
''
/>
{
paperInfo
.
paperName
}
</
div
>
)
}
{
paperInfo
.
paperId
&&
(
<
div
className=
'table'
>
<
div
className=
'header'
>
<
div
className=
'item'
>
单选题
</
div
>
<
div
className=
'item'
>
多选题
</
div
>
<
div
className=
'item'
>
判断题
</
div
>
<
div
className=
'item'
>
填空题
</
div
>
<
div
className=
'item long'
>
不定项选择题
</
div
>
<
div
className=
'item'
>
合计
</
div
>
</
div
>
<
div
className=
'body-list'
>
<
div
className=
'item'
>
{
paperInfo
.
singleChoiceCnt
||
0
}
题
</
div
>
<
div
className=
'item'
>
{
paperInfo
.
multiChoiceCnt
||
0
}
题
</
div
>
<
div
className=
'item'
>
{
paperInfo
.
judgeCnt
||
0
}
题
</
div
>
<
div
className=
'item'
>
{
paperInfo
.
gapFillingCnt
||
0
}
题
</
div
>
<
div
className=
'item long'
>
{
paperInfo
.
indefiniteChoiceCnt
||
0
}
题
</
div
>
<
div
className=
'item'
>
{
examTotal
}
题
</
div
>
</
div
>
<
div
className=
'body-list'
>
<
div
className=
'item'
>
{
paperInfo
.
singleChoiceScore
||
0
}
分
</
div
>
<
div
className=
'item'
>
{
paperInfo
.
multiChoiceScore
||
0
}
分
</
div
>
<
div
className=
'item'
>
{
paperInfo
.
judgeScore
||
0
}
分
</
div
>
<
div
className=
'item'
>
{
paperInfo
.
gapFillingScore
||
0
}
分
</
div
>
<
div
className=
'item long'
>
{
paperInfo
.
indefiniteChoiceScore
||
0
}
分
</
div
>
<
div
className=
'item'
>
{
paperInfo
.
totalScore
||
0
}
分
</
div
>
</
div
>
</
div
>
)
}
</
Form
.
Item
>
<
Form
.
Item
label=
{
<
div
>
<
span
>
及格线
</
span
>
<
Tooltip
title=
'默认为选中试卷所设置的及格线,可修改'
>
<
span
className=
'icon iconfont'
style=
{
{
color
:
'#BFBFBF'
,
marginLeft
:
4
}
}
>

</
span
>
</
Tooltip
>
</
div
>
}
style=
{
{
marginTop
:
24
}
}
validateStatus=
{
check
&&
!
passRate
?
'error'
:
''
}
help=
{
check
&&
!
passRate
&&
'请输入及格线'
}
required
>
<
InputNumber
value=
{
passRate
}
min=
{
0
}
max=
{
100
}
onChange=
{
(
value
:
any
)
=>
{
setPassRate
(
parseInt
(
value
));
}
}
style=
{
{
width
:
100
}
}
/>
<
span
style=
{
{
marginLeft
:
4
}
}
>
%
</
span
>
<
span
style=
{
{
marginLeft
:
16
,
color
:
'#999'
}
}
>
{
` 总分(${paperInfo.totalScore || 0})*及格线(${passRate || 0}%)=及格分数(${passScore})`
}
</
span
>
</
Form
.
Item
>
<
Form
.
Item
label=
'考试有效期'
validateStatus=
{
check
&&
!
examStartTime
?
'error'
:
''
}
help=
{
check
&&
!
examStartTime
&&
'请选择考试起止时间'
}
required
>
<
RangePicker
style=
{
{
width
:
320
}
}
showTime=
{
{
defaultValue
:
[
moment
().
add
(
5
,
'minutes'
),
moment
().
add
(
5
,
'minutes'
)]
}
}
ranges=
{
{
近七天
:
[
moment
().
add
(
5
,
'minute'
),
moment
().
add
(
6
,
'day'
).
endOf
(
'day'
)],
近
1
个月
:
[
moment
().
add
(
5
,
'minute'
),
moment
().
add
(
1
,
'month'
).
endOf
(
'day'
)],
近
3
个月
:
[
moment
().
add
(
5
,
'minute'
),
moment
().
add
(
3
,
'month'
).
endOf
(
'day'
)],
}
}
disabledDate=
{
disabledDate
}
value=
{
[
examStartTime
?
moment
(
Number
(
examStartTime
))
:
null
,
examEndTime
?
moment
(
Number
(
examEndTime
))
:
null
]
}
disabledTime=
{
disabledRangeTime
}
format=
'YYYY/MM/DD HH:mm'
onChange=
{
(
date
:
any
)
=>
{
setStartTime
(
date
&&
date
[
0
]?.
valueOf
());
setExamEndTime
(
date
&&
date
[
1
]?.
valueOf
());
}
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'考试时长'
validateStatus=
{
check
&&
!
examDuration
?
'error'
:
''
}
help=
{
check
&&
!
examDuration
&&
'请输入考试时长'
}
required
>
<
InputNumber
value=
{
examDuration
}
max=
{
1440
}
min=
{
1
}
onChange=
{
(
value
:
any
)
=>
{
setExamDuration
(
parseInt
(
value
)
as
any
);
}
}
style=
{
{
width
:
100
}
}
/>
<
span
style=
{
{
marginLeft
:
4
}
}
>
分钟
</
span
>
<
span
style=
{
{
marginLeft
:
16
,
color
:
'#999'
}
}
>
{
` 时长不能超过1440分钟(24小时)`
}
</
span
>
</
Form
.
Item
>
<
Form
.
Item
label=
'考试说明'
validateStatus=
{
check
&&
desclen
>
1000
?
'error'
:
''
}
help=
{
check
&&
desclen
>
1000
&&
'最多只能输入1000个字'
}
>
{
(
getData
||
props
.
type
===
'add'
)
&&
(
<
GraphicsEditor
maxLimit=
{
1000
}
isIntro=
{
true
}
detail=
{
{
content
:
examDesc
,
}
}
onChange=
{
(
val
:
any
,
len
:
any
)
=>
{
setExamDesc
(
val
);
setDescLen
(
len
);
}
}
/>
)
}
</
Form
.
Item
>
<
div
className=
'title'
style=
{
{
marginTop
:
40
}
}
>
考试设置
</
div
>
<
Form
.
Item
label=
'身份验证'
required
>
<
div
style=
{
{
display
:
'flex'
,
marginLeft
:
4
}
}
>
<
Switch
style=
{
{
position
:
'relative'
,
top
:
6
}
}
checked=
{
needPhone
==
'NEED_PHONE_VERIFY'
}
onChange=
{
(
val
)
=>
{
setNeedPhone
(
val
?
'NEED_PHONE_VERIFY'
:
'DO_NOT_NEED_PHONE_VERIFY'
);
}
}
></
Switch
>
<
div
style=
{
{
position
:
'relative'
,
top
:
3
,
left
:
8
,
color
:
'#999'
}
}
>
<
p
>
开启:需要绑定手机号的学员才能参加考试
</
p
>
<
p
>
关闭:微信/企业微信登陆直接参加考试
</
p
>
</
div
>
</
div
>
</
Form
.
Item
>
<
Form
.
Item
label=
'选项乱序'
required
>
<
div
style=
{
{
display
:
'flex'
,
marginLeft
:
4
}
}
>
<
Switch
style=
{
{
position
:
'relative'
,
top
:
6
}
}
checked=
{
needOptionDisorder
==
'OPTION_RANDOM'
}
onChange=
{
(
val
)
=>
{
setNeedOptionDisorder
(
val
?
'OPTION_RANDOM'
:
'OPTION_SORT'
);
}
}
></
Switch
>
<
div
style=
{
{
position
:
'relative'
,
top
:
3
,
left
:
8
,
color
:
'#999'
}
}
>
<
p
>
开启:选择题的选项随机排序
</
p
>
<
p
>
关闭:选择题按题目原有顺序展示
</
p
>
</
div
>
</
div
>
</
Form
.
Item
>
<
Form
.
Item
label=
'考试结果查看'
required
>
<
Radio
.
Group
onChange=
{
(
e
:
any
)
=>
{
setResultShow
(
e
.
target
.
value
);
}
}
value=
{
resultShow
}
>
<
Radio
value=
{
'IMMEDIATELY'
}
>
交卷后立即显示考试结果
</
Radio
>
<
Radio
value=
{
'AFTER_EXAM_END'
}
>
到达考试截止日期才显示结果
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
<
Form
.
Item
label=
' 考试结果内容'
required
>
<
Radio
.
Group
onChange=
{
(
e
:
any
)
=>
{
setResultContent
(
e
.
target
.
value
);
}
}
value=
{
resultContent
}
>
<
Radio
value=
{
'PASS_AND_SCORE'
}
>
显示考试分数和是否及格
</
Radio
>
<
Radio
value=
{
'ONLY_SCORE'
}
>
仅显示考试分数
</
Radio
>
<
Radio
value=
{
'ONLY_PASS'
}
>
仅显示是否及格
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
<
Form
.
Item
label=
'答案与解析'
required
>
<
Radio
.
Group
onChange=
{
(
e
:
any
)
=>
{
setAnswerAnalysis
(
e
.
target
.
value
);
}
}
value=
{
answerAnalysis
}
>
<
Radio
value=
{
'ANALYSE_AND_RIGHT_OR_WRONG'
}
>
显示对错与解析
</
Radio
>
<
Radio
value=
{
'RIGHT_OR_WRONG'
}
>
仅显示对错
</
Radio
>
<
Radio
value=
{
'CAN_NOT_CHECK'
}
>
都不显示
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
</
Form
>
</
div
>
</
div
>
{
showModal
&&
(
<
SelectPaperModal
onSelect=
{
(
info
:
any
)
=>
{
setPaperInfo
(
info
);
}
}
paperInfo=
{
paperInfo
}
close=
{
()
=>
{
setShowModal
(
false
);
}
}
></
SelectPaperModal
>
)
}
<
div
className=
'footer shrink-footer'
>
<
Button
onClick=
{
handleGoBack
}
>
取消
</
Button
>
<
Button
onClick=
{
()
=>
{
setPreview
(
true
);
}
}
>
预览
</
Button
>
<
Button
type=
'primary'
onClick=
{
handleSave
}
>
保存
</
Button
>
</
div
>
{
preview
&&
(
<
PreviewModal
info=
{
{
setCheck
(
true
);
const
param
=
{
paperId
,
startTime
:
examStartTime
,
endTime
:
examEndTime
,
...
...
@@ -571,17 +138,409 @@ function AddExam(props: any) {
resultContent
,
answerAnalysis
,
resultShow
,
examDuration
,
examDuration
:
(
examDuration
||
0
)
*
60
*
1000
,
passScore
,
examTotal
,
totalScore
:
paperInfo
.
totalScore
,
}
}
onClose=
{
()
=>
{
setPreview
(
false
);
}
}
></
PreviewModal
>
)
}
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
source
:
0
,
examId
:
''
}
if
(
!
param
.
examName
)
{
message
.
warning
(
'请输入考试名称'
);
return
}
if
(
param
.
examName
&&
param
.
examName
.
length
>
40
)
{
message
.
warning
(
'考试名称最多40字'
);
return
}
if
(
checkExist
(
param
.
examName
))
{
message
.
warning
(
'此考试名称已存在'
);
return
}
if
(
!
paperId
)
{
message
.
warning
(
'请选择试卷'
);
return
}
if
(
!
passRate
)
{
message
.
warning
(
'请输入及格线'
);
return
}
if
(
!
examStartTime
||
!
examEndTime
)
{
message
.
warning
(
'请选择考试起止时间'
);
return
}
if
(
Number
(
examStartTime
)
<
moment
().
valueOf
())
{
message
.
warning
(
'开始时间不能早于现在'
);
return
}
if
(
!
examDuration
)
{
message
.
warning
(
'请输入考试时长'
);
return
}
if
(
examStartTime
+
(
examDuration
as
any
)
*
60
*
1000
>
examEndTime
)
{
message
.
warning
(
'考试时长不得超过考试有效期时长'
);
return
}
if
(
desclen
>
1000
)
{
message
.
warning
(
'内容过长,不能超过1000字'
);
return
}
request
.
current
=
true
;
setTimeout
(()
=>
{
request
.
current
=
false
},
2000
)
if
(
props
.
type
===
'edit'
)
{
param
.
examId
=
match
.
params
.
id
;
}
Service
.
Hades
(
props
.
type
===
'edit'
?
'public/hades/editExam'
:
"public/hades/createExam"
,
param
).
then
((
res
)
=>
{
message
.
success
(
props
.
type
===
'edit'
?
'编辑成功'
:
'创建成功'
);
switch
(
props
.
type
)
{
case
"organizeExam"
:
// 试卷列表-组织考试进入
case
"newPaperToAddExam"
:
// 组卷保存组织考试
case
"editPaperToAddExam"
:
window
.
RCHistory
.
push
(
"/examination-manage-index"
)
break
;
case
"add"
:
case
"edit"
:
// 考试列表-新建或编辑
case
"copy"
:
// 考试列表-新建或编辑
props
.
freshList
()
props
.
history
.
goBack
();
break
;
}
})
}
function
disabledRangeTime
(
date
:
any
,
type
:
any
)
{
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
:
()
=>
[],
};
}
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
:
any
)
{
var
result
:
any
=
null
;
examList
.
forEach
((
item
:
any
)
=>
{
if
(
result
!=
null
)
{
return
result
;
}
if
(
props
.
type
===
'edit'
)
{
if
(
item
.
examName
===
examName
&&
item
.
examId
!==
match
.
params
.
id
)
{
result
=
item
;
}
}
else
{
if
(
item
.
examName
===
examName
)
{
result
=
item
;
}
}
});
return
result
;
};
let
title
=
''
;
switch
(
props
.
type
)
{
case
'add'
:
case
"organizeExam"
:
case
"newPaperToAddExam"
:
case
"editPaperToAddExam"
:
title
=
'新建考试'
;
break
;
case
'edit'
:
title
=
'编辑考试'
;
break
;
case
'copy'
:
title
=
'复制考试'
;
break
;
default
:
break
;
}
return
<
div
className=
"page examPage"
>
<
Breadcrumbs
navList=
{
title
}
goBack=
{
handleGoBack
}
/>
<
div
className=
"box"
>
<
div
className=
"show-tips"
>
<
ShowTips
message=
"请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利"
/>
</
div
>
<
div
className=
"form"
>
<
div
className=
"title"
>
基本信息
</
div
>
<
Form
labelCol=
{
{
span
:
3
}
}
wrapperCol=
{
{
span
:
14
}
}
layout=
"horizontal"
>
<
Form
.
Item
label=
"考试名称"
validateStatus=
{
(
check
&&
(
!
examName
||
(
examName
.
length
>
40
||
checkExist
(
examName
))
))
?
'error'
:
''
}
help=
{
check
&&
(
!
examName
?
'请输入考试名称'
:
(
examName
.
length
>
40
?
'考试名称最多40字'
:
(
checkExist
(
examName
)
&&
'此考试名称已存在'
)))
}
required
>
<
Input
placeholder=
'请输入考试名称(40字以内)'
maxLength=
{
40
}
value=
{
examName
}
onChange=
{
(
e
)
=>
{
setExamName
(
e
.
target
.
value
)
}
}
style=
{
{
width
:
320
}
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"选择试卷"
validateStatus=
{
(
check
&&
!
paperId
)
?
'error'
:
''
}
help=
{
check
&&
!
paperId
&&
'请选择试卷'
}
required
>
<
Button
onClick=
{
()
=>
{
setShowModal
(
true
)
}
}
>
{
paperInfo
.
paperId
?
'重新选择'
:
'选择试卷'
}
</
Button
>
{
paperInfo
.
paperId
&&
<
div
className=
"paperTitle"
><
img
src=
"https://image.xiaomaiketang.com/xm/pY5imEhjzw.png"
alt=
""
/>
{
paperInfo
.
paperName
}
</
div
>
}
{
paperInfo
.
paperId
&&
<
div
className=
"table"
>
<
div
className=
"header"
>
<
div
className=
"item"
>
单选题
</
div
>
<
div
className=
"item"
>
多选题
</
div
>
<
div
className=
"item"
>
判断题
</
div
>
<
div
className=
"item"
>
填空题
</
div
>
<
div
className=
"item long"
>
不定项选择题
</
div
>
<
div
className=
"item"
>
合计
</
div
>
</
div
>
<
div
className=
"body-list"
>
<
div
className=
"item"
>
{
paperInfo
.
singleChoiceCnt
||
0
}
题
</
div
>
<
div
className=
"item"
>
{
paperInfo
.
multiChoiceCnt
||
0
}
题
</
div
>
<
div
className=
"item"
>
{
paperInfo
.
judgeCnt
||
0
}
题
</
div
>
<
div
className=
"item"
>
{
paperInfo
.
gapFillingCnt
||
0
}
题
</
div
>
<
div
className=
"item long"
>
{
paperInfo
.
indefiniteChoiceCnt
||
0
}
题
</
div
>
<
div
className=
"item"
>
{
examTotal
}
题
</
div
>
</
div
>
<
div
className=
"body-list"
>
<
div
className=
"item"
>
{
paperInfo
.
singleChoiceScore
||
0
}
分
</
div
>
<
div
className=
"item"
>
{
paperInfo
.
multiChoiceScore
||
0
}
分
</
div
>
<
div
className=
"item"
>
{
paperInfo
.
judgeScore
||
0
}
分
</
div
>
<
div
className=
"item"
>
{
paperInfo
.
gapFillingScore
||
0
}
分
</
div
>
<
div
className=
"item long"
>
{
paperInfo
.
indefiniteChoiceScore
||
0
}
分
</
div
>
<
div
className=
"item"
>
{
paperInfo
.
totalScore
||
0
}
分
</
div
>
</
div
>
</
div
>
}
</
Form
.
Item
>
<
Form
.
Item
label=
{
<
div
>
<
span
>
及格线
</
span
>
<
Tooltip
title=
"默认为选中试卷所设置的及格线,可修改"
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
'#BFBFBF'
,
marginLeft
:
4
}
}
>

</
span
>
</
Tooltip
>
</
div
>
}
style=
{
{
marginTop
:
24
}
}
validateStatus=
{
(
check
&&
!
passRate
)
?
'error'
:
''
}
help=
{
check
&&
!
passRate
&&
'请输入及格线'
}
required
>
<
InputNumber
value=
{
passRate
}
min=
{
0
}
max=
{
100
}
onChange=
{
(
value
:
any
)
=>
{
setPassRate
(
parseInt
(
value
))
}
}
style=
{
{
width
:
100
}
}
/>
<
span
style=
{
{
marginLeft
:
4
}
}
>
%
</
span
>
<
span
style=
{
{
marginLeft
:
16
,
color
:
"#999"
}
}
>
{
` 总分(${paperInfo.totalScore || 0})*及格线(${passRate || 0}%)=及格分数(${passScore})`
}
</
span
>
</
Form
.
Item
>
<
Form
.
Item
label=
"考试有效期"
validateStatus=
{
(
check
&&
!
examStartTime
)
?
'error'
:
''
}
help=
{
check
&&
!
examStartTime
&&
'请选择考试起止时间'
}
required
>
<
RangePicker
style=
{
{
width
:
320
}
}
showTime=
{
{
defaultValue
:
[
moment
().
add
(
5
,
'minutes'
),
moment
().
add
(
5
,
'minutes'
)]
}
}
ranges=
{
{
'近七天'
:
[
moment
().
add
(
5
,
'minute'
),
moment
().
add
(
6
,
'day'
).
endOf
(
'day'
)],
'近1个月'
:
[
moment
().
add
(
5
,
'minute'
),
moment
().
add
(
1
,
'month'
).
endOf
(
'day'
)],
'近3个月'
:
[
moment
().
add
(
5
,
'minute'
),
moment
().
add
(
3
,
'month'
).
endOf
(
'day'
)],
}
}
disabledDate=
{
disabledDate
}
value=
{
[
examStartTime
?
moment
(
Number
(
examStartTime
))
:
null
,
examEndTime
?
moment
(
Number
(
examEndTime
))
:
null
]
}
disabledTime=
{
disabledRangeTime
}
format=
"YYYY/MM/DD HH:mm"
onChange=
{
(
date
:
any
)
=>
{
setStartTime
(
date
&&
date
[
0
]?.
valueOf
());
setExamEndTime
(
date
&&
date
[
1
]?.
valueOf
());
}
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"考试时长"
validateStatus=
{
(
check
&&
!
examDuration
)
?
'error'
:
''
}
help=
{
check
&&
!
examDuration
&&
'请输入考试时长'
}
required
>
<
InputNumber
value=
{
examDuration
}
max=
{
1440
}
min=
{
1
}
onChange=
{
(
value
:
any
)
=>
{
setExamDuration
(
parseInt
(
value
)
as
any
)
}
}
style=
{
{
width
:
100
}
}
/>
<
span
style=
{
{
marginLeft
:
4
}
}
>
分钟
</
span
>
<
span
style=
{
{
marginLeft
:
16
,
color
:
"#999"
}
}
>
{
` 时长不能超过1440分钟(24小时)`
}
</
span
>
</
Form
.
Item
>
<
Form
.
Item
label=
"考试说明"
validateStatus=
{
(
check
&&
(
desclen
>
1000
))
?
'error'
:
''
}
help=
{
check
&&
(
desclen
>
1000
)
&&
'最多只能输入1000个字'
}
>
{
(
getData
||
(
props
.
type
===
'add'
))
&&
<
GraphicsEditor
maxLimit=
{
1000
}
isIntro=
{
true
}
detail=
{
{
content
:
examDesc
}
}
onChange=
{
(
val
:
any
,
len
:
any
)
=>
{
setExamDesc
(
val
);
setDescLen
(
len
)
}
}
/>
}
</
Form
.
Item
>
<
div
className=
"title"
style=
{
{
marginTop
:
40
}
}
>
考试设置
</
div
>
<
Form
.
Item
label=
"身份验证"
required
>
<
div
style=
{
{
display
:
'flex'
,
marginLeft
:
4
,
}
}
>
<
Switch
style=
{
{
position
:
'relative'
,
top
:
6
}
}
checked=
{
needPhone
==
'NEED_PHONE_VERIFY'
}
onChange=
{
(
val
)
=>
{
setNeedPhone
(
val
?
'NEED_PHONE_VERIFY'
:
'DO_NOT_NEED_PHONE_VERIFY'
)
}
}
></
Switch
>
<
div
style=
{
{
position
:
'relative'
,
top
:
3
,
left
:
8
,
color
:
"#999"
}
}
><
p
>
开启:需要绑定手机号的学员才能参加考试
</
p
>
<
p
>
关闭:微信/企业微信登陆直接参加考试
</
p
></
div
>
</
div
>
</
Form
.
Item
>
<
Form
.
Item
label=
"选项乱序"
required
>
<
div
style=
{
{
display
:
'flex'
,
marginLeft
:
4
,
}
}
>
<
Switch
style=
{
{
position
:
'relative'
,
top
:
6
}
}
checked=
{
needOptionDisorder
==
'OPTION_RANDOM'
}
onChange=
{
(
val
)
=>
{
setNeedOptionDisorder
(
val
?
'OPTION_RANDOM'
:
'OPTION_SORT'
)
}
}
></
Switch
>
<
div
style=
{
{
position
:
'relative'
,
top
:
3
,
left
:
8
,
color
:
"#999"
}
}
><
p
>
开启:选择题的选项随机排序
</
p
>
<
p
>
关闭:选择题按题目原有顺序展示
</
p
></
div
>
</
div
>
</
Form
.
Item
>
<
Form
.
Item
label=
"考试结果查看"
required
>
<
Radio
.
Group
onChange=
{
(
e
:
any
)
=>
{
setResultShow
(
e
.
target
.
value
)
}
}
value=
{
resultShow
}
>
<
Radio
value=
{
'IMMEDIATELY'
}
>
交卷后立即显示考试结果
</
Radio
>
<
Radio
value=
{
'AFTER_EXAM_END'
}
>
到达考试截止日期才显示结果
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
<
Form
.
Item
label=
" 考试结果内容"
required
>
<
Radio
.
Group
onChange=
{
(
e
:
any
)
=>
{
setResultContent
(
e
.
target
.
value
)
}
}
value=
{
resultContent
}
>
<
Radio
value=
{
'PASS_AND_SCORE'
}
>
显示考试分数和是否及格
</
Radio
>
<
Radio
value=
{
'ONLY_SCORE'
}
>
仅显示考试分数
</
Radio
>
<
Radio
value=
{
'ONLY_PASS'
}
>
仅显示是否及格
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
<
Form
.
Item
label=
"答案与解析"
required
>
<
Radio
.
Group
onChange=
{
(
e
:
any
)
=>
{
setAnswerAnalysis
(
e
.
target
.
value
)
}
}
value=
{
answerAnalysis
}
>
<
Radio
value=
{
'ANALYSE_AND_RIGHT_OR_WRONG'
}
>
显示对错与解析
</
Radio
>
<
Radio
value=
{
'RIGHT_OR_WRONG'
}
>
仅显示对错
</
Radio
>
<
Radio
value=
{
'CAN_NOT_CHECK'
}
>
都不显示
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
</
Form
>
</
div
>
</
div
>
{
showModal
&&
<
SelectPaperModal
onSelect=
{
(
info
:
any
)
=>
{
setPaperInfo
(
info
)
}
}
paperInfo=
{
paperInfo
}
close=
{
()
=>
{
setShowModal
(
false
)
}
}
></
SelectPaperModal
>
}
<
div
className=
"footer shrink-footer"
>
<
Button
onClick=
{
handleGoBack
}
>
取消
</
Button
>
<
Button
onClick=
{
()
=>
{
setPreview
(
true
)
}
}
>
预览
</
Button
>
<
Button
type=
"primary"
onClick=
{
handleSave
}
>
保存
</
Button
>
</
div
>
{
preview
&&
<
PreviewModal
info=
{
{
paperId
,
startTime
:
examStartTime
,
endTime
:
examEndTime
,
examName
,
passRate
:
passRate
/
100
,
examStartTime
,
examEndTime
,
examDesc
,
needPhone
,
needOptionDisorder
,
resultContent
,
answerAnalysis
,
resultShow
,
examDuration
,
passScore
,
examTotal
,
totalScore
:
paperInfo
.
totalScore
}
}
onClose=
{
()
=>
{
setPreview
(
false
)
}
}
></
PreviewModal
>
}
</
div
>
);
}
export
default
withRouter
(
AddExam
);
export
default
withRouter
(
AddExam
);
\ No newline at end of file
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