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
ce7a5a1e
Commit
ce7a5a1e
authored
Jul 02, 2021
by
guomingpang
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'rc' of
ssh://xmgit.ixm5.cn:10022/xiaomai-cloud-class/xiaomai-cloud-class-web
into rc
parents
c0fcec6e
1cf7cde7
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
499 additions
and
68 deletions
+499
-68
src/core/page.less
+2
-0
src/modules/course-manage/modal/ShareLiveModal.jsx
+53
-47
src/modules/home/HomeTip.tsx
+2
-1
src/modules/root/App.tsx
+2
-0
src/modules/root/CollegeManagePage.jsx
+1
-1
src/modules/root/Menu.less
+4
-2
src/modules/root/Menu.tsx
+1
-1
src/modules/teach-tool/paper-manage/OperatePaper.jsx
+169
-16
src/modules/teach-tool/paper-manage/OperatePaper.less
+2
-0
src/modules/teach-tool/paper-manage/components/BatchScore.less
+28
-0
src/modules/teach-tool/paper-manage/components/BatchScore.tsx
+233
-0
src/store/context.ts
+2
-0
No files found.
src/core/page.less
View file @
ce7a5a1e
...
...
@@ -12,6 +12,7 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
min-height: 100%;
overflow: hidden;
.page {
position: fixed;
top: 60px;
...
...
@@ -21,6 +22,7 @@
z-index: 102;
overflow: auto;
margin: 0 16px;
.box {
&:first-child {
margin-bottom: 8px;
...
...
src/modules/course-manage/modal/ShareLiveModal.jsx
View file @
ce7a5a1e
...
...
@@ -6,67 +6,67 @@
* @Description: 大班直播分享弹窗
*/
import
React
from
'react'
import
{
Modal
,
Button
,
message
}
from
'antd'
import
domtoimage
from
'dom-to-image'
import
React
from
'react'
;
import
{
Modal
,
Button
,
message
}
from
'antd'
;
import
domtoimage
from
'dom-to-image'
;
import
qrcode
from
'@/libs/qrcode/qrcode.js'
import
User
from
'@/common/js/user'
import
$
from
'jquery'
import
_
from
'underscore'
import
CourseService
from
'@/domains/course-domain/CourseService'
import
qrcode
from
'@/libs/qrcode/qrcode.js'
;
import
User
from
'@/common/js/user'
;
import
$
from
'jquery'
;
import
_
from
'underscore'
;
import
CourseService
from
'@/domains/course-domain/CourseService'
;
import
'./ShareLiveModal.less'
import
'./ShareLiveModal.less'
;
class
ShareLiveModal
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
super
(
props
)
;
this
.
state
=
{
shareUrl
:
'https://xiaomai5.com/liveShare?courseId=12'
,
}
}
;
}
componentDidMount
()
{
// 获取短链接
this
.
handleConvertShortUrl
()
this
.
handleConvertShortUrl
()
;
}
handleConvertShortUrl
=
()
=>
{
const
{
longUrl
}
=
this
.
props
.
data
const
{
longUrl
}
=
this
.
props
.
data
;
// 发请求
CourseService
.
getQrcode
({
urls
:
[
longUrl
],
}).
then
((
res
)
=>
{
const
{
result
=
[]
}
=
res
const
{
result
=
[]
}
=
res
;
this
.
setState
(
{
shareUrl
:
result
[
0
].
shortUrl
,
},
()
=>
{
const
qrcodeWrapDom
=
document
.
querySelector
(
'#qrcodeWrap'
)
const
qrcodeWrapDom
=
document
.
querySelector
(
'#qrcodeWrap'
)
;
const
qrcodeNode
=
new
qrcode
({
text
:
this
.
state
.
shareUrl
,
size
:
98
,
})
qrcodeWrapDom
.
appendChild
(
qrcodeNode
)
})
;
qrcodeWrapDom
.
appendChild
(
qrcodeNode
)
;
const
qrcodeWrapDomDownload
=
document
.
querySelector
(
'#qrcodeWrap-dowload'
)
const
qrcodeWrapDomDownload
=
document
.
querySelector
(
'#qrcodeWrap-dowload'
)
;
const
qrcodeNodeDownLoad
=
new
qrcode
({
text
:
this
.
state
.
shareUrl
,
size
:
196
,
})
qrcodeWrapDomDownload
.
appendChild
(
qrcodeNodeDownLoad
)
})
;
qrcodeWrapDomDownload
.
appendChild
(
qrcodeNodeDownLoad
)
;
}
)
})
}
)
;
})
;
}
;
componentWillUnmount
()
{
// 页面销毁之前清空定时器
clearTimeout
(
this
.
timer
)
clearTimeout
(
this
.
timer
)
;
}
// 下载海报
...
...
@@ -79,31 +79,31 @@ class ShareLiveModal extends React.Component {
()
=>
{
this
.
setState
({
time
:
new
Date
().
valueOf
()
},
()
=>
{
setTimeout
(()
=>
{
let
node
=
document
.
getElementById
(
'poster-dowload'
)
let
node
=
document
.
getElementById
(
'poster-dowload'
)
;
domtoimage
.
toPng
(
node
).
then
((
imgData
)
=>
{
console
.
log
(
imgData
)
const
download
=
document
.
createElement
(
'a'
)
const
{
courseName
}
=
this
.
props
.
data
$
(
download
).
attr
(
'href'
,
imgData
).
attr
(
'download'
,
`
${
courseName
}
.png`
).
get
(
0
).
click
()
})
},
1000
)
})
console
.
log
(
imgData
)
;
const
download
=
document
.
createElement
(
'a'
)
;
const
{
courseName
}
=
this
.
props
.
data
;
$
(
download
).
attr
(
'href'
,
imgData
).
attr
(
'download'
,
`
${
courseName
}
.png`
).
get
(
0
).
click
()
;
})
;
},
1000
)
;
})
;
}
)
}
)
;
}
;
// 复制分享链接
handleCopy
=
()
=>
{
const
textContent
=
document
.
getElementById
(
'shareUrl'
).
innerText
const
textContent
=
document
.
getElementById
(
'shareUrl'
).
innerText
;
window
.
copyText
(
textContent
)
message
.
success
(
'复制成功!'
)
}
window
.
copyText
(
textContent
)
;
message
.
success
(
'复制成功!'
)
;
}
;
render
()
{
const
{
courseDivision
,
data
,
type
,
title
}
=
this
.
props
const
{
courseName
,
scheduleVideoUrl
,
courseMediaVOS
,
coverUrl
}
=
data
const
{
shareUrl
,
showImg
,
time
}
=
this
.
state
const
{
courseDivision
,
data
,
type
,
title
}
=
this
.
props
;
const
{
courseName
,
scheduleVideoUrl
,
courseMediaVOS
,
coverUrl
}
=
data
;
const
{
shareUrl
,
showImg
,
time
}
=
this
.
state
;
// 判断是否是默认图, 默认图不需要在URL后面增加字符串
let
coverImgSrc
=
''
;
switch
(
type
)
{
...
...
@@ -111,21 +111,27 @@ class ShareLiveModal extends React.Component {
if
(
courseMediaVOS
&&
courseMediaVOS
.
length
>
0
)
{
data
.
courseMediaVOS
.
map
((
item
,
index
)
=>
{
if
(
item
.
contentType
===
'COVER'
)
{
coverImgSrc
=
item
.
mediaUrl
coverImgSrc
=
item
.
mediaUrl
;
}
else
{
coverImgSrc
=
'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'
;
}
})
})
;
}
else
{
coverImgSrc
=
'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'
;
}
break
;
case
'videoClass'
:
// 视频课
coverImgSrc
=
coverUrl
||
(
courseDivision
===
'internal'
?
`
${
scheduleVideoUrl
}
?x-oss-process=video/snapshot,t_0,m_fast&anystring=anystring`
:
'https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png'
)
coverImgSrc
=
coverUrl
||
(
courseDivision
===
'internal'
?
`
${
scheduleVideoUrl
}
?x-oss-process=video/snapshot,t_0,m_fast&anystring=anystring`
:
'https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png'
);
break
;
case
'graphicsClass'
:
// 图文课
coverImgSrc
=
coverUrl
||
'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png'
;
break
;
case
'offlineClass'
:
// 线下课
coverImgSrc
=
coverUrl
||
'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
;
coverImgSrc
=
coverUrl
||
'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
;
break
;
}
...
...
@@ -214,8 +220,8 @@ class ShareLiveModal extends React.Component {
</
div
>
</
div
>
</
Modal
>
)
)
;
}
}
export
default
ShareLiveModal
export
default
ShareLiveModal
;
src/modules/home/HomeTip.tsx
View file @
ce7a5a1e
...
...
@@ -3,6 +3,7 @@ import "./HomeTip.less"
import
{
VersionContext
}
from
"@/store/context"
;
import
ContactWidget
from
'@/components/ContactWidget'
;
import
{
Carousel
}
from
"antd"
;
import
moment
from
"moment"
;
export
default
function
HomeTip
()
{
...
...
@@ -43,7 +44,7 @@ export default function HomeTip() {
{
tipType
===
2
&&
(
<
div
className=
"content"
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#FF4F4F"
,
marginRight
:
"8px"
}
}
>

</
span
>
版本到期提醒:当前企业购买的小麦企学院服务已于
{
expirationTime
}
到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#FF4F4F"
,
marginRight
:
"8px"
}
}
>

