Skip to content

Commit 9edfdba

Browse files
committed
feat: add stat page
1 parent 64a5d40 commit 9edfdba

File tree

12 files changed

+276
-206
lines changed

12 files changed

+276
-206
lines changed

src/components/QuestionComponents/QuestionCheckbox/StatComponent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { QuestionCheckboxStatPropsType } from './type'
1212

1313
const StatComponent: FC<QuestionCheckboxStatPropsType> = ({ stat }) => {
1414
return (
15-
<div style={{ width: '400px', height: '300px' }}>
15+
<div style={{ width: '300px', height: '300px' }}>
1616
<ResponsiveContainer width="100%" height="100%">
1717
<BarChart
1818
width={400}

src/components/QuestionComponents/QuestionRadio/StatComponent.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ const StatComponent: FC<QuestionRadioStatPropsType> = ({ stat = [] }) => {
2222
<Pie
2323
dataKey="count"
2424
data={stat}
25-
cx="50%" // x 轴的偏移
26-
cy="50%" // y 轴的偏移
25+
cx="40%" // x 轴的偏移
26+
cy="40%" // y 轴的偏移
2727
outerRadius={50} // 饼图的直径
2828
fill="#8884d8"
2929
label={(i) => `${i.name}: ${format(i.count / sum)}%`}

src/pages/question/stat/components/StatContainer.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,31 @@ import StatContainerCenter from './centerPanel'
44
import StatContainerRight from './rightPanel'
55

66
const StatContainer: FC = () => {
7+
// 状态提升 selectedId type
8+
const [selectedComponentId, setSelectedComponentId] = useState('')
9+
const [selectedComponentType, setSelectedComponentType] = useState('')
10+
711
return (
812
<div className="mx-6 h-full flex">
913
<div className="w-73 bg-white px-3">
10-
<StatContainerLeft />
14+
<StatContainerLeft
15+
selectedComponentId={selectedComponentId}
16+
setSelectedComponentId={setSelectedComponentId}
17+
setSelectedComponentType={setSelectedComponentType}
18+
/>
1119
</div>
12-
<div className="relative flex-1 overflow-hidden">
13-
<StatContainerCenter />
20+
<div className="relative mx-3 flex-1 overflow-hidden">
21+
<StatContainerCenter
22+
selectedComponentId={selectedComponentId}
23+
setSelectedComponentId={setSelectedComponentId}
24+
setSelectedComponentType={setSelectedComponentType}
25+
/>
1426
</div>
1527
<div className="w-75 bg-white px-3">
16-
<StatContainerRight />
28+
<StatContainerRight
29+
selectedComponentId={selectedComponentId}
30+
selectedComponentType={selectedComponentType}
31+
/>
1732
</div>
1833
</div>
1934
)
Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,104 @@
11
import { FC } from 'react'
2+
import { Pagination, Spin, Table, Typography } from 'antd'
3+
import { STAT_PAGE_SIZE } from '@/constant'
4+
import { getQuestionStatListService } from '@/api'
5+
import { useGetComponentInfo } from '@/hooks'
26

3-
const StatContainerCenter: FC = () => {
4-
return <>StatContainerCenter</>
7+
const { Title } = Typography
8+
9+
interface PropsType {
10+
selectedComponentId: string
11+
setSelectedComponentId: (id: string) => void
12+
setSelectedComponentType: (type: string) => void
13+
}
14+
15+
const StatContainerCenter: FC<PropsType> = (props: PropsType) => {
16+
const {
17+
selectedComponentId,
18+
setSelectedComponentId,
19+
setSelectedComponentType,
20+
} = props
21+
22+
const { id = '' } = useParams()
23+
24+
const [page, setPage] = useState(1)
25+
const [pageSize, setPageSize] = useState(STAT_PAGE_SIZE)
26+
const [total, setTotal] = useState(0)
27+
const [list, setList] = useState([])
28+
const { loading } = useRequest(
29+
async () => {
30+
const res = await getQuestionStatListService(id, { page, pageSize })
31+
return res
32+
},
33+
{
34+
refreshDeps: [id, page, pageSize],
35+
onSuccess(res) {
36+
const { total, list = [] } = res
37+
setTotal(total)
38+
setList(list)
39+
},
40+
},
41+
)
42+
43+
const { componentList } = useGetComponentInfo()
44+
const columns = componentList.map((c) => {
45+
const { fe_id, title, props = {}, type } = c
46+
47+
const colTitle = props!.title || title
48+
49+
return {
50+
// title: colTitle,
51+
title: (
52+
<div
53+
style={{ cursor: 'pointer' }}
54+
onClick={() => {
55+
setSelectedComponentId(fe_id)
56+
setSelectedComponentType(type)
57+
}}
58+
>
59+
<span
60+
style={{
61+
color: fe_id === selectedComponentId ? '#1890ff' : 'inherit',
62+
}}
63+
>
64+
{colTitle}
65+
</span>
66+
</div>
67+
),
68+
dataIndex: fe_id,
69+
}
70+
})
71+
72+
const dataSource = list.map((i: any) => ({ ...i, key: i._id }))
73+
const TableElem = (
74+
<>
75+
<Table columns={columns} dataSource={dataSource} pagination={false} />
76+
<div style={{ textAlign: 'center', marginTop: '18px' }}>
77+
<Pagination
78+
total={total}
79+
pageSize={pageSize}
80+
current={page}
81+
onChange={(page) => setPage(page)}
82+
onShowSizeChange={(page, pageSize) => {
83+
setPage(page)
84+
setPageSize(pageSize)
85+
}}
86+
/>
87+
</div>
88+
</>
89+
)
90+
91+
return (
92+
<div>
93+
<Title level={3}>答卷数量: {!loading && total}</Title>
94+
{loading && (
95+
<div style={{ textAlign: 'center' }}>
96+
<Spin />
97+
</div>
98+
)}
99+
{!loading && TableElem}
100+
</div>
101+
)
5102
}
6103

7104
export default StatContainerCenter

src/pages/question/stat/components/leftPanel/ComponentLayer.tsx

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/pages/question/stat/components/leftPanel/ComponentLib.tsx

Lines changed: 0 additions & 64 deletions
This file was deleted.
Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,60 @@
1+
import { getComponentConfByType } from '@/components/QuestionComponents'
2+
import { useGetComponentInfo } from '@/hooks'
3+
import classNames from 'classnames'
14
import { FC } from 'react'
2-
import { Tabs } from 'antd'
3-
import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons'
4-
import ComponentLib from './ComponentLib'
5-
import ComponentLayer from './ComponentLayer'
6-
7-
const StatContainerLeft: FC = () => {
8-
const tabsItems = [
9-
{
10-
key: 'componentLib',
11-
label: (
12-
<span>
13-
<AppstoreOutlined />
14-
组件库
15-
</span>
16-
),
17-
children: <ComponentLib />,
18-
},
19-
{
20-
key: 'layers',
21-
label: (
22-
<span>
23-
<BarsOutlined />
24-
图层
25-
</span>
26-
),
27-
children: <ComponentLayer />,
28-
},
29-
]
30-
31-
return <Tabs defaultActiveKey="componentLib" items={tabsItems} />
5+
6+
interface PropsType {
7+
selectedComponentId: string
8+
setSelectedComponentId: (id: string) => void
9+
setSelectedComponentType: (type: string) => void
10+
}
11+
12+
const StatContainerLeft: FC<PropsType> = (props) => {
13+
const {
14+
selectedComponentId,
15+
setSelectedComponentId,
16+
setSelectedComponentType,
17+
} = props
18+
const { componentList } = useGetComponentInfo()
19+
20+
return (
21+
<div className="min-h-full overflow-y-auto bg-white">
22+
{componentList
23+
.filter((c) => !c.isHidden) // 过滤隐藏的组件
24+
.map((c) => {
25+
const { fe_id, props, type } = c
26+
27+
const componentConf = getComponentConfByType(type)
28+
if (componentConf == null) return null
29+
30+
const { Component } = componentConf
31+
32+
// 拼接 class name
33+
const wrapperDefaultClassName =
34+
'm-3 border-solid border-white px-2 py-3 b-rounded hover:border-blueGray'
35+
const selectedClassName = 'border-gray'
36+
const wrapperClassName = classNames({
37+
[wrapperDefaultClassName]: true,
38+
[selectedClassName]: fe_id === selectedComponentId, // 是否选中
39+
})
40+
41+
return (
42+
<div
43+
className={wrapperClassName}
44+
key={fe_id}
45+
onClick={() => {
46+
setSelectedComponentId(fe_id)
47+
setSelectedComponentType(type)
48+
}}
49+
>
50+
<div className="pointer-events-none opacity-[0.8]">
51+
<Component {...props} />
52+
</div>
53+
</div>
54+
)
55+
})}
56+
</div>
57+
)
3258
}
3359

3460
export default StatContainerLeft

0 commit comments

Comments
 (0)