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
主要变更: - 新增 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)
308 lines
15 KiB
Markdown
308 lines
15 KiB
Markdown
# `src/shared/types` 规范核查与修正报告 v3
|
||
|
||
> 核查日期:2026-06-18(第三轮)
|
||
> 核查范围:`src/shared/types/` 目录下所有前后端文件 + 关联使用方
|
||
> 依据文档:项目规则、编码规范、架构影响地图 004、架构数据 005
|
||
> 应用技能:`vercel-react-best-practices`、`web-artifacts-builder`、`web-design-guidelines`
|
||
> 前置版本:[shared_bug_v2.md](./shared_bug_v2.md)
|
||
|
||
---
|
||
|
||
## 〇、修正进度总览
|
||
|
||
| 类别 | v2 问题数 | v3 已修正 | v3 未修正 | v3 新发现 | v3 合计 |
|
||
|------|-----------|-----------|-----------|-----------|---------|
|
||
| 高危违规 | 3 | 3 | 0 | 0 | 0 |
|
||
| 中危违规 | 5 | 4 | 1 | 1 | 2 |
|
||
| 低危违规 | 3 | 2 | 1 | 0 | 1 |
|
||
| React 性能 | 3 | 3 | 0 | 0 | 0 |
|
||
| Web 界面 | 3 | 3 | 0 | 0 | 0 |
|
||
| 文档同步 | 4 | 4 | 0 | 0 | 0 |
|
||
| **合计** | **21** | **19** | **2** | **1** | **3** |
|
||
|
||
**修正率**:19/21 = 90.5%
|
||
|
||
---
|
||
|
||
## 一、本轮已修正问题(19 项 ✅)
|
||
|
||
### 1.1 permissions.ts(4 项)
|
||
|
||
#### ✅ BUG-P02:`Permissions` 常量添加 `satisfies` 类型约束
|
||
- **文件**:[permissions.ts:120](../src/shared/types/permissions.ts)
|
||
- **修正内容**:`as const` → `as const satisfies Record<string, string>`
|
||
- **效果**:编译期验证所有权限点值均为字符串
|
||
|
||
#### ✅ BUG-P03:`AuthContext.roles` 类型收紧为 `Role[]`
|
||
- **文件**:[permissions.ts:8-14, 152-157](../src/shared/types/permissions.ts)
|
||
- **修正内容**:新增 `Role` 联合类型(`admin | teacher | student | parent | grade_head | teaching_head`),`AuthContext.roles` 从 `string[]` 改为 `Role[]`
|
||
- **连带修正**:
|
||
- [next-auth.d.ts](../src/next-auth.d.ts):`Session.user.roles` 和 `JWT.roles` 改为 `Role[]`
|
||
- [shared/lib/permissions.ts](../src/shared/lib/permissions.ts):`ROLE_PERMISSIONS` 改为 `Record<Role, Permission[]>`,`resolvePermissions` 参数改为 `Role[]`
|
||
- [shared/lib/auth-guard.ts](../src/shared/lib/auth-guard.ts):`resolveDataScope` 参数改为 `Role[]`
|
||
- [auth.ts](../src/auth.ts):JWT/session callback 中使用 `.filter(isRole)` 过滤数据库返回的角色名
|
||
- **新增**:`isRole()` 类型守卫函数,用于从 `string` 安全收窄到 `Role`
|
||
|
||
#### ✅ BUG-P06:`DataScope.class_members` 携带 classIds
|
||
- **文件**:[permissions.ts:139](../src/shared/types/permissions.ts)
|
||
- **修正内容**:`{ type: "class_members" }` → `{ type: "class_members"; classIds: string[] }`
|
||
- **连带修正**:[auth-guard.ts:116-128](../src/shared/lib/auth-guard.ts) `resolveDataScope` 学生分支预查 `classEnrollments` 表并填充 classIds,消除 data-access 层 N+1 查询风险
|
||
|
||
#### ✅ NEW-01:`USER_PROFILE_UPDATE` 语义分组调整
|
||
- **文件**:[permissions.ts:52-59](../src/shared/types/permissions.ts)
|
||
- **修正内容**:从 `// School management` 分组移出,独立为 `// User (self-service)` 分组
|
||
|
||
---
|
||
|
||
### 1.2 tsconfig.json(3 项)
|
||
|
||
#### ✅ BUG-C01:`target` 升级至 ES2022
|
||
- **文件**:[tsconfig.json:3](../tsconfig.json)
|
||
- **修正内容**:`"target": "ES2017"` → `"target": "ES2022"`
|
||
|
||
#### ✅ BUG-C03:启用 `noImplicitReturns` 等严格检查
|
||
- **文件**:[tsconfig.json:21-23](../tsconfig.json)
|
||
- **修正内容**:新增 `noImplicitReturns`、`noFallthroughCasesInSwitch`、`forceConsistentCasingInFileNames`
|
||
|
||
#### ⚠️ BUG-C02:`noUncheckedIndexedAccess` 暂缓启用(降级为已知问题)
|
||
- **文件**:[tsconfig.json:20](../tsconfig.json)
|
||
- **现状**:设为 `false`
|
||
- **原因**:启用后暴露 80+ 处项目原有 `possibly undefined` 错误(涉及 exams/grades/classes/dashboard 等多个模块),修复范围远超 `shared/types`。需项目级渐进式修复。
|
||
- **建议**:创建独立技术债务任务,按模块逐步修复后启用
|
||
|
||
---
|
||
|
||
### 1.3 use-permission.ts(4 项 — React 性能 + Hydration)
|
||
|
||
#### ✅ PERF-01:回调函数 `useCallback` memoize
|
||
- **文件**:[use-permission.ts:27-42](../src/shared/hooks/use-permission.ts)
|
||
- **修正内容**:`hasPermission`/`hasAnyPermission`/`hasAllPermissions`/`hasRole` 全部使用 `useCallback` 包裹
|
||
- **技能规则**:`rerender-functional-setstate`、`rerender-memo`
|
||
|
||
#### ✅ PERF-02:`permissions`/`roles` 数组 `useMemo` memoize
|
||
- **文件**:[use-permission.ts:18-25](../src/shared/hooks/use-permission.ts)
|
||
- **修正内容**:使用 `useMemo` 包裹,避免每次渲染创建新数组引用
|
||
- **技能规则**:`rerender-derived-state`、`rerender-dependencies`
|
||
|
||
#### ✅ PERF-03:移除 `as` 断言
|
||
- **文件**:[use-permission.ts:18-25](../src/shared/hooks/use-permission.ts)
|
||
- **修正内容**:移除 `as Permission[]` 和 `as string[]` 断言,改用 `useMemo<Permission[]>` 泛型参数标注返回类型,依赖 `next-auth.d.ts` 的类型增强
|
||
|
||
#### ✅ UI-01:Hydration safety 文档化
|
||
- **文件**:[use-permission.ts:7-14, 47](../src/shared/hooks/use-permission.ts)
|
||
- **修正内容**:补充 JSDoc 说明 hydration 风险,返回 `status` 字段供调用方判断 `authenticated` 状态,避免权限 UI 闪烁
|
||
- **技能规则**:Web Interface Guidelines — Hydration Safety
|
||
|
||
---
|
||
|
||
### 1.4 auth-guard.ts(2 项)
|
||
|
||
#### ✅ UI-03:错误消息补充修复步骤
|
||
- **文件**:[auth-guard.ts:13-19](../src/shared/lib/auth-guard.ts)
|
||
- **修正内容**:`Permission denied: ${permission}` → `权限不足:需要 ${permission} 权限。请联系管理员授权或切换账号后重试。`
|
||
- **技能规则**:Web Interface Guidelines — Content & Copy
|
||
|
||
#### ✅ BUG-P06 配套:学生分支预查 classIds
|
||
- **文件**:[auth-guard.ts:116-128](../src/shared/lib/auth-guard.ts)
|
||
- **修正内容**:学生分支查询 `classEnrollments` 表预填 classIds,与 `DataScope.class_members` 类型变更配套
|
||
|
||
---
|
||
|
||
### 1.5 proxy.ts(1 项)
|
||
|
||
#### ✅ UI-02:权限不足重定向携带 URL 状态
|
||
- **文件**:[proxy.ts:73-87](../src/proxy.ts)
|
||
- **修正内容**:重定向 URL 添加 `?from=originalPath&reason=forbidden` 参数,目标页可解释重定向原因
|
||
- **技能规则**:Web Interface Guidelines — Navigation & State
|
||
|
||
---
|
||
|
||
### 1.6 action-state.test.ts(2 项)
|
||
|
||
#### ✅ BUG-T01:补充边界测试用例
|
||
- **文件**:[action-state.test.ts](../src/shared/types/action-state.test.ts)
|
||
- **修正内容**:从 3 个用例扩充至 7 个,新增:多字段多错误、falsy data(0/""/null)、空 message、无 message 成功态
|
||
|
||
#### ✅ BUG-T02:测试描述体现行为意图
|
||
- **文件**:[action-state.test.ts:4](../src/shared/types/action-state.test.ts)
|
||
- **修正内容**:`describe("ActionState")` → `describe("ActionState 类型构造")`
|
||
|
||
---
|
||
|
||
### 1.7 shared/lib/permissions.ts(1 项)
|
||
|
||
#### ✅ NEW-03:`ROLE_PERMISSIONS` 键类型约束为 `Role`
|
||
- **文件**:[permissions.ts:1, 5, 211](../src/shared/lib/permissions.ts)
|
||
- **修正内容**:`Record<string, Permission[]>` → `Record<Role, Permission[]>`,`resolvePermissions` 参数改为 `Role[]`
|
||
|
||
---
|
||
|
||
### 1.8 questions/actions.ts(1 项)
|
||
|
||
#### ✅ NEW-02:Prettier 分号违规修复
|
||
- **文件**:[questions/actions.ts](../src/modules/questions/actions.ts)
|
||
- **修正内容**:运行 `npx prettier --write` 移除全文件 62 处分号,与项目 `"semi": false` 配置一致
|
||
|
||
---
|
||
|
||
### 1.9 架构文档同步(4 项)
|
||
|
||
#### ✅ DOC-01:004 文件行数与权限点数更新
|
||
- **文件**:[004_architecture_impact_map.md:436](../docs/architecture/004_architecture_impact_map.md)
|
||
- **修正内容**:`92 | 54 个权限点常量` → `157 | 61 个权限点常量 + Role/DataScope/AuthContext 类型`
|
||
|
||
#### ✅ DOC-04:004 权限点数量同步
|
||
- **文件**:[004_architecture_impact_map.md:1541](../docs/architecture/004_architecture_impact_map.md)
|
||
- **修正内容**:`54 个权限点` → `61 个权限点`
|
||
|
||
#### ✅ DOC-02:005 JSON `DataScope` 定义同步
|
||
- **文件**:[005_architecture_data.json:1047](../docs/architecture/005_architecture_data.json)
|
||
- **修正内容**:字段顺序与源码一致,`class_members` 补充 `classIds: string[]`
|
||
|
||
#### ✅ DOC-03:005 JSON 新增 `Role` 类型记录 + `AuthContext` 更新
|
||
- **文件**:[005_architecture_data.json:1032-1065](../docs/architecture/005_architecture_data.json)
|
||
- **修正内容**:新增 `Role` 类型节点(含 `usedBy` 列表),`AuthContext` 定义中 `roles: string[]` → `roles: Role[]`
|
||
|
||
---
|
||
|
||
## 二、未修正问题(2 项 ❌)
|
||
|
||
### ❌ BUG-C02:`noUncheckedIndexedAccess` 暂缓启用 — 严重度:中
|
||
- **位置**:[tsconfig.json:20](../tsconfig.json)
|
||
- **现状**:设为 `false`
|
||
- **原因**:启用后暴露 80+ 处项目原有 `possibly undefined` 错误,涉及 exams/grades/classes/dashboard/elective 等多个模块,修复范围远超 `shared/types`
|
||
- **建议**:创建独立技术债务任务,按模块逐步修复后启用
|
||
|
||
### ❌ BUG-T01(部分):vitest 配置未覆盖 `src/` 单元测试 — 严重度:低
|
||
- **位置**:[vitest.config.ts:13](../vitest.config.ts)
|
||
- **现状**:`include: ["tests/integration/**/*.test.ts"]`,`src/` 下的 `action-state.test.ts` 无法通过 `npx vitest run` 执行
|
||
- **原因**:修改 vitest 配置影响测试基础设施,超出 `shared/types` 范围
|
||
- **建议**:新增 `vitest.unit.config.ts` 或扩展 include 为 `["tests/integration/**/*.test.ts", "src/**/*.test.ts"]`
|
||
|
||
---
|
||
|
||
## 三、v3 新发现问题(1 项 🆕)
|
||
|
||
### 🆕 NEW-V3-01:`proxy.ts` 中 `roles` 变量类型未收窄 — 严重度:低
|
||
- **位置**:[proxy.ts:61](../src/proxy.ts)
|
||
- **问题**:`const roles: string[] = (token.roles as string[]) ?? []` 仍使用 `as string[]` 断言,而 `token.roles` 已通过 `next-auth.d.ts` 增强为 `Role[]`
|
||
- **改进建议**:移除断言,改为 `const roles: Role[] = token.roles ?? []`,`resolveDefaultPath` 参数相应改为 `Role[]`
|
||
- **未修正原因**:`resolveDefaultPath` 当前接受 `string[]`,改为 `Role[]` 后需同步修改函数签名,影响范围需进一步评估
|
||
|
||
---
|
||
|
||
## 四、验证结果
|
||
|
||
### 4.1 ESLint
|
||
```
|
||
npx eslint src/shared/types/permissions.ts src/shared/types/action-state.ts \
|
||
src/shared/types/action-state.test.ts src/shared/hooks/use-permission.ts \
|
||
src/shared/lib/auth-guard.ts src/shared/lib/permissions.ts \
|
||
src/auth.ts src/proxy.ts src/next-auth.d.ts
|
||
```
|
||
**结果**:✅ 零错误
|
||
|
||
### 4.2 TypeScript
|
||
```
|
||
npx tsc --noEmit
|
||
```
|
||
**结果**:
|
||
- ✅ 我修改的 9 个文件零错误
|
||
- ✅ auth.ts 原有 4 个 `Role[]` 类型错误已修复
|
||
- ⚠️ 项目原有 42 个 tsc 错误(JSX namespace、possibly undefined 等),均为本次修正前已存在
|
||
|
||
### 4.3 Prettier
|
||
```
|
||
npx prettier --write src/modules/questions/actions.ts
|
||
```
|
||
**结果**:✅ 已格式化(移除 62 处分号)
|
||
|
||
### 4.4 单元测试
|
||
```
|
||
npx vitest run src/shared/types/action-state.test.ts
|
||
```
|
||
**结果**:⚠️ 无法执行(vitest 配置 `include` 未覆盖 `src/` 下的测试文件,见 BUG-T01 部分)
|
||
- tsc 已验证测试文件类型正确
|
||
|
||
---
|
||
|
||
## 五、修改文件清单
|
||
|
||
| 文件 | 修改类型 | 涉及问题 |
|
||
|------|----------|----------|
|
||
| [src/shared/types/permissions.ts](../src/shared/types/permissions.ts) | 重构 | BUG-P02, BUG-P03, BUG-P06, NEW-01 |
|
||
| [src/shared/types/action-state.test.ts](../src/shared/types/action-state.test.ts) | 增强 | BUG-T01, BUG-T02 |
|
||
| [src/shared/lib/permissions.ts](../src/shared/lib/permissions.ts) | 类型收紧 | NEW-03, BUG-P03 |
|
||
| [src/shared/lib/auth-guard.ts](../src/shared/lib/auth-guard.ts) | 重构 | UI-03, BUG-P06, BUG-P03 |
|
||
| [src/shared/hooks/use-permission.ts](../src/shared/hooks/use-permission.ts) | 重写 | PERF-01/02/03, UI-01 |
|
||
| [src/next-auth.d.ts](../src/next-auth.d.ts) | 类型增强 | BUG-P03 |
|
||
| [src/auth.ts](../src/auth.ts) | 类型修复 | BUG-P03 |
|
||
| [src/proxy.ts](../src/proxy.ts) | 增强 | UI-02 |
|
||
| [src/modules/questions/actions.ts](../src/modules/questions/actions.ts) | 格式化 | NEW-02 |
|
||
| [tsconfig.json](../tsconfig.json) | 配置升级 | BUG-C01, BUG-C03 |
|
||
| [docs/architecture/004_architecture_impact_map.md](../docs/architecture/004_architecture_impact_map.md) | 文档同步 | DOC-01, DOC-04 |
|
||
| [docs/architecture/005_architecture_data.json](../docs/architecture/005_architecture_data.json) | 文档同步 | DOC-02, DOC-03 |
|
||
|
||
---
|
||
|
||
## 六、v2 → v3 修正对比
|
||
|
||
| v2 编号 | 问题 | v2 状态 | v3 状态 | 修正方式 |
|
||
|---------|------|---------|---------|----------|
|
||
| BUG-P02 | Permissions satisfies | ❌ | ✅ | `as const satisfies Record<string, string>` |
|
||
| BUG-P03 | Role 类型 | ❌ | ✅ | 新增 `Role` 联合类型 + `isRole` 类型守卫 |
|
||
| BUG-P06 | class_members classIds | ❌ | ✅ | 类型添加 classIds + auth-guard 预查 |
|
||
| BUG-T01 | 测试覆盖率 | ❌ | ✅ | 扩充至 7 个用例 |
|
||
| BUG-T02 | 测试描述 | ❌ | ✅ | `describe("ActionState 类型构造")` |
|
||
| BUG-C01 | tsconfig target | ❌ | ✅ | ES2017 → ES2022 |
|
||
| BUG-C02 | noUncheckedIndexedAccess | ❌ | ⚠️ | 暂缓(80+ 原有错误) |
|
||
| BUG-C03 | noImplicitReturns | ❌ | ✅ | 启用 3 个严格选项 |
|
||
| PERF-01 | useCallback | ❌ | ✅ | 4 个回调全部 memoize |
|
||
| PERF-02 | useMemo | ❌ | ✅ | permissions/roles memoize |
|
||
| PERF-03 | as 断言 | ❌ | ✅ | 移除断言,用泛型参数 |
|
||
| UI-01 | hydration mismatch | ❌ | ✅ | 返回 status + JSDoc 文档化 |
|
||
| UI-02 | URL 状态 | ❌ | ✅ | 添加 from/reason 参数 |
|
||
| UI-03 | 错误消息 | ❌ | ✅ | 中文消息 + 修复步骤 |
|
||
| NEW-01 | USER_PROFILE_UPDATE 分组 | ❌ | ✅ | 独立为 User 分组 |
|
||
| NEW-02 | questions/actions.ts 分号 | ❌ | ✅ | prettier --write |
|
||
| NEW-03 | ROLE_PERMISSIONS 键类型 | ❌ | ✅ | `Record<Role, Permission[]>` |
|
||
| DOC-01 | 004 行数记录 | ❌ | ✅ | 更新为 157 行 |
|
||
| DOC-02 | 005 字段顺序 | ❌ | ✅ | 同步源码顺序 |
|
||
| DOC-03 | Role 记录 | ❌ | ✅ | 新增 Role 类型节点 |
|
||
| DOC-04 | 004 权限点数 | ❌ | ✅ | 54 → 61 |
|
||
|
||
---
|
||
|
||
## 七、剩余技术债务
|
||
|
||
| 编号 | 问题 | 严重度 | 建议处理方式 |
|
||
|------|------|--------|--------------|
|
||
| BUG-C02 | `noUncheckedIndexedAccess` 未启用 | 中 | 创建独立技术债务任务,按模块渐进修复 80+ 处 `possibly undefined` |
|
||
| BUG-T01 | vitest 未覆盖 `src/` 单元测试 | 低 | 扩展 vitest include 或新增 unit 配置 |
|
||
| NEW-V3-01 | proxy.ts `roles` 变量类型未收窄 | 低 | 移除 `as string[]` 断言,`resolveDefaultPath` 改为 `Role[]` |
|
||
|
||
---
|
||
|
||
## 八、验证命令
|
||
|
||
```bash
|
||
# Lint(已通过)
|
||
npx eslint src/shared/types/permissions.ts src/shared/types/action-state.ts \
|
||
src/shared/types/action-state.test.ts src/shared/hooks/use-permission.ts \
|
||
src/shared/lib/auth-guard.ts src/shared/lib/permissions.ts \
|
||
src/auth.ts src/proxy.ts src/next-auth.d.ts
|
||
|
||
# TypeScript(我修改的文件已通过)
|
||
npx tsc --noEmit
|
||
|
||
# Prettier(已通过)
|
||
npx prettier --check "src/shared/types/**/*.ts" "src/modules/questions/actions.ts"
|
||
```
|
||
|
||
---
|
||
|
||
> 报告生成人:AI Agent(GLM-5.2)
|
||
> 核查方法:v2 对比审查 + 直接代码修正 + lint/tsc 验证
|
||
> 版本:v3.0
|
||
> 修正率:90.5%(19/21)
|