</
span
>
版本到期提醒:当前企业购买的小麦企学院服务已于
{
moment
(
versionInfo
?.
validEndTimeST
).
format
(
"YYYY-MM-DD HH:mm:ss"
)
}
到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~
<
ContactWidget
placement=
"bottom"
trigger=
"hover"
><
div
className=
"renew-btn"
>
立即续费
</
div
></
ContactWidget
>
</
div
>
)
...
...
src/modules/root/App.tsx
View file @
ce7a5a1e
...
...
@@ -74,6 +74,8 @@ const App: React.FC = (props: any) => {
surplusDayTime
:
version
.
surplusDayTime
,
validEndTime
:
moment
(
version
.
validEndTime
).
format
(
'YYYY-MM-DD'
),
validStartTime
:
moment
(
version
.
validStartTime
).
format
(
'YYYY-MM-DD'
),
validEndTimeST
:
version
.
validEndTime
,
validStartTimeST
:
version
.
validStartTime
,
whetherReachUserNum
:
version
.
whetherReachUserNum
,
};
setVersionInfo
(
versioninfo
)
...
...
src/modules/root/CollegeManagePage.jsx
View file @
ce7a5a1e
...
...
@@ -85,7 +85,7 @@ function ExpirationPopover(props) {
<
div
className=
"title"
>
{
props
.
surplusDayTime
===
0
?
"服务已到期"
:
"服务到期提醒"
}
</
div
>
{
showType
===
3
?
(
<
div
className=
"tip-text"
>
当前企业购买的小麦企学院服务已于
<
span
style=
{
{
color
:
"#FF4F4F"
}
}
>
{
moment
(
props
.
endTime
).
format
(
"YYYY-MM-DD"
)
}
</
span
>
到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~
</
div
>
<
div
className=
"tip-text"
>
当前企业购买的小麦企学院服务已于
<
span
style=
{
{
color
:
"#FF4F4F"
}
}
>
{
moment
(
props
.
endTime
).
format
(
"YYYY-MM-DD
HH:mm:ss
"
)
}
</
span
>
到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~
</
div
>
)
:
(
<
div
className=
"tip-text"
>
当前企业购买的小麦企学院服务
<
span
style=
{
{
color
:
"#FF4F4F"
}
}
>
仅剩
{
props
.
surplusDayTime
}
天
</
span
>
(于
<
span
>
{
moment
(
props
.
endTime
).
format
(
"YYYY-MM-DD"
)
}
</
span
>
到期),为了不影响使用,建议尽快续费购买哦~
</
div
>
)
...
...
src/modules/root/Menu.less
View file @
ce7a5a1e
...
...
@@ -157,11 +157,13 @@
// }
.version-info {
position: absolute;
height:
7
4px;
height:
8
4px;
bottom: 0;
width: 100%;
cursor: pointer;
z-index: -1;
z-index: 10;
padding-top: 10px;
background-color: white;
.row-1 {
width: fit-content;
font-size: 14px;
...
...
src/modules/root/Menu.tsx
View file @
ce7a5a1e
...
...
@@ -64,7 +64,7 @@ function VersionPanel(props: any) {
<
div
className=
'widget'
style=
{
{
marginBottom
:
'16px'
,
width
:
'212px'
}
}
>
<
div
className=
'lable'
>
有效起止日期
</
div
>
<
div
className=
'lable-text'
>
{
versionInfo
?.
validStartTime
}
~
{
versionInfo
?.
validEndTime
}
{
versionInfo
?.
validStartTime
ST
===
versionInfo
?.
validEndTimeST
?
"-"
:
`${versionInfo?.validStartTime}~${versionInfo?.validEndTime}`
}
</
div
>
</
div
>
<
div
className=
'widget'
style=
{
{
marginRight
:
'26px'
,
marginBottom
:
'8px'
,
width
:
'70px'
}
}
>
...
...
src/modules/teach-tool/paper-manage/OperatePaper.jsx
View file @
ce7a5a1e
/*
* @Author: yuananting
* @Date: 2021-03-27 16:15:13
* @LastEditors:
fusanqias
ng
* @LastEditTime: 2021-0
6-15 17:20:48
* @LastEditors:
yuananti
ng
* @LastEditTime: 2021-0
7-01 18:03:16
* @Description: 助学工具-新建/复制/编辑试卷
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -21,7 +21,8 @@ import Bus from '@/core/bus';
import
_
from
'underscore'
;
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
*
as
paperEmpty
from
'../../lottie/paperEmpty/data.json'
;
import
AddExam
from
'@/modules/teach-tool/examination-manager/AddExam'
;
import
AddExam
from
"@/modules/teach-tool/examination-manager/AddExam"
;
import
BatchScore
from
"./components/BatchScore"
;
const
questionTypeEnum
=
{
SINGLE_CHOICE
:
'单选题'
,
...
...
@@ -59,7 +60,8 @@ class OperatePaper extends Component {
},
selectQuestionModal
:
null
,
paperPreviewModal
:
null
,
quickSortModalVisible
:
false
,
// 快捷排序弹窗显隐
quickSortModalVisible
:
false
,
// 快捷排序弹窗显隐
batchSetScoreVisible
:
false
,
//批量设置题型分数
selectQuestionList
:
[],
currentOperate
:
''
,
currentNav
:
''
,
...
...
@@ -85,6 +87,38 @@ class OperatePaper extends Component {
typeKey
:
'INDEFINITE_CHOICE'
,
},
],
scoreRule
:
[
{
typeKey
:
"SINGLE_CHOICE"
,
score
:
2
,
portionScore
:
0
,
totalQuestion
:
0
,
},
{
typeKey
:
"MULTI_CHOICE"
,
score
:
2
,
portionScore
:
0
,
totalQuestion
:
0
,
},
{
typeKey
:
"JUDGE"
,
score
:
2
,
portionScore
:
0
,
totalQuestion
:
0
,
},
{
typeKey
:
"GAP_FILLING"
,
score
:
2
,
portionScore
:
0
,
totalQuestion
:
0
,
},
{
typeKey
:
"INDEFINITE_CHOICE"
,
score
:
2
,
portionScore
:
0
,
totalQuestion
:
0
,
},
]
};
}
...
...
@@ -95,10 +129,10 @@ class OperatePaper extends Component {
this
.
setState
({
currentOperate
:
'new'
,
currentNav
:
'新建试卷'
});
break
;
case
'edit'
:
this
.
setState
({
currentOperate
:
'edit'
,
currentNav
:
'编辑试卷'
},
()
=>
this
.
queryPaperDetail
());
this
.
setState
({
currentOperate
:
'edit'
,
currentNav
:
'编辑试卷'
},
()
=>
this
.
queryPaperDetail
(
'edit'
));
break
;
case
'copy'
:
this
.
setState
({
currentOperate
:
'copy'
,
currentNav
:
'复制试卷'
},
()
=>
this
.
queryPaperDetail
());
this
.
setState
({
currentOperate
:
'copy'
,
currentNav
:
'复制试卷'
},
()
=>
this
.
queryPaperDetail
(
'copy'
));
break
;
}
}
...
...
@@ -122,7 +156,7 @@ class OperatePaper extends Component {
};
// 编辑/复制试卷时获取相应试卷详情
queryPaperDetail
=
async
()
=>
{
queryPaperDetail
=
async
(
flag
)
=>
{
this
.
setState
({
loading
:
true
});
const
{
currentOperate
}
=
this
.
state
;
let
query
=
{
...
...
@@ -130,6 +164,7 @@ class OperatePaper extends Component {
source
:
0
,
userId
:
User
.
getStoreUserId
(),
tenantId
:
User
.
getStoreId
(),
flag
:
flag
===
'copy'
,
};
const
res
=
await
AidToolService
.
queryPaperDetail
(
query
);
const
{
result
}
=
res
;
...
...
@@ -190,6 +225,29 @@ class OperatePaper extends Component {
},
0
);
const
passScore
=
Math
.
round
(
totalScore
*
formData
.
passRate
*
0.01
);
let
_scorerule
=
_
.
map
(
this
.
state
.
scoreRule
,(
item
)
=>
{
switch
(
item
.
typeKey
)
{
case
"SINGLE_CHOICE"
:
item
.
totalQuestion
=
singleQuestion
.
length
;
break
;
case
"MULTI_CHOICE"
:
item
.
totalQuestion
=
multiQuestion
.
length
;
break
;
case
"JUDGE"
:
item
.
totalQuestion
=
judgeQuestion
.
length
;
break
;
case
"GAP_FILLING"
:
item
.
totalQuestion
=
gapQuestion
.
length
;
break
;
case
"INDEFINITE_CHOICE"
:
item
.
totalQuestion
=
indefiniteQuestion
.
length
;
break
;
default
:
item
.
totalQuestion
=
0
break
;
}
return
item
})
this
.
setState
({
formData
:
{
...
formData
,
...
...
@@ -207,6 +265,7 @@ class OperatePaper extends Component {
questionCnt
:
_selectQuestionList
.
length
,
totalScore
,
},
scoreRule
:
_scorerule
,
});
};
...
...
@@ -217,9 +276,11 @@ class OperatePaper extends Component {
<
SelectQuestionModal
getSelectedQuestion=
{
selectQuestionList
}
setSelectedQuestion=
{
(
list
)
=>
{
//按分数规则给每一题重新设置分数(只对新增题目有效)
let
_list
=
this
.
setScoreByRule
(
list
)
this
.
setState
({
selectQuestionModal
:
null
},
()
=>
{
this
.
setFormData
(
list
);
this
.
quickSorter
(
list
,
sorterMethod
,
sorterBy
);
this
.
setFormData
(
_
list
);
this
.
quickSorter
(
_
list
,
sorterMethod
,
sorterBy
);
});
}
}
close=
{
()
=>
{
...
...
@@ -232,6 +293,25 @@ class OperatePaper extends Component {
this
.
setState
({
selectQuestionModal
:
m
});
};
setScoreByRule
=
(
list
)
=>
{
//按批量设置分数规则给每一题重新设置分数(只对新增题目有效)
return
_
.
map
(
list
,
(
item
)
=>
{
let
exist
=
_
.
find
(
this
.
state
.
selectQuestionList
,
(
q
)
=>
{
return
q
.
questionId
===
item
.
questionId
})
if
(
exist
)
{
return
item
}
let
rule
=
_
.
find
(
this
.
state
.
scoreRule
,(
g
)
=>
{
return
g
.
typeKey
===
item
.
questionType
})
if
(
rule
)
{
item
.
score
=
rule
.
score
item
.
portionScore
=
rule
.
portionScore
}
return
item
})
}
// 移动已选题目
handleMoveItem
=
(
index
,
moveLength
)
=>
{
const
selectQuestionList
=
[...
this
.
state
.
selectQuestionList
];
...
...
@@ -505,6 +585,10 @@ class OperatePaper extends Component {
max=
{
100
}
value=
{
record
.
score
||
2
}
onChange=
{
(
value
)
=>
{
value
=
Math
.
round
(
value
)
if
(
value
<=
record
.
portionScore
)
{
return
}
const
_selectQuestionList
=
[...
selectQuestionList
];
this
.
setState
(
{
...
...
@@ -528,9 +612,10 @@ class OperatePaper extends Component {
{
record
.
questionType
===
'GAP_FILLING'
?
<
span
>
半对得
</
span
>
:
<
span
>
漏选得
</
span
>
}{
' '
}
<
InputNumber
min=
{
0
}
max=
{
record
.
score
-
1
}
max=
{
record
.
score
<=
0
?
0
:
record
.
score
-
1
}
value=
{
record
.
portionScore
||
0
}
onChange=
{
(
value
)
=>
{
value
=
Math
.
round
(
value
)
const
_selectQuestionList
=
[...
selectQuestionList
];
this
.
setState
(
{
...
...
@@ -586,6 +671,52 @@ class OperatePaper extends Component {
return
columns
;
};
//
onBatchScoreOK
=
(
rules
)
=>
{
this
.
setState
({
batchSetScoreVisible
:
false
,
scoreRule
:
rules
},()
=>
{
let
questionList
=
_
.
map
(
this
.
state
.
selectQuestionList
,(
item
)
=>
{
let
rule
=
_
.
find
(
this
.
state
.
scoreRule
,(
s
)
=>
{
return
s
.
typeKey
===
item
.
questionType
})
if
(
rule
)
{
item
.
score
=
rule
.
score
item
.
portionScore
=
rule
.
portionScore
}
return
item
})
// 各类型题目总分值
const
{
formData
,
scoreRule
}
=
this
.
state
const
{
singleChoiceCnt
,
multiChoiceCnt
,
judgeCnt
,
gapFillingCnt
,
indefiniteChoiceCnt
}
=
formData
const
singleChoiceScore
=
singleChoiceCnt
*
scoreRule
.
find
((
item
)
=>
{
return
item
.
typeKey
===
"SINGLE_CHOICE"
}).
score
const
multiChoiceScore
=
multiChoiceCnt
*
scoreRule
.
find
((
item
)
=>
{
return
item
.
typeKey
===
"MULTI_CHOICE"
}).
score
const
judgeScore
=
judgeCnt
*
scoreRule
.
find
((
item
)
=>
{
return
item
.
typeKey
===
"JUDGE"
}).
score
const
gapFillingScore
=
gapFillingCnt
*
scoreRule
.
find
((
item
)
=>
{
return
item
.
typeKey
===
"GAP_FILLING"
}).
score
const
indefiniteChoiceScore
=
indefiniteChoiceCnt
*
scoreRule
.
find
((
item
)
=>
{
return
item
.
typeKey
===
"INDEFINITE_CHOICE"
}).
score
const
totalScore
=
questionList
.
reduce
((
prev
,
cur
)
=>
{
return
prev
+
Number
(
cur
.
score
)
||
0
;
},
0
);
const
passScore
=
Math
.
round
(
totalScore
*
formData
.
passRate
*
0.01
);
this
.
setState
({
selectQuestionList
:
questionList
,
formData
:
{
...
formData
,
singleChoiceScore
,
multiChoiceScore
,
judgeScore
,
gapFillingScore
,
indefiniteChoiceScore
,
totalScore
,
passScore
,
}
})
message
.
success
(
"设置成功"
)
})
}
// 上下移题型
handleMoveTypeSorter
=
(
index
,
moveLength
)
=>
{
const
sorterTypeList
=
[...
this
.
state
.
sorterTypeList
];
...
...
@@ -724,6 +855,7 @@ class OperatePaper extends Component {
max=
{
100
}
value=
{
passRate
}
onChange=
{
(
value
)
=>
{
value
=
Math
.
round
(
value
)
this
.
setState
(
{
formData
:
{
...
...
@@ -757,22 +889,36 @@ class OperatePaper extends Component {
}
}
>
快捷排序
</
Button
>
<
Button
className=
"choose-btn"
onClick=
{
()
=>
{
this
.
setState
({
batchSetScoreVisible
:
true
,
});
}
}
>
批量设置分数
</
Button
>
</
Space
>
{
questionCnt
>
0
&&
(
<
div
className=
'paper-info-tip'
style=
{
{
margin
:
'0 auto 12px'
}
}
>
总计
<
span
>
{
totalScore
}
</
span
>
分,共
<
span
>
{
questionCnt
}
</
span
>
题。
{
singleChoiceCnt
>
0
&&
`单选题${singleChoiceCnt}题,共${singleChoiceScore}分;`
}
{
multiChoiceCnt
>
0
&&
`多选题${multiChoiceCnt}题,共${multiChoiceScore}分;`
}
{
judgeCnt
>
0
&&
`判断题${judgeCnt}题,共${judgeScore}分,`
}
{
gapFillingCnt
>
0
&&
`填空题${gapFillingCnt}题,共${gapFillingScore}分,`
}
{
indefiniteChoiceCnt
>
0
&&
`不定项选择题${indefiniteChoiceCnt}题,共${indefiniteChoiceScore}分`
}
题。
{
" "
}
{
singleChoiceCnt
>
0
&&
`单选题${singleChoiceCnt}题,共${singleChoiceScore}分;`
}
{
multiChoiceCnt
>
0
&&
`多选题${multiChoiceCnt}题,共${multiChoiceScore}分;`
}
{
judgeCnt
>
0
&&
`判断题${judgeCnt}题,共${judgeScore}分;`
}
{
gapFillingCnt
>
0
&&
`填空题${gapFillingCnt}题,共${gapFillingScore}分;`
}
{
indefiniteChoiceCnt
>
0
&&
`不定项选择题${indefiniteChoiceCnt}题,共${indefiniteChoiceScore}分;`
}
</
div
>
)
}
<
XMTable
className=
'table-style'
scroll=
{
{
y
:
350
}
}
columns=
{
this
.
parseColumns
()
}
dataSource=
{
selectQuestionList
}
pagination=
{
false
}
...
...
@@ -833,6 +979,13 @@ class OperatePaper extends Component {
/>
)
}
</
Modal
>
{
/* 批量设置分数规则 */
}
<
BatchScore
visible=
{
this
.
state
.
batchSetScoreVisible
}
onOK=
{
this
.
onBatchScoreOK
}
onCancel=
{
()
=>
this
.
setState
({
batchSetScoreVisible
:
false
})
}
rules=
{
this
.
state
.
scoreRule
}
/>
</
div
>
<
Route
path=
{
`${match.url}/exam-operate-page`
}
...
...
src/modules/teach-tool/paper-manage/OperatePaper.less
View file @
ce7a5a1e
...
...
@@ -7,6 +7,8 @@
.table-style {
border: 1px solid #f0f0f0 !important;
margin-bottom: 70px;
max-height: calc(~'100vh - 465px');
overflow: scroll;
}
.ant-tabs {
color: #666666;
...
...
src/modules/teach-tool/paper-manage/components/BatchScore.less
0 → 100644
View file @
ce7a5a1e
.batchscore {
.content {
.item {
display: flex;
width: 612px;
height: 48px;
background: #F7F8F9;
font-size: 14px;
line-height: 48px;
font-weight: 400;
color: #333333;
padding-left: 16px;
.type {
width: 112px;
}
.score {
margin-left: 8px;
margin-right: 29px;
width: 258px;
}
}
.item:not(:last-of-type) {
margin-bottom: 8px;
}
}
}
\ No newline at end of file
src/modules/teach-tool/paper-manage/components/BatchScore.tsx
0 → 100644
View file @
ce7a5a1e
import
React
,
{
useEffect
,
useState
}
from
"react"
;
import
{
Modal
,
Button
,
InputNumber
,
message
}
from
'antd'
;
import
"./BatchScore.less"
import
_
from
"underscore"
;
interface
Rule
{
typeKey
:
"GAP_FILLING"
|
"INDEFINITE_CHOICE"
|
"JUDGE"
|
"MULTI_CHOICE"
|
"SINGLE_CHOICE"
,
score
:
number
,
portionScore
:
number
,
totalQuestion
:
number
,
}
interface
BatchScoreProps
{
visible
:
boolean
,
rules
:
Rule
[],
onOK
:
(
rules
:
Rule
[])
=>
void
,
onCancel
:
()
=>
void
,
}
export
default
function
BatchScore
(
props
:
BatchScoreProps
)
{
const
[
rules
,
setRules
]
=
useState
<
Rule
[]
>
(
_
.
sortBy
(
props
.
rules
,
"typeKey"
))
const
[
singleCount
,
setSingleCount
]
=
useState
<
number
[]
>
([
0
])
const
[
multiCount
,
setMultiCount
]
=
useState
<
number
[]
>
([
0
])
const
[
judgeCount
,
setJudgeCount
]
=
useState
<
number
[]
>
([
0
])
const
[
gapCount
,
setgapCount
]
=
useState
<
number
[]
>
([
0
])
const
[
indefiniteCount
,
setIndefiniteCount
]
=
useState
<
number
[]
>
([
0
])
useEffect
(()
=>
{
_
.
map
(
props
.
rules
,(
item
)
=>
{
//更新分数统计
switch
(
item
.
typeKey
)
{
case
"SINGLE_CHOICE"
:
setSingleCount
([
item
.
totalQuestion
,
item
.
totalQuestion
*
item
.
score
])
break
;
case
"MULTI_CHOICE"
:
setMultiCount
([
item
.
totalQuestion
,
item
.
totalQuestion
*
item
.
score
])
break
;
case
"JUDGE"
:
setJudgeCount
([
item
.
totalQuestion
,
item
.
totalQuestion
*
item
.
score
])
break
;
case
"GAP_FILLING"
:
setgapCount
([
item
.
totalQuestion
,
item
.
totalQuestion
*
item
.
score
])
break
;
case
"INDEFINITE_CHOICE"
:
setIndefiniteCount
([
item
.
totalQuestion
,
item
.
totalQuestion
*
item
.
score
])
break
;
default
:
break
;
}
})
},[
props
.
rules
,
rules
])
if
(
!
props
.
visible
)
{
return
(
""
)
}
function
onOk
()
{
for
(
let
i
=
0
;
i
<
rules
.
length
;
++
i
)
{
if
(
rules
[
i
].
score
<=
0
||
rules
[
i
].
score
>
100
)
{
message
.
error
(
"分值设置错误"
)
return
;
}
}
props
.
onOK
(
rules
)
}
function
onCancel
()
{
props
.
onCancel
()
}
const
inputNumberStyle
=
{
width
:
"57px"
,
margin
:
"0 8px"
}
return
(
<
Modal
className=
"batchscore"
title=
"批量设置分数"
onCancel=
{
onCancel
}
onOk=
{
onOk
}
visible=
{
props
.
visible
}
maskClosable=
{
false
}
width=
{
660
}
>
<
div
className=
"content"
>
<
div
className=
"item"
>
<
span
className=
"type"
>
【单选题】
</
span
>
<
span
className=
"score"
>
每题
<
InputNumber
min=
{
1
}
max=
{
100
}
value=
{
rules
[
4
].
score
}
defaultValue=
{
rules
[
4
].
score
}
style=
{
inputNumberStyle
}
onChange=
{
(
v
)
=>
{
v
=
Math
.
round
(
v
)
let
_rules
=
[...
rules
]
rules
[
4
].
score
=
v
setRules
(
_rules
)
}
}
/>
分
</
span
>
<
span
className=
"total"
>
共
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
singleCount
[
0
]
}
</
span
>
题,合计
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
singleCount
[
1
]
}
</
span
>
分
</
span
>
</
div
>
<
div
className=
"item"
>
<
span
className=
"type"
>
【多选题】
</
span
>
<
span
className=
"score"
>
每题
<
InputNumber
min=
{
1
}
max=
{
100
}
defaultValue=
{
rules
[
3
].
score
}
value=
{
rules
[
3
].
score
}
style=
{
inputNumberStyle
}
onChange=
{
(
v
)
=>
{
v
=
Math
.
round
(
v
)
if
(
v
<=
rules
[
3
].
portionScore
)
{
return
}
let
_r
=
[...
rules
]
_r
[
3
].
score
=
v
setRules
(
_r
)
}
}
/>
分,漏选得
<
InputNumber
min=
{
0
}
max=
{
rules
[
3
].
score
<=
0
?
0
:
rules
[
3
].
score
-
1
}
defaultValue=
{
rules
[
3
].
portionScore
}
value=
{
rules
[
3
].
portionScore
}
style=
{
inputNumberStyle
}
onChange=
{
(
v
)
=>
{
v
=
Math
.
round
(
v
)
let
_r
=
[...
rules
]
_r
[
3
].
portionScore
=
v
setRules
(
_r
)
}
}
/>
分
</
span
>
<
span
className=
"total"
>
共
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
multiCount
[
0
]
}
</
span
>
题,合计
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
multiCount
[
1
]
}
</
span
>
分
</
span
>
</
div
>
<
div
className=
"item"
>
<
span
className=
"type"
>
【不定项选择题】
</
span
>
<
span
className=
"score"
>
每题
<
InputNumber
min=
{
1
}
max=
{
100
}
defaultValue=
{
rules
[
1
].
score
}
value=
{
rules
[
1
].
score
}
style=
{
inputNumberStyle
}
onChange=
{
(
v
)
=>
{
v
=
Math
.
round
(
v
)
if
(
v
<=
rules
[
1
].
portionScore
)
{
return
}
let
_r
=
[...
rules
]
_r
[
1
].
score
=
v
setRules
(
_r
)
}
}
/>
分,漏选得
<
InputNumber
min=
{
0
}
max=
{
rules
[
1
].
score
<=
0
?
0
:
rules
[
1
].
score
-
1
}
defaultValue=
{
rules
[
1
].
portionScore
}
value=
{
rules
[
1
].
portionScore
}
style=
{
inputNumberStyle
}
onChange=
{
(
v
)
=>
{
v
=
Math
.
round
(
v
)
let
_r
=
[...
rules
]
_r
[
1
].
portionScore
=
v
setRules
(
_r
)
}
}
/>
分
</
span
>
<
span
className=
"total"
>
共
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
indefiniteCount
[
0
]
}
</
span
>
题,合计
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
indefiniteCount
[
1
]
}
</
span
>
分
</
span
>
</
div
>
<
div
className=
"item"
>
<
span
className=
"type"
>
【判断题】
</
span
>
<
span
className=
"score"
>
每题
<
InputNumber
min=
{
1
}
max=
{
100
}
defaultValue=
{
rules
[
2
].
score
}
value=
{
rules
[
2
].
score
}
style=
{
inputNumberStyle
}
onChange=
{
(
v
)
=>
{
v
=
Math
.
round
(
v
)
let
_r
=
[...
rules
]
_r
[
2
].
score
=
v
setRules
(
_r
)
}
}
/>
分
</
span
>
<
span
className=
"total"
>
共
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
judgeCount
[
0
]
}
</
span
>
题,合计
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
judgeCount
[
1
]
}
</
span
>
分
</
span
>
</
div
>
<
div
className=
"item"
>
<
span
className=
"type"
>
【填空题】
</
span
>
<
span
className=
"score"
>
每题
<
InputNumber
min=
{
1
}
max=
{
100
}
defaultValue=
{
rules
[
0
].
score
}
value=
{
rules
[
0
].
score
}
style=
{
inputNumberStyle
}
onChange=
{
(
v
)
=>
{
v
=
Math
.
round
(
v
)
if
(
v
<=
rules
[
0
].
portionScore
)
{
return
}
let
_r
=
[...
rules
]
_r
[
0
].
score
=
v
setRules
(
_r
)
}
}
/>
分,半对得
<
InputNumber
min=
{
0
}
max=
{
rules
[
0
].
score
<=
0
?
0
:
rules
[
0
].
score
-
1
}
defaultValue=
{
rules
[
0
].
portionScore
}
value=
{
rules
[
0
].
portionScore
}
style=
{
inputNumberStyle
}
onChange=
{
(
v
)
=>
{
v
=
Math
.
round
(
v
)
let
_r
=
[...
rules
]
_r
[
0
].
portionScore
=
v
setRules
(
_r
)
}
}
/>
分
</
span
>
<
span
className=
"total"
>
共
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
gapCount
[
0
]
}
</
span
>
题,合计
<
span
style=
{
{
color
:
"#2966FF"
}
}
>
{
gapCount
[
1
]
}
</
span
>
分
</
span
>
</
div
>
</
div
>
</
Modal
>
)
}
\ No newline at end of file
src/store/context.ts
View file @
ce7a5a1e
...
...
@@ -16,6 +16,8 @@ export interface VersionInfo {
userNum
:
number
;
//限制人数
validEndTime
:
string
;
validStartTime
:
string
;
validEndTimeST
:
number
;
validStartTimeST
:
number
;
whetherReachUserNum
:
boolean
;
}
...
...
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