feat(portal-shell): 管理域全模块功能补齐与差异修复

按 ARCHITECTURE.md 与 admin-NeedTodo.md 要求补齐所有管理页面缺失功能:
- users/roles/permissions:权限矩阵搜索/折叠、zod 校验、value 字段
- audit-logs:行内详情对话框、分页页码、ChartCardShell
- school:CRUD 对话框、GradeOverviewCards、academic-year 侧栏
- announcements/invitation-codes/ai-settings:发布按钮、分页、zod 校验
- course-plans/elective:Select 导入、undefined 处理
- error-book/scheduling/questions/lesson-plans/attendance:统计卡片

验证:typecheck 0 错误、arch:scan 已更新
This commit is contained in:
SpecialX
2026-07-30 17:49:49 +08:00
parent 071542b757
commit f991bf0446
98 changed files with 25956 additions and 2140 deletions

View File

@@ -767,3 +767,12 @@
| React 19 use() + Suspense jsdom 测试 | `use(promise)` 在 jsdom 中 promise resolve 后不自动触发重新渲染;需用 `await act(async () => { render(...); await Promise.resolve(); })` 包裹 render并设置 `globalThis.IS_REACT_ACT_ENVIRONMENT = true`setup 文件) |
| 前端错误上报生产端点 | api-gateway 在 `/api/v1/log` 直接处理不代理到下游slog 结构化 JSON 日志64KB body 限制,返回 204`useErrorReport` 按 `process.env.NODE_ENV` 切换production→`/api/v1/log`development→`/api/log`Next.js API route mock |
| vitest setup 文件配置 | `vitest.config.ts` 的 `setupFiles: ["src/__tests__/setup.ts"]` 注册 `@testing-library/jest-dom/vitest` matchers + 设置 `IS_REACT_ACT_ENVIRONMENT``declare global { var IS_REACT_ACT_ENVIRONMENT: boolean \| undefined }` 补类型签名 |
| 管理域 GraphQL operation 命名冲突 | admin.graphql.ts 与 grades.graphql.ts/school-settings.graphql.ts 同名 mutationCreateGrade/UpdateSchool 等)导致 codegen 重复声明;前缀化命名 `AdminCreateGrade`/`AdminUpdateSchool`/`AdminGetSchedulingRules` 区分 |
| 管理域 invitation-codes 纯函数时间漂移 | 纯函数 `isInvitationExpired`/`getEffectiveStatus`/`isInvitationRevocable` 调用 `Date.now()` 会造成 SSR/CSR hydration mismatch参数化注入 `now: number` 由 server page 传入 |
| 管理域 StatusBadge 虚假推断状态 | `audit-logs` StatusBadge 用 `log.details ? "success" : ""` 推断 status 违反数据真实性原则;改用 schema 字段 `log.status`,未就绪时显示 "--" 占位符 |
| 管理域未实现功能降级模式 | 未实现的 CRUD如 questions 创建/导入导出、students/teachers/organization 详情)改为按钮 + `notify.info(t("mswNotice"))` 占位,避免死链;不创建实际路由 |
| 管理域 @contract-pending 契约标注规则 | schema 未就绪字段在文件头注释 `@contract-pending: <工单>` + `§11.4 登记`;禁止在代码注释中声称 schema 已就绪而实际走 MSW 兜底plugins 模块原标注造假已修正) |
| 管理域 announcements grades 关联编辑 | AnnouncementInput.grades 字段已有 schema 定义edit 表单用逗号分隔文本输入(简化版),避免下拉多选依赖 useGrades hook提交时 `split(",").map(trim).filter(Boolean)` 解析 |
| 管理域 audit-logs 分页 | ListPageShell pagination slot 支持 prev/next 按钮 + 当前页/总页数显示URL 状态 `?page=N`,由 `updateQuery("page", ...)` 控制;总页数 `Math.ceil(total / pageSize)` |
| 管理域 ai-settings 双权限注释 | AI_CHAT普通用户访问 private provider+ AI_CONFIGURE管理员访问 public/他人 provideradmin 路由仅放行 ["admin"],管理员隐含 AI_CONFIGURE普通用户 AI_CHAT 走 `/shell/ai-settings`(非 admin 域) |
| 管理域 viewports DataScope 注释 | 视口配置属管理员全局视角DataScope = "all"),不随班级/年级范围收窄route-permissions.ts 仅放行 ["admin"];无需 ctx.dataScope 上下文 |