移除已废弃的 ReviewTreeChart 组件。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
import ReactECharts from 'echarts-for-react'
|
||||
import type { Exam, ReviewStatus } from '../types'
|
||||
import { REVIEW_STATUS_LABELS } from '../types'
|
||||
|
||||
interface Props {
|
||||
exams: Exam[]
|
||||
}
|
||||
|
||||
const STATUS_ORDER: ReviewStatus[] = ['careless', 'unknown', 'nervous', 'normal']
|
||||
|
||||
const STATUS_COLORS: Record<ReviewStatus, string> = {
|
||||
careless: '#fa8c16',
|
||||
unknown: '#ff4d4f',
|
||||
nervous: '#722ed1',
|
||||
normal: '#52c41a',
|
||||
}
|
||||
|
||||
function buildTreeData(exams: Exam[]) {
|
||||
const byStatus: Record<ReviewStatus, Record<string, number>> = {
|
||||
careless: {},
|
||||
unknown: {},
|
||||
nervous: {},
|
||||
normal: {},
|
||||
}
|
||||
|
||||
for (const exam of exams) {
|
||||
for (const score of exam.scores) {
|
||||
const subjectName = score.subject_name || `科目${score.subject_id}`
|
||||
for (const status of score.review_statuses || []) {
|
||||
byStatus[status][subjectName] = (byStatus[status][subjectName] || 0) + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const children = STATUS_ORDER.map((status) => {
|
||||
const subjectMap = byStatus[status]
|
||||
const subjectChildren = Object.entries(subjectMap).map(([name, value]) => ({
|
||||
name: `${name} (${value})`,
|
||||
value,
|
||||
itemStyle: { color: STATUS_COLORS[status] },
|
||||
}))
|
||||
const total = subjectChildren.reduce((sum, item) => sum + item.value, 0)
|
||||
if (total === 0) return null
|
||||
return {
|
||||
name: `${REVIEW_STATUS_LABELS[status]} (${total})`,
|
||||
value: total,
|
||||
itemStyle: { color: STATUS_COLORS[status] },
|
||||
children: subjectChildren,
|
||||
}
|
||||
}).filter(Boolean)
|
||||
|
||||
return { name: '复盘统计', children: children.length ? children : [{ name: '暂无数据', value: 0 }] }
|
||||
}
|
||||
|
||||
export default function ReviewTreeChart({ exams }: Props) {
|
||||
const treeData = buildTreeData(exams)
|
||||
const hasData = STATUS_ORDER.some((status) =>
|
||||
exams.some((exam) =>
|
||||
exam.scores.some((score) => (score.review_statuses || []).includes(status)),
|
||||
),
|
||||
)
|
||||
|
||||
if (!hasData) {
|
||||
return (
|
||||
<div style={{ textAlign: 'center', padding: 32, color: '#999' }}>
|
||||
暂无复盘数据,请在录入成绩或下方复盘中填写考试状态
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: (params: { name: string; value?: number }) => {
|
||||
if (params.value != null && params.value > 0) {
|
||||
return `${params.name}<br/>次数: ${params.value}`
|
||||
}
|
||||
return params.name
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'tree',
|
||||
data: [treeData],
|
||||
top: 20,
|
||||
left: 40,
|
||||
bottom: 20,
|
||||
right: 120,
|
||||
symbolSize: 10,
|
||||
orient: 'LR',
|
||||
label: {
|
||||
position: 'left',
|
||||
verticalAlign: 'middle',
|
||||
align: 'right',
|
||||
fontSize: 13,
|
||||
},
|
||||
leaves: {
|
||||
label: {
|
||||
position: 'right',
|
||||
verticalAlign: 'middle',
|
||||
align: 'left',
|
||||
},
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'descendant',
|
||||
},
|
||||
expandAndCollapse: true,
|
||||
animationDuration: 400,
|
||||
animationDurationUpdate: 400,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ReactECharts option={option} style={{ height: 360, width: '100%' }} notMerge />
|
||||
<p style={{ color: '#888', fontSize: 12, marginTop: 8 }}>
|
||||
树状图按「状态 → 科目」统计次数;同一科可多选状态,分别计数
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user