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
f48a2dd4
Commit
f48a2dd4
authored
Mar 29, 2021
by
yuananting
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:题库代码优化
parent
3935654b
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1536 additions
and
926 deletions
+1536
-926
src/modules/teach-tool/components/CourseCategoryManage.jsx
+232
-228
src/modules/teach-tool/components/CourseCategoryManage.less
+3
-11
src/modules/teach-tool/components/CourseCategorySiderTree.jsx
+37
-40
src/modules/teach-tool/components/CourseCategorySiderTree.less
+2
-10
src/modules/teach-tool/examination-paper/NewExaminationPaper.jsx
+118
-31
src/modules/teach-tool/examination-paper/components/ExaminationPaperContent.jsx
+1
-3
src/modules/teach-tool/examination-paper/components/SelectQuestionContent.jsx
+438
-0
src/modules/teach-tool/examination-paper/components/SelectQuestionContent.less
+84
-0
src/modules/teach-tool/examination-paper/modal/SelectQuestionModal.jsx
+68
-0
src/modules/teach-tool/examination-paper/modal/SelectQuestionModal.less
+17
-0
src/modules/teach-tool/modal/NewEditCourseCategoryModal.jsx
+35
-32
src/modules/teach-tool/question-bank/AddNewQuestion.jsx
+111
-69
src/modules/teach-tool/question-bank/AddNewQuestion.less
+1
-9
src/modules/teach-tool/question-bank/QuestionBankIndex.jsx
+2
-7
src/modules/teach-tool/question-bank/QuestionBankIndex.less
+1
-9
src/modules/teach-tool/question-bank/components/NewQuestionTab.jsx
+204
-251
src/modules/teach-tool/question-bank/components/NewQuestionTab.less
+0
-41
src/modules/teach-tool/question-bank/components/QuestionManageContent.jsx
+151
-146
src/modules/teach-tool/question-bank/components/QuestionManageContent.less
+0
-13
src/modules/teach-tool/question-bank/modal/BatchImportQuestionModal.jsx
+6
-5
src/modules/teach-tool/question-bank/modal/BatchImportQuestionModal.less
+10
-11
src/modules/teach-tool/question-bank/modal/QuestionPreviewModal.jsx
+13
-8
src/modules/teach-tool/question-bank/modal/QuestionPreviewModal.less
+2
-2
No files found.
src/modules/teach-tool/components/CourseCategoryManage.jsx
View file @
f48a2dd4
...
...
@@ -2,8 +2,8 @@
* @Author: yuananting
* @Date: 2021-02-23 18:28:50
* @LastEditors: yuananting
* @LastEditTime: 2021-03-2
7 13:49:14
* @Description: 助学工具-
题库-课程分类管理
* @LastEditTime: 2021-03-2
9 19:50:28
* @Description: 助学工具-
课程分类
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
...
...
@@ -32,8 +32,9 @@ class CourseCategoryManage extends Component {
this
.
state
=
{
NewEditCourseCategoryModal
:
null
,
//新增或编辑分类模态框
treeData
:
[],
originTreeData
:
[],
treeMap
:
{},
selectedKeys
:
[
"
0
"
],
selectedKeys
:
[
"
null
"
],
autoExpandParent
:
true
,
};
}
...
...
@@ -42,8 +43,34 @@ class CourseCategoryManage extends Component {
this
.
queryCategoryTree
(
"search"
);
}
getWholeTree
=
()
=>
{
let
query
=
{
source
:
0
,
userId
:
User
.
getStoreUserId
(),
tenantId
:
User
.
getStoreId
(),
};
QuestionBankService
.
queryCategoryTree
(
query
).
then
((
res
)
=>
{
const
{
result
}
=
res
;
this
.
setState
({
originTreeData
:
result
},
()
=>
{
let
map
=
{};
let
topItem
=
[];
result
.
forEach
((
item
)
=>
{
topItem
.
push
(
item
);
});
this
.
setState
({
treeMap
:
Object
.
assign
(
this
.
getTreeMap
(
result
,
map
),
{
0
:
{
sonCategoryList
:
topItem
,
},
}),
});
});
});
};
// 查询分类树
queryCategoryTree
=
(
operateType
,
categoryName
)
=>
{
this
.
getWholeTree
();
this
.
setState
({
categoryName
});
let
query
=
{
source
:
0
,
...
...
@@ -67,7 +94,7 @@ class CourseCategoryManage extends Component {
this
.
setState
({
expandedKeys
:
nodeId
});
}
else
{
const
defaultNode
=
{
id
:
"
0
"
,
id
:
"
null
"
,
categoryName
:
"未分类"
,
categoryCount
:
0
,
parentId
:
"0"
,
...
...
@@ -88,16 +115,14 @@ class CourseCategoryManage extends Component {
}
else
{
this
.
setState
({
autoExpandParent
:
false
});
const
defaultNode
=
{
id
:
"
0
"
,
id
:
"
null
"
,
categoryName
:
"未分类"
,
categoryCount
:
0
,
parentId
:
"0"
,
categoryLevel
:
0
,
};
result
.
unshift
(
defaultNode
);
this
.
setState
({
treeData
:
this
.
renderTreeNodes
(
result
,
categoryName
),
});
this
.
setState
({
treeData
:
this
.
renderTreeNodes
(
result
,
categoryName
)
});
if
(
operateType
===
"search"
)
{
this
.
setState
({
expandedKeys
:
[]
});
}
...
...
@@ -105,32 +130,144 @@ class CourseCategoryManage extends Component {
});
};
// 删除分类
delCategory
=
(
item
)
=>
{
return
confirm
({
title
:
"确认删除该分类吗?"
,
content
:
"删除后,分类下的所有内容将自动转入“未分类”中。"
,
icon
:
(
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
),
okText
:
"删除"
,
okType
:
"danger"
,
cancelText
:
"取消"
,
onOk
:
()
=>
{
let
params
=
{
categoryId
:
item
.
id
,
source
:
0
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
};
QuestionBankService
.
delCategory
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"删除分类成功"
);
this
.
queryCategoryTree
(
"change"
);
}
});
},
// 树节点渲染-内容处理
renderTreeNodes
=
(
data
,
value
)
=>
{
let
newTreeData
=
data
.
map
((
item
)
=>
{
item
.
title
=
item
.
categoryName
;
item
.
key
=
item
.
id
;
item
.
title
=
(
<
div
style=
{
{
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
,
}
}
className=
"node-title-div"
onMouseOver=
{
(
e
)
=>
{
let
mouseNodeOpts
=
e
.
currentTarget
.
getElementsByTagName
(
"div"
)[
0
];
if
(
mouseNodeOpts
)
{
mouseNodeOpts
.
style
.
visibility
=
"visible"
;
}
}
}
onMouseOut=
{
(
e
)
=>
{
let
mouseNodeOpts
=
e
.
currentTarget
.
getElementsByTagName
(
"div"
)[
0
];
if
(
mouseNodeOpts
)
{
mouseNodeOpts
.
style
.
visibility
=
"hidden"
;
}
}
}
>
<
span
>
{
item
.
categoryName
}
</
span
>
{
item
.
categoryName
!==
"未分类"
&&
(
<
Space
className=
"title-opts"
size=
{
16
}
>
<
span
onClick=
{
()
=>
{
let
nodesCount
=
0
;
const
{
originTreeData
}
=
this
.
state
;
console
.
log
(
"orororo"
,
originTreeData
);
if
(
(
item
.
categoryLevel
===
0
&&
originTreeData
.
length
>=
29
)
||
(
item
.
categoryLevel
>
0
&&
this
.
getRelatedNodes
(
item
.
parentId
).
length
>=
30
)
)
{
return
message
.
info
(
"最多只能添加30个分类"
);
}
this
.
newEditCourseCategory
(
"newEqualLevelCategory"
,
"equal"
,
"new"
,
item
);
}
}
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#BFBFBF"
}
}
>

{
" "
}
</
span
>
<
span
>
同级
</
span
>
</
span
>
{
item
.
categoryLevel
<
4
&&
(
<
span
onClick=
{
()
=>
{
if
(
this
.
getRelatedNodes
(
item
.
id
)
&&
this
.
getRelatedNodes
(
item
.
id
).
length
>=
30
)
{
message
.
info
(
"最多只能添加30个子分类"
);
return
;
}
this
.
newEditCourseCategory
(
"newChildLevelCategory"
,
"child"
,
"new"
,
item
);
}
}
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#BFBFBF"
}
}
>

{
" "
}
</
span
>
<
span
>
子级
</
span
>
</
span
>
)
}
<
Dropdown
overlay=
{
this
.
initDropMenu
(
item
)
}
>
<
span
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#BFBFBF"
}
}
>

{
" "
}
</
span
>
<
span
>
更多
</
span
>
</
span
>
</
Dropdown
>
</
Space
>
)
}
</
div
>
);
item
.
icon
=
item
.
categoryName
===
"未分类"
?
(
<
img
style=
{
{
width
:
"24px"
,
height
:
"24px"
,
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
,
}
}
src=
"https://image.xiaomaiketang.com/xm/defaultCategory.png"
alt=
""
/>
)
:
(
<
img
style=
{
{
width
:
"24px"
,
height
:
"24px"
,
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
,
}
}
src=
"https://image.xiaomaiketang.com/xm/hasCategory.png"
alt=
""
/>
);
if
(
item
.
sonCategoryList
)
{
item
.
children
=
this
.
renderTreeNodes
(
item
.
sonCategoryList
,
value
);
}
return
item
;
});
return
newTreeData
;
};
// 树结构平铺
getTreeMap
=
(
data
,
map
)
=>
{
data
.
forEach
((
item
)
=>
{
map
[
item
.
id
]
=
item
;
if
(
item
.
sonCategoryList
&&
item
.
sonCategoryList
.
length
>
0
)
{
this
.
getTreeMap
(
item
.
sonCategoryList
,
map
);
}
});
return
map
;
};
// 新增或编辑分类
...
...
@@ -160,11 +297,10 @@ class CourseCategoryManage extends Component {
node=
{
node
}
addLevelType=
{
addLevelType
}
type=
{
type
}
treeData=
{
this
.
state
.
treeData
}
title=
{
title
}
label=
{
label
}
close=
{
()
=>
{
this
.
queryCategoryTree
(
"change"
);
this
.
queryCategoryTree
(
"change"
,
this
.
state
.
categoryName
);
this
.
setState
({
NewEditCourseCategoryModal
:
null
,
});
...
...
@@ -174,6 +310,35 @@ class CourseCategoryManage extends Component {
this
.
setState
({
NewEditCourseCategoryModal
:
m
});
};
// 删除分类
delCategory
=
(
item
)
=>
{
return
confirm
({
title
:
"确认删除该分类吗?"
,
content
:
"删除后,分类下的所有内容将自动转入“未分类”中。"
,
icon
:
(
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
),
okText
:
"删除"
,
okType
:
"danger"
,
cancelText
:
"取消"
,
onOk
:
()
=>
{
let
params
=
{
categoryId
:
item
.
id
,
source
:
0
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
};
QuestionBankService
.
delCategory
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"删除分类成功"
);
this
.
queryCategoryTree
(
"change"
,
this
.
state
.
categoryName
);
}
});
},
});
};
// 更多操作-【重命名 删除】
initDropMenu
=
(
item
)
=>
{
return
(
<
Menu
>
...
...
@@ -203,12 +368,14 @@ class CourseCategoryManage extends Component {
);
};
// 获取相关节点
getRelatedNodes
=
(
parentId
)
=>
{
return
this
.
state
.
treeMap
[
parentId
]
?
this
.
state
.
treeMap
[
parentId
].
sonCategoryList
:
[];
};
// 获取拖拽目标父节点层级
getParentDragNodesLevel
=
(
dragNode
)
=>
{
if
(
!
dragNode
)
{
return
[];
...
...
@@ -224,6 +391,7 @@ class CourseCategoryManage extends Component {
return
dragNodes
;
};
// 获取拖拽节点层级
getDragNodesLevel
=
(
dragNode
)
=>
{
let
dragNodes
=
[];
if
(
dragNode
.
sonCategoryList
&&
dragNode
.
sonCategoryList
.
length
>
0
)
{
...
...
@@ -237,6 +405,7 @@ class CourseCategoryManage extends Component {
return
[...
new
Set
(
dragNodes
)];
};
// 拖拽
onDrop
=
(
info
)
=>
{
if
(
this
.
state
.
categoryName
)
{
return
;
...
...
@@ -257,23 +426,30 @@ class CourseCategoryManage extends Component {
return
;
let
targetParentId
=
info
.
dropToGap
?
info
.
node
.
parentId
:
info
.
node
.
id
;
if
(
this
.
state
.
treeMap
[
targetParentId
].
categoryLevel
===
4
)
{
return
message
.
info
(
"最多支持5级分类"
);
}
else
{
let
nodesArr
=
this
.
getDragNodesLevel
(
this
.
state
.
treeMap
[
info
.
dragNode
.
id
]
);
let
parentArr
=
this
.
getParentDragNodesLevel
(
this
.
state
.
treeMap
[
targetParentId
]
);
if
(
nodesArr
.
length
+
parentArr
.
length
>
4
)
{
let
relatedNodes
=
this
.
getRelatedNodes
(
targetParentId
);
if
(
!
(
(
info
.
dropToGap
&&
info
.
node
.
parentId
===
info
.
dragNode
.
parentId
)
||
(
!
info
.
dropToGap
&&
info
.
node
.
id
===
info
.
dragNode
.
parentId
)
)
)
{
if
(
this
.
state
.
treeMap
[
targetParentId
].
categoryLevel
===
4
)
{
return
message
.
info
(
"最多支持5级分类"
);
}
else
{
let
nodesArr
=
this
.
getDragNodesLevel
(
this
.
state
.
treeMap
[
info
.
dragNode
.
id
]
);
let
parentArr
=
this
.
getParentDragNodesLevel
(
this
.
state
.
treeMap
[
targetParentId
]
);
if
(
nodesArr
.
length
+
parentArr
.
length
>
4
)
{
console
.
log
(
nodesArr
.
length
,
parentArr
.
length
);
return
message
.
info
(
"最多支持5级分类"
);
}
}
if
(
relatedNodes
&&
relatedNodes
.
length
>=
30
)
{
return
message
.
info
(
"最多只能添加30个分类"
);
}
}
let
relatedNodes
=
this
.
getRelatedNodes
(
targetParentId
);
if
(
relatedNodes
&&
relatedNodes
.
length
===
30
)
{
return
message
.
info
(
"最多只能添加30个子分类"
);
}
const
dropKey
=
info
.
node
.
key
;
const
dragKey
=
info
.
dragNode
.
key
;
...
...
@@ -389,186 +565,12 @@ class CourseCategoryManage extends Component {
return
data
;
};
/** 获取树状第一级key 设置默认展开第一项 */
getFirstLevelKeys
=
(
data
)
=>
{
let
firstLevelKeys
=
[];
data
.
forEach
((
item
)
=>
{
if
(
item
.
categoryLevel
===
0
)
{
firstLevelKeys
.
push
(
item
.
key
);
}
});
return
firstLevelKeys
;
};
/** 树状展开事件 */
// 树状展开事件
onExpand
=
(
expandedKeys
)
=>
{
this
.
setState
({
expandedKeys
});
};
renderTreeNodes
=
(
data
,
value
)
=>
{
let
newTreeData
=
data
.
map
((
item
)
=>
{
item
.
title
=
item
.
categoryName
;
item
.
key
=
item
.
id
;
item
.
title
=
(
<
div
style=
{
{
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
,
}
}
className=
"node-title-div"
onMouseOver=
{
(
e
)
=>
{
let
mouseNodeOpts
=
e
.
currentTarget
.
getElementsByTagName
(
"div"
)[
0
];
if
(
mouseNodeOpts
)
{
mouseNodeOpts
.
style
.
visibility
=
"visible"
;
}
}
}
onMouseOut=
{
(
e
)
=>
{
let
mouseNodeOpts
=
e
.
currentTarget
.
getElementsByTagName
(
"div"
)[
0
];
if
(
mouseNodeOpts
)
{
mouseNodeOpts
.
style
.
visibility
=
"hidden"
;
}
}
}
>
<
span
>
{
item
.
categoryName
}
</
span
>
{
item
.
categoryName
!==
"未分类"
&&
(
<
Space
className=
"title-opts"
size=
{
16
}
>
<
span
onClick=
{
()
=>
{
let
nodesCount
=
0
;
const
{
treeData
}
=
this
.
state
;
if
(
item
.
categoryLevel
===
0
)
{
// 第一层级
nodesCount
=
treeData
.
length
;
}
else
{
let
parentNodes
=
this
.
getRelatedNodes
(
item
.
parentId
);
if
(
parentNodes
.
length
>
0
&&
parentNodes
[
0
].
sonCategoryList
)
{
nodesCount
=
parentNodes
[
0
].
sonCategoryList
.
length
;
}
else
{
nodesCount
=
0
;
}
}
if
(
nodesCount
>=
30
)
{
message
.
info
(
"最多只能添加30个分类"
);
return
;
}
this
.
newEditCourseCategory
(
"newEqualLevelCategory"
,
"equal"
,
"new"
,
item
);
}
}
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#BFBFBF"
}
}
>

{
" "
}
</
span
>
<
span
>
同级
</
span
>
</
span
>
{
item
.
categoryLevel
<
4
&&
(
<
span
onClick=
{
()
=>
{
if
(
item
.
sonCategoryList
&&
item
.
sonCategoryList
.
length
>=
30
)
{
message
.
info
(
"最多只能添加30个子分类"
);
return
;
}
this
.
newEditCourseCategory
(
"newChildLevelCategory"
,
"child"
,
"new"
,
item
);
}
}
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#BFBFBF"
}
}
>

{
" "
}
</
span
>
<
span
>
子级
</
span
>
</
span
>
)
}
<
Dropdown
overlay=
{
this
.
initDropMenu
(
item
)
}
>
<
span
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#BFBFBF"
}
}
>

{
" "
}
</
span
>
<
span
>
更多
</
span
>
</
span
>
</
Dropdown
>
</
Space
>
)
}
</
div
>
);
item
.
icon
=
item
.
categoryName
===
"未分类"
?
(
<
img
style=
{
{
width
:
"24px"
,
height
:
"24px"
,
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
,
}
}
src=
"https://image.xiaomaiketang.com/xm/defaultCategory.png"
alt=
""
/>
)
:
(
<
img
style=
{
{
width
:
"24px"
,
height
:
"24px"
,
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
,
}
}
src=
"https://image.xiaomaiketang.com/xm/hasCategory.png"
alt=
""
/>
);
if
(
item
.
sonCategoryList
)
{
item
.
children
=
this
.
renderTreeNodes
(
item
.
sonCategoryList
,
value
);
}
return
item
;
});
let
map
=
{};
let
topItem
=
[];
data
.
forEach
((
item
)
=>
{
topItem
.
push
(
item
);
});
this
.
setState
({
treeMap
:
Object
.
assign
(
this
.
getTreeMap
(
data
,
map
),
{
0
:
{
sonCategoryList
:
topItem
,
},
}),
});
return
newTreeData
;
};
getTreeMap
=
(
data
,
map
)
=>
{
data
.
forEach
((
item
)
=>
{
map
[
item
.
id
]
=
item
;
if
(
item
.
sonCategoryList
&&
item
.
sonCategoryList
.
length
>
0
)
{
this
.
getTreeMap
(
item
.
sonCategoryList
,
map
);
}
});
return
map
;
};
/** 树状选中事件 */
// 树状选中事件
onSelect
=
(
selectedKeys
)
=>
{
this
.
setState
({
selectedKeys
});
};
...
...
@@ -576,9 +578,11 @@ class CourseCategoryManage extends Component {
render
()
{
const
{
treeData
,
originTreeData
,
expandedKeys
,
selectedKeys
,
autoExpandParent
,
NewEditCourseCategoryModal
,
}
=
this
.
state
;
return
(
<
div
className=
"page course-category-manage"
>
...
...
@@ -608,7 +612,7 @@ class CourseCategoryManage extends Component {
<
Button
type=
"primary"
onClick=
{
()
=>
{
if
(
treeData
.
length
>=
30
)
{
if
(
originTreeData
.
length
>=
29
)
{
message
.
info
(
"最多只能添加30个分类"
);
return
;
}
...
...
@@ -641,7 +645,7 @@ class CourseCategoryManage extends Component {
></
DirectoryTree
>
</
div
>
</
div
>
{
this
.
state
.
NewEditCourseCategoryModal
}
{
NewEditCourseCategoryModal
}
</
div
>
);
}
...
...
src/modules/teach-tool/components/CourseCategoryManage.less
View file @
f48a2dd4
/*
* @Author: yuananting
* @Date: 2021-02-23 19:41:42
* @LastEditors: yuananting
* @LastEditTime: 2021-03-27 13:49:00
* @Description: 助学工具-题库-课程分类管理样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.course-category-manage {
.course-category-manage {
position: relative;
.search-condition {
width: 30%;
...
...
@@ -22,7 +14,7 @@
position: relative;
margin-top: 16px;
width: 900px;
border: 1px solid #
E8E8E
8;
border: 1px solid #
e8e8e
8;
.ant-tree.ant-tree-directory {
font-size: 14px;
font-weight: 400;
...
...
@@ -75,6 +67,6 @@
}
.ant-tree.ant-tree-directory .ant-tree-treenode:hover::before {
background-color: #
F3F6FA
;
background-color: #
f3f6fa
;
}
}
src/modules/teach-tool/components/CourseCategorySiderTree.jsx
View file @
f48a2dd4
...
...
@@ -2,8 +2,8 @@
* @Author: yuananting
* @Date: 2021-02-22 10:59:43
* @LastEditors: yuananting
* @LastEditTime: 2021-03-2
7 13:51:4
3
* @Description: 助学工具-
题库-
课程分类侧边栏
* @LastEditTime: 2021-03-2
9 16:17:5
3
* @Description: 助学工具-课程分类侧边栏
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
...
...
@@ -18,14 +18,8 @@ const { DirectoryTree } = Tree;
class
CourseCategorySiderTree
extends
Component
{
constructor
(
props
)
{
super
(
props
);
const
categoryId
=
getParameterByName
(
"categoryId"
);
this
.
state
=
{
selectedKeys
:
categoryId
?
categoryId
===
"null"
?
[
"0"
]
:
[
categoryId
]
:
[
"0"
],
searchValue
:
null
,
selectedKeys
:
[
getParameterByName
(
"categoryId"
)
||
"null"
],
treeData
:
this
.
props
.
treeData
||
[],
autoExpandParent
:
false
,
};
...
...
@@ -33,11 +27,9 @@ class CourseCategorySiderTree extends Component {
componentDidMount
()
{
this
.
queryCategoryTree
(
"change"
);
this
.
props
.
getSelectedCategoryId
(
getParameterByName
(
"categoryId"
)
?
[
getParameterByName
(
"categoryId"
)]
:
[
"0"
]
);
this
.
props
.
getSelectedCategoryId
([
getParameterByName
(
"categoryId"
)
||
"null"
,
]);
}
shouldComponentUpdate
(
nextProps
,
nextState
)
{
...
...
@@ -51,28 +43,6 @@ class CourseCategorySiderTree extends Component {
return
true
;
}
/** 获取树状第一级key 设置默认展开第一项 */
getFirstLevelKeys
=
(
data
)
=>
{
let
firstLevelKeys
=
[];
data
.
forEach
((
item
)
=>
{
if
(
item
.
categoryLevel
===
0
)
{
firstLevelKeys
.
push
(
item
.
key
);
}
});
return
firstLevelKeys
;
};
/** 树状展开事件 */
onExpand
=
(
expandedKeys
)
=>
{
this
.
setState
({
expandedKeys
});
};
/** 树状选中事件 */
onSelect
=
(
selectedKeys
)
=>
{
this
.
setState
({
selectedKeys
});
this
.
props
.
getSelectedCategoryId
(
selectedKeys
);
};
// 查询分类树
queryCategoryTree
=
(
type
,
categoryName
)
=>
{
let
query
=
{
...
...
@@ -99,7 +69,7 @@ class CourseCategorySiderTree extends Component {
}
}
else
{
const
defaultNode
=
{
id
:
"
0
"
,
id
:
"
null
"
,
categoryName
:
"未分类"
,
categoryCount
:
noCategoryCnt
,
parentId
:
"0"
,
...
...
@@ -120,7 +90,7 @@ class CourseCategorySiderTree extends Component {
}
else
{
this
.
setState
({
autoExpandParent
:
false
});
const
defaultNode
=
{
id
:
"
0
"
,
id
:
"
null
"
,
categoryName
:
"未分类"
,
categoryCount
:
noCategoryCnt
,
parentId
:
"0"
,
...
...
@@ -137,6 +107,7 @@ class CourseCategorySiderTree extends Component {
});
};
// 树结构平铺
getTreeMap
=
(
data
,
map
)
=>
{
data
.
forEach
((
item
)
=>
{
map
[
item
.
id
]
=
item
;
...
...
@@ -147,6 +118,18 @@ class CourseCategorySiderTree extends Component {
return
map
;
};
// 树状展开事件
onExpand
=
(
expandedKeys
)
=>
{
this
.
setState
({
expandedKeys
});
};
// 树状选中事件
onSelect
=
(
selectedKeys
)
=>
{
this
.
setState
({
selectedKeys
});
this
.
props
.
getSelectedCategoryId
(
selectedKeys
);
};
// 树节点渲染-内容处理
renderTreeNodes
=
(
data
,
value
)
=>
{
let
newTreeData
=
data
.
map
((
item
)
=>
{
item
.
title
=
item
.
categoryName
;
...
...
@@ -164,13 +147,27 @@ class CourseCategorySiderTree extends Component {
item
.
icon
=
item
.
categoryName
===
"未分类"
?
(
<
img
style=
{
{
width
:
"24px"
,
height
:
"24px"
,
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
}
}
style=
{
{
width
:
"24px"
,
height
:
"24px"
,
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
,
}
}
src=
"https://image.xiaomaiketang.com/xm/defaultCategory.png"
alt=
""
/>
)
:
(
<
img
style=
{
{
width
:
"24px"
,
height
:
"24px"
,
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
}
}
style=
{
{
width
:
"24px"
,
height
:
"24px"
,
opacity
:
!
value
||
(
value
&&
item
.
categoryName
.
indexOf
(
value
)
>
-
1
)
?
1
:
0.5
,
}
}
src=
"https://image.xiaomaiketang.com/xm/hasCategory.png"
alt=
""
/>
...
...
src/modules/teach-tool/components/CourseCategorySiderTree.less
View file @
f48a2dd4
/*
* @Author: yuananting
* @Date: 2021-02-22 12:02:34
* @LastEditors: yuananting
* @LastEditTime: 2021-03-27 13:52:19
* @Description: 助学工具-题库-课程分类侧边栏样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.category-tree-sider {
.category-tree-sider {
position: relative;
.sider-title {
height: 22px;
...
...
@@ -68,6 +60,6 @@
}
.ant-tree.ant-tree-directory .ant-tree-treenode:hover::before {
background-color: #
F3F6FA
;
background-color: #
f3f6fa
;
}
}
src/modules/teach-tool/examination-paper/NewExaminationPaper.jsx
View file @
f48a2dd4
...
...
@@ -2,18 +2,29 @@
* @Author: yuananting
* @Date: 2021-03-27 16:15:13
* @LastEditors: yuananting
* @LastEditTime: 2021-03-2
7 18:19:13
* @LastEditTime: 2021-03-2
9 10:54:49
* @Description: 助学工具-新建试卷
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
import
{
Form
,
Button
,
Select
,
Input
,
Space
,
Table
}
from
"antd"
;
import
{
Form
,
Button
,
Select
,
Input
,
Space
,
Table
,
InputNumber
,
ConfigProvider
,
Empty
,
}
from
"antd"
;
import
{
PlusOutlined
}
from
"@ant-design/icons"
;
import
ShowTips
from
"@/components/ShowTips"
;
import
Breadcrumbs
from
"@/components/Breadcrumbs"
;
import
{
PageControl
}
from
"@/components"
;
import
"./NewExaminationPaper.less"
;
import
SelectQuestionModal
from
"./modal/SelectQuestionModal"
;
const
{
TextArea
}
=
Input
;
const
formItemLayout
=
{
labelCol
:
{
xs
:
{
span
:
24
},
...
...
@@ -25,6 +36,42 @@ const formItemLayout = {
},
};
class
NewExaminationPaper
extends
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
current
:
1
,
size
:
10
,
total
:
20
,
};
}
// 自定义表格空状态
customizeRenderEmpty
=
()
=>
{
return
(
<
Empty
image=
"https://image.xiaomaiketang.com/xm/emptyTable.png"
imageStyle=
{
{
height
:
100
,
}
}
description=
{
"请在右上角选择出题方式添加题"
}
></
Empty
>
);
};
// 选择题目
chooseQuestion
=
()
=>
{
const
m
=
(
<
SelectQuestionModal
close=
{
()
=>
{
this
.
setState
({
SelectQuestionModal
:
null
,
});
}
}
/>
);
this
.
setState
({
SelectQuestionModal
:
m
});
}
render
()
{
const
columns
=
[
{
...
...
@@ -36,12 +83,24 @@ class NewExaminationPaper extends Component {
dataIndex
:
"questionType"
,
filters
:
[
{
text
:
"
London
"
,
value
:
"
London
"
,
text
:
"
单选题
"
,
value
:
"
SINGLE_CHOICE
"
,
},
{
text
:
"New York"
,
value
:
"New York"
,
text
:
"多选题"
,
value
:
"MULTI_CHOICE"
,
},
{
text
:
"判断题"
,
value
:
"JUDGE"
,
},
{
text
:
"填空题"
,
value
:
"GAP_FILLING"
,
},
{
text
:
"不定项选择题"
,
value
:
"INDEFINITE_CHOICE"
,
},
],
filterMultiple
:
false
,
...
...
@@ -50,37 +109,35 @@ class NewExaminationPaper extends Component {
{
title
:
"题目"
,
dataIndex
:
"questionContent"
,
},
];
const
data
=
[
{
key
:
"1"
,
name
:
"John Brown"
,
age
:
32
,
address
:
"New York No. 1 Lake Park"
,
},
{
key
:
"2"
,
name
:
"Jim Green"
,
age
:
42
,
address
:
"London No. 1 Lake Park"
,
title
:
"分值"
,
dataIndex
:
"score"
,
render
:
(
val
)
=>
{
return
<
InputNumber
min=
{
1
}
max=
{
100
}
defaultValue=
{
2
}
/>;
},
},
{
key
:
"3"
,
name
:
"Joe Black"
,
age
:
32
,
address
:
"Sidney No. 1 Lake Park"
,
dataIndex
:
"extraScore"
,
render
:
(
val
)
=>
{
return
(
<
div
>
漏选得
<
InputNumber
defaultValue=
{
0
}
/>
</
div
>
);
},
},
{
key
:
"4"
,
name
:
"Jim Red"
,
age
:
32
,
address
:
"London No. 2 Lake Park"
,
title
:
"操作"
,
dataIndex
:
"operate"
,
render
:
(
val
,
record
)
=>
<
span
>
移除
</
span
>,
},
];
const
data
=
[];
const
{
current
,
size
,
total
,
SelectQuestionModal
}
=
this
.
state
;
return
(
<
div
className=
"page new-examination-paper"
>
<
Breadcrumbs
navList=
{
"新建试卷"
}
goBack=
{
()
=>
this
.
handleGoBack
()
}
/>
...
...
@@ -105,13 +162,42 @@ class NewExaminationPaper extends Component {
>
<
h1
style=
{
{
fontSize
:
16
}
}
>
题目管理
</
h1
>
<
Space
>
<
Button
icon=
{
<
PlusOutlined
/>
}
>
自选题目
</
Button
>
<
Button
icon=
{
<
PlusOutlined
/>
}
onClick=
{
this
.
chooseQuestion
}
>
自选题目
</
Button
>
<
Button
icon=
{
<
PlusOutlined
/>
}
>
系统抽题
</
Button
>
<
Button
icon=
{
<
PlusOutlined
/>
}
>
一人一卷
</
Button
>
</
Space
>
</
div
>
<
Form
.
Item
>
<
Table
columns=
{
columns
}
dataSource=
{
data
}
/>
<
div
>
总计40分,共20题。
单选题5题,共10分;多选题2题,共4分;判断题3题,共6分,填空题5题,共10分,不定项选择题5题,共10分
</
div
>
<
ConfigProvider
renderEmpty=
{
this
.
customizeRenderEmpty
}
>
<
Table
columns=
{
columns
}
dataSource=
{
data
}
pagination=
{
false
}
/>
</
ConfigProvider
>
<
div
className=
"box-footer"
>
<
PageControl
current=
{
current
-
1
}
pageSize=
{
size
}
total=
{
total
}
toPage=
{
(
page
)
=>
{
const
_query
=
{
...
query
,
current
:
page
+
1
};
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
()
);
}
}
showSizeChanger=
{
true
}
onShowSizeChange=
{
this
.
onShowSizeChange
}
/>
</
div
>
</
Form
.
Item
>
<
Form
.
Item
label=
"及格线:"
>
<
div
>
<
InputNumber
min=
{
1
}
defaultValue=
{
60
}
/>
%
<
span
style=
{
{
marginLeft
:
20
}
}
>
总分(0)*及格线(60%)=及格分数(0)
</
span
>
</
div
>
</
Form
.
Item
>
</
Form
>
</
div
>
...
...
@@ -120,6 +206,7 @@ class NewExaminationPaper extends Component {
<
Button
>
预览
</
Button
>
<
Button
type=
"primary"
>
保存
</
Button
>
</
div
>
{
SelectQuestionModal
}
</
div
>
);
}
...
...
src/modules/teach-tool/examination-paper/components/ExaminationPaperContent.jsx
View file @
f48a2dd4
...
...
@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-02-25 11:23:47
* @LastEditors: yuananting
* @LastEditTime: 2021-03-2
7 16:54:25
* @LastEditTime: 2021-03-2
9 13:57:20
* @Description: 助学工具-题库-题目管理主页面列表数据
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -335,8 +335,6 @@ class ExaminationPaperContent extends Component {
/>
</
div
>
)
}
{
/* {this.state.QuestionPreviewModal} */
}
{
/* {this.state.ImportQuestionModal} */
}
</
div
>
</
div
>
);
...
...
src/modules/teach-tool/examination-paper/components/SelectQuestionContent.jsx
0 → 100644
View file @
f48a2dd4
/*
* @Author: yuananting
* @Date: 2021-02-25 11:23:47
* @LastEditors: yuananting
* @LastEditTime: 2021-03-29 14:23:42
* @Description: 助学工具-新建试卷-选择题目列表
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
import
{
Table
,
ConfigProvider
,
Empty
,
Row
,
Input
,
Select
,
Tooltip
,
Space
,
Button
,
Modal
,
message
,
}
from
"antd"
;
import
{
PageControl
}
from
"@/components"
;
import
"./SelectQuestionContent.less"
;
import
User
from
"@/common/js/user"
;
import
QuestionBankService
from
"@/domains/question-bank-domain/QuestionBankService"
;
import
_
from
"underscore"
;
import
ShowTips
from
"@/components/ShowTips"
;
const
{
Search
}
=
Input
;
const
questionTypeEnum
=
{
SINGLE_CHOICE
:
"单选题"
,
MULTI_CHOICE
:
"多选题"
,
JUDGE
:
"判断题"
,
GAP_FILLING
:
"填空题"
,
INDEFINITE_CHOICE
:
"不定项选择题"
,
};
const
questionTypeList
=
[
{
label
:
"单选题"
,
value
:
"SINGLE_CHOICE"
,
},
{
label
:
"多选题"
,
value
:
"MULTI_CHOICE"
,
},
{
label
:
"判断题"
,
value
:
"JUDGE"
,
},
{
label
:
"填空题"
,
value
:
"GAP_FILLING"
,
},
{
label
:
"不定项选择题"
,
value
:
"INDEFINITE_CHOICE"
,
},
];
class
QuestionListContent
extends
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
query
:
{
current
:
1
,
size
:
10
,
order
:
"UPDATED_DESC"
,
// 排序规则[ ACCURACY_DESC, ACCURACY_ASC, CREATED_DESC, CREATED_ASC, UPDATED_DESC, UPDATED_ASC ]
categoryId
:
null
,
// 当前题库分类Id
questionName
:
null
,
// 题目名称
questionType
:
null
,
// 题目类型
source
:
0
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
},
questionTypeList
:
[],
// 题型列表
dataSource
:
[],
totalCount
:
0
,
selectedRowKeys
:
[],
};
}
componentDidMount
()
{}
shouldComponentUpdate
(
nextProps
,
nextState
)
{
let
{
selectedCategoryId
}
=
nextProps
;
const
_query
=
this
.
state
.
query
;
if
(
this
.
props
.
selectedCategoryId
!==
selectedCategoryId
)
{
if
(
selectedCategoryId
===
"null"
)
{
selectedCategoryId
=
null
;
}
_query
.
categoryId
=
selectedCategoryId
;
_query
.
questionName
=
null
;
_query
.
questionType
=
null
;
_query
.
current
=
1
;
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
());
}
return
true
;
}
queryQuestionPageList
=
(
remain
)
=>
{
const
_query
=
this
.
state
.
query
;
if
(
_query
.
categoryId
===
"0"
)
_query
.
categoryId
=
null
;
QuestionBankService
.
queryQuestionPageList
(
_query
).
then
((
res
)
=>
{
const
{
records
=
[],
total
=
0
}
=
res
.
result
;
this
.
setState
({
dataSource
:
records
});
this
.
setState
({
total
},
()
=>
this
.
props
.
updatedSiderTree
(
total
,
this
.
props
.
selectedCategoryId
)
);
});
};
handleCreateQuestionBank
=
()
=>
{
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?categoryId=
${
this
.
state
.
query
.
categoryId
}
`
,
});
};
delQuestionConfirm
(
record
)
{
return
Modal
.
confirm
({
title
:
"提示"
,
content
:
"确定要删除此题目吗?"
,
icon
:
(
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
),
okText
:
"删除"
,
cancelText
:
"取消"
,
onOk
:
()
=>
{
this
.
deleteQuestion
(
record
);
},
});
}
deleteQuestion
=
(
record
)
=>
{
let
params
=
{
id
:
record
.
id
,
source
:
0
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
};
QuestionBankService
.
deleteQuestion
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"删除成功"
);
const
{
query
,
total
}
=
this
.
state
;
const
{
size
,
current
}
=
query
;
const
_query
=
query
;
if
(
total
/
size
<
current
)
{
if
(
total
%
size
===
1
)
{
_query
.
current
=
1
;
}
}
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
());
}
});
};
// 排序
handleChangeTable
=
(
pagination
,
filters
,
sorter
)
=>
{
const
{
columnKey
,
order
}
=
sorter
;
let
sort
=
null
;
if
(
columnKey
===
"accuracy"
&&
order
===
"ascend"
)
{
sort
=
"ACCURACY_ASC"
;
}
if
(
columnKey
===
"accuracy"
&&
order
===
"descend"
)
{
sort
=
"ACCURACY_DESC"
;
}
if
(
columnKey
===
"updateTime"
&&
order
===
"ascend"
)
{
sort
=
"UPDATED_ASC"
;
}
if
(
columnKey
===
"updateTime"
&&
order
===
"descend"
)
{
sort
=
"UPDATED_DESC"
;
}
const
_query
=
this
.
state
.
query
;
_query
.
order
=
sort
||
"UPDATED_DESC"
;
_query
.
current
=
1
;
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
());
};
// 清空搜索条件
handleReset
=
()
=>
{
const
_query
=
{
...
this
.
state
.
query
,
current
:
1
,
order
:
"ACCURACY_DESC"
,
// 排序规则
questionName
:
null
,
// 题目名称
questionType
:
null
,
// 题目类型
};
this
.
setState
({
query
:
_query
},
()
=>
{
this
.
queryQuestionPageList
();
});
};
toEditQuestion
=
(
id
,
type
)
=>
{
const
{
categoryId
}
=
this
.
state
.
query
;
if
(
categoryId
)
{
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?id=
${
id
}
&type=
${
type
}
&categoryId=
${
categoryId
}
`
,
});
}
else
{
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?id=
${
id
}
&type=
${
type
}
`
,
});
}
};
// 表头设置
parseColumns
=
()
=>
{
const
isPermiss
=
[
"CloudManager"
,
"StoreManager"
].
includes
(
User
.
getUserRole
()
);
const
columns
=
[
{
title
:
"题目"
,
key
:
"questionStem"
,
dataIndex
:
"questionStem"
,
ellipsis
:
{
showTitle
:
false
,
},
render
:
(
val
,
record
)
=>
{
var
handleVal
=
val
;
handleVal
=
handleVal
.
replace
(
/<
(?!
img|input
)
.*
?
>/g
,
""
);
handleVal
=
handleVal
.
replace
(
/<
\s?
input
[^
>
]
*>/gi
,
"_、"
);
handleVal
=
handleVal
.
replace
(
/<
\s?
img
[^
>
]
*>/gi
,
"【图片】"
);
handleVal
=
handleVal
.
replace
(
/
\&
nbsp
\;
/gi
,
" "
);
return
(
<
Tooltip
overlayClassName=
"tool-list"
title=
{
<
div
style=
{
{
maxWidth
:
700
,
width
:
"auto"
}
}
>
{
handleVal
}
</
div
>
}
placement=
"topLeft"
overlayStyle=
{
{
maxWidth
:
700
}
}
>
{
handleVal
}
</
Tooltip
>
);
},
},
{
title
:
"题型"
,
key
:
"questionTypeEnum"
,
dataIndex
:
"questionTypeEnum"
,
render
:
(
val
)
=>
{
return
questionTypeEnum
[
val
];
},
},
{
title
:
"正确率"
,
key
:
"accuracy"
,
dataIndex
:
"accuracy"
,
sorter
:
true
,
showSorterTooltip
:
false
,
render
:
(
val
)
=>
{
return
val
+
"%"
;
},
},
];
return
columns
;
};
// 自定义表格空状态
customizeRenderEmpty
=
()
=>
{
const
{
categoryId
}
=
this
.
state
.
query
;
return
(
<
Empty
image=
"https://image.xiaomaiketang.com/xm/emptyTable.png"
imageStyle=
{
{
height
:
100
,
}
}
description=
{
<
div
>
<
span
>
还没有题目
</
span
>
{
[
"CloudManager"
,
"StoreManager"
].
includes
(
User
.
getUserRole
())
&&
!
[
"0"
,
null
].
includes
(
categoryId
)
&&
(
<
span
>
,快去
<
span
className=
"empty-list-tip"
onClick=
{
()
=>
{
this
.
handleCreateQuestionBank
();
}
}
>
新建一个
</
span
>
吧!
</
span
>
)
}
</
div
>
}
></
Empty
>
);
};
onShowSizeChange
=
(
current
,
size
)
=>
{
if
(
current
==
size
)
{
return
;
}
let
_query
=
this
.
state
.
query
;
_query
.
size
=
size
;
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
());
};
// 改变搜索条件
handleChangeQuery
=
(
searchType
,
value
)
=>
{
this
.
setState
(
{
query
:
{
...
this
.
state
.
query
,
[
searchType
]:
value
||
null
,
current
:
1
,
},
},
()
=>
{
if
(
searchType
===
"questionName"
)
return
;
this
.
queryQuestionPageList
();
}
);
};
render
()
{
const
{
dataSource
=
[],
total
,
query
,
selectedRowKeys
}
=
this
.
state
;
const
{
current
,
size
,
categoryId
,
questionName
,
questionType
}
=
query
;
const
rowSelection
=
{
selectedRowKeys
,
columnWidth
:
"48px"
,
};
return
(
<
div
className=
"select-question-content"
>
<
div
className=
"select-question-filter"
>
<
Row
type=
"flex"
justify=
"space-between"
align=
"top"
>
<
div
className=
"search-condition"
>
<
div
className=
"search-condition__item"
>
<
span
className=
"search-label"
>
题目:
</
span
>
<
Search
placeholder=
"搜索题目名称"
value=
{
questionName
}
style=
{
{
width
:
"calc(100% - 84px)"
}
}
onChange=
{
(
e
)
=>
{
this
.
handleChangeQuery
(
"questionName"
,
e
.
target
.
value
);
}
}
onSearch=
{
()
=>
{
this
.
queryQuestionPageList
();
}
}
enterButton=
{
<
span
className=
"icon iconfont"
>

</
span
>
}
/>
</
div
>
<
div
className=
"search-condition__item"
>
<
span
className=
"search-label"
>
题型:
</
span
>
<
Select
placeholder=
"请选择题目类型"
value=
{
questionType
}
style=
{
{
width
:
"calc(100% - 70px)"
}
}
showSearch
allowClear
enterButton=
{
<
span
className=
"icon iconfont"
>

</
span
>
}
filterOption=
{
(
inputVal
,
option
)
=>
option
.
props
.
children
.
includes
(
inputVal
)
}
onChange=
{
(
value
)
=>
{
if
(
_
.
isEmpty
(
value
))
{
this
.
handleChangeQuery
(
"questionType"
,
value
);
}
}
}
onSelect=
{
(
value
)
=>
{
this
.
handleChangeQuery
(
"questionType"
,
value
);
}
}
>
{
_
.
map
(
questionTypeList
,
(
item
,
index
)
=>
{
return
(
<
Select
.
Option
value=
{
item
.
value
}
key=
{
item
.
key
}
>
{
item
.
label
}
</
Select
.
Option
>
);
})
}
</
Select
>
</
div
>
</
div
>
<
div
className=
"reset-fold-area"
>
<
Tooltip
title=
"清空筛选"
>
<
span
className=
"resetBtn iconfont icon"
onClick=
{
this
.
handleReset
}
>

{
" "
}
</
span
>
</
Tooltip
>
</
div
>
</
Row
>
</
div
>
<
ShowTips
message=
{
<
div
>
<
span
>
已选
{
200
}
题(单选题
{
1
}
题、多选题
{
2
}
题、判断题
{
3
}
题、填空题
{
4
}
题、不定项选择题
{
5
}
题)
</
span
>
<
span
style=
{
{
marginLeft
:
20
}
}
>
清空
</
span
>
</
div
>
}
/>
<
div
className=
"question-manage-list"
>
<
ConfigProvider
renderEmpty=
{
this
.
customizeRenderEmpty
}
>
<
Table
rowSelection=
{
rowSelection
}
rowKey=
{
(
record
)
=>
record
.
id
}
dataSource=
{
dataSource
}
columns=
{
this
.
parseColumns
()
}
pagination=
{
false
}
bordered
onChange=
{
this
.
handleChangeTable
}
/>
</
ConfigProvider
>
<
div
className=
"box-footer"
>
<
PageControl
current=
{
current
-
1
}
pageSize=
{
size
}
total=
{
total
}
toPage=
{
(
page
)
=>
{
const
_query
=
{
...
query
,
current
:
page
+
1
};
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
()
);
}
}
showSizeChanger=
{
true
}
onShowSizeChange=
{
this
.
onShowSizeChange
}
/>
</
div
>
</
div
>
</
div
>
);
}
}
export
default
QuestionListContent
;
src/modules/teach-tool/examination-paper/components/SelectQuestionContent.less
0 → 100644
View file @
f48a2dd4
/*
* @Author: yuananting
* @Date: 2021-02-25 11:26:28
* @LastEditors: yuananting
* @LastEditTime: 2021-03-29 13:39:28
* @Description: 助学工具-题库-题目管理右侧内容样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.select-question-content {
.select-question-filter {
position: relative;
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
width: 30%;
margin-right: 3%;
margin-bottom: 16px;
.search-label {
vertical-align: middle;
display: inline-block;
height: 32px;
line-height: 32px;
}
}
}
.reset-fold-area {
position: absolute;
right: 12px;
.resetBtn {
color: #999999;
font-size: 18px;
margin-right: 8px;
}
.fold-btn {
font-size: 14px;
color: #666666;
line-height: 20px;
.fold-icon {
font-size: 12px;
margin-left: 4px;
}
}
}
}
.data-icon {
cursor: pointer;
}
.question-manage-list {
position: relative;
margin-top: 16px;
.empty-list-tip {
color: #ffb714;
cursor: pointer;
}
.record-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.record-operate {
display: flex;
&__item {
color: #5289fa;
cursor: pointer;
&.split {
margin: 0 8px;
color: #bfbfbf;
}
}
}
}
}
.tool-list {
.ant-tooltip-inner {
max-width: 700px !important;
}
}
src/modules/teach-tool/examination-paper/modal/SelectQuestionModal.jsx
0 → 100644
View file @
f48a2dd4
/*
* @Author: yuananting
* @Date: 2021-03-29 10:52:26
* @LastEditors: yuananting
* @LastEditTime: 2021-03-29 14:09:08
* @Description: 助学工具-新建试卷-选择题目弹窗
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
import
{
Modal
}
from
"antd"
;
import
CourseCategorySiderTree
from
"../../components/CourseCategorySiderTree"
;
import
SelectQuestionContent
from
"../components/SelectQuestionContent"
;
import
"./SelectQuestionModal.less"
class
SelectQuestionModal
extends
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
updatedCategoryId
:
null
,
selectedCategoryId
:
null
,
};
}
getCategoryIdFromSider
=
(
selectedCategoryId
)
=>
{
if
(
selectedCategoryId
&&
selectedCategoryId
.
length
>
0
)
{
this
.
setState
({
selectedCategoryId
:
selectedCategoryId
[
0
]
});
}
};
updatedSiderTreeFromList
=
(
updatedCategoryId
)
=>
{
this
.
setState
({
updatedCategoryId
});
};
render
()
{
const
{
updatedCategoryId
,
selectedCategoryId
}
=
this
.
state
;
return
(
<
Modal
title=
"选择题目"
visible=
{
true
}
width=
{
1200
}
// onOk={handleOk}
onCancel=
{
this
.
props
.
close
}
className=
"select-question-modal"
>
<
div
className=
"box content-body"
>
<
div
style=
{
{
borderRight
:
"0.5px solid #EEEEEE"
,
paddingRight
:
"4px"
}
}
>
<
div
className=
"sider"
>
<
CourseCategorySiderTree
getSelectedCategoryId=
{
this
.
getCategoryIdFromSider
.
bind
(
this
)
}
updatedCategoryId
/>
</
div
>
</
div
>
<
div
className=
"content"
>
<
SelectQuestionContent
updatedSiderTree=
{
this
.
updatedSiderTreeFromList
.
bind
(
this
)
}
selectedCategoryId
/>
</
div
>
</
div
>
</
Modal
>
);
}
}
export
default
SelectQuestionModal
;
src/modules/teach-tool/examination-paper/modal/SelectQuestionModal.less
0 → 100644
View file @
f48a2dd4
.select-question-modal {
.content-body {
display: flex;
.site-layout-background {
background: #fff;
}
.sider {
min-width: 244px;
}
.content {
width: 100%;
margin-left: 24px;
height: calc(100vh - 160px);
}
}
}
\ No newline at end of file
src/modules/teach-tool/modal/NewEditCourseCategoryModal.jsx
View file @
f48a2dd4
...
...
@@ -2,12 +2,12 @@
* @Author: yuananting
* @Date: 2021-02-22 17:51:28
* @LastEditors: yuananting
* @LastEditTime: 2021-03-2
7 14:08:47
* @Description: 助学工具-
题库-
新建编辑课程分类模态框
* @LastEditTime: 2021-03-2
9 19:37:03
* @Description: 助学工具-新建编辑课程分类模态框
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
import
{
Modal
,
Form
,
Input
,
message
}
from
"antd"
;
import
{
Modal
,
Form
,
Input
}
from
"antd"
;
import
User
from
"@/common/js/user"
;
import
QuestionBankService
from
"@/domains/question-bank-domain/QuestionBankService"
;
class
NewEditCourseCategoryModal
extends
Component
{
...
...
@@ -51,7 +51,7 @@ class NewEditCourseCategoryModal extends Component {
//新增
params
.
categoryName
=
categoryName
;
if
(
addLevelType
===
"equal"
)
{
params
.
parentId
=
node
?
node
.
parentId
:
0
params
.
parentId
=
node
?
node
.
parentId
:
0
;
params
.
categoryLevel
=
node
?
node
.
categoryLevel
:
0
;
}
else
{
params
.
parentId
=
node
.
id
;
...
...
@@ -86,29 +86,51 @@ class NewEditCourseCategoryModal extends Component {
}
};
// 校验是否重名
checkExist
=
(
sameLevelNodes
,
categoryName
)
=>
{
if
(
sameLevelNodes
.
length
>
0
&&
sameLevelNodes
[
0
].
parentId
===
"0"
)
{
if
(
categoryName
===
"未分类"
)
{
return
true
;
}
}
var
result
=
null
;
sameLevelNodes
.
forEach
((
item
)
=>
{
if
(
result
!=
null
)
{
return
result
;
}
if
(
item
.
categoryName
===
categoryName
)
{
result
=
item
;
}
});
return
result
;
};
// 查询同级节点
getEqualLevelNodes
=
(
data
,
parentId
)
=>
{
let
nodes
=
[];
data
.
forEach
((
item
)
=>
{
if
(
item
.
parentId
===
parentId
)
{
nodes
.
push
(
item
);
}
if
(
item
.
children
)
{
nodes
.
push
(...
this
.
getEqualLevelNodes
(
item
.
children
,
parentId
));
if
(
item
.
sonCategoryList
)
{
nodes
.
push
(...
this
.
getEqualLevelNodes
(
item
.
sonCategoryList
,
parentId
));
}
});
return
nodes
;
};
// 查询子级节点
getChildLevelNodes
=
(
data
,
id
)
=>
{
let
nodes
=
[];
data
.
forEach
((
item
)
=>
{
if
(
item
.
id
===
id
&&
item
.
children
)
{
nodes
.
push
(...
item
.
children
);
if
(
item
.
id
===
id
&&
item
.
sonCategoryList
)
{
nodes
.
push
(...
item
.
sonCategoryList
);
}
if
(
item
.
children
)
{
nodes
.
push
(...
this
.
getChildLevelNodes
(
item
.
children
,
id
));
if
(
item
.
sonCategoryList
)
{
nodes
.
push
(...
this
.
getChildLevelNodes
(
item
.
sonCategoryList
,
id
));
}
});
console
.
log
(
nodes
)
return
nodes
;
};
...
...
@@ -123,28 +145,9 @@ class NewEditCourseCategoryModal extends Component {
return
sameLevelNodes
;
};
// 查询是否重名
checkExist
=
(
sameLevelNodes
,
categoryName
)
=>
{
if
((
sameLevelNodes
.
length
>
0
&&
sameLevelNodes
[
0
].
parentId
===
"0"
))
{
if
(
categoryName
===
"未分类"
)
{
return
true
;
}
}
var
result
=
null
;
sameLevelNodes
.
forEach
((
item
)
=>
{
if
(
result
!=
null
)
{
return
result
;
}
if
(
item
.
categoryName
===
categoryName
)
{
result
=
item
;
}
});
return
result
;
};
render
()
{
const
{
title
,
label
,
treeData
,
addLevelType
}
=
this
.
props
;
const
{
categoryName
}
=
this
.
state
;
const
{
title
,
label
,
addLevelType
}
=
this
.
props
;
const
{
categoryName
,
treeData
}
=
this
.
state
;
const
_that
=
this
;
return
(
<
Modal
...
...
@@ -182,7 +185,7 @@ class NewEditCourseCategoryModal extends Component {
defaultValue=
{
categoryName
}
placeholder=
{
`请输入${title},最多10个字`
}
maxLength=
{
10
}
autoComplete=
"off"
autoComplete=
"off"
onChange=
{
(
e
)
=>
{
this
.
setState
({
categoryName
:
e
.
target
.
value
,
...
...
src/modules/teach-tool/question-bank/AddNewQuestion.jsx
View file @
f48a2dd4
...
...
@@ -2,8 +2,8 @@
* @Author: yuananting
* @Date: 2021-02-25 13:46:35
* @LastEditors: yuananting
* @LastEditTime: 2021-03-2
7 14:42:23
* @Description: 助学工具-题库-
题目管理-新增
题目
* @LastEditTime: 2021-03-2
9 20:24:01
* @Description: 助学工具-题库-
新建
题目
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
...
...
@@ -59,6 +59,7 @@ class AddNewQuestion extends Component {
return
p
;
};
// 编辑题目时获取相应题目详情
queryQuestionDetails
=
()
=>
{
let
query
=
{
id
:
getParameterByName
(
"id"
),
...
...
@@ -104,6 +105,7 @@ class AddNewQuestion extends Component {
});
};
// 保存并继续添加时重新构建题目结构
handleRest
=
(
type
)
=>
{
this
.
setState
({
currentOperate
:
"add"
});
switch
(
type
)
{
...
...
@@ -147,6 +149,67 @@ class AddNewQuestion extends Component {
chooseOptions
.
push
(
defineJudgeOptionInfo
(
content
));
};
// 取消编辑并返回上一级路由
handleGoBack
=
()
=>
{
Modal
.
confirm
({
title
:
"确定要返回吗?"
,
content
:
"返回后,本次编辑的内容将不被保存"
,
okText
:
"确认返回"
,
cancelText
:
"留在本页"
,
icon
:
(
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
),
onOk
:
()
=>
{
window
.
RCHistory
.
push
({
pathname
:
`/question-bank-index?categoryId=
${
getParameterByName
(
"categoryId"
)}
`
,
});
},
});
};
// 校验保存题目
confirmSaveQuestion
=
(
next
)
=>
{
const
{
singleChoiceContent
,
multiChoiceContent
,
judgeContent
,
gapFillingContent
,
indefiniteChoiceContent
,
}
=
this
.
state
;
switch
(
this
.
state
.
activeKey
)
{
case
"SINGLE_CHOICE"
:
if
(
this
.
singleChoiceRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
singleChoiceContent
,
"SINGLE_CHOICE"
,
next
);
}
break
;
case
"MULTI_CHOICE"
:
if
(
this
.
multiChoiceRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
multiChoiceContent
,
"MULTI_CHOICE"
,
next
);
}
break
;
case
"JUDGE"
:
if
(
this
.
judgeRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
judgeContent
,
"JUDGE"
,
next
);
}
break
;
case
"GAP_FILLING"
:
if
(
this
.
gapRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
gapFillingContent
,
"GAP_FILLING"
,
next
);
}
break
;
case
"INDEFINITE_CHOICE"
:
if
(
this
.
indefiniteRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
indefiniteChoiceContent
,
"INDEFINITE_CHOICE"
,
next
);
}
break
;
}
};
// 确认保存题目
saveCurrentQuestion
=
(
content
,
type
,
next
)
=>
{
content
.
questionStemList
.
map
((
item
,
index
)
=>
{
item
.
sort
=
index
;
...
...
@@ -169,7 +232,7 @@ class AddNewQuestion extends Component {
params
=
{
...
content
,
id
:
getParameterByName
(
"id"
),
categoryId
:
categoryId
||
null
,
categoryId
:
categoryId
===
"null"
?
null
:
categoryId
,
source
:
0
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
...
...
@@ -183,7 +246,7 @@ class AddNewQuestion extends Component {
}
if
(
next
===
"close"
)
{
window
.
RCHistory
.
push
({
pathname
:
`/question-bank-index?categoryId=
${
params
.
categoryId
}
`
,
pathname
:
`/question-bank-index?categoryId=
${
categoryId
}
`
,
});
}
}
...
...
@@ -191,7 +254,7 @@ class AddNewQuestion extends Component {
}
else
{
params
=
{
...
content
,
categoryId
:
getParameterByName
(
"categoryId"
)
,
categoryId
,
source
:
0
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
...
...
@@ -204,7 +267,7 @@ class AddNewQuestion extends Component {
}
if
(
next
===
"close"
)
{
window
.
RCHistory
.
push
({
pathname
:
`/question-bank-index?categoryId=
${
params
.
categoryId
}
`
,
pathname
:
`/question-bank-index?categoryId=
${
categoryId
}
`
,
});
}
}
...
...
@@ -212,63 +275,6 @@ class AddNewQuestion extends Component {
}
};
// 取消编辑并返回上一级路由
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
,
judgeContent
,
gapFillingContent
,
indefiniteChoiceContent
,
}
=
this
.
state
;
switch
(
this
.
state
.
activeKey
)
{
case
"SINGLE_CHOICE"
:
if
(
this
.
singleChoiceRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
singleChoiceContent
,
"SINGLE_CHOICE"
,
next
);
}
break
;
case
"MULTI_CHOICE"
:
if
(
this
.
multiChoiceRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
multiChoiceContent
,
"MULTI_CHOICE"
,
next
);
}
break
;
case
"JUDGE"
:
if
(
this
.
judgeRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
judgeContent
,
"JUDGE"
,
next
);
}
break
;
case
"GAP_FILLING"
:
if
(
this
.
gapRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
gapFillingContent
,
"GAP_FILLING"
,
next
);
}
break
;
case
"INDEFINITE_CHOICE"
:
if
(
this
.
indefiniteRef
.
checkInput
()
===
0
)
{
this
.
saveCurrentQuestion
(
indefiniteChoiceContent
,
"INDEFINITE_CHOICE"
,
next
);
}
break
;
}
};
handleLogger
=
(
en
,
cn
)
=>
{
const
{
onLogger
}
=
this
.
props
;
onLogger
&&
onLogger
(
en
,
cn
);
...
...
@@ -308,7 +314,13 @@ class AddNewQuestion extends Component {
<
TabPane
tab=
{
<
span
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"SINGLE_CHOICE"
?
"#ffb714"
:
"#CCCCCC"
}
}
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"SINGLE_CHOICE"
?
"#ffb714"
:
"#CCCCCC"
,
}
}
>

{
" "
}
</
span
>
<
span
>
单选题
</
span
>
...
...
@@ -331,7 +343,13 @@ class AddNewQuestion extends Component {
<
TabPane
tab=
{
<
span
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"MULTI_CHOICE"
?
"#ffb714"
:
"#CCCCCC"
}
}
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"MULTI_CHOICE"
?
"#ffb714"
:
"#CCCCCC"
,
}
}
>

{
" "
}
</
span
>
<
span
>
多选题
</
span
>
...
...
@@ -354,7 +372,12 @@ class AddNewQuestion extends Component {
<
TabPane
tab=
{
<
span
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"JUDGE"
?
"#ffb714"
:
"#CCCCCC"
}
}
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"JUDGE"
?
"#ffb714"
:
"#CCCCCC"
,
}
}
>

{
" "
}
</
span
>
<
span
>
判断题
</
span
>
...
...
@@ -376,7 +399,13 @@ class AddNewQuestion extends Component {
<
TabPane
tab=
{
<
span
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"GAP_FILLING"
?
"#ffb714"
:
"#CCCCCC"
}
}
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"GAP_FILLING"
?
"#ffb714"
:
"#CCCCCC"
,
}
}
>

{
" "
}
</
span
>
<
span
>
填空题
</
span
>
...
...
@@ -398,12 +427,25 @@ class AddNewQuestion extends Component {
<
TabPane
tab=
{
<
span
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"INDEFINITE_CHOICE"
?
"#ffb714"
:
"#CCCCCC"
}
}
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
activeKey
===
"INDEFINITE_CHOICE"
?
"#ffb714"
:
"#CCCCCC"
,
}
}
>

{
" "
}
</
span
>
<
span
>
不定项选择题
</
span
>
<
Tooltip
title=
"至少有一项正确,至多不限的选择题,多项选择题的一种特殊形式"
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#BFBFBF"
}
}
>

</
span
>
<
span
className=
"icon iconfont"
style=
{
{
color
:
"#BFBFBF"
}
}
>

</
span
>
</
Tooltip
>
</
span
>
}
...
...
src/modules/teach-tool/question-bank/AddNewQuestion.less
View file @
f48a2dd4
/*
* @Author: yuananting
* @Date: 2021-02-25 13:52:01
* @LastEditors: yuananting
* @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/question-bank/QuestionBankIndex.jsx
View file @
f48a2dd4
...
...
@@ -2,11 +2,10 @@
* @Author: yuananting
* @Date: 2021-02-21 17:51:01
* @LastEditors: yuananting
* @LastEditTime: 2021-03-2
7 14:58:13
* @LastEditTime: 2021-03-2
9 16:11:41
* @Description: 助学工具-题库-题库主页面
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
import
"./QuestionBankIndex.less"
;
import
CourseCategorySiderTree
from
"../components/CourseCategorySiderTree"
;
...
...
@@ -15,13 +14,9 @@ import QuestionManageContent from "./components/QuestionManageContent";
class
QuestionBankIndex
extends
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
selectedCategoryId
:
""
,
};
this
.
state
=
{};
}
componentDidMount
()
{}
getCategoryIdFromSider
=
(
selectedCategoryId
)
=>
{
if
(
selectedCategoryId
&&
selectedCategoryId
.
length
>
0
)
{
this
.
setState
({
selectedCategoryId
:
selectedCategoryId
[
0
]
});
...
...
src/modules/teach-tool/question-bank/QuestionBankIndex.less
View file @
f48a2dd4
/*
* @Author: yuananting
* @Date: 2021-02-21 18:27:43
* @LastEditors: yuananting
* @LastEditTime: 2021-03-24 16:15:03
* @Description: 助学工具-题库-题库主页面样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-bank-index {
.question-bank-index {
.content-body {
display: flex;
.site-layout-background {
...
...
src/modules/teach-tool/question-bank/components/NewQuestionTab.jsx
View file @
f48a2dd4
...
...
@@ -2,8 +2,8 @@
* @Author: yuananting
* @Date: 2021-02-25 14:34:29
* @LastEditors: yuananting
* @LastEditTime: 2021-03-2
7 14:45:03
* @Description: 助学工具-题库-
题目管理-
新建题目Tab
* @LastEditTime: 2021-03-2
9 16:22:15
* @Description: 助学工具-题库-新建题目Tab
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
...
...
@@ -24,7 +24,10 @@ import {
NUM_TO_WORD_MAP
,
MEDIA_FILE_ACCEPT
,
}
from
"@/common/constants/punchClock/punchClock"
;
import
{
defineOptionInfo
,
defineJudgeOptionInfo
}
from
"../../components/model"
;
import
{
defineOptionInfo
,
defineJudgeOptionInfo
,
}
from
"../../components/model"
;
import
XMAudio
from
"../../components/XMAudio"
;
import
XMRecord
from
"../../components/XMRecord"
;
import
ScanFileModal
from
"@/modules/resource-disk/modal/ScanFileModal"
;
...
...
@@ -151,162 +154,7 @@ class NewQuestionTab extends Component {
});
};
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
=
()
=>
{
let
validateError
=
0
;
// 题干校验
let
stemContent
=
_
.
find
(
this
.
state
.
stemContent
,
(
contentItem
)
=>
contentItem
.
type
===
"RICH_TEXT"
);
let
stem
=
stemContent
.
content
.
replace
(
/<
[^
>
]
+>/g
,
""
);
stem
=
stem
.
replace
(
/
\&
nbsp
\;
/gi
,
""
);
stem
=
stem
.
replace
(
/
\s
+/g
,
""
);
if
(
this
.
props
.
questionTypeKey
===
"GAP_FILLING"
)
{
if
(
this
.
state
.
blanksList
.
length
===
0
||
stem
.
length
===
0
)
{
this
.
setState
({
stemValidate
:
"error"
,
stemText
:
(
<
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
++
;
}
else
{
this
.
setState
({
stemValidate
:
"success"
,
stemText
:
""
});
}
}
else
{
if
(
stem
.
length
===
0
)
{
this
.
setState
({
stemValidate
:
"error"
,
stemText
:
"请输入题干"
});
validateError
++
;
}
else
{
this
.
setState
({
stemValidate
:
"success"
,
stemText
:
""
});
}
}
// 选项校验
let
optionUnChecked
=
0
;
const
{
chooseOptions
}
=
this
.
state
;
if
(
this
.
props
.
questionTypeKey
===
"GAP_FILLING"
)
{
this
.
state
.
gapFillingAnswer
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
correctAnswerList
.
length
===
0
)
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"error"
,
[
`optionsText_
${
index
}
`
]:
"请输入答案"
,
});
validateError
++
;
}
else
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"success"
,
[
`optionsText_
${
index
}
`
]:
""
,
});
}
});
}
else
{
chooseOptions
.
forEach
((
item
,
index
)
=>
{
const
optionContent
=
item
.
questionOptionContentList
;
optionUnChecked
=
item
.
isCorrectAnswer
?
optionUnChecked
:
optionUnChecked
+
1
;
let
optionInput
=
optionContent
[
0
].
content
.
replace
(
/<
[^
>
]
+>/g
,
""
);
optionInput
=
optionInput
.
replace
(
/
\&
nbsp
\;
/gi
,
""
);
optionInput
=
optionInput
.
replace
(
/
\s
+/g
,
""
);
if
(
optionContent
.
length
===
1
&&
optionContent
[
0
].
type
===
"RICH_TEXT"
&&
optionInput
.
length
===
0
)
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"error"
,
[
`optionsText_
${
index
}
`
]:
"请输入选项"
,
});
validateError
++
;
}
else
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"success"
,
[
`optionsText_
${
index
}
`
]:
""
,
});
}
});
var
chooseIcon
=
[];
if
([
"SINGLE_CHOICE"
,
"JUDGE"
].
includes
(
this
.
props
.
questionTypeKey
))
{
chooseIcon
=
document
.
getElementsByClassName
(
"ant-radio-inner"
);
}
else
if
(
[
"MULTI_CHOICE"
,
"INDEFINITE_CHOICE"
].
includes
(
this
.
props
.
questionTypeKey
)
)
{
chooseIcon
=
document
.
getElementsByClassName
(
"ant-checkbox-inner"
);
}
if
(
optionUnChecked
===
chooseOptions
.
length
)
{
this
.
setState
({
radioValidate
:
"error"
,
radioText
:
(
<
span
>
正确答案
<
br
/>
不能为空
</
span
>
),
});
chooseIcon
.
forEach
((
item
)
=>
{
item
.
setAttribute
(
"style"
,
"border:1px solid #ff4d4f;"
);
});
validateError
++
;
}
else
{
this
.
setState
({
radioValidate
:
"success"
,
radioText
:
""
});
chooseIcon
.
forEach
((
item
)
=>
{
item
.
removeAttribute
(
"style"
);
});
}
if
(
this
.
props
.
questionTypeKey
===
"MULTI_CHOICE"
&&
this
.
state
.
chooseOptions
.
length
-
optionUnChecked
===
1
)
{
this
.
setState
({
radioValidate
:
"error"
,
radioText
:
"最少选两个"
});
chooseIcon
.
forEach
((
item
)
=>
{
item
.
setAttribute
(
"style"
,
"border:1px solid #ff4d4f;"
);
});
validateError
++
;
}
}
return
validateError
;
};
/**
* 预览
*
* @memberof QuestionInputItem
*/
handleScanFile
=
(
scanFileType
,
scanFileAddress
)
=>
{
this
.
setState
({
showScanFile
:
true
,
scanFileAddress
,
scanFileType
,
});
};
/**
* 添加选项
*
* @memberof QuestionInputItem
*/
// 添加选项
handleAddOption
=
(
content
)
=>
{
const
{
chooseOptions
}
=
this
.
state
;
if
(
chooseOptions
.
length
>=
20
)
{
...
...
@@ -317,22 +165,7 @@ class NewQuestionTab extends Component {
}
};
/**
* 初始化判断选项
*
* @memberof QuestionInputItem
*/
initJudgeOption
=
(
content
)
=>
{
const
{
chooseOptions
}
=
this
.
state
;
chooseOptions
.
push
(
defineJudgeOptionInfo
(
content
));
this
.
_onSetState
();
};
/**
* 删除选项
*
* @memberof QuestionInputItem
*/
// 删除选项
handleDelOption
=
(
optionIndex
)
=>
{
const
{
chooseOptions
}
=
this
.
state
;
this
.
handleLogger
(
"delete_option"
,
"删除选项"
);
...
...
@@ -344,11 +177,7 @@ class NewQuestionTab extends Component {
}
};
/**
* 移动选项
*
* @memberof QuestionInputItem
*/
// 移动选项
handleMoveOption
=
(
optionIndex
,
moveLength
)
=>
{
const
{
chooseOptions
}
=
this
.
state
;
const
optionItem
=
chooseOptions
.
splice
(
optionIndex
+
moveLength
,
1
);
...
...
@@ -356,11 +185,8 @@ class NewQuestionTab extends Component {
chooseOptions
.
splice
(
optionIndex
,
0
,
optionItem
[
0
]);
this
.
_onSetState
();
};
/**
* 选择上传文件类型
*
* @memberof QuestionInputItem
*/
// 选择上传文件类型
handleChangeMedia
=
(
key
,
uploadItemTarget
,
contentType
)
=>
{
const
pictureMediaArr
=
_
.
filter
(
uploadItemTarget
,
(
mediaItem
)
=>
{
return
mediaItem
.
type
===
"PICTURE"
;
...
...
@@ -577,6 +403,38 @@ class NewQuestionTab extends Component {
});
}
// 完成语音录制
handleFinishRecord
=
(
mp3URL
,
duration
)
=>
{
const
originArr
=
mp3URL
.
split
(
"."
);
const
originType
=
originArr
[
originArr
.
length
-
1
];
this
.
state
.
onAudioFinish
();
const
{
uploadItemTarget
,
contentType
}
=
this
.
state
;
uploadItemTarget
.
push
({
contentType
,
type
:
"AUDIO"
,
contentName
:
`
${
window
.
random_string
(
16
)}
.
${
originType
}
`
,
// 文件名
fileType
:
originType
,
// 文件后缀
content
:
mp3URL
,
size
:
duration
,
});
this
.
_onSetState
({
showRecord
:
false
});
};
// 取消录制
handleCancelRecord
=
()
=>
{
this
.
setState
({
showRecord
:
false
});
};
// 云盘文件筛选
handleSelectMedia
=
(
file
)
=>
{
this
.
uploadFile
(
file
);
this
.
setState
({
showSelectFileModal
:
false
,
});
};
// 填空内容改变-联动答案
changeBlankCount
=
(
data
,
idx
)
=>
{
let
_gap
=
this
.
state
.
gapFillingAnswer
;
if
(
data
.
length
===
0
)
{
...
...
@@ -615,6 +473,7 @@ class NewQuestionTab extends Component {
);
};
// 填空-tag新增答案
addAnswerTag
=
(
optionItem
)
=>
{
const
_blanksList
=
this
.
state
.
blanksList
;
_blanksList
.
forEach
((
item
)
=>
{
...
...
@@ -625,7 +484,7 @@ class NewQuestionTab extends Component {
this
.
setState
({
blanksList
:
_blanksList
});
};
// 填空选项
//
确认输入
填空选项
handleInputConfirm
=
(
optionItem
,
val
)
=>
{
var
tagContent
=
val
.
replace
(
/
\&
nbsp
\;
/gi
,
""
);
tagContent
=
val
.
replace
(
/
\s
+/g
,
""
);
...
...
@@ -651,6 +510,7 @@ class NewQuestionTab extends Component {
);
};
// 填空-删除已填答案tag
handleTagClose
=
(
optionItem
,
removedTag
,
removedIndex
)
=>
{
const
_blanksList
=
this
.
state
.
blanksList
;
const
{
gapFillingAnswer
}
=
this
.
state
;
...
...
@@ -670,7 +530,7 @@ class NewQuestionTab extends Component {
);
};
// 输入框关闭
//
填空-
输入框关闭
handleInputClose
=
(
optionItem
)
=>
{
const
_blanksList
=
this
.
state
.
blanksList
;
_blanksList
.
forEach
((
item
)
=>
{
...
...
@@ -682,16 +542,15 @@ class NewQuestionTab extends Component {
this
.
setState
({
blanksList
:
_blanksList
});
};
handleInputEdit
=
(
optionItem
,
index
)
=>
{
const
_blanksList
=
this
.
state
.
blanksList
;
_blanksList
.
forEach
((
item
)
=>
{
if
(
item
.
id
===
optionItem
.
id
)
{
item
.
correctAnswerList
.
map
();
}
});
this
.
setState
({
blanksList
:
_blanksList
});
// 填空-字符串转html
transferStemDocument
=
(
txt
)
=>
{
const
template
=
`<div class='stem'>
${
txt
}
</div>`
;
let
doc
=
new
DOMParser
().
parseFromString
(
template
,
"text/html"
);
let
div
=
doc
.
querySelector
(
".stem"
);
return
div
;
};
// 填空答案渲染
renderGapFillingAnswer
=
(
optionItem
,
optionIndex
)
=>
{
const
{
gapFillingAnswer
}
=
this
.
state
;
const
list
=
...
...
@@ -753,16 +612,161 @@ class NewQuestionTab extends Component {
);
};
// 初始化判断选项
initJudgeOption
=
(
content
)
=>
{
const
{
chooseOptions
}
=
this
.
state
;
chooseOptions
.
push
(
defineJudgeOptionInfo
(
content
));
this
.
_onSetState
();
};
// 判断题选项渲染
renderJudgeOption
=
(
judgeOptions
)
=>
{
return
(
<
div
dangerouslySetInnerHTML=
{
{
__html
:
judgeOptions
[
0
].
content
}
}
/>
);
};
/**
* 渲染输入内容
*
* @memberof QuestionInputItem
*/
// 保存校验
checkInput
=
()
=>
{
let
validateError
=
0
;
// 题干校验
let
stemContent
=
_
.
find
(
this
.
state
.
stemContent
,
(
contentItem
)
=>
contentItem
.
type
===
"RICH_TEXT"
);
let
stem
=
stemContent
.
content
.
replace
(
/<
[^
>
]
+>/g
,
""
);
stem
=
stem
.
replace
(
/
\&
nbsp
\;
/gi
,
""
);
stem
=
stem
.
replace
(
/
\s
+/g
,
""
);
if
(
this
.
props
.
questionTypeKey
===
"GAP_FILLING"
)
{
if
(
this
.
state
.
blanksList
.
length
===
0
||
stem
.
length
===
0
)
{
this
.
setState
({
stemValidate
:
"error"
,
stemText
:
(
<
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
++
;
}
else
{
this
.
setState
({
stemValidate
:
"success"
,
stemText
:
""
});
}
}
else
{
if
(
stem
.
length
===
0
)
{
this
.
setState
({
stemValidate
:
"error"
,
stemText
:
"请输入题干"
});
validateError
++
;
}
else
{
this
.
setState
({
stemValidate
:
"success"
,
stemText
:
""
});
}
}
// 选项校验
let
optionUnChecked
=
0
;
const
{
chooseOptions
}
=
this
.
state
;
if
(
this
.
props
.
questionTypeKey
===
"GAP_FILLING"
)
{
this
.
state
.
gapFillingAnswer
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
correctAnswerList
.
length
===
0
)
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"error"
,
[
`optionsText_
${
index
}
`
]:
"请输入答案"
,
});
validateError
++
;
}
else
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"success"
,
[
`optionsText_
${
index
}
`
]:
""
,
});
}
});
}
else
{
chooseOptions
.
forEach
((
item
,
index
)
=>
{
const
optionContent
=
item
.
questionOptionContentList
;
optionUnChecked
=
item
.
isCorrectAnswer
?
optionUnChecked
:
optionUnChecked
+
1
;
let
optionInput
=
optionContent
[
0
].
content
.
replace
(
/<
[^
>
]
+>/g
,
""
);
optionInput
=
optionInput
.
replace
(
/
\&
nbsp
\;
/gi
,
""
);
optionInput
=
optionInput
.
replace
(
/
\s
+/g
,
""
);
if
(
optionContent
.
length
===
1
&&
optionContent
[
0
].
type
===
"RICH_TEXT"
&&
optionInput
.
length
===
0
)
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"error"
,
[
`optionsText_
${
index
}
`
]:
"请输入选项"
,
});
validateError
++
;
}
else
{
this
.
setState
({
[
`optionsValidate_
${
index
}
`
]:
"success"
,
[
`optionsText_
${
index
}
`
]:
""
,
});
}
});
var
chooseIcon
=
[];
if
([
"SINGLE_CHOICE"
,
"JUDGE"
].
includes
(
this
.
props
.
questionTypeKey
))
{
chooseIcon
=
document
.
getElementsByClassName
(
"ant-radio-inner"
);
}
else
if
(
[
"MULTI_CHOICE"
,
"INDEFINITE_CHOICE"
].
includes
(
this
.
props
.
questionTypeKey
)
)
{
chooseIcon
=
document
.
getElementsByClassName
(
"ant-checkbox-inner"
);
}
if
(
optionUnChecked
===
chooseOptions
.
length
)
{
this
.
setState
({
radioValidate
:
"error"
,
radioText
:
(
<
span
>
正确答案
<
br
/>
不能为空
</
span
>
),
});
chooseIcon
.
forEach
((
item
)
=>
{
item
.
setAttribute
(
"style"
,
"border:1px solid #ff4d4f;"
);
});
validateError
++
;
}
else
{
this
.
setState
({
radioValidate
:
"success"
,
radioText
:
""
});
chooseIcon
.
forEach
((
item
)
=>
{
item
.
removeAttribute
(
"style"
);
});
}
if
(
this
.
props
.
questionTypeKey
===
"MULTI_CHOICE"
&&
this
.
state
.
chooseOptions
.
length
-
optionUnChecked
===
1
)
{
this
.
setState
({
radioValidate
:
"error"
,
radioText
:
"最少选两个"
});
chooseIcon
.
forEach
((
item
)
=>
{
item
.
setAttribute
(
"style"
,
"border:1px solid #ff4d4f;"
);
});
validateError
++
;
}
}
return
validateError
;
};
// 预览
handleScanFile
=
(
scanFileType
,
scanFileAddress
)
=>
{
this
.
setState
({
showScanFile
:
true
,
scanFileAddress
,
scanFileType
,
});
};
// 渲染输入内容
renderContent
=
(
contentList
,
placehold
,
...
...
@@ -1060,57 +1064,6 @@ class NewQuestionTab extends Component {
);
};
/**
* 取消上传
*
* @memberof QuestionInputItem
*/
handleAbort
=
(
uploadItem
,
index
)
=>
{
const
{
uploadItemTarget
}
=
this
.
state
;
const
{
xhr
}
=
uploadItem
;
xhr
&&
xhr
.
abort
&&
xhr
.
abort
();
uploadItemTarget
.
splice
(
index
,
1
);
this
.
_onSetState
();
};
/**
* 完成语音录制
*
* @memberof QuestionInputItem
*/
handleFinishRecord
=
(
mp3URL
,
duration
)
=>
{
const
originArr
=
mp3URL
.
split
(
"."
);
const
originType
=
originArr
[
originArr
.
length
-
1
];
this
.
state
.
onAudioFinish
();
const
{
uploadItemTarget
,
contentType
}
=
this
.
state
;
uploadItemTarget
.
push
({
contentType
,
type
:
"AUDIO"
,
contentName
:
`
${
window
.
random_string
(
16
)}
.
${
originType
}
`
,
// 文件名
fileType
:
originType
,
// 文件后缀
content
:
mp3URL
,
size
:
duration
,
});
this
.
_onSetState
({
showRecord
:
false
});
};
/**
* 取消录制
*
* @memberof QuestionInputItem
*/
handleCancelRecord
=
()
=>
{
this
.
setState
({
showRecord
:
false
});
};
handleSelectMedia
=
(
file
)
=>
{
this
.
uploadFile
(
file
);
this
.
setState
({
showSelectFileModal
:
false
,
});
};
render
()
{
const
{
stemContent
,
...
...
src/modules/teach-tool/question-bank/components/NewQuestionTab.less
View file @
f48a2dd4
...
...
@@ -175,12 +175,6 @@
margin-right: 187px;
}
// .question-item_options {
// display: flex;
// align-items: center;
// padding-bottom: 15px;
// }
.question-item_options__list {
flex: 1;
position: relative;
...
...
@@ -440,38 +434,3 @@
}
}
}
.question_skeleton {
background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 37%, #f2f2f2 63%);
background-size: 400% 100%;
animation: question-editor_skeleton__loading 1.4s ease infinite;
}
.question_skeleton__editor {
min-height: 33px;
max-height: 140px;
overflow: hidden;
}
.question_skeleton__img {
width: 88px;
height: 88px;
}
.question_skeleton__voice {
height: 48px;
width: 280px;
}
.question_skeleton__video {
width: 100%;
height: 100%;
}
@keyframes question-editor_skeleton__loading {
0% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
src/modules/teach-tool/question-bank/components/QuestionManageContent.jsx
View file @
f48a2dd4
...
...
@@ -2,8 +2,8 @@
* @Author: yuananting
* @Date: 2021-02-25 11:23:47
* @LastEditors: yuananting
* @LastEditTime: 2021-03-2
7 15:30:34
* @Description: 助学工具-题库-
题目管理主页面
列表数据
* @LastEditTime: 2021-03-2
9 16:21:50
* @Description: 助学工具-题库-列表数据
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
...
...
@@ -76,15 +76,12 @@ class QuestionManageContent extends Component {
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
},
questionTypeList
:
[],
// 题型列表
dataSource
:
[],
totalCount
:
0
,
dataSource
:
[],
// 题库列表
QuestionPreviewModal
:
null
,
// 题目预览模态框
BatchImportQuestionModal
:
null
,
// 批量导入模态框
};
}
componentDidMount
()
{}
shouldComponentUpdate
(
nextProps
,
nextState
)
{
let
{
selectedCategoryId
}
=
nextProps
;
const
_query
=
this
.
state
.
query
;
...
...
@@ -101,9 +98,40 @@ class QuestionManageContent extends Component {
return
true
;
}
queryQuestionPageList
=
(
remain
)
=>
{
// 改变搜索条件
handleChangeQuery
=
(
searchType
,
value
)
=>
{
this
.
setState
(
{
query
:
{
...
this
.
state
.
query
,
[
searchType
]:
value
||
null
,
current
:
1
,
},
},
()
=>
{
if
(
searchType
===
"questionName"
)
return
;
this
.
queryQuestionPageList
();
}
);
};
// 清空搜索条件
handleReset
=
()
=>
{
const
_query
=
{
...
this
.
state
.
query
,
current
:
1
,
order
:
"ACCURACY_DESC"
,
// 排序规则
questionName
:
null
,
// 题目名称
questionType
:
null
,
// 题目类型
};
this
.
setState
({
query
:
_query
},
()
=>
{
this
.
queryQuestionPageList
();
});
};
// 题库列表查询
queryQuestionPageList
=
()
=>
{
const
_query
=
this
.
state
.
query
;
if
(
_query
.
categoryId
===
"0"
)
_query
.
categoryId
=
null
;
QuestionBankService
.
queryQuestionPageList
(
_query
).
then
((
res
)
=>
{
const
{
records
=
[],
total
=
0
}
=
res
.
result
;
this
.
setState
({
dataSource
:
records
});
...
...
@@ -113,48 +141,37 @@ class QuestionManageContent extends Component {
});
};
handleCreateQuestionBank
=
()
=>
{
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?categoryId=
${
this
.
state
.
query
.
categoryId
}
`
,
});
};
delQuestionConfirm
(
record
)
{
return
Modal
.
confirm
({
title
:
"提示"
,
content
:
"确定要删除此题目吗?"
,
icon
:
(
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
),
okText
:
"删除"
,
cancelText
:
"取消"
,
onOk
:
()
=>
{
this
.
deleteQuestion
(
record
);
},
});
}
deleteQuestion
=
(
record
)
=>
{
let
params
=
{
id
:
record
.
id
,
source
:
0
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
};
QuestionBankService
.
deleteQuestion
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"删除成功"
);
const
{
query
,
total
}
=
this
.
state
;
const
{
size
,
current
}
=
query
;
const
_query
=
query
;
if
(
total
/
size
<
current
)
{
if
(
total
%
size
===
1
)
{
_query
.
current
=
1
;
}
// 自定义表格空状态
customizeRenderEmpty
=
()
=>
{
const
{
categoryId
}
=
this
.
state
.
query
;
return
(
<
Empty
image=
"https://image.xiaomaiketang.com/xm/emptyTable.png"
imageStyle=
{
{
height
:
100
,
}
}
description=
{
<
div
>
<
span
>
还没有题目
</
span
>
{
[
"CloudManager"
,
"StoreManager"
].
includes
(
User
.
getUserRole
())
&&
categoryId
&&
(
<
span
>
,快去
<
span
className=
"empty-list-tip"
onClick=
{
()
=>
{
this
.
handleCreateQuestionBank
();
}
}
>
新建一个
</
span
>
吧!
</
span
>
)
}
</
div
>
}
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
());
}
});
></
Empty
>
);
};
// 排序
...
...
@@ -179,49 +196,9 @@ class QuestionManageContent extends Component {
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
());
};
// 清空搜索条件
handleReset
=
()
=>
{
const
_query
=
{
...
this
.
state
.
query
,
current
:
1
,
order
:
"ACCURACY_DESC"
,
// 排序规则
questionName
:
null
,
// 题目名称
questionType
:
null
,
// 题目类型
};
this
.
setState
({
query
:
_query
},
()
=>
{
this
.
queryQuestionPageList
();
});
};
previewQuestion
=
(
id
)
=>
{
const
m
=
(
<
QuestionPreviewModal
id=
{
id
}
close=
{
()
=>
{
this
.
setState
({
QuestionPreviewModal
:
null
,
});
}
}
/>
);
this
.
setState
({
QuestionPreviewModal
:
m
});
};
toEditQuestion
=
(
id
,
type
)
=>
{
const
{
categoryId
}
=
this
.
state
.
query
;
if
(
categoryId
)
{
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?id=
${
id
}
&type=
${
type
}
&categoryId=
${
categoryId
}
`
,
});
}
else
{
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?id=
${
id
}
&type=
${
type
}
`
,
});
}
};
// 表头设置
parseColumns
=
()
=>
{
// 权限判断
const
isPermiss
=
[
"CloudManager"
,
"StoreManager"
].
includes
(
User
.
getUserRole
()
);
...
...
@@ -233,7 +210,7 @@ class QuestionManageContent extends Component {
ellipsis
:
{
showTitle
:
false
,
},
render
:
(
val
,
record
)
=>
{
render
:
(
val
)
=>
{
var
handleVal
=
val
;
handleVal
=
handleVal
.
replace
(
/<
(?!
img|input
)
.*
?
>/g
,
""
);
handleVal
=
handleVal
.
replace
(
/<
\s?
input
[^
>
]
*>/gi
,
"_、"
);
...
...
@@ -305,7 +282,7 @@ class QuestionManageContent extends Component {
<
div
className=
"record-operate__item"
onClick=
{
()
=>
this
.
toE
ditQuestion
(
record
.
id
,
record
.
questionTypeEnum
)
this
.
e
ditQuestion
(
record
.
id
,
record
.
questionTypeEnum
)
}
>
编辑
...
...
@@ -330,39 +307,7 @@ class QuestionManageContent extends Component {
return
columns
;
};
// 自定义表格空状态
customizeRenderEmpty
=
()
=>
{
const
{
categoryId
}
=
this
.
state
.
query
;
return
(
<
Empty
image=
"https://image.xiaomaiketang.com/xm/emptyTable.png"
imageStyle=
{
{
height
:
100
,
}
}
description=
{
<
div
>
<
span
>
还没有题目
</
span
>
{
[
"CloudManager"
,
"StoreManager"
].
includes
(
User
.
getUserRole
())
&&
!
[
"0"
,
null
].
includes
(
categoryId
)
&&
(
<
span
>
,快去
<
span
className=
"empty-list-tip"
onClick=
{
()
=>
{
this
.
handleCreateQuestionBank
();
}
}
>
新建一个
</
span
>
吧!
</
span
>
)
}
</
div
>
}
></
Empty
>
);
};
// 设置表格每页展示条数
onShowSizeChange
=
(
current
,
size
)
=>
{
if
(
current
==
size
)
{
return
;
...
...
@@ -372,40 +317,100 @@ class QuestionManageContent extends Component {
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
());
};
// 改变搜索条件
handleChangeQuery
=
(
searchType
,
value
)
=>
{
this
.
setState
(
{
query
:
{
...
this
.
state
.
query
,
[
searchType
]:
value
||
null
,
current
:
1
,
},
// 预览题目
previewQuestion
=
(
id
)
=>
{
const
m
=
(
<
QuestionPreviewModal
id=
{
id
}
close=
{
()
=>
{
this
.
setState
({
QuestionPreviewModal
:
null
,
});
}
}
/>
);
this
.
setState
({
QuestionPreviewModal
:
m
});
};
// 编辑题目
editQuestion
=
(
id
,
type
)
=>
{
const
{
categoryId
}
=
this
.
state
.
query
;
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?id=
${
id
}
&type=
${
type
}
&categoryId=
${
categoryId
}
`
,
});
};
// 删除题目确认弹窗
delQuestionConfirm
(
record
)
{
return
Modal
.
confirm
({
title
:
"提示"
,
content
:
"确定要删除此题目吗?"
,
icon
:
(
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
),
okText
:
"删除"
,
cancelText
:
"取消"
,
onOk
:
()
=>
{
this
.
deleteQuestion
(
record
);
},
()
=>
{
if
(
searchType
===
"questionName"
)
return
;
this
.
queryQuestionPageList
();
});
}
// 删除题目
deleteQuestion
=
(
record
)
=>
{
let
params
=
{
id
:
record
.
id
,
source
:
0
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
};
QuestionBankService
.
deleteQuestion
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"删除成功"
);
const
{
query
,
total
}
=
this
.
state
;
const
{
size
,
current
}
=
query
;
const
_query
=
query
;
if
(
total
/
size
<
current
)
{
if
(
total
%
size
===
1
)
{
_query
.
current
=
1
;
}
}
this
.
setState
({
query
:
_query
},
()
=>
this
.
queryQuestionPageList
());
}
);
}
);
};
// 创建题目-跳转新建页
handleCreateQuestionBank
=
()
=>
{
window
.
RCHistory
.
push
({
pathname
:
`/create-new-question?categoryId=
${
this
.
state
.
query
.
categoryId
}
`
,
});
};
// 批量导入弹窗
batchImportQuestion
=
()
=>
{
const
{
categoryId
}
=
this
.
state
.
query
;
const
ImportQuestionModal
=
(
const
m
=
(
<
BatchImportQuestionModal
close=
{
()
=>
{
this
.
setState
({
ImportQuestionModal
:
null
},
()
=>
{
this
.
setState
({
Batch
ImportQuestionModal
:
null
},
()
=>
{
this
.
queryQuestionPageList
();
});
}
}
categoryId=
{
categoryId
}
/>
);
this
.
setState
({
ImportQuestionModal
});
this
.
setState
({
BatchImportQuestionModal
:
m
});
};
render
()
{
const
{
dataSource
=
[],
total
,
query
}
=
this
.
state
;
const
{
dataSource
=
[],
total
,
query
,
QuestionPreviewModal
,
BatchImportQuestionModal
,
}
=
this
.
state
;
const
{
current
,
size
,
categoryId
,
questionName
,
questionType
}
=
query
;
return
(
<
div
className=
"question-manage-content"
>
...
...
@@ -473,7 +478,7 @@ class QuestionManageContent extends Component {
</
Row
>
</
div
>
{
[
"CloudManager"
,
"StoreManager"
].
includes
(
User
.
getUserRole
())
&&
!
[
"0"
,
null
].
includes
(
categoryId
)
&&
(
categoryId
&&
(
<
Space
size=
{
16
}
>
<
Button
type=
"primary"
onClick=
{
this
.
handleCreateQuestionBank
}
>
新建题目
...
...
@@ -509,8 +514,8 @@ class QuestionManageContent extends Component {
/>
</
div
>
)
}
{
this
.
state
.
QuestionPreviewModal
}
{
this
.
state
.
ImportQuestionModal
}
{
QuestionPreviewModal
}
{
Batch
ImportQuestionModal
}
</
div
>
</
div
>
);
...
...
src/modules/teach-tool/question-bank/components/QuestionManageContent.less
View file @
f48a2dd4
/*
* @Author: yuananting
* @Date: 2021-02-25 11:26:28
* @LastEditors: yuananting
* @LastEditTime: 2021-03-25 14:32:01
* @Description: 助学工具-题库-题目管理右侧内容样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-manage-content {
.question-manage-filter {
position: relative;
...
...
@@ -81,8 +73,3 @@
max-width: 700px !important;
}
}
.fill-line {
padding: 0 10px;
border-bottom: 1px solid;
}
src/modules/teach-tool/question-bank/modal/BatchImportQuestionModal.jsx
View file @
f48a2dd4
/*
* @Author: zhangyi
* @Date: 2019-12-09 10:29:55
* @Last Modified by: mikey.wanghaofeng
* @Last Modified time: 2020-09-25 11:03:47
* @Author: yuananting
* @Date: 2021-03-27 11:15:03
* @LastEditors: yuananting
* @LastEditTime: 2021-03-29 16:22:28
* @Description: 助学工具-题库-批量导入题目
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
import
{
Modal
,
Button
,
message
,
Spin
}
from
"antd"
;
import
"./BatchImportQuestionModal.less"
;
...
...
src/modules/teach-tool/question-bank/modal/BatchImportQuestionModal.less
View file @
f48a2dd4
@import
'@/core/mixins.less'
;
@import
"@/core/mixins.less"
;
.import-score-modal {
.step-section {
margin-bottom: 24px;
...
...
@@ -48,7 +48,7 @@
}
}
.file-box :hover {
background-color: #
FFF8E
8;
background-color: #
fff8e
8;
.del-img {
visibility: visible !important;
}
...
...
@@ -63,7 +63,7 @@
}
.down-btn {
text-align: left;
color: #5289
FA
;
color: #5289
fa
;
font-size: 12px;
display: block;
margin-top: 8px;
...
...
@@ -73,18 +73,18 @@
width: 200px;
.ant-upload-list-item-name {
.text-overflow-ellipsis();
width:70%;
width:
70%;
}
}
}
.import-status-box {
height:430px;
height:
430px;
overflow: hidden;
.status-content {
margin:auto;
margin:
auto;
text-align: center;
margin-top:100px;
>img {
margin-top:
100px;
>
img {
width: 76px;
}
.status {
...
...
@@ -97,9 +97,9 @@
color: #666666;
margin-bottom: 16px;
.num {
color: #
FC9C6B
;
color: #
fc9c6b
;
}
}
}
}
}
\ No newline at end of file
}
src/modules/teach-tool/question-bank/modal/QuestionPreviewModal.jsx
View file @
f48a2dd4
/*
* @Author: yuananting
* @Date: 2021-03-27 11:15:03
* @LastEditors: yuananting
* @LastEditTime: 2021-03-29 16:19:35
* @Description: 助学工具-题库-预览题目
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
Component
}
from
"react"
;
import
{
Modal
}
from
"antd"
;
import
User
from
"@/common/js/user"
;
...
...
@@ -42,6 +50,7 @@ class QuestionPreviewModal extends Component {
});
};
// 查看图片或视频
handleScanFile
=
(
scanFileType
,
scanFileAddress
)
=>
{
this
.
setState
({
showScanFile
:
true
,
...
...
@@ -50,13 +59,6 @@ class QuestionPreviewModal extends Component {
});
};
transferStemDocument
=
(
txt
)
=>
{
const
template
=
`<p class='content'>
${
txt
}
</p>`
;
let
doc
=
new
DOMParser
().
parseFromString
(
template
,
"text/html"
);
let
p
=
doc
.
querySelector
(
".content"
);
return
p
;
};
render
()
{
const
{
showScanFile
,
...
...
@@ -225,7 +227,10 @@ class QuestionPreviewModal extends Component {
)
}
{
[
"JUDGE"
].
includes
(
questionTypeEnum
)
&&
_
.
map
(
questionOptionContentList
,
(
item
,
index
)
=>
{
item
.
content
=
item
.
content
.
replace
(
/<
\/?[^
>
]
*>/g
,
""
);
item
.
content
=
item
.
content
.
replace
(
/<
\/?[^
>
]
*>/g
,
""
);
return
<
span
key=
{
index
}
>
{
item
.
content
}
</
span
>;
})
}
</
div
>
...
...
src/modules/teach-tool/question-bank/modal/QuestionPreviewModal.less
View file @
f48a2dd4
...
...
@@ -17,7 +17,7 @@
}
.question-stem {
margin-bottom: 16px;
border-bottom: 1px solid #
E8E8E
8;
border-bottom: 1px solid #
e8e8e
8;
padding-bottom: 16px;
&__title {
height: 22px;
...
...
@@ -140,7 +140,7 @@
}
.question-answer {
margin-bottom: 16px;
border-bottom: 1px solid #
E8E8E
8;
border-bottom: 1px solid #
e8e8e
8;
padding-bottom: 16px;
img {
max-width: 88px;
...
...
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