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
462c5b38
Commit
462c5b38
authored
Mar 16, 2021
by
yuananting
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:填空修改暂存
parent
96b7a4c4
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
838 additions
and
461 deletions
+838
-461
src/data-source/questionBank/request-apis.ts
+6
-1
src/domains/question-bank-domain/QuestionBankService.ts
+8
-2
src/modules/store-manage/StoreWebDecorationTab.jsx
+2
-2
src/modules/teach-tool/AddNewQuestion.jsx
+10
-4
src/modules/teach-tool/components/GapFillingStem.jsx
+10
-7
src/modules/teach-tool/components/GapFillingStem.less
+2
-1
src/modules/teach-tool/components/NewQuestionTab.jsx
+428
-360
src/modules/teach-tool/components/NewQuestionTab.less
+5
-4
src/modules/teach-tool/components/QuestionManageContent.jsx
+31
-9
src/modules/teach-tool/components/QuestionManageContent.less
+6
-1
src/modules/teach-tool/modal/BatchImportQuestionModal.jsx
+107
-0
src/modules/teach-tool/modal/BatchImportQuestionModal.less
+84
-0
src/modules/teach-tool/modal/QuestionPreviewModal.jsx
+116
-70
src/modules/teach-tool/modal/QuestionPreviewModal.less
+23
-0
No files found.
src/data-source/questionBank/request-apis.ts
View file @
462c5b38
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Author: yuananting
* @Date: 2021-03-03 15:13:12
* @Date: 2021-03-03 15:13:12
* @LastEditors: yuananting
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
5 19:44:31
* @LastEditTime: 2021-03-1
6 15:11:25
* @Description: 助学工具接口
* @Description: 助学工具接口
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
...
@@ -51,4 +51,8 @@ export function queryQuestionDetails(params: object) {
...
@@ -51,4 +51,8 @@ export function queryQuestionDetails(params: object) {
export
function
editQuestion
(
params
:
object
)
{
export
function
editQuestion
(
params
:
object
)
{
return
Service
.
Hades
(
"anon/hades/question/editQuestion"
,
params
);
return
Service
.
Hades
(
"anon/hades/question/editQuestion"
,
params
);
}
export
function
batchImport
(
params
:
object
)
{
return
Service
.
Hades
(
"anon/hades/question/batchImport"
,
params
);
}
}
\ No newline at end of file
src/domains/question-bank-domain/QuestionBankService.ts
View file @
462c5b38
...
@@ -2,11 +2,11 @@
...
@@ -2,11 +2,11 @@
* @Author: yuananting
* @Author: yuananting
* @Date: 2021-03-11 11:34:37
* @Date: 2021-03-11 11:34:37
* @LastEditors: yuananting
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
5 19:45:10
* @LastEditTime: 2021-03-1
6 15:12:09
* @Description: 描述一下咯
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
import
{
queryCategoryTree
,
addCategory
,
delCategory
,
editCategory
,
editCategoryTree
,
queryQuestionCategoryTree
,
addQuestion
,
queryQuestionPageList
,
deleteQuestion
,
queryQuestionDetails
,
editQuestion
}
from
'@/data-source/questionBank/request-apis'
;
import
{
queryCategoryTree
,
addCategory
,
delCategory
,
editCategory
,
editCategoryTree
,
queryQuestionCategoryTree
,
addQuestion
,
queryQuestionPageList
,
deleteQuestion
,
queryQuestionDetails
,
editQuestion
,
batchImport
}
from
'@/data-source/questionBank/request-apis'
;
export
default
class
QuestionBankService
{
export
default
class
QuestionBankService
{
// 获取题目分类树
// 获取题目分类树
static
queryCategoryTree
(
params
:
any
)
{
static
queryCategoryTree
(
params
:
any
)
{
...
@@ -62,4 +62,9 @@ export default class QuestionBankService {
...
@@ -62,4 +62,9 @@ export default class QuestionBankService {
static
editQuestion
(
params
:
any
)
{
static
editQuestion
(
params
:
any
)
{
return
editQuestion
(
params
);
return
editQuestion
(
params
);
}
}
// 批量导入
static
batchImport
(
params
:
any
)
{
return
batchImport
(
params
);
}
}
}
\ No newline at end of file
src/modules/store-manage/StoreWebDecorationTab.jsx
View file @
462c5b38
/*
/*
* @Author: wufan
* @Author: wufan
* @Date: 2020-11-30 10:47:38
* @Date: 2020-11-30 10:47:38
* @LastEditors:
wufan
* @LastEditors:
yuananting
* @LastEditTime: 2021-0
1-18 14:59:57
* @LastEditTime: 2021-0
3-16 15:28:55
* @Description: web店铺banner页面
* @Description: web店铺banner页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
...
...
src/modules/teach-tool/AddNewQuestion.jsx
View file @
462c5b38
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Author: yuananting
* @Date: 2021-02-25 13:46:35
* @Date: 2021-02-25 13:46:35
* @LastEditors: yuananting
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
5 21:14:47
* @LastEditTime: 2021-03-1
6 16:44:23
* @Description: 助学工具-题库-题目管理-新增题目
* @Description: 助学工具-题库-题目管理-新增题目
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
...
@@ -15,6 +15,7 @@ import NewQuestionTab from "./components/NewQuestionTab";
...
@@ -15,6 +15,7 @@ import NewQuestionTab from "./components/NewQuestionTab";
import
{
defineQuestionInfo
}
from
"./components/model"
;
import
{
defineQuestionInfo
}
from
"./components/model"
;
import
QuestionBankService
from
"@/domains/question-bank-domain/QuestionBankService"
;
import
QuestionBankService
from
"@/domains/question-bank-domain/QuestionBankService"
;
import
User
from
"@/common/js/user"
;
import
User
from
"@/common/js/user"
;
import
UploadOss
from
"@/core/upload"
;
const
{
TabPane
}
=
Tabs
;
const
{
TabPane
}
=
Tabs
;
class
AddNewQuestion
extends
Component
{
class
AddNewQuestion
extends
Component
{
...
@@ -144,10 +145,14 @@ class AddNewQuestion extends Component {
...
@@ -144,10 +145,14 @@ class AddNewQuestion extends Component {
}
}
break
;
break
;
case
"JUDGE"
:
case
"JUDGE"
:
this
.
judgeRef
.
checkInput
();
if
(
this
.
judgeRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
judgeContent
);
}
break
;
break
;
case
"GAP_FILLING"
:
case
"GAP_FILLING"
:
this
.
CompletionRef
.
checkInput
();
if
(
this
.
gapRef
.
checkInput
()
===
0
)
{
// this.saveCurrentQuestion(gapFillingContent);
}
break
;
break
;
case
"INDEFINITE_CHOICE"
:
case
"INDEFINITE_CHOICE"
:
if
(
this
.
indefiniteRef
.
checkInput
()
===
0
)
{
if
(
this
.
indefiniteRef
.
checkInput
()
===
0
)
{
...
@@ -242,10 +247,11 @@ class AddNewQuestion extends Component {
...
@@ -242,10 +247,11 @@ class AddNewQuestion extends Component {
<
NewQuestionTab
<
NewQuestionTab
questionTypeKey=
"GAP_FILLING"
questionTypeKey=
"GAP_FILLING"
onRef=
{
(
ref
)
=>
{
onRef=
{
(
ref
)
=>
{
this
.
Completion
Ref
=
ref
;
this
.
gap
Ref
=
ref
;
}
}
}
}
questionInfo=
{
gapFillingContent
}
questionInfo=
{
gapFillingContent
}
onSetState=
{
(
newContent
)
=>
{
onSetState=
{
(
newContent
)
=>
{
console
.
log
(
"gapFillingContent:"
,
newContent
);
Object
.
assign
(
gapFillingContent
,
newContent
);
Object
.
assign
(
gapFillingContent
,
newContent
);
}
}
}
}
/>
/>
...
...
src/modules/teach-tool/components/
Completion
Stem.jsx
→
src/modules/teach-tool/components/
GapFilling
Stem.jsx
View file @
462c5b38
import
React
,
{
Component
}
from
"react"
;
import
React
,
{
Component
}
from
"react"
;
import
{
message
,
Button
}
from
"antd"
;
import
{
message
,
Button
}
from
"antd"
;
import
UploadOss
from
"@/core/upload"
;
import
UploadOss
from
"@/core/upload"
;
import
"./
Completion
Stem.less"
;
import
"./
GapFilling
Stem.less"
;
const
MEDIA_MAP
=
[
const
MEDIA_MAP
=
[
{
{
title
:
"音频"
,
title
:
"音频"
,
...
@@ -24,7 +24,7 @@ const MEDIA_MAP = [
...
@@ -24,7 +24,7 @@ const MEDIA_MAP = [
key
:
"VIDEO"
,
key
:
"VIDEO"
,
},
},
];
];
class
Completion
Stem
extends
Component
{
class
GapFilling
Stem
extends
Component
{
constructor
(
props
)
{
constructor
(
props
)
{
super
(
props
);
super
(
props
);
this
.
state
=
{
this
.
state
=
{
...
@@ -48,13 +48,14 @@ class CompletionStem extends Component {
...
@@ -48,13 +48,14 @@ class CompletionStem extends Component {
var
_blanksList
=
[];
var
_blanksList
=
[];
const
stemInput
=
document
.
getElementById
(
"editor-box_content"
);
const
stemInput
=
document
.
getElementById
(
"editor-box_content"
);
stemInput
.
childNodes
.
forEach
((
item
)
=>
{
stemInput
.
childNodes
.
forEach
((
item
)
=>
{
if
(
item
.
nodeName
===
"SPAN"
)
{
if
(
item
.
nodeName
===
"SPAN"
&&
item
.
id
)
{
_blanksList
.
push
(
item
);
_blanksList
.
push
(
item
);
}
}
});
});
this
.
setState
({
blanksList
:
_blanksList
})
this
.
setState
({
blanksList
:
_blanksList
})
this
.
handleStemStyle
();
this
.
handleStemStyle
();
this
.
props
.
changeBlankCount
(
this
.
state
.
blanksList
);
this
.
props
.
onChange
(
stemInput
.
innerHTML
)
this
.
props
.
changeBlankCount
(
_blanksList
);
};
};
/**
/**
...
@@ -66,6 +67,7 @@ class CompletionStem extends Component {
...
@@ -66,6 +67,7 @@ class CompletionStem extends Component {
insertBlanks
=
()
=>
{
insertBlanks
=
()
=>
{
document
.
getElementById
(
"editor-box_content"
).
focus
();
document
.
getElementById
(
"editor-box_content"
).
focus
();
const
_blanksList
=
this
.
state
.
blanksList
;
const
_blanksList
=
this
.
state
.
blanksList
;
console
.
log
(
"888888888888:"
,
_blanksList
);
var
blanks
=
document
.
createElement
(
"span"
);
var
blanks
=
document
.
createElement
(
"span"
);
blanks
.
className
=
"fill-line"
;
blanks
.
className
=
"fill-line"
;
blanks
.
innerHTML
=
"填空"
;
blanks
.
innerHTML
=
"填空"
;
...
@@ -75,6 +77,7 @@ class CompletionStem extends Component {
...
@@ -75,6 +77,7 @@ class CompletionStem extends Component {
this
.
setState
({
blanksList
:
_blanksList
});
this
.
setState
({
blanksList
:
_blanksList
});
var
sel
,
range
;
var
sel
,
range
;
sel
=
window
.
getSelection
();
sel
=
window
.
getSelection
();
console
.
log
(
"*****:"
,
sel
)
if
(
sel
.
getRangeAt
&&
sel
.
rangeCount
)
{
if
(
sel
.
getRangeAt
&&
sel
.
rangeCount
)
{
range
=
sel
.
getRangeAt
(
0
);
range
=
sel
.
getRangeAt
(
0
);
range
.
deleteContents
();
range
.
deleteContents
();
...
@@ -134,7 +137,7 @@ class CompletionStem extends Component {
...
@@ -134,7 +137,7 @@ class CompletionStem extends Component {
}
=
this
.
props
;
}
=
this
.
props
;
return
(
return
(
<
div
<
div
className=
"
completion
-question-edtior_box"
className=
"
gap
-question-edtior_box"
style=
{
{
zIndex
}
}
style=
{
{
zIndex
}
}
onMouseEnter=
{
()
=>
{
onMouseEnter=
{
()
=>
{
if
(
visibleMediaBox
||
focusFlag
)
return
;
if
(
visibleMediaBox
||
focusFlag
)
return
;
...
@@ -177,7 +180,7 @@ class CompletionStem extends Component {
...
@@ -177,7 +180,7 @@ class CompletionStem extends Component {
/
{
limitLength
}
/
{
limitLength
}
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className=
"editor-fill-info"
>
<
div
className=
"editor-fill-info"
style=
{
{
top
:
this
.
props
.
validateStatus
===
"error"
?
"56px"
:
"36px"
}
}
>
在需要填写答案的地方
在需要填写答案的地方
<
Button
<
Button
type=
"link"
type=
"link"
...
@@ -227,4 +230,4 @@ class CompletionStem extends Component {
...
@@ -227,4 +230,4 @@ class CompletionStem extends Component {
);
);
}
}
}
}
export
default
Completion
Stem
;
export
default
GapFilling
Stem
;
src/modules/teach-tool/components/
Completion
Stem.less
→
src/modules/teach-tool/components/
GapFilling
Stem.less
View file @
462c5b38
.
completion
-question-edtior_box {
.
gap
-question-edtior_box {
position: relative;
position: relative;
.editor-box-single {
.editor-box-single {
border-radius: 4px;
border-radius: 4px;
...
@@ -56,6 +56,7 @@
...
@@ -56,6 +56,7 @@
}
}
.editor-fill-info {
.editor-fill-info {
// position: absolute;
height: 20px;
height: 20px;
font-size: 14px;
font-size: 14px;
line-height: 20px;
line-height: 20px;
...
...
src/modules/teach-tool/components/NewQuestionTab.jsx
View file @
462c5b38
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Author: yuananting
* @Date: 2021-02-25 14:34:29
* @Date: 2021-02-25 14:34:29
* @LastEditors: yuananting
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
5 21:12:14
* @LastEditTime: 2021-03-1
6 17:23:02
* @Description: 助学工具-题库-题目管理-新建题目Tab
* @Description: 助学工具-题库-题目管理-新建题目Tab
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
...
@@ -11,7 +11,7 @@ import { Form, Radio, message, Checkbox, Tag, Tooltip, Input } from "antd";
...
@@ -11,7 +11,7 @@ import { Form, Radio, message, Checkbox, Tag, Tooltip, Input } from "antd";
import
"./NewQuestionTab.less"
;
import
"./NewQuestionTab.less"
;
import
Upload
from
"@/core/upload"
;
import
Upload
from
"@/core/upload"
;
import
QuestionEditor
from
"./QuestionEditor"
;
import
QuestionEditor
from
"./QuestionEditor"
;
import
CompletionStem
from
"./Completion
Stem"
;
import
GapFillingStem
from
"./GapFilling
Stem"
;
import
{
PlusOutlined
,
CloseOutlined
}
from
"@ant-design/icons"
;
import
{
PlusOutlined
,
CloseOutlined
}
from
"@ant-design/icons"
;
import
{
import
{
NUM_TO_WORD_MAP
,
NUM_TO_WORD_MAP
,
...
@@ -22,7 +22,8 @@ import UploadingProgress from "./UploadingProgress";
...
@@ -22,7 +22,8 @@ import UploadingProgress from "./UploadingProgress";
import
XMAudio
from
"./XMAudio"
;
import
XMAudio
from
"./XMAudio"
;
import
XMRecord
from
"./XMRecord"
;
import
XMRecord
from
"./XMRecord"
;
import
ScanFileModal
from
"@/modules/resource-disk/modal/ScanFileModal"
;
import
ScanFileModal
from
"@/modules/resource-disk/modal/ScanFileModal"
;
import
_
from
'lodash'
;
import
_
from
"lodash"
;
import
UploadOss
from
"@/core/upload"
;
class
NewQuestionTab
extends
Component
{
class
NewQuestionTab
extends
Component
{
constructor
(
props
)
{
constructor
(
props
)
{
...
@@ -30,33 +31,22 @@ class NewQuestionTab extends Component {
...
@@ -30,33 +31,22 @@ class NewQuestionTab extends Component {
const
{
questionInfo
=
{}
}
=
props
;
const
{
questionInfo
=
{}
}
=
props
;
const
{
const
{
questionStemList
,
questionStemList
,
gapFillingAnswerList
,
optionList
,
optionList
,
questionAnswerDescList
,
questionAnswerDescList
,
showBox
,
showBox
,
}
=
questionInfo
;
}
=
questionInfo
;
this
.
state
=
{
this
.
state
=
{
stemContent
:
JSON
.
parse
(
JSON
.
stringify
(
questionStemList
)),
// 题干内容
stemContent
:
JSON
.
parse
(
JSON
.
stringify
(
questionStemList
)),
// 题干内容
chooseOptions
:
JSON
.
parse
(
JSON
.
stringify
(
optionList
)),
// 单选多选不定项-选项列表
gapFillingAnswer
:
JSON
.
parse
(
JSON
.
stringify
(
gapFillingAnswerList
)),
// 填空题-选项列表
chooseOptions
:
JSON
.
parse
(
JSON
.
stringify
(
optionList
)),
// 单选多选不定项判断-选项列表
questionAnswerDesc
:
JSON
.
parse
(
JSON
.
stringify
(
questionAnswerDescList
)),
// 答案解析
questionAnswerDesc
:
JSON
.
parse
(
JSON
.
stringify
(
questionAnswerDescList
)),
// 答案解析
accept
:
QUESTION_FILE_ACCEPT
[
"PICTURE"
],
// 上传媒体类型
accept
:
QUESTION_FILE_ACCEPT
[
"PICTURE"
],
// 上传媒体类型
fileType
:
"PICTURE"
,
// 媒体枚举
fileType
:
"PICTURE"
,
// 媒体枚举
showRecord
:
false
,
// 录音弹窗
showRecord
:
false
,
// 录音弹窗
showBox
:
showBox
,
showBox
:
showBox
,
completion
Options
:
[],
gapFilling
Options
:
[],
blanksList
:
[],
// 填空列表
blanksList
:
[],
// 填空列表
judgeOptions
:
[
{
// 判断-选项列表
label
:
"正确"
,
value
:
true
,
isCorrectAnswer
:
null
,
},
{
label
:
"错误"
,
value
:
false
,
isCorrectAnswer
:
null
,
},
],
};
};
this
.
uploadInput
=
React
.
createRef
();
this
.
uploadInput
=
React
.
createRef
();
this
.
markKey
=
window
.
random_string
(
16
);
this
.
markKey
=
window
.
random_string
(
16
);
...
@@ -64,12 +54,18 @@ class NewQuestionTab extends Component {
...
@@ -64,12 +54,18 @@ class NewQuestionTab extends Component {
componentDidMount
()
{
componentDidMount
()
{
const
{
chooseOptions
}
=
this
.
state
;
const
{
chooseOptions
}
=
this
.
state
;
if
(
chooseOptions
.
length
===
0
)
{
if
(
// 选择题(单选 多选 不定项)-插入4条默认选项
[
"INDEFINITE_CHOICE"
,
"MULTI_CHOICE"
,
"SINGLE_CHOICE"
].
includes
(
for
(
var
i
=
0
;
i
<
4
;
i
++
)
{
this
.
props
.
questionTypeKey
this
.
handleAddOption
();
)
this
.
setState
({
[
`optionsValidate_
${
i
}
`
]:
"success"
});
)
{
this
.
setState
({
[
`optionsText_
${
i
}
`
]:
""
});
if
(
chooseOptions
.
length
===
0
)
{
// 选择题(单选 多选 不定项)-插入4条默认选项
for
(
var
i
=
0
;
i
<
4
;
i
++
)
{
this
.
handleAddOption
();
this
.
setState
({
[
`optionsValidate_
${
i
}
`
]:
"success"
});
this
.
setState
({
[
`optionsText_
${
i
}
`
]:
""
});
}
}
}
}
}
this
.
props
.
onRef
(
this
);
this
.
props
.
onRef
(
this
);
...
@@ -96,63 +92,122 @@ class NewQuestionTab extends Component {
...
@@ -96,63 +92,122 @@ class NewQuestionTab extends Component {
shouldComponentUpdate
(
nextProps
,
nextState
)
{
shouldComponentUpdate
(
nextProps
,
nextState
)
{
const
{
questionInfo
}
=
nextProps
;
const
{
questionInfo
}
=
nextProps
;
if
(
this
.
props
.
questionInfo
!==
questionInfo
)
{
if
(
this
.
props
.
questionInfo
!==
questionInfo
)
{
this
.
setState
({
stemContent
:
JSON
.
parse
(
JSON
.
stringify
(
questionInfo
.
questionStemList
))});
// 题干内容
this
.
setState
({
this
.
setState
({
chooseOptions
:
JSON
.
parse
(
JSON
.
stringify
(
questionInfo
.
optionList
))});
// 单选多选不定项-选项列表
stemContent
:
JSON
.
parse
(
JSON
.
stringify
(
questionInfo
.
questionStemList
)),
this
.
setState
({
questionAnswerDesc
:
JSON
.
parse
(
JSON
.
stringify
(
questionInfo
.
questionAnswerDescList
))});
// 答案解析
});
// 题干内容
this
.
_onSetState
()
this
.
setState
({
chooseOptions
:
JSON
.
parse
(
JSON
.
stringify
(
questionInfo
.
optionList
)),
});
// 单选多选不定项-选项列表
this
.
setState
({
questionAnswerDesc
:
JSON
.
parse
(
JSON
.
stringify
(
questionInfo
.
questionAnswerDescList
)
),
});
// 答案解析
this
.
_onSetState
();
}
}
return
true
;
return
true
;
}
}
_onSetState
=
(
params
=
{})
=>
{
_onSetState
=
(
params
=
{})
=>
{
this
.
setState
({
...
params
,
updateKey
:
window
.
random_string
(
16
)
},
this
.
setState
({
...
params
,
updateKey
:
window
.
random_string
(
16
)
},
()
=>
{
()
=>
{
this
.
props
.
onSetState
({
this
.
props
.
onSetState
({
questionStemList
:
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
stemContent
)),
questionStemList
:
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
stemContent
)),
gapFillingAnswerList
:
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
gapFillingAnswer
)
),
optionList
:
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
chooseOptions
)),
optionList
:
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
chooseOptions
)),
questionAnswerDescList
:
JSON
.
parse
(
questionAnswerDescList
:
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
questionAnswerDesc
)
JSON
.
stringify
(
this
.
state
.
questionAnswerDesc
)
),
),
});
});
});
};
dataURItoBlob
=
(
dataURI
)
=>
{
var
mimeString
=
dataURI
.
split
(
","
)[
0
].
split
(
":"
)[
1
].
split
(
";"
)[
0
];
// mime类型
var
byteString
=
atob
(
dataURI
.
split
(
","
)[
1
]);
//base64 解码
var
arrayBuffer
=
new
ArrayBuffer
(
byteString
.
length
);
//创建缓冲数组
var
intArray
=
new
Uint8Array
(
arrayBuffer
);
//创建视图
for
(
var
i
=
0
;
i
<
byteString
.
length
;
i
++
)
{
intArray
[
i
]
=
byteString
.
charCodeAt
(
i
);
}
}
);
return
new
Blob
([
intArray
],
{
type
:
mimeString
}
);
};
};
// 保存校验
// 保存校验
checkInput
=
()
=>
{
checkInput
=
async
()
=>
{
let
validateError
=
0
;
let
validateError
=
0
;
// 题干校验
// 题干校验
cons
t
stemContent
=
_
.
find
(
le
t
stemContent
=
_
.
find
(
this
.
state
.
stemContent
,
this
.
state
.
stemContent
,
(
contentItem
)
=>
contentItem
.
type
===
"RICH_TEXT"
(
contentItem
)
=>
contentItem
.
type
===
"RICH_TEXT"
);
);
const
stem
=
stemContent
.
content
.
replace
(
/<
[^
>
]
+>/g
,
""
);
const
stem
=
stemContent
.
content
.
replace
(
/<
[^
>
]
+>/g
,
""
);
if
(
stem
.
length
===
0
)
{
this
.
setState
({
stemValidate
:
"error"
});
if
(
this
.
props
.
questionTypeKey
===
"GAP_FILLING"
)
{
this
.
setState
({
stemText
:
"请输入题干"
});
// stemContent.content.replace(
validateError
++
;
// /<img [^>]*src=['"]([^'"]+)[^>]*>/gi,
}
else
{
// (match, capture) => {
this
.
setState
({
stemValidate
:
"success"
});
// let blob = this.dataURItoBlob(capture);
this
.
setState
({
stemText
:
""
});
// const imageUrl = await UploadOss.uploadBlobToOSS(
}
// blob,
// window.random_string(16) + ".png"
// );
// 选项校验
// newImgHtml = `<img src=${imageUrl} alt="" />`;
let
optionUnChecked
=
0
;
// console.log("newImgHtml:", newImgHtml);
const
{
chooseOptions
,
judgeOptions
}
=
this
.
state
;
// }
const
{
questionTypeKey
}
=
this
.
props
;
// );
if
(
questionTypeKey
===
"JUDGE"
)
{
// console.log("修改:", stemContent);
optionUnChecked
=
judgeOptions
.
filter
(
// this._onSetState();
(
item
)
=>
item
.
isCorrectAnswer
===
null
if
(
this
.
state
.
blanksList
.
length
===
0
)
{
).
length
;
this
.
setState
({
stemValidate
:
"error"
});
if
(
optionUnChecked
===
judgeOptions
.
length
)
{
this
.
setState
({
this
.
setState
({
radioValidate
:
"error"
});
stemText
:
(
this
.
setState
({
radioText
:
"请选择正确答案"
});
<
div
style=
{
{
marginTop
:
8
,
minWidth
:
"523px"
}
}
>
请输入正确格式,示例:党章规定,凡事有
<
span
style=
{
{
padding
:
"0 10px"
,
borderBottom
:
"1px solid"
}
}
>
填空1
</
span
>
人以上的
<
span
style=
{
{
padding
:
"0 10px"
,
borderBottom
:
"1px solid"
}
}
>
填空2
</
span
>
,都应该成立党的基层组织
</
div
>
),
});
validateError
++
;
validateError
++
;
}
else
{
}
else
{
this
.
setState
({
radio
Validate
:
"success"
});
this
.
setState
({
stem
Validate
:
"success"
});
this
.
setState
({
radio
Text
:
""
});
this
.
setState
({
stem
Text
:
""
});
}
}
}
else
{
}
else
{
if
(
stem
.
length
===
0
)
{
this
.
setState
({
stemValidate
:
"error"
});
this
.
setState
({
stemText
:
"请输入题干"
});
validateError
++
;
}
else
{
this
.
setState
({
stemValidate
:
"success"
});
this
.
setState
({
stemText
:
""
});
}
}
// 选项校验
let
optionUnChecked
=
0
;
const
{
chooseOptions
}
=
this
.
state
;
if
(
this
.
props
.
questionTypeKey
===
"GAP_FILLING"
)
{
this
.
state
.
blanksList
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
answerTagList
.
length
===
0
)
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"error"
});
this
.
setState
({
[
`optionsText_
${
index
}
`
]:
"请输入答案"
});
validateError
++
;
}
else
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"success"
});
this
.
setState
({
[
`optionsText_
${
index
}
`
]:
""
});
}
});
}
else
{
chooseOptions
.
forEach
((
item
,
index
)
=>
{
chooseOptions
.
forEach
((
item
,
index
)
=>
{
const
optionContent
=
item
.
questionOptionContentList
;
const
optionContent
=
item
.
questionOptionContentList
;
optionUnChecked
=
item
.
isCorrectAnswer
optionUnChecked
=
item
.
isCorrectAnswer
...
@@ -219,7 +274,6 @@ class NewQuestionTab extends Component {
...
@@ -219,7 +274,6 @@ class NewQuestionTab extends Component {
}
}
};
};
/**
/**
* 删除选项
* 删除选项
*
*
...
@@ -254,7 +308,7 @@ class NewQuestionTab extends Component {
...
@@ -254,7 +308,7 @@ class NewQuestionTab extends Component {
* @memberof QuestionInputItem
* @memberof QuestionInputItem
*/
*/
handleChangeMedia
=
(
key
,
uploadItemTarget
,
contentType
)
=>
{
handleChangeMedia
=
(
key
,
uploadItemTarget
,
contentType
)
=>
{
this
.
setState
({
contentType
})
this
.
setState
({
contentType
})
;
const
{
mediaFirstType
}
=
this
.
state
;
const
{
mediaFirstType
}
=
this
.
state
;
const
mediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
const
mediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
!==
"RICH_TEXT"
;
return
mediaItem
.
type
!==
"RICH_TEXT"
;
...
@@ -293,16 +347,16 @@ class NewQuestionTab extends Component {
...
@@ -293,16 +347,16 @@ class NewQuestionTab extends Component {
return
mediaItem
.
type
===
"VIDEO"
;
return
mediaItem
.
type
===
"VIDEO"
;
});
});
if
(
pictureMediaArr
.
length
>
0
)
{
if
(
pictureMediaArr
.
length
>
0
)
{
existType
.
push
(
"PICTURE"
)
existType
.
push
(
"PICTURE"
)
;
}
}
if
(
voiceMediaArr
.
length
>
0
)
{
if
(
voiceMediaArr
.
length
>
0
)
{
existType
.
push
(
"VOICE"
)
existType
.
push
(
"VOICE"
)
;
}
}
if
(
recordMediaArr
.
length
>
0
)
{
if
(
recordMediaArr
.
length
>
0
)
{
existType
.
push
(
"RECORD"
)
existType
.
push
(
"RECORD"
)
;
}
}
if
(
videodMediaArr
.
length
>
0
)
{
if
(
videodMediaArr
.
length
>
0
)
{
existType
.
push
(
"VIDEO"
)
existType
.
push
(
"VIDEO"
)
;
}
}
if
(
existType
.
length
>
2
&&
!
existType
.
includes
(
key
))
{
if
(
existType
.
length
>
2
&&
!
existType
.
includes
(
key
))
{
return
message
.
warning
(
"只能添加3种类型的多媒体文件"
);
return
message
.
warning
(
"只能添加3种类型的多媒体文件"
);
...
@@ -433,7 +487,9 @@ class NewQuestionTab extends Component {
...
@@ -433,7 +487,9 @@ class NewQuestionTab extends Component {
changeBlankCount
=
(
data
)
=>
{
changeBlankCount
=
(
data
)
=>
{
data
.
map
((
item
)
=>
{
data
.
map
((
item
)
=>
{
item
.
answerTagList
=
[];
if
(
!
item
.
answerTagList
)
{
item
.
answerTagList
=
[];
}
item
.
inputVisible
=
false
;
item
.
inputVisible
=
false
;
item
.
errorHold
=
false
;
item
.
errorHold
=
false
;
item
.
editInput
=
false
;
item
.
editInput
=
false
;
...
@@ -454,7 +510,9 @@ class NewQuestionTab extends Component {
...
@@ -454,7 +510,9 @@ class NewQuestionTab extends Component {
handleInputConfirm
=
(
optionItem
,
val
)
=>
{
handleInputConfirm
=
(
optionItem
,
val
)
=>
{
const
_blanksList
=
this
.
state
.
blanksList
;
const
_blanksList
=
this
.
state
.
blanksList
;
var
gapFillingAnswer
=
[];
_blanksList
.
forEach
((
item
)
=>
{
_blanksList
.
forEach
((
item
)
=>
{
gapFillingAnswer
.
push
({
correctAnswerList
:
item
.
answerTagList
});
if
(
item
.
id
===
optionItem
.
id
)
{
if
(
item
.
id
===
optionItem
.
id
)
{
if
(
val
)
{
if
(
val
)
{
optionItem
.
answerTagList
.
push
(
val
);
optionItem
.
answerTagList
.
push
(
val
);
...
@@ -464,6 +522,7 @@ class NewQuestionTab extends Component {
...
@@ -464,6 +522,7 @@ class NewQuestionTab extends Component {
}
}
}
}
});
});
this
.
setState
({
gapFillingAnswer
},
()
=>
this
.
_onSetState
());
this
.
setState
({
blanksList
:
_blanksList
});
this
.
setState
({
blanksList
:
_blanksList
});
};
};
...
@@ -489,14 +548,14 @@ class NewQuestionTab extends Component {
...
@@ -489,14 +548,14 @@ class NewQuestionTab extends Component {
this
.
setState
({
blanksList
:
_blanksList
});
this
.
setState
({
blanksList
:
_blanksList
});
};
};
render
Completion
Answer
=
(
optionItem
,
optionIndex
)
=>
{
render
GapFilling
Answer
=
(
optionItem
,
optionIndex
)
=>
{
return
(
return
(
<
div
className=
"
completion-answer-box"
>
<
div
className=
"
gap-answer-box"
key=
{
optionIndex
}
>
<
span
className=
"
completion
-answer-label"
>
<
span
className=
"
gap
-answer-label"
>
{
optionItem
.
innerHTML
}
{
optionItem
.
innerHTML
}
{
optionIndex
+
1
}
.
{
optionIndex
+
1
}
.
</
span
>
</
span
>
<
div
className=
"
completion
-answer-content"
>
<
div
className=
"
gap
-answer-content"
>
{
optionItem
.
answerTagList
.
map
((
tag
,
index
)
=>
{
{
optionItem
.
answerTagList
.
map
((
tag
,
index
)
=>
{
return
optionItem
.
editInput
?
(
return
optionItem
.
editInput
?
(
<
Input
<
Input
...
@@ -557,6 +616,13 @@ class NewQuestionTab extends Component {
...
@@ -557,6 +616,13 @@ class NewQuestionTab extends Component {
);
);
};
};
renderJudgeOption
=
(
judgeOptions
)
=>
{
return
(
<
React
.
Fragment
>
<
div
>
{
judgeOptions
[
0
].
content
}
</
div
>
</
React
.
Fragment
>
);
};
/**
/**
* 渲染输入内容
* 渲染输入内容
*
*
...
@@ -569,7 +635,7 @@ class NewQuestionTab extends Component {
...
@@ -569,7 +635,7 @@ class NewQuestionTab extends Component {
contentType
,
contentType
,
validateStatus
validateStatus
)
=>
{
)
=>
{
const
is
Completion
=
this
.
props
.
questionTypeKey
===
"COMPLETION
"
;
const
is
GapFilling
=
this
.
props
.
questionTypeKey
===
"GAP_FILLING
"
;
const
editorContent
=
_
.
find
(
const
editorContent
=
_
.
find
(
contentList
,
contentList
,
(
contentItem
)
=>
contentItem
.
type
===
"RICH_TEXT"
(
contentItem
)
=>
contentItem
.
type
===
"RICH_TEXT"
...
@@ -590,13 +656,17 @@ class NewQuestionTab extends Component {
...
@@ -590,13 +656,17 @@ class NewQuestionTab extends Component {
return
(
return
(
<
React
.
Fragment
>
<
React
.
Fragment
>
<
div
>
<
div
>
{
is
Completion
&&
contentType
===
"QUESTION_STEM"
?
(
{
is
GapFilling
&&
contentType
===
"QUESTION_STEM"
?
(
<
Completion
Stem
<
GapFilling
Stem
placehold=
{
placehold
}
placehold=
{
placehold
}
validateStatus=
{
validateStatus
}
validateStatus=
{
validateStatus
}
detail=
{
contentList
}
detail
Info
=
{
contentList
}
mediaBtn=
{
mediaBtn
}
mediaBtn=
{
mediaBtn
}
changeBlankCount=
{
this
.
changeBlankCount
.
bind
(
this
)
}
changeBlankCount=
{
this
.
changeBlankCount
.
bind
(
this
)
}
onChange=
{
(
html
)
=>
{
editorContent
.
content
=
html
;
this
.
_onSetState
();
}
}
onUploadMedia=
{
(
key
)
=>
{
onUploadMedia=
{
(
key
)
=>
{
this
.
handleChangeMedia
(
key
,
contentList
,
contentType
);
this
.
handleChangeMedia
(
key
,
contentList
,
contentType
);
}
}
}
}
...
@@ -623,191 +693,207 @@ class NewQuestionTab extends Component {
...
@@ -623,191 +693,207 @@ class NewQuestionTab extends Component {
/>
/>
)
}
)
}
</
div
>
</
div
>
{
contentType
===
"QUESTION_ANSWER_DESC"
?
{
contentType
===
"QUESTION_ANSWER_DESC"
?
(
<
div
className=
"question-desc-box"
>
<
div
className=
"question-desc-box"
>
{
pictureMediaList
.
length
>
0
&&
<
div
className=
"desc-picture-box"
>
{
pictureMediaList
.
length
>
0
&&
(
{
_
.
map
(
pictureMediaList
,
(
pictureItem
,
pictureIndex
)
=>
{
<
div
className=
"desc-picture-box"
>
let
{
content
,
status
}
=
pictureItem
;
{
_
.
map
(
pictureMediaList
,
(
pictureItem
,
pictureIndex
)
=>
{
if
([
"init"
,
"fail"
].
includes
(
status
))
{
let
{
content
,
status
}
=
pictureItem
;
return
(
if
([
"init"
,
"fail"
].
includes
(
status
))
{
<
div
className=
"mt12"
key=
{
pictureIndex
}
>
return
(
<
UploadingProgress
<
div
className=
"mt12"
key=
{
pictureIndex
}
>
fileDesc=
{
pictureItem
}
<
UploadingProgress
canCancelUpload
fileDesc=
{
pictureItem
}
onReupload=
{
()
=>
this
.
handleReupload
(
pictureItem
)
}
canCancelUpload
onAbort=
{
()
=>
this
.
handleAbort
(
pictureItem
,
pictureIndex
)
}
onReupload=
{
()
=>
this
.
handleReupload
(
pictureItem
)
}
/>
onAbort=
{
()
=>
</
div
>
this
.
handleAbort
(
pictureItem
,
pictureIndex
)
);
}
}
else
{
/>
return
(
</
div
>
<
div
className=
"picture-box"
key=
{
pictureIndex
}
>
);
<
img
}
else
{
className=
"img-box"
return
(
src=
{
content
}
<
div
className=
"picture-box"
key=
{
pictureIndex
}
>
onClick=
{
()
=>
this
.
handleScanFile
(
"JPG"
,
content
)
}
<
img
/>
className=
"img-box"
<
span
src=
{
content
}
className=
"icon_arrow iconfont"
onClick=
{
()
=>
this
.
handleScanFile
(
"JPG"
,
content
)
}
onClick=
{
()
=>
{
/>
contentList
.
map
((
item
,
index
)
=>
{
<
span
if
(
item
.
contentName
===
pictureItem
.
contentName
)
{
className=
"icon_arrow iconfont"
contentList
.
splice
(
index
,
1
);
onClick=
{
()
=>
{
return
item
contentList
.
map
((
item
,
index
)
=>
{
}
if
(
})
item
.
contentName
===
pictureItem
.
contentName
this
.
_onSetState
();
)
{
}
}
contentList
.
splice
(
index
,
1
);
>
return
item
;

}
</
span
>
});
</
div
>
this
.
_onSetState
();
)
}
}
}
>
})
}

</
div
>
}
</
span
>
{
recordMediaList
.
length
>
0
&&
<
div
className=
"desc-audio-box"
>
</
div
>
{
_
.
map
(
recordMediaList
,
(
recordItem
,
recordIndex
)
=>
{
);
let
{
content
,
status
,
size
}
=
recordItem
;
}
if
([
"init"
,
"fail"
].
includes
(
status
))
{
})
}
return
(
</
div
>
<
div
className=
"mt12"
key=
{
recordIndex
}
>
)
}
<
UploadingProgress
{
recordMediaList
.
length
>
0
&&
(
fileDesc=
{
recordItem
}
<
div
className=
"desc-audio-box"
>
canCancelUpload
{
_
.
map
(
recordMediaList
,
(
recordItem
,
recordIndex
)
=>
{
onReupload=
{
()
=>
this
.
handleReupload
(
recordItem
)
}
let
{
content
,
status
,
size
}
=
recordItem
;
onAbort=
{
()
=>
this
.
handleAbort
(
recordItem
,
recordIndex
)
}
if
([
"init"
,
"fail"
].
includes
(
status
))
{
/>
return
(
</
div
>
<
div
className=
"mt12"
key=
{
recordIndex
}
>
);
<
UploadingProgress
}
else
{
fileDesc=
{
recordItem
}
return
(
canCancelUpload
<
div
className=
"audio-box"
key=
{
recordIndex
}
>
onReupload=
{
()
=>
this
.
handleReupload
(
recordItem
)
}
<
XMAudio
onAbort=
{
()
=>
forbidParse
this
.
handleAbort
(
recordItem
,
recordIndex
)
url=
{
content
}
}
getDuration=
{
(
durationSize
)
=>
{
/>
size
=
durationSize
;
</
div
>
this
.
setState
({});
);
}
}
}
else
{
index=
{
recordIndex
}
return
(
size=
{
size
||
1000
}
<
div
className=
"audio-box"
key=
{
recordIndex
}
>
/>
<
XMAudio
<
span
forbidParse
className=
"icon_sider iconfont"
url=
{
content
}
onClick=
{
()
=>
{
getDuration=
{
(
durationSize
)
=>
{
contentList
.
map
((
item
,
index
)
=>
{
size
=
durationSize
;
if
(
item
.
contentName
===
recordItem
.
contentName
)
{
this
.
setState
({});
contentList
.
splice
(
index
,
1
);
}
}
return
item
index=
{
recordIndex
}
}
size=
{
size
||
1000
}
})
/>
this
.
_onSetState
();
<
span
}
}
className=
"icon_sider iconfont"
>
onClick=
{
()
=>
{

contentList
.
map
((
item
,
index
)
=>
{
</
span
>
if
(
item
.
contentName
===
recordItem
.
contentName
)
{
</
div
>
contentList
.
splice
(
index
,
1
);
)
return
item
;
}
}
})
}
});
</
div
>
}
this
.
_onSetState
();
{
voiceMediaList
.
length
>
0
&&
<
div
className=
"desc-audio-box"
>
}
}
{
_
.
map
(
voiceMediaList
,
(
voiceItem
,
voiceIndex
)
=>
{
>
let
{
content
,
status
,
size
}
=
voiceItem
;

if
([
"init"
,
"fail"
].
includes
(
status
))
{
</
span
>
return
(
</
div
>
<
div
className=
"mt12"
key=
{
voiceIndex
}
>
);
<
UploadingProgress
}
fileDesc=
{
voiceItem
}
})
}
canCancelUpload
</
div
>
onReupload=
{
()
=>
this
.
handleReupload
(
voiceItem
)
}
)
}
onAbort=
{
()
=>
this
.
handleAbort
(
voiceItem
,
voiceIndex
)
}
{
voiceMediaList
.
length
>
0
&&
(
/>
<
div
className=
"desc-audio-box"
>
</
div
>
{
_
.
map
(
voiceMediaList
,
(
voiceItem
,
voiceIndex
)
=>
{
);
let
{
content
,
status
,
size
}
=
voiceItem
;
}
else
{
if
([
"init"
,
"fail"
].
includes
(
status
))
{
return
(
return
(
<
div
className=
"audio-box"
key=
{
voiceIndex
}
>
<
div
className=
"mt12"
key=
{
voiceIndex
}
>
<
XMAudio
<
UploadingProgress
forbidParse
fileDesc=
{
voiceItem
}
url=
{
content
}
canCancelUpload
getDuration=
{
(
durationSize
)
=>
{
onReupload=
{
()
=>
this
.
handleReupload
(
voiceItem
)
}
size
=
durationSize
;
onAbort=
{
()
=>
this
.
setState
({});
this
.
handleAbort
(
voiceItem
,
voiceIndex
)
}
}
}
index=
{
voiceIndex
}
/>
size=
{
size
||
1000
}
</
div
>
/>
);
<
span
}
else
{
className=
"icon_sider iconfont"
return
(
onClick=
{
()
=>
{
<
div
className=
"audio-box"
key=
{
voiceIndex
}
>
contentList
.
map
((
item
,
index
)
=>
{
<
XMAudio
if
(
item
.
contentName
===
voiceItem
.
contentName
)
{
forbidParse
contentList
.
splice
(
index
,
1
);
url=
{
content
}
return
item
getDuration=
{
(
durationSize
)
=>
{
}
size
=
durationSize
;
})
this
.
setState
({});
this
.
_onSetState
();
}
}
}
}
index=
{
voiceIndex
}
>
size=
{
size
||
1000
}

/>
</
span
>
<
span
</
div
>
className=
"icon_sider iconfont"
)
onClick=
{
()
=>
{
}
contentList
.
map
((
item
,
index
)
=>
{
})
}
if
(
item
.
contentName
===
voiceItem
.
contentName
)
{
</
div
>
}
contentList
.
splice
(
index
,
1
);
{
videoMediaList
.
length
>
0
&&
<
div
className=
"desc-video-box"
>
return
item
;
{
_
.
map
(
videoMediaList
,
(
videoItem
,
videoIndex
)
=>
{
}
let
{
content
,
status
}
=
videoItem
;
});
if
([
"init"
,
"fail"
].
includes
(
status
))
{
this
.
_onSetState
();
return
(
}
}
<
div
className=
"mt12"
key=
{
videoIndex
}
>
>
<
UploadingProgress

fileDesc=
{
videoItem
}
</
span
>
canCancelUpload
</
div
>
onReupload=
{
()
=>
this
.
handleReupload
(
videoItem
)
}
);
onAbort=
{
()
=>
this
.
handleAbort
(
videoItem
,
videoIndex
)
}
}
/>
})
}
</
div
>
</
div
>
);
)
}
}
else
{
{
videoMediaList
.
length
>
0
&&
(
return
(
<
div
className=
"desc-video-box"
>
<
div
{
_
.
map
(
videoMediaList
,
(
videoItem
,
videoIndex
)
=>
{
className=
"video-box"
let
{
content
,
status
}
=
videoItem
;
key=
{
videoIndex
}
if
([
"init"
,
"fail"
].
includes
(
status
))
{
>
return
(
<
img
<
div
className=
"mt12"
key=
{
videoIndex
}
>
className=
"video-box_content"
<
UploadingProgress
src=
{
`${content}?x-oss-process=video/snapshot,t_0,m_fast`
}
fileDesc=
{
videoItem
}
/>
canCancelUpload
<
img
onReupload=
{
()
=>
this
.
handleReupload
(
videoItem
)
}
className=
"video-box_btn"
onAbort=
{
()
=>
src=
"https://image.xiaomaiketang.com/xm/r5H8cYm4ch.png"
this
.
handleAbort
(
videoItem
,
videoIndex
)
onClick=
{
()
=>
this
.
handleScanFile
(
"MP4"
,
content
)
}
}
/>
/>
<
span
</
div
>
className=
"icon_arrow iconfont"
);
onClick=
{
()
=>
{
}
else
{
contentList
.
map
((
item
,
index
)
=>
{
return
(
if
(
item
.
contentName
===
videoItem
.
contentName
)
{
<
div
className=
"video-box"
key=
{
videoIndex
}
>
contentList
.
splice
(
index
,
1
);
<
img
return
item
className=
"video-box_content"
}
src=
{
`${content}?x-oss-process=video/snapshot,t_0,m_fast`
}
})
/>
this
.
_onSetState
();
<
img
}
}
className=
"video-box_btn"
>
src=
"https://image.xiaomaiketang.com/xm/r5H8cYm4ch.png"

onClick=
{
()
=>
this
.
handleScanFile
(
"MP4"
,
content
)
}
</
span
>
/>
</
div
>
<
span
)
className=
"icon_arrow iconfont"
}
onClick=
{
()
=>
{
})
}
contentList
.
map
((
item
,
index
)
=>
{
</
div
>
}
if
(
item
.
contentName
===
videoItem
.
contentName
)
{
contentList
.
splice
(
index
,
1
);
return
item
;
}
});
this
.
_onSetState
();
}
}
>

</
span
>
</
div
>
);
}
})
}
</
div
>
)
}
</
div
>
</
div
>
:
_
.
map
(
contentList
,
(
contentItem
,
index
)
=>
{
)
:
(
_
.
map
(
contentList
,
(
contentItem
,
index
)
=>
{
const
{
type
,
content
,
status
}
=
contentItem
;
const
{
type
,
content
,
status
}
=
contentItem
;
let
dom
=
""
;
let
dom
=
""
;
if
([
"init"
,
"fail"
].
includes
(
status
))
{
if
([
"init"
,
"fail"
].
includes
(
status
))
{
...
@@ -907,10 +993,11 @@ class NewQuestionTab extends Component {
...
@@ -907,10 +993,11 @@ class NewQuestionTab extends Component {
}
}
}
}
>
>


</
span
>
</
span
>
</
div
>
</
div
>
)
:
null
;
)
:
null
;
})
}
})
)
}
</
React
.
Fragment
>
</
React
.
Fragment
>
);
);
};
};
...
@@ -992,7 +1079,6 @@ class NewQuestionTab extends Component {
...
@@ -992,7 +1079,6 @@ class NewQuestionTab extends Component {
const
{
const
{
stemContent
,
stemContent
,
chooseOptions
,
chooseOptions
,
judgeOptions
,
questionAnswerDesc
,
questionAnswerDesc
,
accept
,
accept
,
showRecord
,
showRecord
,
...
@@ -1003,8 +1089,8 @@ class NewQuestionTab extends Component {
...
@@ -1003,8 +1089,8 @@ class NewQuestionTab extends Component {
}
=
this
.
state
;
}
=
this
.
state
;
const
{
stemValidate
,
stemText
,
radioValidate
,
radioText
}
=
this
.
state
;
const
{
stemValidate
,
stemText
,
radioValidate
,
radioText
}
=
this
.
state
;
const
isJudge
=
this
.
props
.
questionTypeKey
===
"JUDGE"
;
const
isJudge
=
this
.
props
.
questionTypeKey
===
"JUDGE"
;
const
is
Completion
=
this
.
props
.
questionTypeKey
===
"COMPLETION
"
;
const
is
GapFilling
=
this
.
props
.
questionTypeKey
===
"GAP_FILLING
"
;
const
placehold
=
is
Completion
?
(
const
placehold
=
is
GapFilling
?
(
<
span
>
<
span
>
示例:党章规定,凡事有
示例:党章规定,凡事有
<
span
className=
"fill-line"
>
填空1
</
span
>
<
span
className=
"fill-line"
>
填空1
</
span
>
...
@@ -1034,7 +1120,7 @@ class NewQuestionTab extends Component {
...
@@ -1034,7 +1120,7 @@ class NewQuestionTab extends Component {
stemValidate
stemValidate
)
}
)
}
</
Form
.
Item
>
</
Form
.
Item
>
{
is
Completion
?
(
{
is
GapFilling
?
(
<
Form
.
Item
<
Form
.
Item
name=
"answer"
name=
"answer"
label=
{
label=
{
...
@@ -1057,7 +1143,14 @@ class NewQuestionTab extends Component {
...
@@ -1057,7 +1143,14 @@ class NewQuestionTab extends Component {
<
span
className=
"answer-tip"
>
请在题干中插入答案占位符
</
span
>
<
span
className=
"answer-tip"
>
请在题干中插入答案占位符
</
span
>
)
:
(
)
:
(
_
.
map
(
blanksList
,
(
item
,
index
)
=>
{
_
.
map
(
blanksList
,
(
item
,
index
)
=>
{
return
this
.
renderCompletionAnswer
(
item
,
index
);
return
(
<
Form
.
Item
validateStatus=
{
this
.
state
[
`optionsValidate_${index}`
]
}
help=
{
this
.
state
[
`optionsText_${index}`
]
}
>
{
this
.
renderGapFillingAnswer
(
item
,
index
)
}
</
Form
.
Item
>
);
})
})
)
}
)
}
</
Form
.
Item
>
</
Form
.
Item
>
...
@@ -1072,119 +1165,93 @@ class NewQuestionTab extends Component {
...
@@ -1072,119 +1165,93 @@ class NewQuestionTab extends Component {
className=
"question-item_options__list"
className=
"question-item_options__list"
data
-
label=
"正确答案"
data
-
label=
"正确答案"
>
>
{
isJudge
{
_
.
map
(
chooseOptions
,
(
optionItem
,
optionIndex
)
=>
{
?
_
.
map
(
judgeOptions
,
(
optionItem
,
optionIndex
)
=>
{
const
{
return
(
questionOptionContentList
,
<
div
className=
"question-item_options__content"
>
isCorrectAnswer
,
<
div
className=
"question-item_options__setting"
>
}
=
optionItem
;
<
Form
.
Item
optionItem
.
optionSort
=
optionIndex
;
validateStatus=
{
radioValidate
}
const
mediaBtn
=
[
"VOICE"
,
"RECORD"
,
"PICTURE"
];
help=
{
const
placeHold
=
optionIndex
===
judgeOptions
.
length
-
1
"必填(1000字以内,可粘贴小图;可以不输入文字,只添加音频或图片)"
;
?
radioText
return
(
:
""
<
div
}
className=
"question-item_options__content"
>
key=
{
optionIndex
}
{
/* 判断 */
}
>
<
div
className=
"question-item_options__setting"
>
<
Form
.
Item
validateStatus=
{
radioValidate
}
help=
{
optionIndex
===
chooseOptions
.
length
-
1
?
radioText
:
""
}
>
{
/* 单选 or 判断*/
}
{
[
"SINGLE_CHOICE"
,
"JUDGE"
].
includes
(
this
.
props
.
questionTypeKey
)
&&
(
<
Radio
<
Radio
checked=
{
optionItem
.
isCorrectAnswer
===
1
}
checked=
{
isCorrectAnswer
}
onClick=
{
()
=>
{
onClick=
{
()
=>
{
_
.
each
(
judgeOptions
,
(
item
)
=>
{
_
.
each
(
chooseOptions
,
(
o
)
=>
{
item
.
isCorrectAnswer
=
0
;
o
.
isCorrectAnswer
=
0
;
});
});
optionItem
.
isCorrectAnswer
=
1
;
optionItem
.
isCorrectAnswer
=
1
;
this
.
_onSetState
();
this
.
_onSetState
();
}
}
}
}
/>
/>
</
Form
.
Item
>
)
}
</
div
>
{
/* 多选 or 不定项 */
}
<
div
className=
"question-item_options__sort mr12"
>
{
[
"INDEFINITE_CHOICE"
,
"MULTI_CHOICE"
].
includes
(
{
NUM_TO_WORD_MAP
[
optionIndex
]
}
.
this
.
props
.
questionTypeKey
</
div
>
)
&&
(
<
div
className=
"question-item_options__input"
>
<
Checkbox
{
optionItem
.
label
}
checked=
{
isCorrectAnswer
===
1
}
</
div
>
onChange=
{
(
e
)
=>
{
const
checked
=
e
.
target
.
checked
?
1
:
0
;
optionItem
.
isCorrectAnswer
=
checked
;
this
.
_onSetState
();
}
}
/>
)
}
</
Form
.
Item
>
</
div
>
</
div
>
);
<
div
className=
"question-item_options__sort mr12"
>
})
{
NUM_TO_WORD_MAP
[
optionIndex
]
}
.
:
_
.
map
(
chooseOptions
,
(
optionItem
,
optionIndex
)
=>
{
</
div
>
const
{
<
div
className=
"question-item_options__input"
>
questionOptionContentList
,
<
Form
.
Item
isCorrectAnswer
,
validateStatus=
{
}
=
optionItem
;
this
.
state
[
`optionsValidate_${optionIndex}`
]
optionItem
.
optionSort
=
optionIndex
;
}
const
mediaBtn
=
[
"VOICE"
,
"RECORD"
,
"PICTURE"
];
help=
{
this
.
state
[
`optionsText_${optionIndex}`
]
}
const
placeHold
=
>
"必填(1000字以内,可粘贴小图;可以不输入文字,只添加音频或图片)"
;
{
isJudge
return
(
?
this
.
renderJudgeOption
(
questionOptionContentList
)
<
div
className=
"question-item_options__content"
key=
{
optionIndex
}
>
:
this
.
renderContent
(
<
div
className=
"question-item_options__setting"
>
questionOptionContentList
,
<
Form
.
Item
placeHold
,
validateStatus=
{
radioValidate
}
mediaBtn
,
help=
{
"QUESTION_OPTION"
,
optionIndex
===
chooseOptions
.
length
-
1
this
.
state
[
`optionsValidate_${optionIndex}`
]
?
radioText
:
""
}
>
{
/* 单选 */
}
{
this
.
props
.
questionTypeKey
===
"SINGLE_CHOICE"
&&
(
<
Radio
checked=
{
isCorrectAnswer
}
onClick=
{
()
=>
{
_
.
each
(
chooseOptions
,
(
o
)
=>
{
o
.
isCorrectAnswer
=
0
;
});
optionItem
.
isCorrectAnswer
=
1
;
this
.
_onSetState
();
}
}
/>
)
}
{
/* 多选 or 不定项 */
}
{
[
"INDEFINITE_CHOICE"
,
"MULTI_CHOICE"
].
includes
(
this
.
props
.
questionTypeKey
)
&&
(
<
Checkbox
checked=
{
isCorrectAnswer
===
1
}
onChange=
{
(
e
)
=>
{
const
checked
=
e
.
target
.
checked
?
1
:
0
;
optionItem
.
isCorrectAnswer
=
checked
;
this
.
_onSetState
();
}
}
/>
)
}
)
}
</
Form
.
Item
>
</
Form
.
Item
>
</
div
>
</
div
>
<
div
className=
"question-item_options__sort mr12"
>
{
[
{
NUM_TO_WORD_MAP
[
optionIndex
]
}
.
"INDEFINITE_CHOICE"
,
</
div
>
"MULTI_CHOICE"
,
<
div
className=
"question-item_options__input"
>
"SINGLE_CHOICE"
,
<
Form
.
Item
].
includes
(
this
.
props
.
questionTypeKey
)
&&
(
validateStatus=
{
this
.
state
[
`optionsValidate_${optionIndex}`
]
}
help=
{
this
.
state
[
`optionsText_${optionIndex}`
]
}
>
{
this
.
renderContent
(
questionOptionContentList
,
placeHold
,
mediaBtn
,
"QUESTION_OPTION"
,
this
.
state
[
`optionsValidate_${optionIndex}`
]
)
}
</
Form
.
Item
>
</
div
>
<
div
className=
"question-item_options__extra"
>
<
div
className=
"question-item_options__extra"
>
<
React
.
Fragment
>
<
React
.
Fragment
>
<
span
<
span
className=
"option-operate_item__icon icon iconfont"
className=
"option-operate_item__icon icon iconfont"
onClick=
{
()
=>
onClick=
{
()
=>
this
.
handleDelOption
(
optionIndex
)
}
this
.
handleDelOption
(
optionIndex
)
}
>
>


</
span
>
</
span
>
{
optionIndex
>
0
&&
(
{
optionIndex
>
0
&&
(
<
span
<
span
className=
"option-operate_item__icon icon iconfont"
className=
"option-operate_item__icon icon iconfont"
...
@@ -1211,9 +1278,10 @@ class NewQuestionTab extends Component {
...
@@ -1211,9 +1278,10 @@ class NewQuestionTab extends Component {
)
}
)
}
</
React
.
Fragment
>
</
React
.
Fragment
>
</
div
>
</
div
>
</
div
>
)
}
);
</
div
>
})
}
);
})
}
{
!
isJudge
&&
(
{
!
isJudge
&&
(
<
div
<
div
className=
"question-item_options__add"
className=
"question-item_options__add"
...
...
src/modules/teach-tool/components/NewQuestionTab.less
View file @
462c5b38
...
@@ -12,7 +12,8 @@
...
@@ -12,7 +12,8 @@
// display: flex;
// display: flex;
// justify-content: space-between;
// justify-content: space-between;
.fill-line {
.fill-line {
text-decoration: underline;
padding: 0 10px;
border-bottom: 1px solid;
}
}
}
}
.editor-fill-box_single:focus {
.editor-fill-box_single:focus {
...
@@ -369,16 +370,16 @@
...
@@ -369,16 +370,16 @@
}
}
}
}
.
completion
-answer-box {
.
gap
-answer-box {
display: inline-flex;
display: inline-flex;
width: 100%;
width: 100%;
padding: 6px 0;
padding: 6px 0;
.
completion
-answer-label {
.
gap
-answer-label {
margin-right: 16px;
margin-right: 16px;
padding-top: 6px;
padding-top: 6px;
width: 50px;
width: 50px;
}
}
.
completion
-answer-content {
.
gap
-answer-content {
display: flex;
display: flex;
background: #ffffff;
background: #ffffff;
border-radius: 4px;
border-radius: 4px;
...
...
src/modules/teach-tool/components/QuestionManageContent.jsx
View file @
462c5b38
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Author: yuananting
* @Date: 2021-02-25 11:23:47
* @Date: 2021-02-25 11:23:47
* @LastEditors: yuananting
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
5 21:08:28
* @LastEditTime: 2021-03-1
6 15:34:57
* @Description: 助学工具-题库-题目管理主页面列表数据
* @Description: 助学工具-题库-题目管理主页面列表数据
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
...
@@ -27,6 +27,8 @@ import User from "@/common/js/user";
...
@@ -27,6 +27,8 @@ import User from "@/common/js/user";
import
QuestionBankService
from
"@/domains/question-bank-domain/QuestionBankService"
;
import
QuestionBankService
from
"@/domains/question-bank-domain/QuestionBankService"
;
import
_
from
"underscore"
;
import
_
from
"underscore"
;
import
QuestionPreviewModal
from
"../modal/QuestionPreviewModal"
;
import
QuestionPreviewModal
from
"../modal/QuestionPreviewModal"
;
import
BatchImportQuestionModal
from
"../modal/BatchImportQuestionModal"
;
const
{
Search
}
=
Input
;
const
{
Search
}
=
Input
;
const
questionTypeEnum
=
{
const
questionTypeEnum
=
{
...
@@ -273,7 +275,9 @@ class QuestionManageContent extends Component {
...
@@ -273,7 +275,9 @@ class QuestionManageContent extends Component {
<
span
className=
"record-operate__item split"
>
|
</
span
>
<
span
className=
"record-operate__item split"
>
|
</
span
>
<
div
<
div
className=
"record-operate__item"
className=
"record-operate__item"
onClick=
{
()
=>
this
.
toEditQuetion
(
record
.
id
,
record
.
questionTypeEnum
)
}
onClick=
{
()
=>
this
.
toEditQuetion
(
record
.
id
,
record
.
questionTypeEnum
)
}
>
>
编辑
编辑
</
div
>
</
div
>
...
@@ -346,6 +350,29 @@ class QuestionManageContent extends Component {
...
@@ -346,6 +350,29 @@ class QuestionManageContent extends Component {
);
);
};
};
batchImportQuestion
=
()
=>
{
const
ImportQuestionModal
=
<
BatchImportQuestionModal
close=
{
()
=>
{
this
.
setState
({
ImportQuestionModal
:
null
});
}
}
onEdit=
{
(
record
)
=>
{
this
.
handleEditRecord
(
record
);
}
}
showTip=
{
()
=>
{
Modal
.
confirm
({
title
:
`提醒`
,
content
:
'系统拼命处理中,为避免你等待时间过长,请前往“任务中心”查看导入结果'
,
onOk
:
()
=>
{
RCHistory
.
push
(
`/download_center/import_record`
);
},
okText
:
'前往任务中心'
,
cancelText
:
'关闭'
,
});
}
}
/>;
this
.
setState
({
ImportQuestionModal
});
}
render
()
{
render
()
{
const
{
dataSource
=
[],
total
,
query
}
=
this
.
state
;
const
{
dataSource
=
[],
total
,
query
}
=
this
.
state
;
const
{
current
,
size
,
categoryId
,
questionName
,
questionType
}
=
query
;
const
{
current
,
size
,
categoryId
,
questionName
,
questionType
}
=
query
;
...
@@ -417,13 +444,7 @@ class QuestionManageContent extends Component {
...
@@ -417,13 +444,7 @@ class QuestionManageContent extends Component {
<
Button
type=
"primary"
onClick=
{
this
.
handleCreateQuestionBank
}
>
<
Button
type=
"primary"
onClick=
{
this
.
handleCreateQuestionBank
}
>
新建题目
新建题目
</
Button
>
</
Button
>
<
Button
<
Button
onClick=
{
this
.
batchImportQuestion
}
>
批量导入
</
Button
>
onClick=
{
()
=>
{
console
.
log
(
"批量导入"
);
}
}
>
批量导入
</
Button
>
</
Space
>
</
Space
>
)
}
)
}
<
div
className=
"question-manage-list"
>
<
div
className=
"question-manage-list"
>
...
@@ -455,6 +476,7 @@ class QuestionManageContent extends Component {
...
@@ -455,6 +476,7 @@ class QuestionManageContent extends Component {
</
div
>
</
div
>
)
}
)
}
{
this
.
state
.
QuestionPreviewModal
}
{
this
.
state
.
QuestionPreviewModal
}
{
this
.
state
.
ImportQuestionModal
}
</
div
>
</
div
>
</
div
>
</
div
>
);
);
...
...
src/modules/teach-tool/components/QuestionManageContent.less
View file @
462c5b38
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Author: yuananting
* @Date: 2021-02-25 11:26:28
* @Date: 2021-02-25 11:26:28
* @LastEditors: yuananting
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
5 09:42:30
* @LastEditTime: 2021-03-1
6 11:14:55
* @Description: 助学工具-题库-题目管理右侧内容样式
* @Description: 助学工具-题库-题目管理右侧内容样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
...
@@ -77,3 +77,8 @@
...
@@ -77,3 +77,8 @@
}
}
}
}
}
}
.fill-line {
padding: 0 10px;
border-bottom: 1px solid;
}
src/modules/teach-tool/modal/BatchImportQuestionModal.jsx
0 → 100644
View file @
462c5b38
/*
* @Author: zhangyi
* @Date: 2019-12-09 10:29:55
* @Last Modified by: mikey.wanghaofeng
* @Last Modified time: 2020-09-25 11:03:47
*/
import
React
,
{
Component
}
from
"react"
;
import
{
Modal
,
Button
,
Upload
,
message
}
from
"antd"
;
import
"./BatchImportQuestionModal.less"
;
import
SelectPrepareFileModal
from
"@/modules/prepare-lesson/modal/SelectPrepareFileModal"
;
class
BatchImportQuestionModal
extends
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
showSelectFileModal
:
false
,
// 云盘列表弹窗显隐
diskList
:
[],
// 资料云盘文件列表
fileList
:
[],
// 上传的文件列表
uploadBtnType
:
"add"
,
// 上传按钮类型(上传文件 | 重新上传)
uploadBlob
:
null
,
// 上传的文件
uploadProps
:
{
accept
:
"application/vnd.ms-excel"
,
beforeUpload
(
file
)
{
this
.
setState
({
uploadBtnType
:
"reAdd"
});
this
.
setState
({
uploadBlob
:
file
});
return
false
;
},
onChange
(
info
)
{
let
fileList
=
[...
info
.
fileList
];
fileList
=
fileList
.
slice
(
-
1
);
this
.
setState
({
fileList
});
},
onRemove
()
{
this
.
setState
({
uploadBtnType
:
"add"
});
},
},
};
}
// 下载题目模板
handleDownTemplate
=
()
=>
{
console
.
log
(
"下载"
);
const
a
=
document
.
createElement
(
"a"
);
a
.
href
=
"https://image.xiaomaiketang.com/xm/question_template.xlsx"
;
a
.
click
();
};
render
()
{
const
{
diskList
,
showSelectFileModal
,
uploadBtnType
,
uploadProps
,
}
=
this
.
state
;
return
(
<
div
>
<
Modal
className=
"import-score-modal"
title=
"导入题目信息"
visible=
{
true
}
width=
{
560
}
maskClosable=
{
false
}
footer=
{
[
<
Button
onClick=
{
this
.
props
.
close
}
>
取消
</
Button
>,
<
Button
type=
"primary"
onClick=
{
this
.
handleImport
}
>
导入
</
Button
>,
]
}
onCancel=
{
()
=>
{
this
.
props
.
close
();
}
}
>
<
div
className=
"step-section"
>
<
h4
className=
"step-title"
>
1.下载导入模板,按要求填写信息
</
h4
>
<
div
className=
"down-btn"
style=
{
{
fontSize
:
"14px"
}
}
onClick=
{
this
.
handleDownTemplate
}
>
下载题目导入模板
</
div
>
</
div
>
<
div
className=
"step-section"
>
<
h4
className=
"step-title"
>
2.选择需要导入的Excel文件
</
h4
>
<
Button
type=
"primary"
className=
"add-btn"
onClick=
{
()
=>
this
.
setState
({
showSelectFileModal
:
true
})
}
>
{
uploadBtnType
==
"reAdd"
?
"重新添加"
:
"添加文件"
}
</
Button
>
</
div
>
</
Modal
>
<
SelectPrepareFileModal
operateType=
"select"
accept=
"image/jpeg,image/png,image/jpg"
selectTypeList=
{
[
"JPG"
,
"JPEG"
,
"PNG"
]
}
tooltip=
"支持文件类型:jpg、jpeg、png"
isOpen=
{
showSelectFileModal
}
diskList=
{
diskList
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
});
}
}
onSelect=
{
this
.
handleSelectImg
}
/>
</
div
>
);
}
}
export
default
BatchImportQuestionModal
;
src/modules/teach-tool/modal/BatchImportQuestionModal.less
0 → 100644
View file @
462c5b38
@import '../../../core/mixins.less';
.import-score-modal {
.step-section {
margin-bottom: 24px;
.step-title {
font-size: 16px;
font-weight: 400;
margin-bottom: 16px;
color: #333;
}
.tip-box {
border: 1px dashed #e8e8e8;
padding: 8px;
margin-bottom: 16px;
.tip-title {
margin-bottom: 4px;
}
.tip-content {
font-size: 12px;
}
}
.add-btn {
border-radius: 2px;
font-size: 14px;
box-shadow: none;
text-shadow: none;
span {
font-weight: 400;
}
}
.remark-input {
width: 304px;
margin-bottom: 8px;
}
.remark-tip {
color: #999;
font-size: 12px;
}
.down-btn {
text-align: left;
color: #FC9C6B;
font-size: 12px;
display: block;
margin-top: 8px;
cursor: pointer;
}
.upload-box {
width: 200px;
.ant-upload-list-item-name {
.text-overflow-ellipsis();
width:70%;
}
}
}
.import-status-box {
height:430px;
overflow: hidden;
.status-content {
margin:auto;
text-align: center;
margin-top:100px;
>img {
width: 76px;
}
.status {
font-size: 16px;
font-weight: 500;
margin: 18px 0 16px;
}
.status-tip {
line-height: 20px;
.num {
color: #FC9C6B;
}
}
.down-btn {
margin-top: 16px;
}
}
}
}
\ No newline at end of file
src/modules/teach-tool/modal/QuestionPreviewModal.jsx
View file @
462c5b38
...
@@ -60,6 +60,7 @@ class QuestionPreviewModal extends Component {
...
@@ -60,6 +60,7 @@ class QuestionPreviewModal extends Component {
const
{
const
{
questionTypeEnum
,
questionTypeEnum
,
questionStemList
,
questionStemList
,
gapFillingAnswerList
,
optionList
,
optionList
,
questionAnswerDescList
,
questionAnswerDescList
,
}
=
questionInfo
;
}
=
questionInfo
;
...
@@ -152,81 +153,126 @@ class QuestionPreviewModal extends Component {
...
@@ -152,81 +153,126 @@ class QuestionPreviewModal extends Component {
</
div
>
</
div
>
</
div
>
</
div
>
<
hr
style=
{
{
margin
:
"16px 0"
,
color
:
"#E8E8E8"
,
height
:
"1px"
}
}
/>
<
hr
style=
{
{
margin
:
"16px 0"
,
color
:
"#E8E8E8"
,
height
:
"1px"
}
}
/>
<
div
className=
"question-option"
>
{
[
<
div
className=
"question-option__title"
>
选项:
</
div
>
"INDEFINITE_CHOICE"
,
<
div
className=
"question-option__content"
>
"MULTI_CHOICE"
,
{
_
.
map
(
optionList
,
(
optionItem
,
optionIndex
)
=>
{
"SINGLE_CHOICE"
,
const
{
questionOptionContentList
}
=
optionItem
;
"JUDGE"
,
const
inputcontent
=
_
.
filter
(
].
includes
(
questionTypeEnum
)
&&
(
questionOptionContentList
,
<
div
className=
"question-option"
>
(
optionItem
)
=>
{
<
div
className=
"question-option__title"
>
选项:
</
div
>
return
optionItem
.
type
===
"RICH_TEXT"
;
<
div
className=
"question-option__content"
>
}
{
_
.
map
(
optionList
,
(
optionItem
,
optionIndex
)
=>
{
);
const
{
questionOptionContentList
}
=
optionItem
;
return
(
const
inputcontent
=
_
.
filter
(
<
div
className=
"option-box"
key=
{
optionIndex
}
>
questionOptionContentList
,
<
div
className=
"option-box-header"
>
(
optionItem
)
=>
{
<
div
className=
"option-sort"
>
return
optionItem
.
type
===
"RICH_TEXT"
;
{
NUM_TO_WORD_MAP
[
optionIndex
]
}
.
}
);
return
(
<
div
className=
"option-box"
key=
{
optionIndex
}
>
<
div
className=
"option-box-header"
>
<
div
className=
"option-sort"
>
{
NUM_TO_WORD_MAP
[
optionIndex
]
}
.
</
div
>
{
[
"INDEFINITE_CHOICE"
,
"MULTI_CHOICE"
,
"SINGLE_CHOICE"
,
].
includes
(
questionTypeEnum
)
&&
(
<
div
className=
"input-box"
dangerouslySetInnerHTML=
{
{
__html
:
inputcontent
[
0
].
content
,
}
}
/>
)
}
{
[
"JUDGE"
].
includes
(
questionTypeEnum
)
&&
_
.
map
(
questionOptionContentList
,
(
item
,
index
)
=>
{
return
<
span
key=
{
index
}
>
{
item
.
content
}
</
span
>;
})
}
</
div
>
</
div
>
<
div
{
[
className=
"input-box"
"INDEFINITE_CHOICE"
,
dangerouslySetInnerHTML=
{
{
"MULTI_CHOICE"
,
__html
:
inputcontent
[
0
].
content
,
"SINGLE_CHOICE"
,
}
}
].
includes
(
questionTypeEnum
)
&&
/>
_
.
map
(
questionOptionContentList
,
(
item
,
index
)
=>
{
let
dom
=
""
;
let
{
type
,
content
,
size
}
=
item
;
switch
(
type
)
{
case
"PICTURE"
:
dom
=
(
<
div
key=
{
index
+
1
}
className=
"picture-box"
>
<
img
src=
{
content
}
onClick=
{
()
=>
this
.
handleScanFile
(
"JPG"
,
content
)
}
/>
</
div
>
);
break
;
case
"VOICE"
:
dom
=
(
<
div
key=
{
index
+
1
}
className=
"voice-box"
>
<
XMAudio
forbidParse
url=
{
content
}
getDuration=
{
(
durationSize
)
=>
{
size
=
durationSize
;
this
.
setState
({});
}
}
index=
{
index
}
size=
{
size
||
1000
}
/>
</
div
>
);
break
;
}
return
dom
;
})
}
</
div
>
</
div
>
{
_
.
map
(
questionOptionContentList
,
(
item
,
index
)
=>
{
);
let
dom
=
""
;
})
}
let
{
type
,
content
,
size
}
=
item
;
</
div
>
switch
(
type
)
{
case
"PICTURE"
:
dom
=
(
<
div
key=
{
index
+
1
}
className=
"picture-box"
>
<
img
src=
{
content
}
onClick=
{
()
=>
this
.
handleScanFile
(
"JPG"
,
content
)
}
/>
</
div
>
);
break
;
case
"VOICE"
:
dom
=
(
<
div
key=
{
index
+
1
}
className=
"voice-box"
>
<
XMAudio
forbidParse
url=
{
content
}
getDuration=
{
(
durationSize
)
=>
{
size
=
durationSize
;
this
.
setState
({});
}
}
index=
{
index
}
size=
{
size
||
1000
}
/>
</
div
>
);
break
;
}
return
dom
;
})
}
</
div
>
);
})
}
</
div
>
</
div
>
</
div
>
)
}
<
div
className=
"question-answer"
>
<
div
className=
"question-answer"
>
<
div
className=
"question-answer__title"
>
答案:
</
div
>
<
div
className=
"question-answer__title"
>
答案:
</
div
>
<
div
className=
"question-answer__content"
>
{
[
{
_
.
map
(
rightAnswerSort
,
(
item
,
index
)
=>
{
"INDEFINITE_CHOICE"
,
return
(
"MULTI_CHOICE"
,
<
div
className=
"option-sort"
key=
{
index
}
>
"SINGLE_CHOICE"
,
{
NUM_TO_WORD_MAP
[
item
]
}
"JUDGE"
,
</
div
>
].
includes
(
questionTypeEnum
)
&&
(
);
<
div
className=
"question-answer__content"
>
})
}
{
_
.
map
(
rightAnswerSort
,
(
item
,
index
)
=>
{
</
div
>
return
(
<
div
className=
"option-sort"
key=
{
index
}
>
{
NUM_TO_WORD_MAP
[
item
]
}
</
div
>
);
})
}
</
div
>
)
}
{
questionTypeEnum
===
"GAP_FILLING"
&&
(
<
div
className=
"question-gap-answer"
>
{
_
.
map
(
gapFillingAnswerList
,
(
item
,
index
)
=>
{
return
(
<
div
>
<
div
className=
"gap-label"
>
填空
{
index
+
1
}
.
</
div
>
<
div
className=
"gap-content"
key=
{
index
}
>
{
_
.
map
(
item
.
correctAnswerList
,
(
childItem
,
childIndex
)
=>
{
return
<
span
>
{
childItem
}
</
span
>
})
}
</
div
>
</
div
>
);
})
}
</
div
>
)
}
</
div
>
</
div
>
<
hr
style=
{
{
margin
:
"16px 0"
,
color
:
"#E8E8E8"
,
height
:
"1px"
}
}
/>
<
hr
style=
{
{
margin
:
"16px 0"
,
color
:
"#E8E8E8"
,
height
:
"1px"
}
}
/>
<
div
className=
"question-desc"
>
<
div
className=
"question-desc"
>
...
...
src/modules/teach-tool/modal/QuestionPreviewModal.less
View file @
462c5b38
...
@@ -117,6 +117,25 @@
...
@@ -117,6 +117,25 @@
margin-right: 8px;
margin-right: 8px;
}
}
}
}
.question-gap-answer {
margin-bottom: 8px;
.gap-label {
display: inline-block;
width: 48px;
height: 20px;
color: #666666;
line-height: 20px;
}
.gap-content {
display: inline-block;
span {
background: #F7F8F9;
border-radius: 2px;
padding: 2px 12px;
margin-right: 8px;
}
}
}
}
}
.question-desc {
.question-desc {
margin-bottom: 16px;
margin-bottom: 16px;
...
@@ -195,3 +214,7 @@
...
@@ -195,3 +214,7 @@
.question-preview-modal.ant-modal {
.question-preview-modal.ant-modal {
max-height: 60% !important;
max-height: 60% !important;
}
}
.fill-line {
padding: 0 10px;
border-bottom: 1px solid;
}
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