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
e6cb1d98
Commit
e6cb1d98
authored
Aug 16, 2021
by
zhujian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix
parent
4f691a3e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
526 additions
and
14 deletions
+526
-14
src/modules/task-center/data-center/Index.tsx
+14
-5
src/modules/task-center/data-center/components/DataAnalysic.tsx
+63
-0
src/modules/task-center/data-center/components/ExamData.tsx
+321
-0
src/modules/task-center/data-center/components/ExamTable.tsx
+13
-5
src/modules/task-center/data-center/components/LeftStageList.jsx
+1
-1
src/modules/task-center/data-center/components/StudyTable.tsx
+2
-3
src/modules/task-center/data-center/components/UserData.tsx
+0
-0
src/modules/task-center/data-center/components/dataAnalysic.less
+22
-0
src/modules/task-center/data-center/components/userData.less
+90
-0
No files found.
src/modules/task-center/data-center/Index.tsx
View file @
e6cb1d98
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
withRouter
}
from
"react-router-dom"
;
import
{
Tabs
}
from
'antd'
;
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
Service
from
'@/common/js/service'
;
import
Breadcrumbs
from
"@/components/Breadcrumbs"
;
import
UserLearningData
from
'./UserLearningData'
;
import
DataInfo
from
'./components/DataInfo'
import
CourseTable
from
'./components/CourseTable'
;
import
DataAnalysic
from
'./components/DataAnalysic'
;
import
ExamTable
from
'./components/ExamTable'
;
import
StudyTable
from
'./components/StudyTable'
;
import
'./index.less'
const
{
TabPane
}
=
Tabs
;
function
DataCenter
(
props
:
any
)
{
const
{
match
:
{
params
:
{
taskId
}
}
}
=
props
;
const
{
match
}
=
props
;
const
{
params
:
{
taskId
}
}
=
match
;
const
[
info
,
setInfo
]
=
useState
<
any
>
({})
const
[
tabKey
,
setTabKey
]
=
useState
<
any
>
(
''
)
...
...
@@ -44,8 +47,8 @@ function DataCenter(props: any) {
res
.
result
.
trainingStageList
.
map
((
item
:
any
)
=>
{
item
.
open
=
true
})
res
.
result
.
cover
=
res
.
result
.
courseMediaVOS
.
filter
((
item
:
any
)
=>
item
.
contentType
===
'COVER'
)[
0
]
||
{};
res
.
result
.
intro
=
res
.
result
.
courseMediaVOS
.
filter
((
item
:
any
)
=>
item
.
contentType
===
'INTRO'
)[
0
]
||
{};
res
.
result
.
cover
=
res
.
result
.
courseMediaVOS
.
filter
((
item
:
any
)
=>
item
.
contentType
===
'COVER'
)[
0
]
||
{};
res
.
result
.
intro
=
res
.
result
.
courseMediaVOS
.
filter
((
item
:
any
)
=>
item
.
contentType
===
'INTRO'
)[
0
]
||
{};
setInfo
(
res
.
result
)
})
}
...
...
@@ -72,7 +75,13 @@ function DataCenter(props: any) {
</
Tabs
>
</
div
>
<
Route
path=
{
`${match.url}/analysic/:id`
}
render=
{
()
=>
{
return
<
DataAnalysic
/>;
}
}
/>
<
Route
path=
{
`${props.match.url}/user-learning-data/:storeCustomerId`
}
render=
{
()
=>
<
UserLearningData
taskId=
{
taskId
}
/>
}
/>
</
div
>
}
...
...
src/modules/task-center/data-center/components/DataAnalysic.tsx
0 → 100644
View file @
e6cb1d98
import
React
,
{
useState
,
useRef
,
useEffect
,
useContext
}
from
'react'
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
Breadcrumbs
from
"@/components/Breadcrumbs"
;
import
UserData
from
'./UserData'
;
import
ExamData
from
'./ExamData'
import
Service
from
"@/common/js/service"
;
import
{
Tabs
}
from
'antd'
;
import
User
from
"@/common/js/user"
;
import
'./dataAnalysic.less'
const
{
TabPane
}
=
Tabs
;
function
DataAnalysic
(
props
:
any
)
{
const
examDetailInit
:
any
=
{};
const
[
selectKey
,
setSelectKey
]
=
useState
(
'user'
)
const
[
examDetail
,
setExamDetail
]
=
useState
(
examDetailInit
);
const
{
match
}
=
props
;
const
examId
=
match
.
params
.
id
;
useEffect
(()
=>
{
queryExamDetail
();
},
[])
function
queryExamDetail
()
{
Service
.
Hades
(
"public/hades/queryExamDetail"
,
{
examId
:
examId
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
source
:
0
}).
then
((
res
)
=>
{
const
{
result
}
=
res
setExamDetail
(
result
)
})
}
return
<
div
className=
"page dataAnalysic"
>
<
Breadcrumbs
navList=
{
"考试数据"
}
goBack=
{
props
.
history
.
goBack
}
/>
<
div
className=
"box"
>
<
div
className=
"titleBox "
>
考试名称:
{
examDetail
.
examName
}
</
div
>
</
div
>
<
div
className=
"box"
style=
{
{
paddingTop
:
0
}
}
>
<
Tabs
activeKey=
{
selectKey
}
onChange=
{
(
key
:
any
)
=>
{
setSelectKey
(
key
)
}
}
>
<
TabPane
tab=
"考试人员数据"
key=
"user"
>
<
UserData
examDetail
={
examDetail
}
examId=
{
examId
}
/>
</
TabPane
>
<
TabPane
tab=
"题目数据"
key=
"exam"
>
<
ExamData
examDetail
={
examDetail
}
examId=
{
examId
}
></
ExamData
>
</
TabPane
>
</
Tabs
>
</
div
>
</
div
>
}
export
default
withRouter
(
DataAnalysic
);
\ No newline at end of file
src/modules/task-center/data-center/components/ExamData.tsx
0 → 100644
View file @
e6cb1d98
import
React
,
{
useState
,
useRef
,
useEffect
}
from
"react"
;
import
Service
from
"@/common/js/service"
;
import
{
PageControl
}
from
"@/components"
;
import
{
Input
,
Select
,
Tooltip
,
Button
}
from
"antd"
;
import
User
from
"@/common/js/user"
;
import
{
XMTable
}
from
"@/components"
;
import
college
from
"@/common/lottie/college.json"
;
import
"./userData.less"
;
interface
sortType
{
type
:
"ascend"
|
"descend"
|
null
|
undefined
;
}
function
ExamData
(
props
:
any
)
{
const
sortStatus
:
sortType
=
{
type
:
undefined
,
};
const
examDataInit
:
any
=
{};
const
queryInit
:
any
=
{
current
:
1
,
size
:
10
,
order
:
"SORT_ASC"
};
const
[
examData
,
setUserData
]
=
useState
(
examDataInit
);
const
[
list
,
setList
]
=
useState
([]);
const
[
query
,
setQuery
]
=
useState
(
queryInit
);
const
[
total
,
setTotal
]
=
useState
(
0
);
const
[
field
,
setfield
]
=
useState
(
""
);
const
[
allData
,
setAllData
]
=
useState
(
0
);
const
[
order
,
setOrder
]
=
useState
(
sortStatus
.
type
);
const
questionTypeList
=
{
SINGLE_CHOICE
:
"单选题"
,
MULTI_CHOICE
:
"多选题"
,
JUDGE
:
"判断题"
,
GAP_FILLING
:
"填空题"
,
INDEFINITE_CHOICE
:
"不定项选择题"
,
};
const
userTypeEnum
=
{
WORK_WE_CHAT
:
"企业微信"
,
WE_CHAT
:
"微信"
,
};
const
userExamStateEnum
=
{
EXAM
:
"进行中"
,
LACK_EXAM
:
"缺考"
,
FINISH_EXAM
:
"已考试"
,
};
const
orderEnum
=
{
currentAccuracy
:
{
ascend
:
"ACCURACY_ASC"
,
descend
:
"ACCURACY_DESC"
,
},
};
const
queryRef
=
useRef
({});
useEffect
(()
=>
{
queryExamUserData
();
},
[]);
useEffect
(()
=>
{
queryRef
.
current
=
query
;
queryExamUserDataList
();
},
[
query
]);
function
queryExamUserData
()
{
Service
.
Hades
(
"public/hades/queryExamQuestionData"
,
{
examId
:
props
.
examId
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
source
:
0
,
}).
then
((
res
)
=>
{
setUserData
(
res
.
result
);
});
}
function
queryExamUserDataList
()
{
Service
.
Hades
(
"public/hades/queryExamQuestionDataList"
,
{
...
query
,
examId
:
props
.
examId
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
source
:
0
,
}).
then
((
res
)
=>
{
setList
(
res
.
result
.
records
);
setTotal
(
parseInt
(
res
.
result
.
total
));
if
(
!
allData
)
{
setAllData
(
parseInt
(
res
.
result
.
total
));
}
});
}
const
columns
=
[
{
title
:
"序号"
,
dataIndex
:
"sort"
,
width
:
60
,
render
:
(
text
:
any
,
record
:
any
,
index
:
any
)
=>
<
span
>
{
index
+
1
}
</
span
>,
},
{
title
:
"题目"
,
dataIndex
:
"questionStem"
,
ellipsis
:
true
,
width
:
350
,
render
:
(
val
:
any
)
=>
{
var
handleVal
=
val
;
handleVal
=
handleVal
.
replace
(
/<
(?!
img|input
)
.*
?
>/g
,
""
);
handleVal
=
handleVal
.
replace
(
/<
\s?
input
[^
>
]
*>/gi
,
"_、"
);
handleVal
=
handleVal
.
replace
(
/
\&
nbsp
\;
/gi
,
" "
);
return
(
<
Tooltip
overlayClassName=
"aid-tool-list"
title=
{
<
div
style=
{
{
maxWidth
:
700
,
width
:
"auto"
}
}
>
{
handleVal
}
</
div
>
}
placement=
"topLeft"
overlayStyle=
{
{
maxWidth
:
700
}
}
>
{
handleVal
}
</
Tooltip
>
);
},
},
{
title
:
"题型"
,
dataIndex
:
"questionType"
,
render
:
(
text
:
any
)
=>
<
span
>
{
(
questionTypeList
as
any
)[
text
]
}
</
span
>,
filters
:
Object
.
keys
(
questionTypeList
).
map
((
key
)
=>
{
return
{
text
:
(
questionTypeList
as
any
)[
key
],
value
:
key
,
};
}),
},
{
title
:
"本次正确率"
,
dataIndex
:
"currentAccuracy"
,
sorter
:
true
,
sortOrder
:
field
===
"currentAccuracy"
?
order
:
sortStatus
.
type
,
render
:
(
text
:
any
)
=>
<
span
>
{
parseInt
((
text
*
100
)
as
any
)
}
%
</
span
>,
},
{
title
:
(
<
div
>
历史正确率
{
" "
}
<
Tooltip
overlayClassName=
"tool-list"
title=
"包含本次考试正确率"
placement=
"top"
overlayStyle=
{
{
maxWidth
:
700
}
}
>
{
" "
}
<
span
style=
{
{
color
:
"rgba(191, 191, 191, 1)"
,
fontWeight
:
400
}
}
className=
"icon iconfont"
>

</
span
>
</
Tooltip
>
</
div
>
),
dataIndex
:
"totalAccuracy"
,
render
:
(
text
:
any
)
=>
<
span
>
{
parseInt
((
text
*
100
)
as
any
)
}
%
</
span
>,
},
];
function
onChange
(
pagination
:
any
,
filters
:
any
,
sorter
:
any
,
extra
:
any
)
{
console
.
log
(
filters
,
sorter
);
setfield
(
sorter
.
field
);
setOrder
(
sorter
.
order
);
console
.
log
(
sorter
.
field
,
sorter
.
order
,
(
orderEnum
as
any
)[
sorter
.
field
]);
let
_query
:
any
=
{
...
queryRef
.
current
};
console
.
log
(
filters
.
questionType
);
if
(
filters
.
questionType
)
{
console
.
log
(
233232
);
_query
.
questionType
=
filters
.
questionType
;
_query
.
current
=
1
;
}
else
{
delete
_query
.
questionType
;
}
_query
.
order
=
(
orderEnum
as
any
)[
sorter
.
field
][
sorter
.
order
];
setQuery
(
_query
);
}
function
download
()
{
Service
.
Hades
(
"public/hades/exportExamData"
,
{
// ...query,
examId
:
props
.
examId
,
exportDataType
:
"EXAM_QUESTION_DATA"
,
tenantId
:
User
.
getStoreId
(),
userId
:
User
.
getStoreUserId
(),
source
:
0
,
}).
then
((
res
)
=>
{
const
dom
=
(
document
as
any
).
getElementById
(
"load-play-back-excel"
);
dom
.
setAttribute
(
"href"
,
res
.
result
);
dom
.
click
();
});
}
return
(
<
div
className=
"rr"
>
<
a
download
id=
"load-play-back-excel"
style=
{
{
position
:
"absolute"
,
left
:
"-10000px"
}
}
></
a
>
<
div
className=
"dataPanal"
>
{
!!
examData
.
singleChoiceCnt
&&
(
<
div
className=
"item"
>
<
div
className=
"num"
>
{
Math
.
round
((
examData
.
singleChoiceAccuracy
||
0
)
*
100
)
}
%
</
div
>
<
div
className=
"percent"
>
正确率
</
div
>
<
div
className=
"subTitle"
>
<
div
className=
"type"
>
<
span
className=
"icon iconfont"
>

</
span
>
单选题
{
" "
}
<
span
>
(共
{
examData
.
singleChoiceCnt
}
题)
</
span
>
</
div
>
</
div
>
</
div
>
)
}
{
!!
examData
.
multiChoiceCnt
&&
(
<
div
className=
"item"
>
<
div
className=
"num"
>
{
Math
.
round
((
examData
.
multiChoiceAccuracy
||
0
)
*
100
)
}
%
</
div
>
<
div
className=
"percent"
>
正确率
</
div
>
<
div
className=
"subTitle"
>
<
div
className=
"type"
>
<
span
className=
"icon iconfont"
>

</
span
>
多选题
<
span
>
(共
{
examData
.
multiChoiceCnt
}
题)
</
span
>
</
div
>
</
div
>
</
div
>
)
}
{
!!
examData
.
judgeCnt
&&
(
<
div
className=
"item"
>
<
div
className=
"num"
>
{
Math
.
round
((
examData
.
judgeAccuracy
||
0
)
*
100
)
}
%
</
div
>
<
div
className=
"percent"
>
正确率
</
div
>
<
div
className=
"subTitle"
>
<
div
className=
"type"
>
<
span
className=
"icon iconfont"
>

</
span
>
判断题
<
span
>
(共
{
examData
.
judgeCnt
}
题)
</
span
>
</
div
>
</
div
>
</
div
>
)
}
{
!!
examData
.
gapFillingCnt
&&
(
<
div
className=
"item"
>
<
div
className=
"num"
>
{
Math
.
round
((
examData
.
gapFillingAccuracy
||
0
)
*
100
)
}
%
</
div
>
<
div
className=
"percent"
>
正确率
</
div
>
<
div
className=
"subTitle"
>
<
div
className=
"type"
>
<
span
className=
"icon iconfont"
>

</
span
>
填空题
<
span
>
(共
{
examData
.
gapFillingCnt
}
题)
</
span
>
</
div
>
</
div
>
</
div
>
)
}
{
!!
examData
.
indefiniteChoiceCnt
&&
(
<
div
className=
"item"
>
<
div
className=
"num"
>
{
Math
.
round
((
examData
.
indefiniteChoiceAccuracy
||
0
)
*
100
)
}
%
</
div
>
<
div
className=
"percent"
>
正确率
</
div
>
<
div
className=
"subTitle"
>
<
div
className=
"type"
>
<
span
className=
"icon iconfont"
>

</
span
>
不定项选择题
{
" "
}
<
span
>
(共
{
examData
.
indefiniteChoiceCnt
}
题)
</
span
>
</
div
>
</
div
>
</
div
>
)
}
</
div
>
{
!!
allData
&&
(
<
Button
style=
{
{
marginBottom
:
12
,
marginTop
:
12
}
}
onClick=
{
download
}
>
导出
</
Button
>
)
}
<
div
className=
"content"
>
<
XMTable
renderEmpty=
{
{
image
:
college
,
description
:
'暂无数据'
}
}
bordered
size=
"small"
columns=
{
columns
}
dataSource=
{
list
}
onChange=
{
onChange
}
pagination=
{
false
}
></
XMTable
>
{
total
>
0
&&
(
<
PageControl
size=
"small"
current=
{
query
.
current
-
1
}
pageSize=
{
query
.
size
}
total=
{
total
}
toPage=
{
(
page
:
any
)
=>
{
console
.
log
(
page
);
let
_query
:
any
=
{
...
queryRef
.
current
};
_query
.
current
=
page
+
1
;
setQuery
(
_query
);
}
}
/>
)
}
</
div
>
</
div
>
);
}
export
default
ExamData
;
src/modules/task-center/data-center/components/ExamTable.tsx
View file @
e6cb1d98
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
withRouter
}
from
"react-router-dom"
;
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
{
PageControl
,
XMTable
}
from
'@/components'
;
import
Service
from
'@/common/js/service'
;
import
User
from
'@/common/js/user'
;
function
ExamTable
(
props
:
any
)
{
const
{
match
}
=
props
;
console
.
log
(
match
)
const
[
query
,
setQuery
]
=
useState
<
any
>
({
current
:
1
,
size
:
10
,
taskId
:
props
.
taskId
,
...
...
@@ -22,8 +25,8 @@ function ExamTable(props: any) {
function
getList
()
{
Service
.
Hades
(
'public/hades/queryTrainingExamUserData'
,
query
).
then
((
res
:
any
)
=>
{
setList
(
res
.
result
.
records
)
setTotal
(
res
.
result
.
t
atal
)
setList
(
res
.
result
.
records
)
;
setTotal
(
res
.
result
.
t
otal
);
})
}
...
...
@@ -79,7 +82,11 @@ function ExamTable(props: any) {
render
:
(
val
:
any
,
record
:
any
)
=>
{
return
(
<
div
className=
'operate-area'
>
<
span
className=
'operate-item'
onClick=
{
()
=>
{
}
}
>
<
span
className=
'operate-item'
style=
{
{
color
:
'rgba(41, 102, 255, 1)'
,
cursor
:
'pointer'
}
}
onClick=
{
()
=>
{
props
.
history
.
push
({
pathname
:
`${match.url}/analysic/${record.examId}`
,
});
}
}
>
查看数据
</
span
>
...
...
@@ -90,6 +97,7 @@ function ExamTable(props: any) {
];
return
<
div
className=
"study_Table"
>
<
div
style=
{
{
marginTop
:
12
}
}
>
...
...
@@ -121,7 +129,7 @@ function ExamTable(props: any) {
</
div
>
)
}
</
div
>
</
div
>
}
...
...
src/modules/task-center/data-center/components/LeftStageList.jsx
View file @
e6cb1d98
...
...
@@ -36,7 +36,7 @@ function LeftStageList(props) {
<
span
className=
"icon iconfont edit-icon"
>

</
span
>
)
}
</
div
>
<
div
className=
"stage-name"
>
<
div
className=
"stage-name
oneLineText
"
>
{
ENUM
.
IndexToSort
[
index
+
1
]
}
、
{
item
.
stageName
}
</
div
>
</
div
>
...
...
src/modules/task-center/data-center/components/StudyTable.tsx
View file @
e6cb1d98
...
...
@@ -8,8 +8,7 @@ import Service from '@/common/js/service';
import
ENUM
from
'../../enum'
;
import
User
from
'@/common/js/user'
;
import
moment
from
'moment'
;
import
UserLearningData
from
'../UserLearningData'
;
import
{
timers
}
from
'jquery'
;
const
{
Search
}
=
Input
;
const
{
Option
}
=
Select
;
declare
var
formatDate
:
any
;
...
...
@@ -294,7 +293,7 @@ function StudyTable(props: any) {
</
div
>
)
}
</
div
>
<
Route
path=
{
`${props.match.url}/user-learning-data/:storeCustomerId`
}
render=
{
()
=>
<
UserLearningData
taskId=
{
props
.
taskId
}
/>
}
/>
</
div
>
}
...
...
src/modules/task-center/data-center/components/UserData.tsx
0 → 100644
View file @
e6cb1d98
This diff is collapsed.
Click to expand it.
src/modules/task-center/data-center/components/dataAnalysic.less
0 → 100644
View file @
e6cb1d98
.dataAnalysic {
.titleBox {
position: relative;
font-size: 19px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 26px;
background: #ffffff;
&::before {
width: 4px;
height: 12px;
content: '';
background-image: linear-gradient(#2966ff 83.5%, #0acca4 16.5%);
display: inline-block;
margin-right: 8px;
}
}
.ant-tabs-content-holder {
margin-top: 8px;
}
}
src/modules/task-center/data-center/components/userData.less
0 → 100644
View file @
e6cb1d98
.dataPanal {
border-radius: 4px;
border: 1px solid #e8e8e8;
display: flex;
.item {
text-align: center;
// width: 29.9%;
position: relative;
flex: 1;
.num {
font-size: 26px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 26px;
margin-top: 12px;
}
.percent {
margin-top: 6px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 17px;
height: 20px;
margin-bottom: 18px;
}
.subTitle {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 20px;
margin-bottom: 12px;
}
.type {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
span {
color: rgba(153, 153, 153, 1);
}
.icon {
color: rgba(204, 204, 204, 1);
font-size: 16px;
margin-right: 4px;
position: relative;
top: 1px;
}
}
&:after {
content: '';
width: 0px;
height: 40px;
position: absolute;
width: 1px;
background-color: rgba(232, 232, 232, 1);
top: 40px;
right: 0px;
}
&:last-child {
&:after {
display: none;
}
}
}
.exstatus {
width: 4px;
height: 4px;
background: rgb(35, 143, 255);
display: inline-block;
border-radius: 50%;
position: relative;
top: -4px;
}
}
.answer-detail {
color: rgb(35, 143, 255);
}
.analysic-content {
.ant-table-bordered .ant-table-tbody tr {
&.analysic-content-row {
height: 50px;
}
}
}
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