Bug fixes (from bugs/ directory): - Fix cross-module DB queries in 9 modules (homework, grades, parent, diagnostic, elective, proctoring, notifications, scheduling, classes) by routing through data-access functions - Fix shared/lib <-> auth circular dependency via new session.ts module - Fix divide-by-zero guard in grades data-access - Fix audit export data truncation (paginated fetch for full datasets) - Fix missing transactions in homework grading and elective lottery - Fix missing revalidatePath in course-plans actions - Fix frontend permission checks using requirePermission instead of requireAuth - Fix dashboard role routing using session.user.roles - Fix student auth pattern (migrate getDemoStudentUser to users module) - Fix ActionState return type handling in components Code quality fixes: - Remove 60+ as type assertions (replace with type guards) - Remove non-null assertions (use optional chaining or explicit checks) - Convert dynamic imports to static imports (grades, diagnostic) - Add React.cache() wrapping for read functions - Parallelize independent queries with Promise.all - Add explicit return types to 30+ arrow functions - Replace any with unknown + type guards - Fix import type for type-only imports - Add Zod validation schemas for classes and diagnostic modules - Extract duplicate code (normalizeRoleName, normalizeBcryptHash, logger IP extraction) - Add console.error to silent catch blocks - Fix permission naming consistency (exam:proctor_read -> exam:proctor:read) Architecture doc sync: - Update 004_architecture_impact_map.md and 005_architecture_data.json - Update management-modules-audit.md for P0-7 cross-module fix Moved deleted proctoring event route to deletes/ folder.
14 KiB
14 KiB
src/shared/types 规范核查报告
核查日期:2026-06-18 核查范围:
src/shared/types/目录下所有前后端文件 依据文档:项目规则、编码规范、架构影响地图 004、架构数据 005 应用技能:vercel-react-best-practices、web-artifacts-builder、web-design-guidelines
一、核查文件清单
| 文件 | 行数 | 类型 | 用途 |
|---|---|---|---|
| action-state.ts | 5 | 类型定义 | Server Action 统一返回类型 |
| action-state.test.ts | 33 | 单元测试 | ActionState 类型测试 |
| permissions.ts | 114 | 类型定义+常量 | 权限点常量、Permission/DataScope/AuthContext 类型 |
二、违规问题清单
2.1 action-state.ts — 严重度:高
BUG-A01:Prettier 配置违规(使用分号)
- 位置:
src/shared/types/action-state.ts:1-5 - 问题:文件使用分号(
;)结尾,但项目.prettierrc配置"semi": false,应移除所有分号 - 现状:
export type ActionState<T = void> = { success: boolean; message?: string; errors?: Record<string, string[]>; data?: T; }; - 改进建议:移除所有分号,与
permissions.ts、action-state.test.ts保持一致
BUG-A02:缺少 JSDoc 文档注释
- 位置:
src/shared/types/action-state.ts:1 - 问题:
ActionState<T>类型缺少 JSDoc 注释,未说明类型用途、泛型参数、各字段含义 - 规范依据:编码规范 5.4「必须编写 JSDoc」
- 改进建议:补充类型级 JSDoc,说明
@template T、各 property 语义
2.2 permissions.ts — 严重度:高
BUG-P01:权限点命名不一致(下划线 vs 驼峰)
- 位置:
src/shared/types/permissions.ts:91 - 问题:
EXAM_PROCTOR_READ: "exam:proctor_read"使用下划线分隔,而其他 READ 权限均使用单词形式(如exam:read、question:read) - 改进建议:统一为
exam:proctor:read(嵌套资源用冒号分隔)
BUG-P02:Permissions 常量缺少 satisfies 类型约束
- 位置:
src/shared/types/permissions.ts:4-96 - 问题:使用
as const但未用satisfies验证所有值均为字符串,无法在编译期捕获值类型错误 - 规范依据:编码规范 4.2.3「可用
satisfies保持类型推导」 - 改进建议:
as const satisfies Record<string, string>
BUG-P03:AuthContext.roles 类型过于宽松
- 位置:
src/shared/types/permissions.ts:111 - 问题:
roles: string[]允许任意字符串,但项目角色是有限集合(admin/teacher/student/parent/grade_head/teaching_head) - 影响:拼写错误(如
"techer")无法在编译期发现;与proxy.ts:21中resolveDefaultPath(roles: string[])的硬编码角色判断形成隐患 - 改进建议:定义
Role联合类型,AuthContext.roles改为Role[],ROLE_PERMISSIONS改为Record<Role, Permission[]>
BUG-P04:DataScope 缺少 JSDoc 与字段说明
- 位置:
src/shared/types/permissions.ts:101-107 - 问题:6 种数据范围类型未说明各自语义、适用角色、使用场景
- 改进建议:补充类型级 JSDoc,说明每种
type的适用角色与语义
BUG-P05:AuthContext 接口缺少 JSDoc
- 位置:
src/shared/types/permissions.ts:109-114 - 问题:接口无文档说明,使用者无法快速理解字段语义
- 规范依据:编码规范 5.4
- 改进建议:补充接口级 JSDoc,说明「认证上下文,由
getAuthContext()返回,贯穿所有 Server Action」
BUG-P06:DataScope.class_members 缺少关联数据
- 位置:
src/shared/types/permissions.ts:104 - 问题:
{ type: "class_members" }不携带 classIds,导致 data-access 层每次都需要额外查询学生所在班级,存在 N+1 查询风险 - 影响:
exams/data-access.ts、homework/data-access.ts等模块在过滤时需重复查询classMembers表 - 改进建议:在
resolveDataScope中预查并携带 classIds:{ type: "class_members"; classIds: string[] }
2.3 action-state.test.ts — 严重度:中
BUG-T01:测试覆盖率不足
- 位置:
src/shared/types/action-state.test.ts:4-33 - 问题:仅测试 3 种基本状态,缺少以下场景:
errors字段包含多个字段、每个字段多条错误消息data为null、undefined、0、""等 falsy 值时的行为- 同时存在
errors和data(虽然语义上不应出现,但类型允许) message为空字符串
- 规范依据:编码规范十、测试规范「工具函数覆盖率目标 100%」
BUG-T02:测试描述缺少行为意图
- 位置:
src/shared/types/action-state.test.ts:4 - 问题:
describe("ActionState")过于宽泛,未说明被测行为 - 规范依据:编码规范 10.2「描述应说明预期行为」
- 改进建议:
describe("ActionState 类型构造")
2.4 跨文件违规(使用方导入问题)
BUG-X01:exams/actions.ts 类型导入违规
- 位置:
src/modules/exams/actions.ts:4 - 问题:
import { ActionState } from "@/shared/types/action-state"—ActionState仅作为类型使用,应使用import type - 规范依据:编码规范 4.2.6「所有仅用于类型的导入必须使用
import type」 - 改进建议:
import type { ActionState } from "@/shared/types/action-state"
BUG-X02:questions/actions.ts 类型导入违规
- 位置:
src/modules/questions/actions.ts:7 - 问题:同 BUG-X01,
import { ActionState }应为import type { ActionState } - 改进建议:
import type { ActionState } from "@/shared/types/action-state"
2.5 tsconfig.json 配置不达标(影响类型安全)
BUG-C01:target 低于规范要求
- 位置:
tsconfig.json:3 - 问题:
"target": "ES2017",编码规范 4.1 要求"ES2022" - 影响:无法使用 ES2022 特性(如
Array.at()、Object.hasOwn()) - 改进建议:
"target": "ES2022"
BUG-C02:缺少 noUncheckedIndexedAccess
- 位置:
tsconfig.json - 问题:未启用
noUncheckedIndexedAccess,数组/对象索引访问返回T而非T | undefined - 影响:
permissions.ts:198中ROLE_PERMISSIONS[name]在name不存在时返回Permission[]而非Permission[] | undefined,存在运行时风险 - 规范依据:编码规范 4.1
- 改进建议:
"noUncheckedIndexedAccess": true
BUG-C03:缺少 noImplicitReturns 和 noFallthroughCasesInSwitch
- 位置:
tsconfig.json - 问题:未启用这两个严格检查
- 规范依据:编码规范 4.1
- 改进建议:补充
"noImplicitReturns": true、"noFallthroughCasesInSwitch": true、"forceConsistentCasingInFileNames": true
三、React 性能优化(应用 vercel-react-best-practices 技能)
PERF-01:use-permission.ts 回调函数未 memoize
- 位置:
src/shared/hooks/use-permission.ts:11-25 - 问题:
hasPermission、hasAnyPermission、hasAllPermissions、hasRole每次渲染都创建新函数引用,导致依赖这些函数的子组件不必要重渲染 - 违反规则:
rerender-functional-setstate、rerender-memo - 改进建议:使用
useCallback包裹所有回调函数
PERF-02:permissions 和 roles 数组未 memoize
- 位置:
src/shared/hooks/use-permission.ts:8-9 - 问题:每次渲染都执行
?? []创建新数组引用,导致下游useEffect/useMemo依赖项失效 - 违反规则:
rerender-derived-state、rerender-dependencies - 改进建议:使用
useMemo包裹数组派生
PERF-03:as 断言使用
- 位置:
src/shared/hooks/use-permission.ts:8-9 - 问题:
as Permission[]和as string[]使用了类型断言,违反编码规范 4.2.3 - 改进建议:依赖
next-auth.d.ts的类型增强(已存在),移除断言;或增加类型守卫
use-permission.ts 完整改进示例
import { useCallback, useMemo } from "react"
import { useSession } from "next-auth/react"
import type { Permission } from "@/shared/types/permissions"
export function usePermission() {
const { data: session } = useSession()
const permissions = useMemo(
() => (session?.user?.permissions ?? []) as Permission[],
[session?.user?.permissions]
)
const roles = useMemo(
() => (session?.user?.roles ?? []) as string[],
[session?.user?.roles]
)
const hasPermission = useCallback(
(permission: Permission): boolean => permissions.includes(permission),
[permissions]
)
const hasAnyPermission = useCallback(
(...perms: Permission[]): boolean => perms.some((p) => permissions.includes(p)),
[permissions]
)
const hasAllPermissions = useCallback(
(...perms: Permission[]): boolean => perms.every((p) => permissions.includes(p)),
[permissions]
)
const hasRole = useCallback(
(role: string): boolean => roles.includes(role),
[roles]
)
return { permissions, roles, hasPermission, hasAnyPermission, hasAllPermissions, hasRole }
}
四、Web 界面规范审查(应用 web-design-guidelines 技能)
说明:
src/shared/types/为纯类型定义文件,无直接 UI 代码。以下审查针对类型定义所支撑的 UI 实现层(use-permission.ts、proxy.ts、auth-guard.ts)是否符合 Web Interface Guidelines。
UI-01:权限状态可能导致 hydration mismatch
- 位置:
src/shared/hooks/use-permission.ts:7 - 问题:
useSession()在服务端渲染时返回null/loading,客户端首次渲染后才有权限数据,导致权限相关的 UI(如菜单项、按钮)在 hydration 后闪烁 - 违反规则:Web Interface Guidelines — Hydration Safety
- 改进建议:
- 服务端组件应通过
auth()获取权限并作为 props 传递 - 客户端组件在
session === null时渲染骨架屏或占位,避免权限相关 UI 闪烁 - 对权限相关的动态 UI 使用
suppressHydrationWarning或延迟渲染
- 服务端组件应通过
UI-02:权限不足时的重定向未反映在 URL
- 位置:
src/proxy.ts:75-76 - 问题:权限不足时直接重定向到默认页,URL 中未携带原始路径信息,用户无法知道「为何被重定向」
- 违反规则:Web Interface Guidelines — Navigation & State「URL reflects state」
- 改进建议:重定向时携带
?from=originalPath&reason=forbidden参数,目标页显示提示
UI-03:错误消息缺少修复步骤
- 位置:
src/shared/lib/auth-guard.ts:13 - 问题:
Permission denied: ${permission}仅描述问题,未提供下一步操作 - 违反规则:Web Interface Guidelines — Content & Copy「Error messages include fix/next step」
- 改进建议:
权限不足:需要 ${permission} 权限。请联系管理员授权或切换账号。
五、架构文档同步问题
DOC-01:004 文件行数记录过期
- 位置:
docs/architecture/004_architecture_impact_map.md:408 - 问题:记录
types/permissions.ts | 92 | 54 个权限点常量,实际文件 114 行,含DataScope、AuthContext类型定义 - 改进建议:更新为
114 行 | 54 个权限点 + DataScope + AuthContext
DOC-02:005 JSON 中 DataScope 定义字段顺序与代码不一致
- 位置:
docs/architecture/005_architecture_data.json:993 - 问题:JSON 中字段顺序为
all, owned, class_taught, grade_managed, class_members, children,代码中为all, owned, class_members, grade_managed, class_taught, children - 改进建议:同步 JSON 字段顺序与源码一致
DOC-03:缺少 Role 类型定义记录
- 问题:若按 BUG-P03 建议新增
Role类型,需在 005 JSON 的shared.types数组中补充记录 - 改进建议:新增
Role类型节点,记录usedBy: ["auth-guard", "permissions", "proxy"]
六、问题汇总统计
| 严重度 | 数量 | 问题编号 |
|---|---|---|
| 高 | 8 | BUG-A01, BUG-A02, BUG-P01, BUG-P02, BUG-P03, BUG-P04, BUG-P05, BUG-P06 |
| 中 | 6 | BUG-T01, BUG-T02, BUG-X01, BUG-X02, BUG-C01, BUG-C02 |
| 低 | 3 | BUG-C03, DOC-01, DOC-02, DOC-03 |
| 性能 | 3 | PERF-01, PERF-02, PERF-03 |
| 界面 | 3 | UI-01, UI-02, UI-03 |
| 合计 | 23 |
七、修复优先级建议
P0(立即修复 — 影响类型安全与一致性)
- BUG-A01:移除
action-state.ts分号 - BUG-X01、BUG-X02:修正
import type违规 - BUG-C01、BUG-C02、BUG-C03:升级
tsconfig.json
P1(本迭代修复 — 影响可维护性)
- BUG-P01:统一权限点命名
- BUG-P02:
Permissions添加satisfies - BUG-P03:新增
Role类型 - BUG-A02、BUG-P04、BUG-P05:补充 JSDoc
- PERF-01、PERF-02、PERF-03:
use-permission.ts性能优化
P2(下迭代修复 — 增强健壮性)
- BUG-T01、BUG-T02:补充测试用例
- BUG-P06:
DataScope.class_members携带 classIds - UI-01、UI-02、UI-03:界面规范改进
P3(文档同步)
- DOC-01、DOC-02、DOC-03:同步架构文档
八、验证命令
修复完成后应运行以下命令确保零错误:
npm run lint
npx tsc --noEmit
npm run test:unit -- action-state
报告生成人:AI Agent(GLM-5.2) 核查方法:人工逐行审查 + 架构图比对 + 技能规则匹配