Files
NextEdu/bugs/admin_bug_v2.md
SpecialX 978d9a8309
Some checks failed
Security / deep-security-scan (push) Failing after 20m5s
DR Drill / dr-drill (push) Failing after 1m31s
CI / scheduled-backup (push) Failing after 1m31s
CI / backup-verify (push) Has been skipped
CI / weekly-dr-drill (push) Failing after 0s
CI / build-deploy (push) Has been cancelled
CI / security-scan (push) Has been cancelled
feat: 新增备课模块并修复全模块 P0/P1/P2 缺陷
主要变更:

- 新增 lesson-preparation 模块: 备课编辑器、节点编辑、AI 建议、知识点选择、版本历史、作业发布

- 新增 shared 通用组件: charts/question-bank-filters/schedule-list/ui (chip-nav/filter-bar/page-header/stat-card/stat-item)

- 新增 student/admin 端 loading.tsx 与 error.tsx, 优化加载与错误态体验

- 新增 teacher/lesson-plans 页面 (列表/新建/编辑)

- 新增 drizzle 迁移 0002_tiny_lionheart 及 snapshot

- 新增 textbooks/schema.ts 与 exams/utils/normalize-structure.ts

- 修复 Tiptap v3 SSR hydration 崩溃 (rich-text-block immediatelyRender: false)

- 重构多模块 data-access/actions/组件, 修复权限校验与类型规范

- 同步架构文档 004/005 反映新增模块、导出、依赖关系

