27 KiB
学情诊断(Diagnostic)模块审计报告 v2
审计日期:2026-06-25 审计范围:
src/modules/diagnostic/**、src/app/(dashboard)/{teacher,student,parent}/diagnostic/**参照规则:.trae/rules/project_rules.md、docs/architecture/004_architecture_impact_map.md§2.22、docs/architecture/005_architecture_data.json前置文档:
- diagnostic-audit-report.md(v1,2026-06-22,3 P0 + 5 P1 + 5 P2 全部完成)
- grades-diagnostic-audit-report-v4.md(v4,2026-06-23,12 项 P1 全部完成)
一、现有实现概要
1.1 v1/v4 已完成项回顾
v1 与 v4 审计共完成 25 项改进(3 P0 + 5 P1 + 5 P2 + 12 v4-P1),涵盖:跨模块 WidgetBoundary 提升到 shared、教师页面标题 i18n 化、教师 error.tsx i18n 化、as 断言消除、分享按钮移除、报告内容 i18n 驱动、Excel 导出 i18n 化、班级报告导出明细、角色配置驱动(role-config.ts)、年级诊断报告纵向切片、热力图键盘导航、DataScope 行级权限、师生关系校验、草稿隔离、通知机制、热力图图例、移动端表格滚动等。
1.2 当前文件分布(v2 实测)
| 层 | 文件 | 行数 | 职责 |
|---|---|---|---|
| 类型 | types.ts | 126 | DiagnosticReport / Mastery / Summary 类型定义(含 v4-P2-3 GradeMasterySummary) |
| 数据访问 | data-access.ts | 519 | 掌握度查询 + 从提交/作业/成绩更新掌握度(含事务) |
| 数据访问 | data-access-reports.ts | 323 | 诊断报告 CRUD + DataScope 过滤 + 结构化错误码 |
| 统计服务 | stats-service.ts | 506 | 14 个纯统计函数(含年级聚合) |
| Server Actions | actions.ts | 302 | 6 个 Action(含年级生成 + 通知) |
| 校验 | schema.ts | 39 | 5 个 Zod schema |
| 导出 | export.ts | 175 | Excel 导出(含班级明细 3 Sheet) |
| 角色配置 | role-config.ts | 40 | 角色配置驱动(v4-P2-2) |
| 组件 | components/student-diagnostic-view.tsx | 299 | 学生诊断视图(概览+雷达+强弱项+报告+历史) |
| 组件 | components/class-diagnostic-view.tsx | 449 | 班级诊断视图(热力图+筛选+排名+关注列表+生成) |
| 组件 | components/report-list.tsx | 373 | 报告列表(过滤+表格+发布/删除/导出) |
| 组件 | components/mastery-radar-chart.tsx | 85 | 雷达图封装 |
| 组件 | components/confidence-utils.ts | 31 | 置信度计算 |
| 页面 | 4 个 page.tsx + 5 个 loading.tsx + 5 个 error.tsx |
— | teacher/student/parent 三角色路由 |
| i18n | zh-CN/diagnostic.json + en/diagnostic.json | 252 / 同步 | 翻译文件 |
1.3 数据流
page.tsx (RSC)
├─ getStudentMasterySummary / getClassMasterySummary / getGradeMasterySummary / getKnowledgePointStats (data-access)
│ └─ db (drizzle) → knowledgePointMastery / knowledgePoints 表
│ └─ 跨模块 data-access:classes / users / school / exams / homework / questions
├─ getDiagnosticReports (data-access-reports, 含 DataScope 过滤)
│ └─ db → learningDiagnosticReports 表
└─ <StudentDiagnosticView> / <ClassDiagnosticView> / <ReportList> (client)
└─ generateStudentReportAction / generateClassReportAction / generateGradeReportAction
/ publishReportAction / deleteReportAction / exportDiagnosticReportAction
/ getClassStudentsByKnowledgePointAction
1.4 架构图记录完整性
经核对 004_architecture_impact_map.md §2.22 与 005_architecture_data.json modules.diagnostic 节点,架构图对诊断模块的记录基本完整,已涵盖 v1/v4 全部修复。但本次 v2 审计发现以下偏差需后续同步:
- 架构图未记录
getDiagnosticReports中grade_managedscope 未过滤的已知缺陷(v2-P1-1)。 - 架构图未记录
confidence-utils.ts的置信度计算逻辑过于简化(v2-P1-5)。 - 架构图未记录 3 个子路由 error.tsx 仍存在硬编码中文(v2-P0-1)。
二、现存问题与原因分析
2.1 国际化
问题 2.1.1 | 3 个子路由 error.tsx 硬编码中文(P0)
- 位置:
- teacher/diagnostic/class/[classId]/error.tsx#L17-22:
title="班级学情诊断加载失败"description="抱歉,加载班级诊断数据时发生了意外错误。请稍后重试。"label="重试" - teacher/diagnostic/student/[studentId]/error.tsx#L17-22:
title="学生学情诊断加载失败"同样硬编码 - parent/diagnostic/error.tsx#L17-22:
title="子女学情诊断加载失败"同样硬编码
- teacher/diagnostic/class/[classId]/error.tsx#L17-22:
- 现象:三个 error.tsx 客户端组件未使用
useTranslations,全部硬编码中文文案。 - 违反规则:项目规则"所有用户可见文本必须适配 i18n(使用 next-intl),提取翻译键"。
- 原因:v1 审计 P0-3 仅修复了
teacher/diagnostic/error.tsx(教师报告列表页),遗漏了教师子路由和学生/家长子路由的 error.tsx。 - 后果:英文环境下这三个错误页显示中文,与系统其他已 i18n 化的错误页风格不一致。
问题 2.1.2 | i18n 标签与代码逻辑不一致(P1)
- 位置:
- i18n:zh-CN/diagnostic.json#L78:
"weaknesses": { "title": "弱项(<60%)" } - 代码:stats-service.ts#L83-99:
classifyStrengthsWeaknesses中弱项阈值为< 80(P3-16 修复:消除 60-79 盲区)
- i18n:zh-CN/diagnostic.json#L78:
- 现象:i18n 标签显示"弱项(<60%)",但代码实际将掌握度 < 80 的知识点都归类为弱项。
- 违反规则:项目规则"所有用户可见文本必须适配 i18n"——文本需与逻辑一致。
- 原因:P3-16 修复弱项分类阈值时未同步更新 i18n 标签。
- 后果:用户看到"弱项(<60%)"标签,但实际列表包含 60-79% 的知识点,造成认知混乱。
问题 2.1.3 | 死 i18n 键未清理(P2)
- 位置:zh-CN/diagnostic.json#L157-165
- 现象:
reportList.share、reportList.shareAriaLabel、reportList.shareTitle、reportList.shareDescription、reportList.shareLinkLabel、reportList.copyLink、reportList.copyLinkSuccess、reportList.copyLinkFailed、reportList.shareLinkAriaLabel共 9 个键仍保留在翻译文件中,但 v1-P1-3 已移除分享按钮,这些键不再被引用。 - 违反规则:项目规则精神——保持代码与配置一致,避免死代码。
- 原因:移除分享按钮时未清理对应的 i18n 键。
- 后果:翻译文件臃肿,维护成本增加;新增语言时需翻译无用的键。
问题 2.1.4 | 热力图 aria-label 硬编码中文标点格式(P1)
- 位置:class-diagnostic-view.tsx#L195
- 现象:
aria-label={${kp.knowledgePointName}:${kp.averageMastery.toFixed(1)}%,${levelLabel},${kp.masteredCount}/${kp.totalStudents}}使用硬编码中文全角冒号":"和逗号","。 - 违反规则:项目规则"所有用户可见文本必须适配 i18n"。
- 原因:aria-label 拼接时未使用 i18n 模板。
- 后果:英文环境下屏幕阅读器读出中文标点,影响无障碍体验。
问题 2.1.5 | export.ts 错误消息硬编码英文(P2)
- 位置:export.ts#L28:
throw new Error("Report not found") - 现象:导出报告不存在时抛出硬编码英文错误。
- 违反规则:项目规则"所有用户可见文本必须适配 i18n"。
- 后果:中文环境下用户看到英文错误消息。
2.2 权限与安全
问题 2.2.1 | grade_managed DataScope 未过滤(P1,安全漏洞)
- 位置:data-access-reports.ts#L220-238
- 现象:
getDiagnosticReports仅处理children和class_taught两种 DataScope,对grade_managed(年级主任)和class_members(学生)scope 不做任何过滤。代码注释明确写道:// grade_managed 需要跨模块查询年级学生,由调用方自行过滤。 - 违反规则:项目规则"所有敏感数据查询必须在 data-access 层结合当前用户权限过滤,Server Action 二次校验"。
- 原因:grade_managed scope 需要跨模块查询年级学生 ID(通过
getUserIdsByGradeId),实现时为避免跨模块依赖未在 data-access 层完成过滤。 - 后果:年级主任(grade_head / teaching_head)角色调用时,
getDiagnosticReports返回全校所有学生的诊断报告,存在数据越权风险。虽然当前 teacher/diagnostic/page.tsx 在客户端对 class_members 做了二次过滤,但 grade_managed 完全未过滤。
问题 2.2.2 | 教师报告列表页客户端过滤 class_members(P2)
- 位置:teacher/diagnostic/page.tsx#L56-59
- 现象:
const visibleReports = ctx.dataScope.type === "class_members" ? reports.reports.filter((r) => r.studentId === ctx.userId) : reports.reports - 违反规则:项目规则"所有敏感数据查询必须在 data-access 层结合当前用户权限过滤"——客户端过滤不安全。
- 原因:教师页面理论上不应被学生角色访问,但代码保留了 class_members 分支作为防御性过滤。这种过滤应在 data-access 层完成。
- 后果:虽然不影响功能(学生不会访问教师路由),但违背了"数据过滤在 data-access 层"的原则,且 data-access 已返回了不该返回的数据。
2.3 架构解耦
问题 2.3.1 | 组件直接 import actions,无服务接口抽象(P1)
- 位置:
- report-list.tsx#L41:
import { publishReportAction, deleteReportAction, exportDiagnosticReportAction } from "../actions" - class-diagnostic-view.tsx#L33:
import { generateClassReportAction, getClassStudentsByKnowledgePointAction } from "../actions"
- report-list.tsx#L41:
- 现象:客户端组件直接 import 并调用 Server Actions,未通过接口抽象或依赖注入。
- 违反规则:项目规则"通过定义 TypeScript 接口抽象数据依赖,使用 React Context 注入数据服务,模块内部组件绝不直接 import 其他业务模块的 actions 或 data-access(只能通过注入的接口调用)"。
- 原因:v1 审计将此项列为"后续建议"未实施,但用户在本次审计中将其升级为强制要求。
- 后果:组件无法独立测试(测试时必须 mock 整个 actions 模块);无法在不修改组件代码的情况下替换 actions 实现;组件与 Server Action 实现紧耦合。
2.4 错误处理与边界
问题 2.4.1 | 无 Error Boundary 包裹独立数据区块(P1)
- 位置:
- student-diagnostic-view.tsx:概览卡片、雷达图、强弱项、报告、历史列表均在同一组件内,无 Error Boundary 隔离。
- class-diagnostic-view.tsx:概览、热力图、筛选、排名、关注列表、生成报告均在同一组件内。
- 现象:仅页面级有 error.tsx 错误边界,组件内部各数据区块无独立 Error Boundary。
- 违反规则:项目规则"每个独立的数据区块必须用 React Error Boundary 包裹"。
- 原因:v4-P2 已将 WidgetBoundary 提升到 shared 层并用于页面级包裹,但未下沉到组件内部各数据区块。
- 后果:雷达图渲染失败会导致整个诊断页面崩溃;热力图数据异常会波及排名表和关注列表。
问题 2.4.2 | 异步数据无 Suspense + 骨架屏(P2)
- 位置:所有页面均使用
await Promise.all一次性获取所有数据后传给客户端组件。 - 现象:未使用 React Suspense 流式渲染,数据获取完成前整个页面阻塞。
- 违反规则:项目规则"异步数据使用 React Suspense + 骨架屏"。
- 后果:首屏白屏时间长;无法渐进式展示数据区块。
2.5 可测试性与置信度
问题 2.5.1 | 置信度计算过于简化(P1)
- 位置:confidence-utils.ts#L18-21
- 现象:
getConfidenceLevel仅判断overallScore === null返回 "insufficient",否则一律返回 "high"。注释承认"后续可扩展为基于 totalQuestions 等数据量字段的多级判断",但未实施。 - 违反规则:项目规则"数据获取、计算、格式化等纯逻辑全部放入纯函数或 hooks,与 UI 分离"——置信度计算虽已提取为纯函数,但逻辑不完整。
- 原因:v4-P3-7 引入置信度时为简化首版,未实现多级判断。
- 后果:仅做了 1 道题的报告也显示"高置信度",误导教师判断报告可信度。
问题 2.5.2 | stats-service 14 个纯函数无单测(P2)
- 位置:stats-service.ts
- 现象:14 个纯函数(
computeAverageMastery、classifyStrengthsWeaknesses、aggregateClassMastery等)已正确提取为纯函数,但无对应的单元测试文件。 - 违反规则:项目规则"可测试性:数据获取、计算、格式化等纯逻辑全部放入纯函数或 hooks,与 UI 分离;导出清晰的接口类型以便 mock"。
- 后果:统计数据计算逻辑变更无回归保障;P3-16 弱项阈值修复这类边界 case 无法自动验证。
2.6 可复用性与扩展性
问题 2.6.1 | 雷达图知识点名称截断无 tooltip(P2)
- 位置:mastery-radar-chart.tsx#L22-26
- 现象:
shortName: d.knowledgePoint.length > 8 ? ${d.knowledgePoint.slice(0, 8)}... : d.knowledgePoint截断超过 8 字符的知识点名称,但未提供 tooltip 显示完整名称。 - 违反规则:项目规则"明确处理空数据、无权限、网络异常等边界状态"——信息截断是边界状态。
- 后果:长名称知识点被截断,用户无法查看完整名称,影响数据理解。
问题 2.6.2 | 通知类型使用 "grade" 而非专用类型(P2)
- 位置:actions.ts#L157, L173
- 现象:
createNotification({ type: "grade", ... })诊断报告发布通知复用了成绩通知类型 "grade"。 - 违反规则:项目规则精神——类型应语义准确,便于分类与过滤。
- 后果:学生无法区分"成绩通知"和"诊断报告通知";通知筛选功能无法按类型精确过滤诊断报告。
问题 2.6.3 | 无监控埋点接口(P2)
- 位置:整个模块无任何监控/埋点代码。
- 现象:报告生成、发布、删除、导出等关键操作无埋点。
- 违反规则:项目规则"监控:方案中预留关键操作埋点接口"。
- 后果:无法追踪诊断报告的使用情况;无法度量报告生成/发布转化率;异常无法主动发现。
2.7 parent 页面细节
问题 2.7.1 | parent/diagnostic/page.tsx noRecordsTitle 与 noRecordsDescription 重复(P2)
- 位置:parent/diagnostic/page.tsx#L97-98
- 现象:
noRecordsTitle={t("parent.noReports")}和noRecordsDescription={t("parent.noReports")}使用同一个 i18n 键。 - 原因:复制粘贴时未区分标题和描述。
- 后果:空状态时标题和描述显示相同文本,UI 不够精细。
三、行业差距对比
对标 PowerSchool、Infinite Campus、Skyward、Alma、智学网、班级小管家、超星学习通、ClassIn 等 K12 系统,本模块在 v1/v4 修复后仍有以下差距:
| 维度 | 优秀实践 | 本模块现状 | 影响 |
|---|---|---|---|
| 掌握度时间线 | PowerSchool/智学网支持掌握度时间线,展示知识点掌握度随时间的变化趋势,支持按知识点钻取历史 | 仅展示当前快照,knowledgePointMastery 表无历史版本,lastAssessedAt 仅记录最近一次 |
教师无法判断学生是否在进步或退步;无法评估教学干预效果 |
| 个性化学习路径 | Alma/智学网基于弱项推荐具体学习资源(题目、视频、文档),形成学习路径 | 仅提供练习按钮跳转题目库,无资源推荐算法 | 推荐不够精准,学生需自行筛选练习内容 |
| 学生×知识点掌握度矩阵 | Infinite Campus/Alma 提供学生×知识点矩阵热力图,支持点击单元格查看明细 | 班级视图仅有知识点聚合热力图,无学生维度矩阵 | 教师无法快速定位"哪个学生在哪个知识点上薄弱" |
| 预测性分析(at-risk 预警) | PowerSchool/Infinite Campus 基于历史数据预测 at-risk 学生,提前干预 | 无预测模型,仅基于当前掌握度 <60 判定需关注 | 无法主动预警,错失早期干预窗口 |
| 报告模板自定义 | PowerSchool 支持学校自定义报告模板(推荐话术、评分区间、logo) | 报告内容固定由 stats-service 生成,仅 i18n 可切换语言 | 无法按学校需求定制报告风格 |
| 多维度诊断 | Infinite Campus 结合成绩+出勤+行为做多维综合诊断 | 仅基于知识点掌握度单一维度 | 诊断维度单一,无法反映学生综合学习状态 |
| PDF 导出 | 所有对标系统支持 PDF 导出(便于打印分发) | 仅支持 Excel 导出 | 无法满足打印分发场景 |
| 数据置信度可视化 | Alma 在报告上标注数据量与置信度,帮助教师判断结论可靠性 | 置信度计算过于简化(仅 null/非 null 两级) | 教师无法判断报告可信度 |
| 流式渲染 | 现代 K12 系统使用 React Suspense 流式渲染,首屏快速可见 | 全部 await Promise.all 阻塞渲染 |
首屏白屏时间长 |
四、改进优先级建议
P0(紧急,影响核心规范或安全)
| 编号 | 问题 | 改进方向 |
|---|---|---|
| v2-P0-1 | 3 个子路由 error.tsx 硬编码中文 | 接入 useTranslations("diagnostic"),新增对应 i18n 键 |
P1(重要,影响安全/解耦/一致性)
| 编号 | 问题 | 改进方向 |
|---|---|---|
| v2-P1-1 | grade_managed DataScope 未过滤 | 在 data-access-reports.ts 中处理 grade_managed scope,调用 getUserIdsByGradeId 过滤 |
| v2-P1-2 | i18n 弱项标签与代码逻辑不一致 | 更新 i18n 标签为"弱项(<80%)" |
| v2-P1-3 | 热力图 aria-label 硬编码中文标点 | 使用 i18n 模板键 heatmapCellAriaLabel |
| v2-P1-4 | 组件直接 import actions 无接口抽象 | 定义 DiagnosticService 接口,通过 React Context 注入;组件通过 useDiagnosticService() 获取 |
| v2-P1-5 | 置信度计算过于简化 | 基于 totalQuestions 实现多级置信度(<5 insufficient / 5-15 low / 16-30 medium / >30 high) |
| v2-P1-6 | 无 Error Boundary 包裹独立数据区块 | 在概览、雷达图、强弱项、报告、历史等区块外包裹 WidgetBoundary |
P2(增强,提升完整性与企业级能力)
| 编号 | 问题 | 改进方向 |
|---|---|---|
| v2-P2-1 | 死 i18n 键未清理 | 移除 9 个 share 相关 i18n 键 |
| v2-P2-2 | 教师页面客户端过滤 class_members | 在 data-access 层过滤,移除客户端 filter |
| v2-P2-3 | export.ts 错误消息硬编码 | 改用 DiagnosticReportError 结构化错误码 |
| v2-P2-4 | 异步数据无 Suspense 流式渲染 | 拆分数据获取为独立 async 组件,使用 Suspense 包裹(中长期) |
| v2-P2-5 | 雷达图名称截断无 tooltip | 为截断的名称添加 Tooltip 显示完整名称 |
| v2-P2-6 | 通知类型使用 "grade" | 新增 "diagnostic" 通知类型(需 notifications 模块配合) |
| v2-P2-7 | 无监控埋点接口 | 定义 DiagnosticMonitor 接口,在关键操作处调用 |
| v2-P2-8 | stats-service 无单测 | 为 14 个纯函数补充单元测试 |
| v2-P2-9 | parent noRecordsTitle/Description 重复 | 区分标题和描述 i18n 键 |
P3(长期,需较大投入)
| 编号 | 问题 | 改进方向 |
|---|---|---|
| v2-P3-1 | 掌握度时间线 | 新增 knowledgePointMasteryHistory 表记录历史版本,前端展示时间线图表 |
| v2-P3-2 | 个性化学习路径推荐 | 基于弱项推荐具体学习资源 |
| v2-P3-3 | 学生×知识点掌握度矩阵 | 新增矩阵视图组件 |
| v2-P3-4 | 预测性分析 | 基于 historical mastery 训练 at-risk 预测模型 |
| v2-P3-5 | 报告模板自定义 | 允许学校配置报告模板 |
| v2-P3-6 | PDF 导出 | 新增 PDF 导出能力 |
五、架构图同步说明
本次 v2 审计发现架构图需同步以下内容:
004_architecture_impact_map.md §2.22
- 已知问题新增:
- 记录 v2-P0-1 三个子路由 error.tsx 硬编码中文及修复
- 记录 v2-P1-1 grade_managed DataScope 未过滤及修复
- 记录 v2-P1-4 组件解耦 Context 注入
- 记录 v2-P1-5 置信度计算改进
- 记录 v2-P1-6 数据区块 Error Boundary 包裹
- 依赖关系更新:标注 diagnostic 模块新增
DiagnosticServiceContext依赖注入机制
005_architecture_data.json
modules.diagnostic.exports补充DiagnosticService接口、DiagnosticServiceProvider、useDiagnosticServicehookmodules.diagnostic.knownIssues新增 v2 系列问题记录modules.diagnostic.dependencies标注 grade_managed scope 现已调用getUserIdsByGradeId过滤
六、实施计划
6.1 本次实施范围(P0 + P1 + 可快速完成的 P2)
本次实施 P0 全部 + P1 全部 + 6 项 P2,P3 长期项记录备查不实施。
6.2 重构方案设计(满足强制原则)
完全解耦
定义 TypeScript 接口 DiagnosticService 抽象所有数据依赖:
// src/modules/diagnostic/services/diagnostic-service.ts
export interface DiagnosticService {
generateStudentReport(studentId: string, period: string): Promise<string>
generateClassReport(classId: string, period: string): Promise<string>
generateGradeReport(gradeId: string, period: string): Promise<string>
publishReport(id: string): Promise<void>
deleteReport(id: string): Promise<void>
exportReport(reportId: string): Promise<{ buffer: string; filename: string }>
getClassStudentsByKp(classId: string, kpId: string, threshold?: number): Promise<...>
}
通过 React Context 注入:
// src/modules/diagnostic/services/diagnostic-service-context.tsx
const DiagnosticServiceContext = createContext<DiagnosticService | null>(null)
export function DiagnosticServiceProvider({ service, children }) { ... }
export function useDiagnosticService(): DiagnosticService { ... }
默认实现绑定现有 Server Actions;测试时可注入 mock 实现。
组合优先
StudentDiagnosticView、ClassDiagnosticView、ReportList通过children/ slots 组合子区块。- 逻辑复用提取为
useDiagnosticActionshook(内部调用useDiagnosticService())。
国际化就绪
- 所有新增文本使用
diagnostic.*命名空间翻译键。 - aria-label 模板使用 i18n 占位符:
heatmapCellAriaLabel: "{name}:{level}%,{label},{mastered}/{total}"。
最大化复用
DiagnosticSection通用区块组件(含 WidgetBoundary + Suspense + 标题 + 内容 slot)。useDiagnosticActionshook 统一封装 actions 调用 + toast + router.refresh。
错误与边界处理
- 每个数据区块外包裹
WidgetBoundary。 - 异步子区块使用
Suspense+ 骨架屏(本次仅在页面级流式拆分,组件级 Suspense 列入 P2-4 长期)。
可测试性
DiagnosticService接口清晰,可 mock。confidence-utils置信度计算改为基于totalQuestions的多级判断。
可扩展性
- 角色差异通过
role-config.ts配置驱动(v4-P2-2 已实现)。 - 通知类型、监控埋点通过接口预留扩展点。
企业级补充
- a11y:热力图 aria-label i18n 化;雷达图 tooltip。
- 性能:保持 RSC 获取初始数据。
- 安全:grade_managed scope 在 data-access 层过滤。
- 监控:定义
DiagnosticMonitor接口预留埋点。
6.3 翻译文件结构示例
{
"diagnostic": {
"error": {
"classLoadFailed": "班级学情诊断加载失败",
"classLoadFailedDesc": "抱歉,加载班级诊断数据时发生了意外错误。请稍后重试。",
"studentLoadFailed": "学生学情诊断加载失败",
"studentLoadFailedDesc": "抱歉,加载学生诊断数据时发生了意外错误。请稍后重试。",
"parentLoadFailed": "子女学情诊断加载失败",
"parentLoadFailedDesc": "抱歉,加载子女诊断数据时发生了意外错误。请稍后重试。",
"retry": "重试"
},
"weaknesses": {
"title": "弱项(<80%)"
},
"classDiagnostic": {
"heatmapCellAriaLabel": "{name}:{level}%,{label},{mastered}/{total}"
},
"reportList": {
"radarPointTooltip": "{fullName}"
}
}
}