# Admin 前端文件规范核查报告 > 核查范围:`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-18 --- ## 一、核查概览 | 维度 | 文件数 | 通过 | 待改进 | |------|--------|------|--------| | 架构分层 | 26 | 24 | 2 | | TypeScript 规范 | 26 | 4 | 22 | | 安全与权限 | 26 | 3 | 23 | | UI 一致性与设计令牌 | 26 | 18 | 8 | | 错误与加载边界 | 26 | 0 | 26 | | 代码复用(DRY) | 26 | 0 | 26 | **结论**:整体架构清晰、服务端组件使用规范、并行数据获取到位,但在**返回类型标注、权限校验一致性、加载/错误边界、代码复用、UI 文案一致性**方面存在系统性问题,需统一整改。 --- ## 二、问题清单(按严重程度排序) ### P0 严重问题(必须立即修复) #### P0-1 全部 26 个页面缺少 `error.tsx` 与 `loading.tsx` **违反规范**: - 编码规范 §2.3:「每个路由段应提供 `loading.tsx`(骨架屏)和 `error.tsx`(错误边界)」 - 编码规范 §2.4:「每个路由段都必须提供 `error.tsx`,不得出现未捕获异常导致白屏」 - 编码规范 §2.4:「`loading.tsx` 必须提供骨架屏或最小可感知的加载状态,不得使用全局 spin 遮罩」 **现状**:`src/app/(dashboard)/admin/` 及其所有子路由(`dashboard/`、`announcements/`、`school/*`、`audit-logs/*`、`scheduling/*`、`course-plans/*`、`elective/*`、`attendance/`、`files/`、`users/import/`)均**未提供** `loading.tsx` 和 `error.tsx`。 对比:`teacher/`、`student/` 路由组在关键页面已提供 `loading.tsx`(如 `teacher/exams/all/loading.tsx`、`student/dashboard/loading.tsx`),admin 路由组完全缺失。 **影响**: - 数据获取失败时整页白屏,用户体验差 - 无加载态感知,用户误以为页面卡死 - 不符合 Next.js 16 App Router 最佳实践(Suspense 流式渲染) **修复建议**: 1. 在 `src/app/(dashboard)/admin/` 根目录新增 `error.tsx`(具名导出,客户端组件,含重试按钮) 2. 在 `src/app/(dashboard)/admin/` 根目录新增 `loading.tsx`(骨架屏,匹配各页面布局) 3. 对数据量大的页面(`audit-logs/*`、`school/grades/insights`、`attendance`)单独提供 `loading.tsx` 4. 对动态路由(`[id]/page.tsx`)单独提供 `error.tsx` 处理 `notFound` 以外的异常 --- #### P0-2 `attendance/page.tsx` 缺少权限校验 **文件**:[src/app/(dashboard)/admin/attendance/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/admin/attendance/page.tsx) **违反规范**: - 项目规则:「Server Action 必须使用 `requirePermission()` 进行权限校验」 - 编码规范 §8.3:「权限校验:Server Action 必须使用 `requirePermission()`」 **现状**:第 26 行仅调用 `getAuthContext()` 获取上下文,**未调用 `requirePermission()`** 验证用户是否有考勤查看权限。 ```tsx // 当前代码(第 26 行) const ctx = await getAuthContext() ``` **对比**:同类 admin 页面均做了权限校验: - `audit-logs/page.tsx` 第 22 行:`await requirePermission(Permissions.AUDIT_LOG_READ)` - `audit-logs/login-logs/page.tsx` 第 22 行:`await requirePermission(Permissions.AUDIT_LOG_READ)` - `audit-logs/data-changes/page.tsx` 第 26 行:`await requirePermission(Permissions.AUDIT_LOG_READ)` - `files/page.tsx` 第 12 行:`await requirePermission(Permissions.FILE_READ)` **影响**:越权风险——无考勤查看权限的用户可直接访问 `/admin/attendance` 查看全校考勤数据。 **修复建议**:在 `getAuthContext()` 前增加权限校验: ```tsx await requirePermission(Permissions.ATTENDANCE_READ) const ctx = await getAuthContext() ``` --- ### P1 重要问题(应尽快修复) #### P1-1 全部 26 个页面组件缺少返回类型标注 **违反规范**: - 编码规范 §4.2:「函数返回值必须显式标注,特别是 `Promise`」 - 项目规则:「函数返回值必须显式标注」 **现状**:所有 `page.tsx` 的默认导出函数均未标注返回类型,例如: ```tsx // dashboard/page.tsx export default async function AdminDashboardPage() { // ❌ 缺少 : Promise const data = await getAdminDashboardData() return } ``` **影响**:26 个文件全部不合规,类型推导依赖 TS 隐式推断,不利于代码审查与维护。 **修复建议**:统一补充返回类型: ```tsx export default async function AdminDashboardPage(): Promise { // ... } ``` 涉及文件:admin 目录下全部 26 个 `page.tsx`。 --- #### P1-2 `getParam` 工具函数在 27 个文件中重复定义 **违反规范**: - 编码规范 §一:「单一职责」「工具函数 ≤ 40 行」 - DRY 原则 **现状**:以下 admin 文件各自重复定义了相同的 `getParam` / `SearchParams` 类型与函数: | 文件 | 行号 | |------|------| | `announcements/page.tsx` | 8-13 | | `audit-logs/page.tsx` | 10-15 | | `audit-logs/login-logs/page.tsx` | 10-15 | | `audit-logs/data-changes/page.tsx` | 14-19 | | `scheduling/changes/page.tsx` | 16-21 | | `course-plans/page.tsx` | 7-12 | | `elective/page.tsx` | 7-12 | | `attendance/page.tsx` | 13-18 | | `school/grades/insights/page.tsx` | 15-22 | 全项目共 27 个文件重复(含 teacher / student / management 路由组)。 **影响**:维护成本高,任何一处逻辑变更需同步修改 27 处。 **修复建议**: 1. 在 `src/shared/lib/utils.ts` 新增共享工具: ```tsx export type SearchParams = { [key: string]: string | string[] | undefined } export function getSearchParam(params: SearchParams, key: string): string | undefined { const v = params[key] return Array.isArray(v) ? v[0] : v } ``` 2. 全部页面改为 `import { getSearchParam, type SearchParams } from "@/shared/lib/utils"` 3. 同步更新架构文档 004 / 005 --- #### P1-3 多个页面使用 `as` 类型断言违反 TypeScript 规范 **违反规范**: - 编码规范 §4.2:「不使用 `as` 断言,除非从 `unknown` 强制转换或在测试中(需注释原因)」 - 项目规则:「禁止 `as` 断言(除非从 `unknown` 转换或测试中,需注释原因)」 **现状**:以下文件使用 `as` 进行类型断言而非类型守卫: | 文件 | 行号 | 问题代码 | |------|------|---------| | `audit-logs/page.tsx` | 28 | `(getParam(params, "status") as AuditLogStatus \| undefined)` | | `audit-logs/login-logs/page.tsx` | 26-27 | `as LoginLogAction \| undefined`、`as LoginLogStatus \| undefined` | | `audit-logs/data-changes/page.tsx` | 31 | `as DataChangeAction \| undefined` | | `attendance/page.tsx` | 39 | `as "present" \| "absent" \| "late" \| "early_leave" \| "excused"` | **对比(正确示例)**:以下文件已使用类型守卫,应作为模板推广: - `announcements/page.tsx` 第 15-16 行:`isValidStatus` 类型守卫 - `scheduling/changes/page.tsx` 第 23-24 行:`isValidStatus` 类型守卫 - `course-plans/page.tsx` 第 14-15 行:`isValidStatus` 类型守卫 - `elective/page.tsx` 第 14-15 行:`isValidStatus` 类型守卫 **影响**:运行时无法捕获非法枚举值,类型安全被绕过。 **修复建议**:为每个枚举类型补充类型守卫,替换 `as` 断言: ```tsx const isValidAuditLogStatus = (v?: string): v is AuditLogStatus => v === "success" || v === "failure" || v === "pending" const status = isValidAuditLogStatus(statusParam) ? statusParam : undefined ``` --- #### P1-4 UI 文案语言不统一(中英文混用) **违反规范**: - 编码规范 §一:「可读性优先」 - 项目定位为「Next_Edu K12 智慧教务系统」(中文用户) **现状**: | 文件 | 文案语言 | |------|---------| | `users/import/page.tsx` | 中文("批量导入用户"、"返回") | | `announcements/[id]/page.tsx` | 英文("Edit Announcement") | | `school/schools/page.tsx` | 英文("Schools"、"Manage schools...") | | `school/classes/page.tsx` | 英文("Classes"、"Manage classes...") | | `school/grades/page.tsx` | 英文("Grades"、"Manage grades...") | | `school/grades/insights/page.tsx` | 英文("Grade Insights"、"Filters") | | `school/academic-year/page.tsx` | 英文("Academic Year") | | `school/departments/page.tsx` | 英文("Departments") | | `audit-logs/page.tsx` | 英文("Audit Logs") | | `audit-logs/login-logs/page.tsx` | 英文("Login Logs") | | `audit-logs/data-changes/page.tsx` | 英文("Data Change Logs") | | `scheduling/auto/page.tsx` | 英文("Auto Schedule") | | `scheduling/changes/page.tsx` | 英文("Schedule Change Requests") | | `scheduling/rules/page.tsx` | 英文("Scheduling Rules") | | `course-plans/page.tsx` | 英文("Course Plans") | | `course-plans/create/page.tsx` | 英文("New Course Plan") | | `course-plans/[id]/edit/page.tsx` | 英文("Edit Course Plan") | | `elective/page.tsx` | 英文("Elective Courses") | | `elective/create/page.tsx` | 英文("New Elective Course") | | `elective/[id]/edit/page.tsx` | 英文("Edit Elective Course") | | `attendance/page.tsx` | 英文("Attendance Overview") | **影响**:用户体验割裂,admin 区仅 `users/import` 为中文,其余全英文,与系统定位不符。 **修复建议**:统一为中文(与 `users/import/page.tsx` 保持一致),或引入 i18n 方案统一管理。建议优先统一为中文。 --- ### P2 一般问题(建议修复) #### P2-1 `school/grades/insights/page.tsx` 使用原生 `` 元素,而项目已提供 `@/shared/components/ui/select.tsx`(shadcn Select)。 ```tsx ` 样式难以跨浏览器统一 - 可访问性较弱(缺少 ARIA 属性) **修复建议**:替换为 `@/shared/components/ui/select.tsx` 的 `Select` / `SelectTrigger` / `SelectContent` / `SelectItem` 组合。 --- #### P2-2 `users/import/page.tsx` 使用原生 `` 而非共享组件 **文件**:[src/app/(dashboard)/admin/users/import/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/admin/users/import/page.tsx#L93-L128) **现状**:第 93-128 行使用原生 `
` 元素手写表格,而项目已提供 `@/shared/components/ui/table.tsx`(shadcn Table)。 **影响**:与 `school/grades/insights/page.tsx` 等使用 shadcn Table 的页面风格不一致。 **修复建议**:替换为 `Table` / `TableHeader` / `TableBody` / `TableRow` / `TableHead` / `TableCell` 组合。 --- #### P2-3 Tailwind 任意值违规 **违反规范**: - 编码规范 §6.2:「禁止使用任意值(`w-[137px]`),除非有充分理由并注释说明」 - 项目规则:「禁止使用任意值(`w-[137px]`),除非有充分理由并注释」 **现状**: | 文件 | 行号 | 问题类名 | |------|------|---------| | `school/grades/insights/page.tsx` | 60 | `md:w-[360px]` | | `school/grades/insights/page.tsx` | 82, 89, 96 | `h-[360px]` | | `users/import/page.tsx` | 16 | `h-full flex-1 flex-col`(`flex-1` 合理,但整体布局类应复用) | **修复建议**: - `md:w-[360px]` → 使用设计令牌宽度类(如 `md:w-72` 或 `md:w-80`)或在 globals.css 定义 `--filter-width` 变量 - `h-[360px]` → 使用 `h-80`(320px)或 `h-96`(384px)等标准档位 --- #### P2-4 `users/import/page.tsx` 使用硬编码颜色 **违反规范**: - 编码规范 §6.3:「所有视觉设计决策(颜色、字号、间距)必须体现在设计令牌中,组件中不使用硬编码值」 **文件**:[src/app/(dashboard)/admin/users/import/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/admin/users/import/page.tsx#L67) **现状**:第 67 行使用 `text-amber-500` 硬编码颜色: ```tsx ``` **修复建议**:使用设计令牌颜色,如 `text-warning`(若存在)或在 globals.css 定义 `--warning` 变量。如暂无 warning 令牌,可使用 `text-primary` 或 `text-muted-foreground` 保持一致。 --- #### P2-5 `school/grades/insights/page.tsx` 导入顺序违规 **违反规范**: - 编码规范 §4.3:「导入顺序:React → 第三方 → 内部绝对路径 → 相对路径 → 类型导入」 - 项目规则引用的 ESLint `import/order` 规则 **文件**:[src/app/(dashboard)/admin/school/grades/insights/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/admin/school/grades/insights/page.tsx#L1-L11) **现状**:第 1-11 行导入顺序混乱,`lucide-react`(第三方库)被放在所有 `@/` 内部导入之后: ```tsx import Link from "next/link" // next(外部) import { getGrades } from "@/modules/school/data-access" // 内部 import { getGradeHomeworkInsights } from "@/modules/classes/data-access" import { EmptyState } from "@/shared/components/ui/empty-state" import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card" import { Badge } from "@/shared/components/ui/badge" import { Button } from "@/shared/components/ui/button" import { Table, TableBody, ... } from "@/shared/components/ui/table" import { formatDate } from "@/shared/lib/utils" import { BarChart3 } from "lucide-react" // ❌ 第三方应在前 ``` **修复建议**:调整为 `next` → `lucide-react` → `@/` 内部导入,分组间空一行: ```tsx import Link from "next/link" import { BarChart3 } from "lucide-react" import { getGrades } from "@/modules/school/data-access" // ... ``` --- #### P2-6 `course-plans/[id]/edit/page.tsx` 同模块重复导入 **文件**:[src/app/(dashboard)/admin/course-plans/[id]/edit/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/admin/course-plans/[id]/edit/page.tsx#L3-L4) **现状**:第 3-4 行从同一模块 `@/modules/course-plans/data-access` 分两行导入: ```tsx import { getCoursePlanById } from "@/modules/course-plans/data-access" import { getSubjectOptions } from "@/modules/course-plans/data-access" ``` **修复建议**:合并为单行: ```tsx import { getCoursePlanById, getSubjectOptions } from "@/modules/course-plans/data-access" ``` --- #### P2-7 `scheduling/*` 页面从 `actions` 而非 `data-access` 获取数据 **违反规范**: - 编码规范 §7.1:「服务端数据获取通过模块的 `data-access.ts` 函数」 - 架构影响地图:「actions.ts(编排层:权限 + 调用 data-access + revalidate)」 **现状**:以下页面从 `@/modules/scheduling/actions` 导入数据查询函数: | 文件 | 导入函数 | |------|---------| | `scheduling/auto/page.tsx` | `getAdminClassesForScheduling` | | `scheduling/changes/page.tsx` | `getAdminClassesForScheduling`、`getScheduleChanges` | | `scheduling/rules/page.tsx` | `getAdminClassesForScheduling`、`getSchedulingRules` | **说明**:规范允许 `app/` 调用 Server Actions,但 Server Actions 的职责是「编排:权限 + 调用 data-access + revalidate」,主要用于**变更操作**。纯读取操作应通过 `data-access.ts` 暴露,避免在 Server Component 中触发不必要的 `revalidate` 逻辑。 **修复建议**:将 `getAdminClassesForScheduling`、`getScheduleChanges`、`getSchedulingRules` 等纯查询函数迁移到 `scheduling/data-access.ts`,或在 actions 中明确标注其为只读封装。需同步更新架构文档 004 / 005。 --- ## 三、React 性能优化建议(基于最佳实践) ### R1 利用 Suspense 流式渲染提升首屏感知性能 **现状**:所有页面使用 `export const dynamic = "force-dynamic"` 整页动态渲染,数据获取完成前无任何内容呈现。 **建议**:对数据量大的页面(`audit-logs/*`、`school/grades/insights`、`attendance`)拆分为多个 Suspense 边界,优先渲染页面骨架,慢查询部分流式注入: ```tsx import { Suspense } from "react" export default async function AuditLogsPage(): Promise { return (
}> }>
) } ``` ### R2 `school/grades/insights/page.tsx` 串行查询可优化为并行 **文件**:[src/app/(dashboard)/admin/school/grades/insights/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/admin/school/grades/insights/page.tsx#L30-L33) **现状**:第 30-33 行先 `await getGrades()` 再条件 `await getGradeHomeworkInsights()`,两次串行查询: ```tsx const grades = await getGrades() const selected = gradeId && gradeId !== "all" ? gradeId : "" const insights = selected ? await getGradeHomeworkInsights({ gradeId: selected, limit: 50 }) : null ``` **说明**:`insights` 依赖 `selected`(来自 URL 参数,非 `grades` 结果),两者无数据依赖,可并行: ```tsx const selected = gradeId && gradeId !== "all" ? gradeId : "" const [grades, insights] = await Promise.all([ getGrades(), selected ? getGradeHomeworkInsights({ gradeId: selected, limit: 50 }) : Promise.resolve(null), ]) ``` ### R3 列表页 `classOptions` 映射可下沉至 data-access **现状**:`scheduling/auto`、`scheduling/changes`、`scheduling/rules`、`attendance`、`course-plans/create`、`course-plans/[id]/edit`、`elective/create`、`elective/[id]/edit` 等页面均在组件内 `.map()` 转换数据形状: ```tsx const classOptions = classes.map((c) => ({ id: c.id, name: c.name, grade: c.grade })) ``` **建议**:在对应 `data-access.ts` 提供 `getClassOptions()`、`getStaffOptions()` 等轻量查询函数,仅返回 `{ id, name }` 形状,减少传输数据量与组件层转换逻辑。 --- ## 四、Web 界面设计规范建议(基于 WCAG 2.2 AA) ### W1 表单 `
` 与语义化标注 **文件**:[src/app/(dashboard)/admin/users/import/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/admin/users/import/page.tsx#L93-L128) **现状**:原生 `` 缺少 ``,或替换为 shadcn Table 后通过 `aria-label` 补充。 ### W3 页面标题层级不统一 **现状**: - 部分页面使用 `