- 归档 bugs/* 测试报告与 e2e 测试脚本 (admin/parent/student/teacher web_test)
2026-06-22 01:06:16 +08:00

27 KiB
Raw Blame History

Admin 前端文件规范核查报告 v2

版本v2基于 v1 报告的二次复查) 核查范围:src/app/(dashboard)/admin/ 下全部 26 个 page.tsx 文件 核查依据:

  • .trae/rules/project_rules.md(项目规则)
  • docs/standards/coding-standards.md(编码规范 v1.0
  • docs/architecture/004_architecture_impact_map.md(架构影响地图)
  • React / Next.js 16 最佳实践
  • Web 界面设计规范WCAG 2.2 AA 核查日期2026-06-18v2 上次核查2026-06-18v1

、v1 → v2 修复状态追踪

重要说明:本次复查发现,自 v1 报告(bugs/admin_bug.md)输出后,src/app/(dashboard)/admin/ 下全部 26 个 page.tsx 文件内容均未发生任何修改src/shared/lib/utils.ts 也未新增共享工具函数。v1 报告提出的所有问题全部未修复

v1 问题修复状态对照表

v1 编号 问题 严重级别 v2 状态 备注
P0-1 全部 26 个页面缺少 error.tsx / loading.tsx P0 未修复 仍无任何 error/loading 边界文件
P0-2 attendance/page.tsx 缺少权限校验 P0 未修复 第 26 行仍为 getAuthContext(),未加 requirePermission
P1-1 全部 26 个页面组件缺少返回类型标注 P1 未修复 全部页面函数仍无 : Promise<JSX.Element>
P1-2 getParam 工具函数在 27 个文件中重复 P1 未修复 shared/lib/utils.ts 未新增 getSearchParam
P1-3 4 个文件使用 as 类型断言 P1 未修复 audit-logs/*attendance 仍用 as
P1-4 UI 文案中英文混用 P1 未修复 users/import 为中文,其余仍英文
P2-1 school/grades/insights 使用原生 <select> P2 未修复 第 57-68 行仍为原生 <select>
P2-2 users/import 使用原生 <table> P2 未修复 第 93-128 行仍为原生 <table>
P2-3 Tailwind 任意值违规 P2 未修复 md:w-[360px]h-[360px] 仍存在
P2-4 users/import 硬编码颜色 text-amber-500 P2 未修复 第 67 行未变
P2-5 school/grades/insights 导入顺序违规 P2 未修复 lucide-react 仍在最后
P2-6 course-plans/[id]/edit 同模块重复导入 P2 未修复 第 3-4 行仍分两行
P2-7 scheduling/*actions 取数 P2 未修复 仍从 @/modules/scheduling/actions 导入

结论v1 提出的 2 个 P0 + 4 个 P1 + 7 个 P2 = 13 个问题0 个已修复


一、v2 新增发现v1 遗漏的问题)

本次复查在 v1 基础上深度审查,新发现 10 个问题

P1 重要问题v2 新增)

P1-5v2 新增)attendance/page.tsx 第 39 行违反 Prettier printWidth: 100

文件src/app/(dashboard)/admin/attendance/page.tsx

违反规范

  • .prettierrc 配置 "printWidth": 100
  • 编码规范 §十五「Prettier 自动保证格式一致」

现状:第 39 行单行长度约 115 字符,超出 100 字符限制:

    status: status && status !== "all" ? (status as "present" | "absent" | "late" | "early_leave" | "excused") : undefined,

说明:项目 .prettierrc 已配置 printWidth: 100,但此行未触发格式化,可能是因为该文件未经过 prettier --write 处理,或 ESLint 未强制 Prettier 规则。

修复建议:抽取状态类型守卫后自然换行(同时解决 P1-3 的 as 断言问题):

const isValidAttendanceStatus = (v?: string): v is AttendanceStatus =>
  v === "present" || v === "absent" || v === "late" || v === "early_leave" || v === "excused"

// 在组件内
status: status && status !== "all" && isValidAttendanceStatus(status) ? status : undefined,

P1-6v2 新增)school/grades/insights/page.tsxgetParam 实现与其他文件不一致

文件src/app/(dashboard)/admin/school/grades/insights/page.tsx

现状:该文件的 getParam 实现与其他 8 个 admin 页面逻辑等价但写法不同

// school/grades/insights/page.tsx第 17-22 行)—— 三分支写法
const getParam = (params: SearchParams, key: string) => {
  const v = params[key]
  if (typeof v === "string") return v
  if (Array.isArray(v)) return v[0]
  return undefined
}

// 其他 8 个 admin 页面 —— 三元写法
const getParam = (params: SearchParams, key: string) => {
  const v = params[key]
  return Array.isArray(v) ? v[0] : v
}

影响:加剧 P1-2 的 DRY 问题,两种实现并存增加维护成本,且 v[0]noUncheckedIndexedAccess 开启后返回 string | undefined,两种写法的类型推导行为可能不同。

修复建议:与 P1-2 一并解决,抽取到 shared/lib/utils.ts 统一实现。


P1-7v2 新增)attendance/page.tsx 第 39 行使用内联字面量类型而非 AttendanceStatus 类型

文件src/app/(dashboard)/admin/attendance/page.tsx

违反规范

  • 编码规范 §4.2:「优先 interface 描述对象形状,type 用于联合、交叉、映射类型」
  • DRY 原则

现状:第 39 行内联了 5 个字面量类型,而非引用 AttendanceStatus 类型:

status as "present" | "absent" | "late" | "early_leave" | "excused"

说明@/modules/attendance/types 应已定义 AttendanceStatus 类型(其他模块如 announcementsschedulingcourse-planselective 均有对应 status 类型导出)。内联字面量导致类型定义重复,若枚举值变更需多处修改。

修复建议

import type { AttendanceStatus } from "@/modules/attendance/types"

const isValidAttendanceStatus = (v?: string): v is AttendanceStatus =>
  v === "present" || v === "absent" || v === "late" || v === "early_leave" || v === "excused"

P2 一般问题v2 新增)

P2-8v2 新增)school/grades/insights/page.tsx 第 24 行 fmt 工具函数内联定义

文件src/app/(dashboard)/admin/school/grades/insights/page.tsx

违反规范

  • 编码规范 §一:「单一职责」
  • 编码规范 §5.3:「工具函数 ≤ 40 行」(此函数 1 行,但属于通用工具应抽取)

现状:第 24 行内联定义数字格式化函数:

const fmt = (v: number | null, digits = 1) => (typeof v === "number" && Number.isFinite(v) ? v.toFixed(digits) : "-")

影响:该函数为通用数字格式化工具,可能在其他统计页面(如 teacher/grades/statsmanagement/grade/insights)重复出现。

修复建议:抽取到 shared/lib/utils.ts

export function formatNumber(v: number | null | undefined, digits = 1): string {
  if (typeof v !== "number" || !Number.isFinite(v)) return "-"
  return v.toFixed(digits)
}

P2-9v2 新增)school/grades/insights/page.tsx 第 137 行可用可选链简化

文件src/app/(dashboard)/admin/school/grades/insights/page.tsx

现状:第 137 行使用三元表达式而非可选链:

<div className="text-xs text-muted-foreground">{insights.latest ? insights.latest.title : "-"}</div>

修复建议:使用可选链 + 空值合并:

<div className="text-xs text-muted-foreground">{insights.latest?.title ?? "-"}</div>

说明:同文件第 136 行已使用 insights.latest?.scoreStats.avg ?? null,写法不一致。


P2-10v2 新增)school/page.tsx 缺少 export const dynamic 声明

文件src/app/(dashboard)/admin/school/page.tsx

现状:该文件仅 5 行,使用 redirect() 跳转,但未声明 export const dynamic = "force-dynamic"

import { redirect } from "next/navigation"

export default function AdminSchoolPage() {
  redirect("/admin/school/classes")
}

对比admin 目录下其他 25 个页面均声明了 export const dynamic = "force-dynamic",仅此文件缺失。

影响Next.js 可能在构建时尝试静态生成此页面,redirect() 在静态生成阶段的行为与运行时不同,可能导致构建警告或行为不一致。

修复建议:补充声明:

import { redirect } from "next/navigation"

export const dynamic = "force-dynamic"

export default function AdminSchoolPage(): never {
  redirect("/admin/school/classes")
}

redirect() 抛出异常永不返回,返回类型应标注为 never


P2-11v2 新增)users/import/page.tsx 是同步函数但无 dynamic 导出,与其他页面不一致

文件src/app/(dashboard)/admin/users/import/page.tsx

现状:第 14 行为同步函数组件,且无 export const dynamic 声明:

export default function UserImportPage() {
  return ( /* ... */ )
}

