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
0e1a2057
Commit
0e1a2057
authored
Mar 18, 2021
by
yuananting
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:云盘上传文件
parent
83229b62
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
404 additions
and
264 deletions
+404
-264
src/common/constants/punchClock/punchClock.js
+7
-1
src/modules/teach-tool/AddNewQuestion.jsx
+67
-28
src/modules/teach-tool/AddNewQuestion.less
+2
-2
src/modules/teach-tool/QuestionBankIndex.jsx
+1
-1
src/modules/teach-tool/QuestionBankIndex.less
+2
-2
src/modules/teach-tool/QuestionCategoryManage.less
+2
-2
src/modules/teach-tool/components/NewQuestionTab.jsx
+252
-182
src/modules/teach-tool/components/QuestionBankSider.jsx
+1
-1
src/modules/teach-tool/components/QuestionBankSider.less
+2
-2
src/modules/teach-tool/components/QuestionEditor.jsx
+33
-26
src/modules/teach-tool/components/QuestionManageContent.jsx
+13
-13
src/modules/teach-tool/components/model.js
+15
-2
src/modules/teach-tool/modal/BatchImportQuestionModal.jsx
+6
-1
src/modules/teach-tool/modal/NewEditQuestionBankCategory.jsx
+1
-1
No files found.
src/common/constants/punchClock/punchClock.js
View file @
0e1a2057
/*
* @Author: 陈剑宇
* @Date: 2020-10-28 14:27:07
* @LastEditTime: 2021-0
2-28 14:22:13
* @LastEditTime: 2021-0
3-17 20:27:44
* @LastEditors: yuananting
* @Description:
* @FilePath: /xiaomai-web-b/app/common/constants/punchClock/punchClock.js
...
...
@@ -113,6 +113,12 @@ export const FILE_ACCEPT = {
VOICE
:
'audio/x-mpeg,audio/mp3,audio/mpeg,audio/wav,audio/x-m4a'
}
export
const
MEDIA_FILE_ACCEPT
=
{
PICTURE
:
'JPG,JPEG,PNG,BMP,GIF'
,
VIDEO
:
'MP4'
,
VOICE
:
'MP3'
}
export
const
QUESTION_FILE_ACCEPT
=
{
PICTURE
:
'image/jpg,image/jpeg,image/png,image/gif'
,
VIDEO
:
'audio/mp4,video/mp4'
,
...
...
src/modules/teach-tool/AddNewQuestion.jsx
View file @
0e1a2057
...
...
@@ -2,12 +2,12 @@
* @Author: yuananting
* @Date: 2021-02-25 13:46:35
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
7 10:45:10
* @LastEditTime: 2021-03-1
8 09:32:02
* @Description: 助学工具-题库-题目管理-新增题目
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
import
{
Tabs
,
Button
,
Tooltip
,
message
}
from
"antd"
;
import
{
Tabs
,
Button
,
Tooltip
,
message
,
Modal
}
from
"antd"
;
import
Breadcrumbs
from
"@/components/Breadcrumbs"
;
import
ShowTips
from
"@/components/ShowTips"
;
import
"./AddNewQuestion.less"
;
...
...
@@ -21,8 +21,16 @@ const { TabPane } = Tabs;
class
AddNewQuestion
extends
Component
{
constructor
(
props
)
{
super
(
props
);
let
activeKey
=
""
if
(
getParameterByName
(
"type"
))
{
activeKey
=
getParameterByName
(
"type"
)
}
else
if
(
getParameterByName
(
"key"
))
{
activeKey
=
getParameterByName
(
"key"
)
}
else
{
activeKey
=
"SINGLE_CHOICE"
}
this
.
state
=
{
activeKey
:
getParameterByName
(
"type"
)
||
"SINGLE_CHOICE"
,
activeKey
:
activeKey
,
// 构建题目基本结构
singleChoiceContent
:
defineQuestionInfo
(
"SINGLE_CHOICE"
),
// 单选题
multiChoiceContent
:
defineQuestionInfo
(
"MULTI_CHOICE"
),
// 多选题
...
...
@@ -69,7 +77,7 @@ class AddNewQuestion extends Component {
});
};
saveCurrentQuestion
=
(
content
)
=>
{
saveCurrentQuestion
=
(
content
,
type
,
next
)
=>
{
content
.
questionStemList
.
map
((
item
,
index
)
=>
{
item
.
sort
=
index
;
return
item
;
...
...
@@ -101,9 +109,16 @@ class AddNewQuestion extends Component {
QuestionBankService
.
editQuestion
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"保存成功"
);
window
.
RCHistory
.
push
({
pathname
:
`/question-bank-index?categoryId=
${
params
.
categoryId
}
`
,
});
if
(
next
===
'add'
)
{
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?categoryId=
${
params
.
categoryId
}
&key=
${
type
}
`
,
});
}
if
(
next
===
'close'
)
{
window
.
RCHistory
.
push
({
pathname
:
`/question-bank-index?categoryId=
${
params
.
categoryId
}
`
,
});
}
}
});
}
else
{
...
...
@@ -117,15 +132,36 @@ class AddNewQuestion extends Component {
QuestionBankService
.
addQuestion
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"保存成功"
);
window
.
RCHistory
.
push
({
pathname
:
`/question-bank-index?categoryId=
${
params
.
categoryId
}
`
,
});
if
(
next
===
'add'
)
{
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?categoryId=
${
params
.
categoryId
}
&key=
${
type
}
`
,
});
}
if
(
next
===
'close'
)
{
window
.
RCHistory
.
push
({
pathname
:
`/question-bank-index?categoryId=
${
params
.
categoryId
}
`
,
});
}
}
});
}
};
confirmSaveQuestion
=
()
=>
{
// 取消编辑并返回上一级路由
handleGoBack
=
()
=>
{
Modal
.
confirm
({
title
:
'确定要返回吗?'
,
content
:
'返回后,本次编辑的内容将不被保存'
,
okText
:
'确认返回'
,
cancelText
:
'留在本页'
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>,
onOk
:
()
=>
{
window
.
RCHistory
.
goBack
();
}
})
}
confirmSaveQuestion
=
(
next
)
=>
{
const
{
singleChoiceContent
,
multiChoiceContent
,
...
...
@@ -136,27 +172,27 @@ class AddNewQuestion extends Component {
switch
(
this
.
state
.
activeKey
)
{
case
"SINGLE_CHOICE"
:
if
(
this
.
singleChoiceRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
singleChoiceContent
);
this
.
saveCurrentQuestion
(
singleChoiceContent
,
"SINGLE_CHOICE"
,
next
);
}
break
;
case
"MULTI_CHOICE"
:
if
(
this
.
multiChoiceRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
multiChoiceContent
);
this
.
saveCurrentQuestion
(
multiChoiceContent
,
"MULTI_CHOICE"
,
next
);
}
break
;
case
"JUDGE"
:
if
(
this
.
judgeRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
judgeContent
);
this
.
saveCurrentQuestion
(
judgeContent
,
"JUDGE"
,
next
);
}
break
;
case
"GAP_FILLING"
:
if
(
this
.
gapRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
gapFillingConten
t
);
}
//
if (this.gapRef.checkInput() === 0) {
this
.
saveCurrentQuestion
(
gapFillingContent
,
"GAP_FILLING"
,
nex
t
);
//
}
break
;
case
"INDEFINITE_CHOICE"
:
if
(
this
.
indefiniteRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
indefiniteChoiceContent
);
this
.
saveCurrentQuestion
(
indefiniteChoiceContent
,
"INDEFINITE_CHOICE"
,
next
);
}
break
;
}
...
...
@@ -180,7 +216,7 @@ class AddNewQuestion extends Component {
<
div
className=
"page add-new-question"
>
<
Breadcrumbs
navList=
{
getParameterByName
(
"id"
)
?
"编辑题目"
:
"新增题目"
}
goBack=
{
()
=>
RCHistory
.
g
oBack
()
}
goBack=
{
()
=>
this
.
handleG
oBack
()
}
/>
<
div
className=
"box"
>
<
div
className=
"show-tips"
>
...
...
@@ -198,12 +234,13 @@ class AddNewQuestion extends Component {
key=
"SINGLE_CHOICE"
>
<
NewQuestionTab
questionTypeKey=
"SINGLE_CHOICE"
questionTypeKey=
{
activeKey
}
onRef=
{
(
ref
)
=>
{
this
.
singleChoiceRef
=
ref
;
}
}
questionInfo=
{
singleChoiceContent
}
onSetState=
{
(
newContent
)
=>
{
console
.
log
(
"newContent:"
,
newContent
)
Object
.
assign
(
singleChoiceContent
,
newContent
);
}
}
onLogger=
{
this
.
handleLogger
}
...
...
@@ -214,7 +251,7 @@ class AddNewQuestion extends Component {
key=
"MULTI_CHOICE"
>
<
NewQuestionTab
questionTypeKey=
"MULTI_CHOICE"
questionTypeKey=
{
activeKey
}
onRef=
{
(
ref
)
=>
{
this
.
multiChoiceRef
=
ref
;
}
}
...
...
@@ -230,7 +267,7 @@ class AddNewQuestion extends Component {
key=
"JUDGE"
>
<
NewQuestionTab
questionTypeKey=
"JUDGE"
questionTypeKey=
{
activeKey
}
onRef=
{
(
ref
)
=>
{
this
.
judgeRef
=
ref
;
}
}
...
...
@@ -245,14 +282,14 @@ class AddNewQuestion extends Component {
key=
"GAP_FILLING"
>
<
NewQuestionTab
questionTypeKey=
"GAP_FILLING"
questionTypeKey=
{
activeKey
}
onRef=
{
(
ref
)
=>
{
this
.
gapRef
=
ref
;
}
}
questionInfo=
{
gapFillingContent
}
onSetState=
{
(
newContent
)
=>
{
Object
.
assign
(
gapFillingContent
,
newContent
);
console
.
log
(
"gapFillingContent:"
,
gapFilling
Content
);
console
.
log
(
"gapFillingContent:"
,
new
Content
);
}
}
/>
</
TabPane
>
...
...
@@ -268,7 +305,7 @@ class AddNewQuestion extends Component {
key=
"INDEFINITE_CHOICE"
>
<
NewQuestionTab
questionTypeKey=
"INDEFINITE_CHOICE"
questionTypeKey=
{
activeKey
}
onRef=
{
(
ref
)
=>
{
this
.
indefiniteRef
=
ref
;
}
}
...
...
@@ -282,12 +319,14 @@ class AddNewQuestion extends Component {
</
Tabs
>
</
div
>
<
div
className=
"footer"
>
<
Button
>
取消
</
Button
>
<
Button
>
保存并继续添加
</
Button
>
<
Button
onClick=
{
()
=>
{
this
.
handleGoBack
()
}
}
>
取消
</
Button
>
<
Button
onClick=
{
()
=>
{
this
.
confirmSaveQuestion
(
"add"
);
}
}
>
保存并继续添加
</
Button
>
<
Button
type=
"primary"
onClick=
{
()
=>
{
this
.
confirmSaveQuestion
();
this
.
confirmSaveQuestion
(
"close"
);
}
}
>
保存
...
...
src/modules/teach-tool/AddNewQuestion.less
View file @
0e1a2057
...
...
@@ -2,11 +2,11 @@
* @Author: yuananting
* @Date: 2021-02-25 13:52:01
* @LastEditors: yuananting
* @LastEditTime: 2021-03-
08 19:07:56
* @LastEditTime: 2021-03-
18 09:32:11
* @Description: 助学工具-题库-题目管理-新增题目样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.add-new-question {
.add-new-question {
position: relative !important;
.box {
margin-bottom: 66px !important;
...
...
src/modules/teach-tool/QuestionBankIndex.jsx
View file @
0e1a2057
...
...
@@ -33,7 +33,7 @@ class QuestionBankIndex extends Component {
}
};
updatedSiderTreeFromList
=
(
updatedCategoryId
)
=>
{
updatedSiderTreeFromList
=
(
updatedCategoryId
)
=>
{
this
.
setState
({
updatedCategoryId
});
};
...
...
src/modules/teach-tool/QuestionBankIndex.less
View file @
0e1a2057
...
...
@@ -2,11 +2,11 @@
* @Author: yuananting
* @Date: 2021-02-21 18:27:43
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
1 19:10:4
4
* @LastEditTime: 2021-03-1
8 09:32:2
4
* @Description: 助学工具-题库-题库主页面样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-bank-index {
.question-bank-index {
.content-body {
display: flex;
.site-layout-background {
...
...
src/modules/teach-tool/QuestionCategoryManage.less
View file @
0e1a2057
...
...
@@ -2,11 +2,11 @@
* @Author: yuananting
* @Date: 2021-02-23 19:41:42
* @LastEditors: yuananting
* @LastEditTime: 2021-03-
05 09:34:00
* @LastEditTime: 2021-03-
18 09:32:37
* @Description: 助学工具-题库-题目分类管理样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-category-manage {
.question-category-manage {
position: relative;
.search-condition {
width: 30%;
...
...
src/modules/teach-tool/components/NewQuestionTab.jsx
View file @
0e1a2057
...
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-02-25 14:34:29
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
6 17:23:02
* @LastEditTime: 2021-03-1
8 09:33:34
* @Description: 助学工具-题库-题目管理-新建题目Tab
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -11,17 +11,17 @@ import { Form, Radio, message, Checkbox, Tag, Tooltip, Input } from "antd";
import
"./NewQuestionTab.less"
;
import
Upload
from
"@/core/upload"
;
import
QuestionEditor
from
"./QuestionEditor"
;
import
GapFillingStem
from
"./GapFillingStem"
;
import
{
PlusOutlined
,
CloseOutlined
}
from
"@ant-design/icons"
;
import
{
NUM_TO_WORD_MAP
,
QUESTION
_FILE_ACCEPT
,
MEDIA
_FILE_ACCEPT
,
}
from
"@/common/constants/punchClock/punchClock"
;
import
{
defineOptionInfo
}
from
"./model"
;
import
{
defineOptionInfo
,
defineJudgeOptionInfo
}
from
"./model"
;
import
UploadingProgress
from
"./UploadingProgress"
;
import
XMAudio
from
"./XMAudio"
;
import
XMRecord
from
"./XMRecord"
;
import
ScanFileModal
from
"@/modules/resource-disk/modal/ScanFileModal"
;
import
SelectPrepareFileModal
from
"@/modules/prepare-lesson/modal/SelectPrepareFileModal"
;
import
_
from
"lodash"
;
import
UploadOss
from
"@/core/upload"
;
...
...
@@ -41,13 +41,17 @@ class NewQuestionTab extends Component {
gapFillingAnswer
:
JSON
.
parse
(
JSON
.
stringify
(
gapFillingAnswerList
)),
// 填空题-选项列表
chooseOptions
:
JSON
.
parse
(
JSON
.
stringify
(
optionList
)),
// 单选多选不定项判断-选项列表
questionAnswerDesc
:
JSON
.
parse
(
JSON
.
stringify
(
questionAnswerDescList
)),
// 答案解析
accept
:
QUESTION
_FILE_ACCEPT
[
"PICTURE"
],
// 上传媒体类型
accept
:
MEDIA
_FILE_ACCEPT
[
"PICTURE"
],
// 上传媒体类型
fileType
:
"PICTURE"
,
// 媒体枚举
showRecord
:
false
,
// 录音弹窗
showBox
:
showBox
,
gapFillingOptions
:
[],
blanksList
:
[],
// 填空列表
showSelectFileModal
:
false
,
mediaType
:
""
,
diskList
:
[],
// 资料云盘文件列表
};
this
.
uploadInput
=
React
.
createRef
();
this
.
markKey
=
window
.
random_string
(
16
);
}
...
...
@@ -67,6 +71,9 @@ class NewQuestionTab extends Component {
this
.
setState
({
[
`optionsText_
${
i
}
`
]:
""
});
}
}
}
else
if
(
this
.
props
.
questionTypeKey
===
"JUDGE"
)
{
this
.
initJudgeOption
(
"正确"
);
this
.
initJudgeOption
(
"错误"
);
}
this
.
props
.
onRef
(
this
);
}
...
...
@@ -92,9 +99,21 @@ class NewQuestionTab extends Component {
shouldComponentUpdate
(
nextProps
,
nextState
)
{
const
{
questionInfo
}
=
nextProps
;
if
(
this
.
props
.
questionInfo
!==
questionInfo
)
{
this
.
setState
({
stemContent
:
JSON
.
parse
(
JSON
.
stringify
(
questionInfo
.
questionStemList
)),
});
// 题干内容
this
.
setState
(
{
stemContent
:
JSON
.
parse
(
JSON
.
stringify
(
questionInfo
.
questionStemList
)
),
},
()
=>
{
const
editorHtml
=
this
.
transferStemDocument
(
questionInfo
.
questionStemList
[
0
].
content
);
const
_blanksList
=
editorHtml
.
getElementsByClassName
(
"fill-line"
);
// this.setState({blanksList:_blanksList})
console
.
log
(
"转:"
,
editorHtml
.
getElementsByClassName
(
"fill-line"
));
}
);
// 题干内容
this
.
setState
({
chooseOptions
:
JSON
.
parse
(
JSON
.
stringify
(
questionInfo
.
optionList
)),
});
// 单选多选不定项-选项列表
...
...
@@ -123,20 +142,15 @@ class NewQuestionTab extends Component {
});
};
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
});
transferStemDocument
=
(
txt
)
=>
{
const
template
=
`<div class='stem'>
${
txt
}
</div>`
;
let
doc
=
new
DOMParser
().
parseFromString
(
template
,
"text/html"
);
let
div
=
doc
.
querySelector
(
".stem"
);
return
div
;
};
// 保存校验
checkInput
=
async
()
=>
{
checkInput
=
()
=>
{
let
validateError
=
0
;
// 题干校验
let
stemContent
=
_
.
find
(
...
...
@@ -144,23 +158,8 @@ class NewQuestionTab extends Component {
(
contentItem
)
=>
contentItem
.
type
===
"RICH_TEXT"
);
const
stem
=
stemContent
.
content
.
replace
(
/<
[^
>
]
+>/g
,
""
);
if
(
this
.
props
.
questionTypeKey
===
"GAP_FILLING"
)
{
// stemContent.content.replace(
// /<img [^>]*src=['"]([^'"]+)[^>]*>/gi,
// (match, capture) => {
// let blob = this.dataURItoBlob(capture);
// const imageUrl = await UploadOss.uploadBlobToOSS(
// blob,
// window.random_string(16) + ".png"
// );
// newImgHtml = `<img src=${imageUrl} alt="" />`;
// console.log("newImgHtml:", newImgHtml);
// }
// );
// console.log("修改:", stemContent);
// this._onSetState();
if
(
this
.
props
.
questionTypeKey
===
"GAP_FILLING"
)
{
if
(
this
.
state
.
blanksList
.
length
===
0
)
{
this
.
setState
({
stemValidate
:
"error"
});
this
.
setState
({
...
...
@@ -275,6 +274,17 @@ class NewQuestionTab extends Component {
};
/**
* 初始化判断选项
*
* @memberof QuestionInputItem
*/
initJudgeOption
=
(
content
)
=>
{
const
{
chooseOptions
}
=
this
.
state
;
chooseOptions
.
push
(
defineJudgeOptionInfo
(
content
));
this
.
_onSetState
();
};
/**
* 删除选项
*
* @memberof QuestionInputItem
...
...
@@ -309,43 +319,67 @@ class NewQuestionTab extends Component {
*/
handleChangeMedia
=
(
key
,
uploadItemTarget
,
contentType
)
=>
{
this
.
setState
({
contentType
});
const
{
mediaFirstType
}
=
this
.
state
;
const
mediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
!==
"RICH_TEXT"
;
const
pictureMediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
===
"PICTURE"
;
});
const
voiceMediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
===
"VOICE"
;
});
const
recordMediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
===
"RECORD"
;
});
const
videodMediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
===
"VIDEO"
;
});
if
(
mediaArr
.
length
===
0
)
{
this
.
setState
({
mediaFirstType
:
key
});
}
switch
(
contentType
)
{
case
"QUESTION_STEM"
:
case
"QUESTION_OPTION"
:
if
(
mediaArr
.
length
>
0
&&
key
!==
mediaFirstType
)
{
var
existType
=
[];
if
(
pictureMediaArr
.
length
>
0
)
{
existType
.
push
(
"PICTURE"
);
}
if
(
voiceMediaArr
.
length
>
0
)
{
existType
.
push
(
"VOICE"
);
}
if
(
recordMediaArr
.
length
>
0
)
{
existType
.
push
(
"RECORD"
);
}
if
(
videodMediaArr
.
length
>
0
)
{
existType
.
push
(
"VIDEO"
);
}
if
(
existType
.
length
>
0
&&
!
existType
.
includes
(
key
))
{
return
message
.
warning
(
"只能添加1种类型的多媒体文件"
);
}
else
{
if
(
key
===
"PICTURE"
&&
pictureMediaArr
.
length
>
8
)
{
return
message
.
warning
(
"只能添加9张图片"
);
}
if
(
key
===
"VOICE"
&&
voiceMediaArr
.
length
>
2
)
{
return
message
.
warning
(
"只能添加3个音频"
);
}
if
(
key
===
"VIDEO"
&&
videodMediaArr
.
length
>
2
)
{
return
message
.
warning
(
"只能添加3个视频"
);
}
}
if
(
mediaFirstType
===
"PICTURE"
&&
mediaArr
.
length
>
8
)
{
return
message
.
warning
(
"只能添加9张图片"
);
break
;
case
"QUESTION_OPTION"
:
var
existType
=
[];
if
(
pictureMediaArr
.
length
>
0
)
{
existType
.
push
(
"PICTURE"
);
}
if
(
mediaFirstType
===
"VOICE"
&&
mediaArr
.
length
>
2
)
{
return
message
.
warning
(
"只能添加3个音频"
);
if
(
voiceMediaArr
.
length
>
0
)
{
existType
.
push
(
"VOICE"
);
}
if
(
recordMediaArr
.
length
>
0
)
{
existType
.
push
(
"RECORD"
);
}
if
(
videodMediaArr
.
length
>
0
)
{
existType
.
push
(
"VIDEO"
);
}
if
(
mediaFirstType
===
"RECORD"
&&
mediaArr
.
length
>
2
)
{
return
message
.
warning
(
"只能添加
3个录音
"
);
if
(
existType
.
length
>
0
)
{
return
message
.
warning
(
"只能添加
1个多媒体文件
"
);
}
break
;
case
"QUESTION_ANSWER_DESC"
:
var
existType
=
[];
const
pictureMediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
===
"PICTURE"
;
});
const
voiceMediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
===
"VOICE"
;
});
const
recordMediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
===
"RECORD"
;
});
const
videodMediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
===
"VIDEO"
;
});
if
(
pictureMediaArr
.
length
>
0
)
{
existType
.
push
(
"PICTURE"
);
}
...
...
@@ -375,8 +409,6 @@ class NewQuestionTab extends Component {
}
}
break
;
default
:
break
;
}
this
.
setState
(
...
...
@@ -384,15 +416,16 @@ class NewQuestionTab extends Component {
uploadItemTarget
,
},
()
=>
{
QUESTION
_FILE_ACCEPT
[
key
]
&&
MEDIA
_FILE_ACCEPT
[
key
]
&&
this
.
setState
(
{
accept
:
QUESTION
_FILE_ACCEPT
[
key
],
accept
:
MEDIA
_FILE_ACCEPT
[
key
],
fileType
:
key
,
},
()
=>
{
this
.
uploadInput
.
current
.
value
=
""
;
this
.
uploadInput
.
current
.
click
();
this
.
setState
({
showSelectFileModal
:
key
!==
"RECORD"
});
// this.uploadInput.current.click();
}
);
...
...
@@ -406,60 +439,65 @@ class NewQuestionTab extends Component {
);
};
async
uploadFile
(
event
)
{
async
uploadFile
(
mediaFile
)
{
const
{
fileType
,
uploadItemTarget
,
contentType
}
=
this
.
state
;
const
mediaFile
=
event
.
target
.
files
[
0
];
if
(
!
mediaFile
)
return
;
if
(
fileType
===
"VOICE"
)
{
if
(
!
QUESTION_FILE_ACCEPT
.
VOICE
.
split
(
","
).
includes
(
mediaFile
.
type
))
{
if
(
!
MEDIA_FILE_ACCEPT
.
VOICE
.
split
(
","
).
includes
(
mediaFile
.
folderFormat
)
)
{
message
.
warning
(
"文件格式不正确"
);
return
;
}
if
(
mediaFile
.
size
>
3
0
*
1024
*
1024
)
{
if
(
mediaFile
.
size
>
2
0
*
1024
*
1024
)
{
Modal
.
warning
({
title
:
"音频过大"
,
content
:
"音频大小超过
3
0M,请压缩后上传"
,
content
:
"音频大小超过
2
0M,请压缩后上传"
,
});
return
;
}
}
if
(
fileType
===
"PICTURE"
)
{
if
(
!
QUESTION_FILE_ACCEPT
.
PICTURE
.
split
(
","
).
includes
(
mediaFile
.
type
))
{
if
(
!
MEDIA_FILE_ACCEPT
.
PICTURE
.
split
(
","
).
includes
(
mediaFile
.
folderFormat
)
)
{
message
.
warning
(
"文件格式不正确"
);
return
;
}
if
(
mediaFile
.
size
>
8
*
1024
*
1024
)
{
if
(
mediaFile
.
folderSize
>
1
*
1024
*
1024
)
{
Modal
.
warning
({
title
:
"图片过大"
,
content
:
"图片大小超过
8
M,请压缩后上传"
,
content
:
"图片大小超过
1
M,请压缩后上传"
,
});
return
;
}
}
if
(
fileType
===
"VIDEO"
)
{
if
(
!
QUESTION_FILE_ACCEPT
.
VIDEO
.
split
(
","
).
includes
(
mediaFile
.
type
))
{
if
(
!
MEDIA_FILE_ACCEPT
.
VIDEO
.
split
(
","
).
includes
(
mediaFile
.
folderFormat
)
)
{
message
.
warning
(
"文件格式不正确"
);
return
;
}
if
(
mediaFile
.
size
>
1024
*
1024
*
1024
)
{
if
(
mediaFile
.
folderSize
>
500
*
1024
*
1024
)
{
Modal
.
warning
({
title
:
"视频过大"
,
content
:
"视频大小超过
1
G,请压缩后上传"
,
content
:
"视频大小超过
500
G,请压缩后上传"
,
});
return
;
}
}
const
originArr
=
mediaFile
.
n
ame
.
split
(
"."
);
const
originArr
=
mediaFile
.
folderN
ame
.
split
(
"."
);
const
originType
=
originArr
[
originArr
.
length
-
1
];
const
uploadObj
=
{
contentType
,
type
:
fileType
,
contentName
:
`
${
window
.
random_string
(
16
)}
.
${
originType
}
`
,
// 文件名
fileType
:
originType
,
// 文件后缀
mediaFile
,
// url
fileType
:
mediaFile
.
folderFormat
,
// 文件后缀
content
:
mediaFile
.
ossUrl
,
// url
};
if
([
"VIDEO"
,
"VOICE"
].
includes
(
fileType
))
{
try
{
...
...
@@ -476,17 +514,18 @@ class NewQuestionTab extends Component {
console
.
log
(
error
);
}
}
else
if
(
fileType
===
"PICTURE"
)
{
uploadObj
.
size
=
mediaFile
.
s
ize
;
uploadObj
.
size
=
mediaFile
.
folderS
ize
;
}
uploadItemTarget
.
push
(
uploadObj
);
this
.
setState
({},
()
=>
{
this
.
handleReupload
(
uploadObj
);
this
.
_onSetState
(
);
this
.
uploadInput
.
current
.
value
=
""
;
});
}
changeBlankCount
=
(
data
)
=>
{
data
.
map
((
item
)
=>
{
console
.
log
(
"data:"
,
data
);
data
.
forEach
((
item
)
=>
{
if
(
!
item
.
answerTagList
)
{
item
.
answerTagList
=
[];
}
...
...
@@ -552,7 +591,7 @@ class NewQuestionTab extends Component {
return
(
<
div
className=
"gap-answer-box"
key=
{
optionIndex
}
>
<
span
className=
"gap-answer-label"
>
{
optionItem
.
innerHTML
}
填空
{
optionIndex
+
1
}
.
</
span
>
<
div
className=
"gap-answer-content"
>
...
...
@@ -618,10 +657,8 @@ class NewQuestionTab extends Component {
renderJudgeOption
=
(
judgeOptions
)
=>
{
return
(
<
React
.
Fragment
>
<
div
>
{
judgeOptions
[
0
].
content
}
</
div
>
</
React
.
Fragment
>
);
<
div
dangerouslySetInnerHTML=
{
{
__html
:
judgeOptions
[
0
].
content
}
}
/>
)
};
/**
* 渲染输入内容
...
...
@@ -656,42 +693,28 @@ class NewQuestionTab extends Component {
return
(
<
React
.
Fragment
>
<
div
>
{
isGapFilling
&&
contentType
===
"QUESTION_STEM"
?
(
<
GapFillingStem
placehold=
{
placehold
}
validateStatus=
{
validateStatus
}
detailInfo=
{
contentList
}
mediaBtn=
{
mediaBtn
}
changeBlankCount=
{
this
.
changeBlankCount
.
bind
(
this
)
}
onChange=
{
(
html
)
=>
{
editorContent
.
content
=
html
;
this
.
_onSetState
();
}
}
onUploadMedia=
{
(
key
)
=>
{
this
.
handleChangeMedia
(
key
,
contentList
,
contentType
);
}
}
/>
)
:
(
<
QuestionEditor
markKey=
{
this
.
markKey
}
placehold=
{
placehold
}
validateStatus=
{
validateStatus
}
detailInfo=
{
editorContent
}
mediaBtn=
{
mediaBtn
}
bindChangeContent=
{
(
cb
,
textElemId
)
=>
{
this
.
setState
({
textElemId
});
editorContent
.
handleChangeContent
=
cb
;
}
}
onChange=
{
(
content
,
textLength
)
=>
{
editorContent
.
content
=
content
;
editorContent
.
textLength
=
textLength
;
this
.
_onSetState
();
}
}
onUploadMedia=
{
(
key
)
=>
{
this
.
handleChangeMedia
(
key
,
contentList
,
contentType
);
}
}
/>
)
}
<
QuestionEditor
markKey=
{
this
.
markKey
}
placehold=
{
placehold
}
validateStatus=
{
validateStatus
}
detailInfo=
{
editorContent
}
isGapFilling=
{
isGapFilling
}
contentType=
{
contentType
}
mediaBtn=
{
mediaBtn
}
changeBlankCount=
{
this
.
changeBlankCount
.
bind
(
this
)
}
bindChangeContent=
{
(
cb
,
textElemId
)
=>
{
this
.
setState
({
textElemId
});
editorContent
.
handleChangeContent
=
cb
;
}
}
onChange=
{
(
content
,
textLength
)
=>
{
editorContent
.
content
=
content
;
editorContent
.
textLength
=
textLength
;
this
.
_onSetState
();
}
}
onUploadMedia=
{
(
key
)
=>
{
this
.
handleChangeMedia
(
key
,
contentList
,
contentType
);
}
}
/>
</
div
>
{
contentType
===
"QUESTION_ANSWER_DESC"
?
(
<
div
className=
"question-desc-box"
>
...
...
@@ -1008,6 +1031,7 @@ class NewQuestionTab extends Component {
* @memberof QuestionInputItem
*/
handleReupload
=
(
uploadItem
)
=>
{
console
.
log
(
"uploadItem:"
,
uploadItem
);
uploadItem
.
status
=
"init"
;
Upload
.
uploadToOSSEvent
(
uploadItem
.
mediaFile
,
...
...
@@ -1056,10 +1080,15 @@ class NewQuestionTab extends Component {
* @memberof QuestionInputItem
*/
handleFinishRecord
=
(
mp3URL
,
duration
)
=>
{
const
originArr
=
mp3URL
.
split
(
"."
);
const
originType
=
originArr
[
originArr
.
length
-
1
];
const
{
uploadItemTarget
,
contentType
}
=
this
.
state
;
uploadItemTarget
.
push
({
contentType
,
type
:
"RECORD"
,
contentName
:
`
${
window
.
random_string
(
16
)}
.
${
originType
}
`
,
// 文件名
fileType
:
originType
,
// 文件后缀
content
:
mp3URL
,
size
:
duration
,
});
...
...
@@ -1075,6 +1104,13 @@ class NewQuestionTab extends Component {
this
.
setState
({
showRecord
:
false
});
};
handleSelectMedia
=
(
file
)
=>
{
this
.
uploadFile
(
file
);
this
.
setState
({
showSelectFileModal
:
false
,
});
};
render
()
{
const
{
stemContent
,
...
...
@@ -1086,9 +1122,14 @@ class NewQuestionTab extends Component {
scanFileType
,
scanFileAddress
,
blanksList
,
showSelectFileModal
,
mediaType
,
diskList
,
}
=
this
.
state
;
const
{
stemValidate
,
stemText
,
radioValidate
,
radioText
}
=
this
.
state
;
const
isJudge
=
this
.
props
.
questionTypeKey
===
"JUDGE"
;
console
.
log
(
"this.props.questionTypeKey:"
,
this
.
props
.
questionTypeKey
)
console
.
log
(
"判断:"
,
isJudge
)
const
isGapFilling
=
this
.
props
.
questionTypeKey
===
"GAP_FILLING"
;
const
placehold
=
isGapFilling
?
(
<
span
>
...
...
@@ -1101,6 +1142,23 @@ class NewQuestionTab extends Component {
)
:
(
"必填(1000字以内,可粘贴小图)"
);
let
acceptType
=
""
;
let
selectTypeList
=
[];
switch
(
mediaType
)
{
case
"PICTURE"
:
acceptType
=
"image/png,image/jpg"
;
selectTypeList
=
[
"JPG"
,
"PNG"
];
break
;
case
"VOICE"
:
acceptType
=
"audio/mp3"
;
selectTypeList
=
[
"MP3"
];
break
;
case
"VIDEO"
:
acceptType
=
"video/mp4"
;
selectTypeList
=
[
"MP4"
];
break
;
}
return
(
<
div
className=
"question-input-item_wrapper"
>
{
/* 题干 */
}
...
...
@@ -1170,6 +1228,7 @@ class NewQuestionTab extends Component {
questionOptionContentList
,
isCorrectAnswer
,
}
=
optionItem
;
console
.
log
(
"questionOptionContentList:"
,
questionOptionContentList
)
optionItem
.
optionSort
=
optionIndex
;
const
mediaBtn
=
[
"VOICE"
,
"RECORD"
,
"PICTURE"
];
const
placeHold
=
...
...
@@ -1192,30 +1251,30 @@ class NewQuestionTab extends Component {
{
[
"SINGLE_CHOICE"
,
"JUDGE"
].
includes
(
this
.
props
.
questionTypeKey
)
&&
(
<
Radio
checked=
{
isCorrectAnswer
}
onClick=
{
()
=>
{
_
.
each
(
chooseOptions
,
(
o
)
=>
{
o
.
isCorrectAnswer
=
0
;
});
optionItem
.
isCorrectAnswer
=
1
;
this
.
_onSetState
();
}
}
/>
)
}
<
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
();
}
}
/>
)
}
<
Checkbox
checked=
{
isCorrectAnswer
===
1
}
onChange=
{
(
e
)
=>
{
const
checked
=
e
.
target
.
checked
?
1
:
0
;
optionItem
.
isCorrectAnswer
=
checked
;
this
.
_onSetState
();
}
}
/>
)
}
</
Form
.
Item
>
</
div
>
<
div
className=
"question-item_options__sort mr12"
>
...
...
@@ -1231,12 +1290,12 @@ class NewQuestionTab extends Component {
{
isJudge
?
this
.
renderJudgeOption
(
questionOptionContentList
)
:
this
.
renderContent
(
questionOptionContentList
,
placeHold
,
mediaBtn
,
"QUESTION_OPTION"
,
this
.
state
[
`optionsValidate_${optionIndex}`
]
)
}
questionOptionContentList
,
placeHold
,
mediaBtn
,
"QUESTION_OPTION"
,
this
.
state
[
`optionsValidate_${optionIndex}`
]
)
}
</
Form
.
Item
>
</
div
>
{
[
...
...
@@ -1244,41 +1303,41 @@ class NewQuestionTab extends Component {
"MULTI_CHOICE"
,
"SINGLE_CHOICE"
,
].
includes
(
this
.
props
.
questionTypeKey
)
&&
(
<
div
className=
"question-item_options__extra"
>
<
React
.
Fragment
>
<
span
className=
"option-operate_item__icon icon iconfont"
onClick=
{
()
=>
this
.
handleDelOption
(
optionIndex
)
}
>

</
span
>
{
optionIndex
>
0
&&
(
<
div
className=
"question-item_options__extra"
>
<
React
.
Fragment
>
<
span
className=
"option-operate_item__icon icon iconfont"
onClick=
{
()
=>
this
.
handleMoveOption
(
optionIndex
,
-
1
)
}
onClick=
{
()
=>
this
.
handleDelOption
(
optionIndex
)
}
>

</
span
>
)
}
{
optionIndex
<
chooseOptions
.
length
-
1
&&
(
<
span
className=
"option-operate_item__icon icon iconfont"
style=
{
{
transform
:
"rotate(180deg)"
,
display
:
"inline-block"
,
}
}
onClick=
{
()
=>
this
.
handleMoveOption
(
optionIndex
,
1
)
}
>

</
span
>
)
}
</
React
.
Fragment
>
</
div
>
)
}

</
span
>
{
optionIndex
>
0
&&
(
<
span
className=
"option-operate_item__icon icon iconfont"
onClick=
{
()
=>
this
.
handleMoveOption
(
optionIndex
,
-
1
)
}
>

</
span
>
)
}
{
optionIndex
<
chooseOptions
.
length
-
1
&&
(
<
span
className=
"option-operate_item__icon icon iconfont"
style=
{
{
transform
:
"rotate(180deg)"
,
display
:
"inline-block"
,
}
}
onClick=
{
()
=>
this
.
handleMoveOption
(
optionIndex
,
1
)
}
>

</
span
>
)
}
</
React
.
Fragment
>
</
div
>
)
}
</
div
>
);
})
}
...
...
@@ -1335,6 +1394,17 @@ class NewQuestionTab extends Component {
}
}
/>
)
}
<
SelectPrepareFileModal
operateType=
"select"
accept=
{
acceptType
}
selectTypeList=
{
selectTypeList
}
isOpen=
{
showSelectFileModal
}
diskList=
{
diskList
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
});
}
}
onSelect=
{
this
.
handleSelectMedia
}
/>
</
div
>
);
}
...
...
src/modules/teach-tool/components/QuestionBankSider.jsx
View file @
0e1a2057
...
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-02-22 10:59:43
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
5 15:22:13
* @LastEditTime: 2021-03-1
8 09:33:50
* @Description: 助学工具-题库-题库主页面侧边栏
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
src/modules/teach-tool/components/QuestionBankSider.less
View file @
0e1a2057
...
...
@@ -2,11 +2,11 @@
* @Author: yuananting
* @Date: 2021-02-22 12:02:34
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
1 20:29:44
* @LastEditTime: 2021-03-1
8 09:34:06
* @Description: 助学工具-题库-题库主页面侧边栏样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-bank-sider {
.question-bank-sider {
position: relative;
.sider-title {
height: 22px;
...
...
src/modules/teach-tool/components/QuestionEditor.jsx
View file @
0e1a2057
...
...
@@ -49,9 +49,15 @@ class QuestionEditor extends Component {
this
.
renderEditor
();
}
static
getDerivedStateFromProps
(
nextProps
,
prevState
)
{
return
{
detailInfo
:
nextProps
.
detailInfo
}
}
shouldComponentUpdate
(
nextProps
,
nextState
)
{
const
{
detailInfo
}
=
nextProps
;
if
(
this
.
props
.
detailInfo
!==
detailInfo
)
{
if
(
this
.
state
.
detailInfo
!==
detailInfo
)
{
this
.
setState
({
detailInfo
:
nextProps
.
detailInfo
},
()
=>
{
this
.
renderEditor
();
});
...
...
@@ -127,7 +133,6 @@ class QuestionEditor extends Component {
};
editorRoot
.
customConfig
.
onchange
=
(
html
)
=>
{
console
.
log
(
"触发:+——+++++++"
,
this
.
state
.
blanksList
);
const
{
focusFlag
}
=
this
.
state
;
const
textLength
=
editorRoot
.
txt
.
text
().
replace
(
/
\&
nbsp
\;
/gi
,
" "
)
.
length
;
...
...
@@ -174,27 +179,27 @@ class QuestionEditor extends Component {
editorRoot
.
create
();
this
.
editorRoot
=
editorRoot
;
if
(
detailInfo
.
content
)
{
const
contentHtml
=
/^
\<
p/
.
test
(
detailInfo
.
content
)
?
detailInfo
.
content
:
`<p>
${
detailInfo
.
content
}
</p>`
;
editorRoot
.
txt
.
html
(
detailInfo
.
content
);
const
textLength
=
editorRoot
.
txt
.
text
().
replace
(
/
\&
nbsp
\;
/gi
,
" "
)
.
length
;
const
imgLength
=
contentHtml
.
match
(
/<img/g
)
?
contentHtml
.
match
(
/<img/g
).
length
*
2
:
0
;
const
contentLength
=
imgLength
+
textLength
;
this
.
setState
(
{
contentLength
,
visiblePlacehold
:
contentLength
===
0
&&
!
this
.
state
.
focusFlag
,
},
()
=>
{
onChange
&&
onChange
(
contentHtml
,
this
.
state
.
contentLength
);
}
);
}
// if (detailInfo &&
detailInfo.content) {
const
contentHtml
=
/^
\<
p/
.
test
(
detailInfo
.
content
)
?
detailInfo
.
content
:
`<p>
${
detailInfo
.
content
}
</p>`
;
editorRoot
.
txt
.
html
(
detailInfo
.
content
);
const
textLength
=
editorRoot
.
txt
.
text
().
replace
(
/
\&
nbsp
\;
/gi
,
" "
)
.
length
;
const
imgLength
=
contentHtml
.
match
(
/<img/g
)
?
contentHtml
.
match
(
/<img/g
).
length
*
2
:
0
;
const
contentLength
=
imgLength
+
textLength
;
this
.
setState
(
{
contentLength
,
visiblePlacehold
:
contentLength
===
0
&&
!
this
.
state
.
focusFlag
,
},
()
=>
{
onChange
&&
onChange
(
contentHtml
,
this
.
state
.
contentLength
);
}
);
//
}
bindChangeContent
&&
bindChangeContent
(
this
.
handleChangeContent
);
}
...
...
@@ -207,6 +212,9 @@ class QuestionEditor extends Component {
var
_blanksList
=
[];
_blanksList
=
document
.
getElementsByClassName
(
"add-fill-line"
);
this
.
setState
({
blanksList
:
_blanksList
});
this
.
setState
({
visiblePlacehold
:
false
,
});
// this.props.changeBlankCount(_blanksList);
};
...
...
@@ -288,9 +296,8 @@ class QuestionEditor extends Component {
</
div
>
)
}
<
div
className=
{
`editor-limit-tip${
contentLength > limitLength ? " mt6" : ""
}`
}
className=
{
`editor-limit-tip${contentLength > limitLength ? " mt6" : ""
}`
}
style=
{
{
height
:
contentLength
>
limitLength
?
20
:
0
}
}
>
最多只能输入1000字
...
...
src/modules/teach-tool/components/QuestionManageContent.jsx
View file @
0e1a2057
...
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-02-25 11:23:47
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
7 12:43:5
3
* @LastEditTime: 2021-03-1
8 09:35:0
3
* @Description: 助学工具-题库-题目管理主页面列表数据
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -84,7 +84,7 @@ class QuestionManageContent extends Component {
};
}
componentDidMount
()
{}
componentDidMount
()
{
}
shouldComponentUpdate
(
nextProps
,
nextState
)
{
const
{
selectedCategoryId
}
=
nextProps
;
...
...
@@ -211,6 +211,8 @@ class QuestionManageContent extends Component {
// 表头设置
parseColumns
=
()
=>
{
const
isPermiss
=
[
"CloudManager"
,
"StoreManager"
].
includes
(
User
.
getUserRole
());
console
.
log
(
isPermiss
,
User
.
getUserRole
())
const
columns
=
[
{
title
:
"题目"
,
...
...
@@ -273,22 +275,22 @@ class QuestionManageContent extends Component {
>
预览
</
div
>
<
span
className=
"record-operate__item split"
>
|
</
span
>
<
div
{
isPermiss
&&
<
span
className=
"record-operate__item split"
>
|
</
span
>
}
{
isPermiss
&&
<
div
className=
"record-operate__item"
onClick=
{
()
=>
this
.
toEditQuetion
(
record
.
id
,
record
.
questionTypeEnum
)
}
>
编辑
</
div
>
<
span
className=
"record-operate__item split"
>
|
</
span
>
<
div
</
div
>
}
{
isPermiss
&&
<
span
className=
"record-operate__item split"
>
|
</
span
>
}
{
isPermiss
&&
<
div
className=
"record-operate__item"
onClick=
{
()
=>
this
.
delCategoryConfirm
(
record
)
}
>
删除
</
div
>
</
div
>
}
</
div
>
);
},
...
...
@@ -311,9 +313,7 @@ class QuestionManageContent extends Component {
<
span
className=
"empty-list-tip"
onClick=
{
()
=>
{
window
.
RCHistory
.
push
({
pathname
:
"/create-question-bank"
,
});
this
.
handleCreateQuestionBank
()
}
}
>
新建一个
...
...
@@ -356,7 +356,7 @@ class QuestionManageContent extends Component {
const
ImportQuestionModal
=
(
<
BatchImportQuestionModal
close=
{
()
=>
{
this
.
setState
({
ImportQuestionModal
:
null
});
this
.
setState
({
ImportQuestionModal
:
null
}
,
()
=>
{
this
.
queryQuestionPageList
();
this
.
props
.
updatedSiderTree
(
this
.
props
.
selectedCategoryId
)
}
);
}
}
categoryId=
{
categoryId
}
/>
...
...
@@ -430,7 +430,7 @@ class QuestionManageContent extends Component {
</
div
>
</
Row
>
</
div
>
{
!
[
"0"
,
null
].
includes
(
categoryId
)
&&
(
{
([
"CloudManager"
,
"StoreManager"
].
includes
(
User
.
getUserRole
())
&&
!
[
"0"
,
null
].
includes
(
categoryId
)
)
&&
(
<
Space
size=
"large"
>
<
Button
type=
"primary"
onClick=
{
this
.
handleCreateQuestionBank
}
>
新建题目
...
...
src/modules/teach-tool/components/model.js
View file @
0e1a2057
/*
* @Author: chenjianyu
* @Date: 2020-09-12 17:00:44
* @LastEditTime: 2021-03-1
5 13:00:10
* @LastEditTime: 2021-03-1
8 09:33:26
* @LastEditors: yuananting
* @Description: 答题模式模板
* @Copyright © 2020 杭州杰竞科技有限公司 版权所有
...
...
@@ -54,7 +54,7 @@ export function defineQuestionInfo(questionType) {
type
:
"RICH_TEXT"
,
// 内容项形式(0:富文本 1:文字 2:图片 3:语音 4:视频 5文件 6.课件)
}
],
// 题干
optionList
:
[],
// 非填空题选项
optionList
:
questionType
===
"JUDGE"
?
[]
:
[],
// 非填空题选项
gapFillingAnswerList
:
[
{
correctAnswerList
:
[]
...
...
@@ -84,6 +84,19 @@ export function defineOptionInfo() {
}
}
export
function
defineJudgeOptionInfo
(
content
)
{
return
{
isCorrectAnswer
:
0
,
// 是否为正确答案选项
questionOptionContentList
:
[
// 选项内容
{
contentType
:
"QUESTION_OPTION"
,
// 内容类型(默认选项)
content
,
// 内容
type
:
"RICH_TEXT"
,
}
]
}
}
export
function
defineOptionData
(
content
=
''
)
{
return
{
itemContentVOList
:
[{
...
...
src/modules/teach-tool/modal/BatchImportQuestionModal.jsx
View file @
0e1a2057
...
...
@@ -101,6 +101,7 @@ class BatchImportQuestionModal extends Component {
return
(
<
div
>
<
Modal
closable=
{
status
!==
"uploading"
}
className=
"import-score-modal"
title=
"导入题目信息"
visible=
{
true
}
...
...
@@ -218,7 +219,11 @@ class BatchImportQuestionModal extends Component {
<
Button
type=
"primary"
className=
"down-btn"
// onClick=
{}
onClick=
{
()
=>
{
this
.
setState
({
status
:
"init"
})
this
.
setState
({
uploadFile
:
null
})
this
.
setState
({
showSelectFileModal
:
true
})
}
}
>
重新上传文件
</
Button
>
...
...
src/modules/teach-tool/modal/NewEditQuestionBankCategory.jsx
View file @
0e1a2057
...
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-02-22 17:51:28
* @LastEditors: yuananting
* @LastEditTime: 2021-03-1
5 09:56
:59
* @LastEditTime: 2021-03-1
8 09:32
:59
* @Description: 助学工具-题库-题库新建或编辑题库分类模态框
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
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