` 作为页面主标题(如 `school/schools`、`audit-logs`) - `users/import/page.tsx` 也使用 `

` - 但页面布局中未见统一的 `

` 主标题层级 **建议**:确认 `(dashboard)/layout.tsx` 是否提供 `

` 或页面 `
` 的 accessible name,若无,建议各页面统一使用 `

` 作为页面主标题,`

` 用于区块标题,保持标题层级连贯。 ### W4 交互式筛选器缺少 `aria-live` 反馈 **文件**:`school/grades/insights/page.tsx`、`attendance/page.tsx`、`audit-logs/*` **现状**:筛选器提交后表格数据刷新,但屏幕阅读器用户无法感知数据已更新。 **违反**:WCAG 2.2 SC 4.1.3(状态消息)。 **建议**:在表格容器添加 `aria-live="polite"` 或使用项目已有的 `useAriaLive` Hook 通知「已加载 N 条记录」。 ### W5 `EmptyState` 组件使用一致但图标语义可优化 **现状**:`scheduling/*`、`attendance`、`school/grades/insights` 均使用 `EmptyState` 组件,图标统一使用 `ClipboardList` / `BarChart3`,体验一致(优点)。 **建议**:`BarChart3` 用于「无数据」与「选择年级」两种语义略显混淆,建议「等待操作」类空状态使用 `MousePointerClick` 或 `Filter` 图标区分。 --- ## 五、优秀实践(已符合规范,应保持) 1. **服务端组件默认化**:全部 26 个页面均为 async 服务端组件,未滥用 `"use client"`,符合 §5.2。 2. **并行数据获取**:`announcements/page.tsx`、`audit-logs/*`、`course-plans/create`、`course-plans/[id]/edit`、`elective/create`、`elective/[id]/edit`、`school/grades`、`scheduling/rules` 等均使用 `Promise.all` 并行查询,性能良好。 3. **类型守卫正确使用**:`announcements/page.tsx`、`scheduling/changes/page.tsx`、`course-plans/page.tsx`、`elective/page.tsx` 使用 `isValidStatus` 类型守卫,是 `as` 断言的正确替代方案。 4. **404 处理**:`announcements/[id]/page.tsx`、`course-plans/[id]/page.tsx`、`course-plans/[id]/edit/page.tsx`、`elective/[id]/edit/page.tsx` 使用 `notFound()` 处理资源不存在场景。 5. **权限校验到位**:`audit-logs/*`(3 个文件)、`files/page.tsx` 正确调用 `requirePermission()`。 6. **模块化组合**:页面仅负责数据获取与组合,UI 逻辑下沉至 `modules/*/components/`,符合三层架构。 7. **`force-dynamic` 标注**:需要实时数据的页面均显式声明 `export const dynamic = "force-dynamic"`。 8. **`metadata` 导出**:`users/import/page.tsx` 正确导出 `metadata` 用于 SEO(建议其他页面补充)。 --- ## 六、修复优先级与建议执行顺序 | 优先级 | 问题编号 | 建议执行顺序 | 影响范围 | |--------|---------|-------------|---------| | P0 | P0-2 | 立即修复 attendance 权限 | 1 文件 | | P0 | P0-1 | 补充 error.tsx / loading.tsx | 新增 ~6 文件 | | P1 | P1-1 | 补充返回类型标注 | 26 文件 | | P1 | P1-2 | 抽取共享 getSearchParam | 27 文件 | | P1 | P1-3 | 替换 as 断言为类型守卫 | 4 文件 | | P1 | P1-4 | 统一 UI 文案语言 | ~20 文件 | | P2 | P2-1 ~ P2-7 | 逐步整改 | 单文件级 | | R1 ~ R3 | 性能优化 | 迭代优化 | 关键页面 | | W1 ~ W5 | 可访问性 | 迭代优化 | 关键页面 | --- ## 七、附:文件清单与合规状态 | 文件 | P0 | P1 | P2 | 备注 | |------|----|----|----|----| | `dashboard/page.tsx` | - | 缺返回类型 | - | 整体合规 | | `announcements/page.tsx` | - | 缺返回类型、getParam 重复 | - | 类型守卫正确 | | `announcements/[id]/page.tsx` | - | 缺返回类型、英文文案 | - | - | | `users/import/page.tsx` | - | 缺返回类型 | 原生 table、硬编码颜色 | 文案为中文(正确) | | `school/page.tsx` | - | 缺返回类型 | - | 仅 redirect | | `school/schools/page.tsx` | - | 缺返回类型、英文文案 | - | - | | `school/classes/page.tsx` | - | 缺返回类型、英文文案 | - | - | | `school/grades/page.tsx` | - | 缺返回类型、英文文案 | - | - | | `school/grades/insights/page.tsx` | - | 缺返回类型、英文文案 | 原生 select、任意值、导入顺序、label 未关联 | 问题最多 | | `school/academic-year/page.tsx` | - | 缺返回类型、英文文案 | - | - | | `school/departments/page.tsx` | - | 缺返回类型、英文文案 | - | - | | `audit-logs/page.tsx` | - | 缺返回类型、as 断言、英文文案、getParam 重复 | - | 权限校验正确 | | `audit-logs/login-logs/page.tsx` | - | 缺返回类型、as 断言、英文文案、getParam 重复 | - | 权限校验正确 | | `audit-logs/data-changes/page.tsx` | - | 缺返回类型、as 断言、英文文案、getParam 重复 | - | 权限校验正确 | | `scheduling/auto/page.tsx` | - | 缺返回类型、英文文案 | 从 actions 取数 | - | | `scheduling/changes/page.tsx` | - | 缺返回类型、英文文案、getParam 重复 | 从 actions 取数 | 类型守卫正确 | | `scheduling/rules/page.tsx` | - | 缺返回类型、英文文案 | 从 actions 取数 | - | | `course-plans/page.tsx` | - | 缺返回类型、英文文案、getParam 重复 | - | 类型守卫正确 | | `course-plans/create/page.tsx` | - | 缺返回类型、英文文案 | - | - | | `course-plans/[id]/page.tsx` | - | 缺返回类型 | - | - | | `course-plans/[id]/edit/page.tsx` | - | 缺返回类型、英文文案 | 重复导入 | - | | `elective/page.tsx` | - | 缺返回类型、英文文案、getParam 重复 | - | 类型守卫正确 | | `elective/create/page.tsx` | - | 缺返回类型、英文文案 | - | - | | `elective/[id]/edit/page.tsx` | - | 缺返回类型、英文文案 | - | - | | `attendance/page.tsx` | **缺权限校验** | 缺返回类型、as 断言、英文文案、getParam 重复 | - | 最高优先级 | | `files/page.tsx` | - | 缺返回类型 | - | 权限校验正确、整体合规 | --- > 报告生成完毕。建议按「六、修复优先级」顺序整改,每完成一批次后运行 `npm run lint` 与 `npx tsc --noEmit` 验证,并同步更新架构文档 004 / 005。

` 描述表格用途,屏幕阅读器无法快速理解表格主题。 **修复建议**:增加 `模板字段说明