对比admin 目录下其他 24 个数据获取页面均声明 export const dynamic = "force-dynamic",仅此文件与 school/page.tsx 缺失。

说明:该页面为纯静态内容(无数据获取),理论上可静态生成,但与 admin 路由组整体策略不一致。需明确决策:

  • 若 admin 路由组统一 force-dynamic(因权限校验需运行时),则此页面应补充声明
  • 若允许静态页面,则应在架构文档中说明例外

修复建议:为保持一致性,补充 export const dynamic = "force-dynamic",或显式注释说明为何例外。


P2-12v2 新增)多个编辑页缺少返回上一页的导航

违反规范

  • Web 界面设计规范:「焦点管理必须合理」
  • 用户体验最佳实践:「始终提供返回路径」

现状:以下编辑/创建页面未提供返回按钮,用户只能通过浏览器后退或侧边栏导航:

文件 是否有返回按钮
announcements/[id]/page.tsx
course-plans/create/page.tsx 无(仅 CoursePlanFormbackHref prop
course-plans/[id]/page.tsx 无(仅 CoursePlanDetailbackHref prop
course-plans/[id]/edit/page.tsx 无(仅 CoursePlanFormbackHref prop
elective/create/page.tsx 无(仅 ElectiveCourseFormbackHref prop
elective/[id]/edit/page.tsx 无(仅 ElectiveCourseFormbackHref prop
users/import/page.tsx 有(第 20-25 行 ArrowLeft 返回按钮)

说明users/import/page.tsx 在页面顶部提供了显式的返回按钮(<Button asChild variant="ghost"><Link href="/admin/dashboard"><ArrowLeft /> 返回</Link></Button>),是正确的做法。其他编辑页虽通过子组件的 backHref prop 传递了返回路径,但返回入口依赖子组件内部实现,页面层未统一控制。

修复建议:在所有编辑/创建页面顶部统一添加返回按钮,与 users/import/page.tsx 保持一致;或将返回按钮抽取为共享组件 PageBackButton


P2-13v2 新增)大部分页面缺少 metadata 导出

违反规范

  • Next.js 16 最佳实践:「页面应导出 metadata 用于 SEO 与标签页标题」
  • 编码规范 §十四:「文档与交付物」

现状

文件 是否导出 metadata
users/import/page.tsx 有(第 9-12 行)
其余 25 个页面

影响:浏览器标签页标题默认显示全局标题,无法区分当前所在 admin 子页面,影响用户体验(多个标签页难以区分)。

修复建议:为每个页面补充 metadata 导出:

import type { Metadata } from "next"

export const metadata: Metadata = {
  title: "审计日志 - Next_Edu",
  description: "查看系统所有用户操作记录",
}

P2-14v2 新增)school/grades/insights/page.tsx 使用原生 <form method="get"> 导致整页刷新

文件src/app/(dashboard)/admin/school/grades/insights/page.tsx

现状:第 55-72 行使用原生 HTML <form action="/admin/school/grades/insights" method="get"> 提交筛选器,会导致整页刷新,丢失当前滚动位置与页面状态。

违反规范

  • 编码规范 §7.3「URL 状态:使用 nuqs(已集成)」
  • React 最佳实践:「避免不必要的整页刷新」

影响

  • 用户体验差:每次筛选都触发整页白屏加载(叠加 P0-1 缺少 loading.tsx 问题更严重)
  • 与项目已集成的 nuqs URL 状态管理方案不一致
  • 其他筛选页(audit-logs/*attendance)使用子组件内的客户端筛选,此页面是唯一使用原生 form 提交的

修复建议

  1. 方案 A推荐:将筛选器提取为客户端组件,使用 nuqsuseQueryState 管理 gradeId 参数,实现无刷新筛选
  2. 方案 B最小改动:保持服务端筛选,但补充 loading.tsx 缓解白屏问题

二、v2 核查概览(含 v1 + v2 全部问题)

维度 文件数 通过 待改进 v2 新增
架构分层 26 24 2 0
TypeScript 规范 26 4 22 +3
安全与权限 26 3 23 0
UI 一致性与设计令牌 26 18 8 +1
错误与加载边界 26 0 26 0
代码复用DRY 26 0 26 +2
格式化Prettier 26 25 1 +1
导航与 UX 26 1 25 +2
SEOmetadata 26 1 25 +1

累计问题数v1 的 13 个 + v2 新增 10 个 = 23 个问题,全部未修复。


三、v2 问题清单汇总(按严重程度排序)

P0 严重(必须立即修复)

编号 问题 v1/v2 文件
P0-1 全部 26 个页面缺少 error.tsx / loading.tsx v1 全部
P0-2 attendance/page.tsx 缺少 requirePermission 权限校验 v1 attendance/page.tsx

P1 重要(应尽快修复)

编号 问题 v1/v2 文件
P1-1 全部 26 个页面缺少返回类型 Promise<JSX.Element> v1 全部
P1-2 getParam 在 27 个文件重复定义 v1 9 个 admin 文件
P1-3 4 个文件使用 as 类型断言 v1 audit-logs/*attendance
P1-4 UI 文案中英文混用 v1 ~20 个文件
P1-5 attendance 第 39 行超 printWidth: 100 v2 attendance/page.tsx
P1-6 school/grades/insightsgetParam 实现不一致 v2 school/grades/insights/page.tsx
P1-7 attendance 使用内联字面量而非 AttendanceStatus 类型 v2 attendance/page.tsx

P2 一般(建议修复)

编号 问题 v1/v2 文件
P2-1 school/grades/insights 使用原生 <select> v1 school/grades/insights/page.tsx
P2-2 users/import 使用原生 <table> v1 users/import/page.tsx
P2-3 Tailwind 任意值 w-[360px]h-[360px] v1 school/grades/insights/page.tsx
P2-4 users/import 硬编码颜色 text-amber-500 v1 users/import/page.tsx
P2-5 school/grades/insights 导入顺序违规 v1 school/grades/insights/page.tsx
P2-6 course-plans/[id]/edit 同模块重复导入 v1 course-plans/[id]/edit/page.tsx
P2-7 scheduling/*actions 取数 v1 scheduling/*
P2-8 fmt 工具函数内联定义 v2 school/grades/insights/page.tsx
P2-9 第 137 行可用可选链简化 v2 school/grades/insights/page.tsx
P2-10 school/page.tsx 缺少 export const dynamic v2 school/page.tsx
P2-11 users/import 缺少 dynamic 声明(不一致) v2 users/import/page.tsx
P2-12 多个编辑页缺少返回按钮 v2 6 个编辑/创建页
P2-13 25 个页面缺少 metadata 导出 v2 25 个文件
P2-14 原生 <form method="get"> 整页刷新 v2 school/grades/insights/page.tsx

四、React 性能优化建议v2 更新)

R1 利用 Suspense 流式渲染v1 提出,未实施)

现状:所有页面使用 export const dynamic = "force-dynamic" 整页动态渲染。

建议:对数据量大的页面(audit-logs/*school/grades/insightsattendance)拆分 Suspense 边界。详见 v1 报告 R1。

R2 school/grades/insights/page.tsx 串行查询可并行v1 提出,未实施)

现状:第 30-33 行 getGrades()getGradeHomeworkInsights() 串行执行,但两者无数据依赖。

建议:改为 Promise.all 并行。详见 v1 报告 R2。

R3 列表页 classOptions 映射可下沉至 data-accessv1 提出,未实施)

详见 v1 报告 R3。

R4v2 新增)school/grades/insights/page.tsx 表格未虚拟化,大数据量下性能风险

文件src/app/(dashboard)/admin/school/grades/insights/page.tsx

现状:第 164-180 行与第 208-220 行使用 insights.assignments.map()insights.classes.map() 直接渲染整张表格,无分页或虚拟化。

说明getGradeHomeworkInsights({ limit: 50 }) 限制为 50 条,但 insights.classes 无限制,大型学校(如 50+ 班级的年级)可能渲染数百行 DOM 节点。

修复建议

  • 短期:在 data-access 层对 classes 也加 limit
  • 长期:引入 @tanstack/react-virtual 虚拟化长列表

五、Web 界面设计规范建议v2 更新)

W1-W5v1 提出,未实施)

详见 v1 报告第四部分:<label> 关联、表格 <caption>、标题层级、aria-liveEmptyState 图标语义。

W6v2 新增)school/grades/insights/page.tsx 原生 <select> 缺少 ARIA 属性

文件src/app/(dashboard)/admin/school/grades/insights/page.tsx

现状:第 57-68 行原生 <select> 缺少 aria-labelaria-labelledby,且 <label> 未通过 htmlFor 关联v1 W1 已记录)。

违反WCAG 2.2 SC 4.1.2(名称、角色、值)。

补充建议:除 v1 建议的 htmlFor/id 关联外,建议直接替换为 shadcn Select 组件P2-1该组件已内置 ARIA 支持。

W7v2 新增)attendance/page.tsx 筛选器无 aria-live 反馈

文件src/app/(dashboard)/admin/attendance/page.tsx

现状AttendanceFilters(客户端组件)提交后,AttendanceRecordList 数据刷新,但屏幕阅读器用户无法感知。

说明:此问题与 v1 W4 相同,但 v1 仅提及 school/grades/insightsattendanceaudit-logs/*,未明确 attendance 的具体位置。

修复建议:在 AttendanceRecordList 容器添加 aria-live="polite",或使用 useAriaLive Hook 通知「已加载 N 条记录」。


六、优秀实践(已符合规范,应保持)

与 v1 报告第五部分一致,本次复查确认以下优秀实践仍然成立:

  1. 服务端组件默认化:全部 26 个页面均为 async 服务端组件,未滥用 "use client"
  2. 并行数据获取:多个页面使用 Promise.all 并行查询。
  3. 类型守卫正确使用announcementsscheduling/changescourse-planselective 使用 isValidStatus 类型守卫。
  4. 404 处理:动态路由页面使用 notFound()
  5. 权限校验到位audit-logs/*files/page.tsx 正确调用 requirePermission()
  6. 模块化组合页面仅负责数据获取与组合UI 逻辑下沉至 modules/*/components/
  7. force-dynamic 标注24/26 个页面显式声明(school/page.tsxusers/import 除外,见 P2-10、P2-11
  8. metadata 导出users/import/page.tsx 正确导出(见 P2-13建议推广
  9. ESLint 通过:本次复查运行 npx eslint "src/app/(dashboard)/admin/**/*.tsx"npx tsc --noEmit 均通过,无编译错误。

七、v2 修复优先级与建议执行顺序

优先级 问题编号 建议执行顺序 影响范围 v1/v2
P0 P0-2 立即修复 attendance 权限 1 文件 v1
P0 P0-1 补充 error.tsx / loading.tsx 新增 ~6 文件 v1
P1 P1-1 补充返回类型标注 26 文件 v1
P1 P1-2 + P1-6 抽取共享 getSearchParam(统一两种实现) 27 文件 v1+v2
P1 P1-3 + P1-5 + P1-7 attendance 类型守卫重构(一并解决 3 个问题) 1 文件 v1+v2
P1 P1-4 统一 UI 文案语言 ~20 文件 v1
P2 P2-5 + P2-6 修复导入顺序与重复导入 2 文件 v1
P2 P2-10 + P2-11 补充 dynamic 声明 2 文件 v2
P2 P2-1 + P2-14 + W6 school/grades/insights 筛选器重构(一并解决) 1 文件 v1+v2
P2 P2-2 + P2-4 users/import 表格与颜色修复 1 文件 v1
P2 P2-3 + P2-8 + P2-9 school/grades/insights 工具函数与任意值 1 文件 v1+v2
P2 P2-7 scheduling/* data-access 迁移 3 文件 v1
P2 P2-12 编辑页返回按钮统一 6 文件 v2
P2 P2-13 补充 metadata 导出 25 文件 v2
R R1-R4 性能优化Suspense、并行、虚拟化 关键页面 v1+v2
W W1-W7 可访问性优化 关键页面 v1+v2

八、附v2 文件清单与合规状态

文件 P0 P1 P2 v2 新增 备注
dashboard/page.tsx - 缺返回类型 缺 metadata - 整体合规
announcements/page.tsx - 缺返回类型、getParam 重复 缺 metadata - 类型守卫正确
announcements/[id]/page.tsx - 缺返回类型、英文文案 缺返回按钮、缺 metadata P2-12 -
users/import/page.tsx - 缺返回类型 原生 table、硬编码颜色、缺 dynamic P2-11 文案为中文(正确)、有返回按钮、有 metadata
school/page.tsx - 缺返回类型 缺 dynamic、缺 metadata P2-10 仅 redirect
school/schools/page.tsx - 缺返回类型、英文文案 缺 metadata - -
school/classes/page.tsx - 缺返回类型、英文文案 缺 metadata - -
school/grades/page.tsx - 缺返回类型、英文文案 缺 metadata - -
school/grades/insights/page.tsx - 缺返回类型、英文文案、getParam 不一致 原生 select、任意值、导入顺序、label 未关联、fmt 内联、可选链、原生 form P1-6, P2-8, P2-9, P2-14 问题最多8 个)
school/academic-year/page.tsx - 缺返回类型、英文文案 缺 metadata - -
school/departments/page.tsx - 缺返回类型、英文文案 缺 metadata - -
audit-logs/page.tsx - 缺返回类型、as 断言、英文文案、getParam 重复 缺 metadata - 权限校验正确
audit-logs/login-logs/page.tsx - 缺返回类型、as 断言、英文文案、getParam 重复 缺 metadata - 权限校验正确
audit-logs/data-changes/page.tsx - 缺返回类型、as 断言、英文文案、getParam 重复 缺 metadata - 权限校验正确
scheduling/auto/page.tsx - 缺返回类型、英文文案 从 actions 取数、缺 metadata - -
scheduling/changes/page.tsx - 缺返回类型、英文文案、getParam 重复 从 actions 取数、缺 metadata - 类型守卫正确
scheduling/rules/page.tsx - 缺返回类型、英文文案 从 actions 取数、缺 metadata - -
course-plans/page.tsx - 缺返回类型、英文文案、getParam 重复 缺 metadata - 类型守卫正确
course-plans/create/page.tsx - 缺返回类型、英文文案 缺返回按钮、缺 metadata P2-12 -
course-plans/[id]/page.tsx - 缺返回类型 缺返回按钮、缺 metadata P2-12 -
course-plans/[id]/edit/page.tsx - 缺返回类型、英文文案 重复导入、缺返回按钮、缺 metadata P2-12 -
elective/page.tsx - 缺返回类型、英文文案、getParam 重复 缺 metadata - 类型守卫正确
elective/create/page.tsx - 缺返回类型、英文文案 缺返回按钮、缺 metadata P2-12 -
elective/[id]/edit/page.tsx - 缺返回类型、英文文案 缺返回按钮、缺 metadata P2-12 -
attendance/page.tsx 缺权限校验 缺返回类型、as 断言、英文文案、getParam 重复、超 printWidth、内联字面量 缺 metadata P1-5, P1-7 最高优先级6 个问题)
files/page.tsx - 缺返回类型 缺 metadata - 权限校验正确、整体合规

九、v2 总结与建议

当前状态

  • v1 提出的 13 个问题0 个已修复
  • v2 新增 10 个问题
  • 累计 23 个问题待处理
  • ESLint 与 tsc 检查通过(说明现有问题多为规范层面,非编译错误)

核心问题集中在三类

  1. 系统性缺失(影响全部 26 个文件):

    • error.tsx / loading.tsxP0-1
    • 缺返回类型标注P1-1
    • metadata 导出P2-13
  2. 代码复用问题(影响 27 个文件):

    • getParam 重复定义且实现不一致P1-2 + P1-6
  3. attendance/page.tsxschool/grades/insights/page.tsx 问题集中

    • attendance6 个问题(含 P0 权限缺失)
    • school/grades/insights8 个问题v2 问题最密集的文件)

建议执行策略

  1. 第一优先级:立即修复 attendance/page.tsx 的权限校验P0-2这是唯一的安全漏洞
  2. 第二优先级:补充 error.tsx / loading.tsxP0-1改善所有页面的错误处理与加载体验
  3. 第三优先级:抽取 shared/lib/utils.tsgetSearchParamP1-2一次性解决 27 个文件的 DRY 问题
  4. 第四优先级:重构 attendance/page.tsxP1-3 + P1-5 + P1-7 一并解决)与 school/grades/insights/page.tsxP2-1 + P2-3 + P2-5 + P2-8 + P2-9 + P2-14 + W6 一并解决)
  5. 第五优先级批量补充返回类型P1-1metadataP2-13可通过脚本辅助
  6. 最后:统一 UI 文案语言P1-4需产品确认中文/英文/i18n 方案

验证要求

每完成一批次修复后,必须运行:

npm run lint
npx tsc --noEmit

确保零错误,并同步更新架构文档 004_architecture_impact_map.md005_architecture_data.json


v2 报告生成完毕。关键提醒v1 报告提出的问题均未修复,请优先处理 P0 级别的权限校验缺失与错误边界缺失问题。