feat(portal-shell): add page templates quartet (list/detail/form/workbench) (P1-3)

P1-3 验收通过:4 个页面模板 + 4 个 dev 示例页 + 三态规范。

新增文件:
- src/shared/components/page-templates/
  - list-page.tsx:ListPageShell + ListPageSkeleton
  - detail-page.tsx:DetailPageShell + DetailSection + DetailField + DetailPageSkeleton
  - form-page.tsx:FormPageShell + FormPageSkeleton
  - workbench-page.tsx:WorkbenchPageShell + WorkbenchPanel + WorkbenchPageSkeleton
  - index.ts:barrel 导出
- src/app/shell/dev/templates/
  - page.tsx:索引页(4 个模板入口)
  - list/page.tsx:列表页示例(支持 ?state=loading|empty|success)
  - detail/page.tsx:详情页示例
  - form/page.tsx:表单页示例
  - workbench/page.tsx:工作台页示例
- src/shared/components/__tests__/page-templates.test.tsx:19 个单测

修改文件:
- src/shared/lib/route-permissions.ts:新增 PREFIX /shell/dev/(空 config = 仅校验登录)
- ARCHITECTURE.md:P1-3 状态回填  + 验收证据

路径命名修正:
- 原 ARCHITECTURE.md 写 /shell/_dev/templates/*,但 Next.js 将下划线开头的
  文件夹视为"私有文件夹"(不参与路由),实测被 [[...route]] catch-all 兜底接管。
- 改用 dev 命名后,显式路由优先匹配,catch-all 不再触发。

三态规范验证:
- GET /shell/dev/templates/list?state=loading → 200,含 animate-pulse 骨架
- GET /shell/dev/templates/list?state=empty → 200,含"暂无数据"空态
- GET /shell/dev/templates/list(默认 success)→ 200,含表格数据

质量校验:
- tsc --noEmit 通过
- eslint(新/改文件)通过
- vitest run 全量 21 test files / 231 tests 全部通过(212 原有 + 19 新增)

Refs: apps/portal-shell/ARCHITECTURE.md §7.3 页面四种类型与模板、
      §7.4 页面级数据获取模式、§11.3 每页硬性清单(DoD)三态规范
This commit is contained in:
SpecialX
2026-07-22 13:02:11 +08:00
parent 03e3ec4f60
commit 994441c2dc
13 changed files with 1564 additions and 2 deletions

View File

@@ -2,7 +2,7 @@
> 版本3.0
> 日期2026-07-20
> 状态:**P0 已完成 + P1-1/P1-2 已完成2026-07-22 验收)+ P1 进行中;架构审计完成 + 重设计方案定稿**
> 状态:**P0 已完成 + P1-1/P1-2/P1-3 已完成2026-07-22 验收)+ P1 进行中;架构审计完成 + 重设计方案定稿**
> 本文档地位:**portal-shell 前端工作的唯一权威指导文档**。所有后续 AI/人工在此模块的工作必须先读本文件,以其为准。
>
> 关联文档(按效力排序):
@@ -765,7 +765,7 @@ export default async function ExamsPage(): Promise<React.ReactElement> {
| ---- | -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| P1-1 | `src/app/shell/layout.tsx` AppFrameTopBar 静态挂载 + Sidebar 导航菜单 `navigation.ts` + 权限过滤) | 4 角色各见各菜单;导航项与 route-permissions 表一致(单测) | ✅ |
| P1-2 | 仪表盘改接真实查询:`teacherDashboard`/`studentDashboard`/`parentDashboard`/`adminDashboard` + `warnings`/`errorBookStats` | 起全栈4 角色仪表盘显示真实聚合数据截图widget 假契约查询grades/homeworks/schedule/attendance/exams/announcements全部下线或改造 | ✅ |
| P1-3 | 页面模板四件套list/detail/form/workbench+ 三态规范 | Storybook 或示例页 4 张(/shell/_dev/templates/*,仅 dev 可见 | |
| P1-3 | 页面模板四件套list/detail/form/workbench+ 三态规范 | Storybook 或示例页 4 张(/shell/dev/templates/*,仅 dev 可见Next.js 私有文件夹 `_xxx` 不参与路由,故使用 `dev` 而非 `_dev` | |
| P1-4 | next-intl 接入 + messages 合并迁移 | 切换 locale 页面文案切换(截图);`useT` 自造函数删除 | ⏳ |
| P1-5 | MSW 兜底层(迁移旧 handlers覆盖 dashboard/users/exams/grades 四域起步) | `NEXT_PUBLIC_MSW=1` 无后端启动,仪表盘 + users 页有数据(截图);生产构建 bundle 无 mocks | ⏳ |
| P1-6 | 31 widget 令牌清债271 处机械替换)+ `border border` 去重 + 未知类检测进 arch:scan | `grep -c "text-heading-\|mt-sm\|py-xs\|p-md" src/widgets` = 0`pnpm lint:tokens` 通过 | ⏳ |
@@ -801,6 +801,28 @@ export default async function ExamsPage(): Promise<React.ReactElement> {
- **三态规范**4 个仪表盘页统一遵循 loadingStatCard isLoading 骨架)→ errorCard 错误提示)→ success真实数据三态
- **质量校验**`tsc --noEmit` 通过;`eslint`(新/改文件)通过;`vitest run` 全量 20 test files / 212 tests 全部通过
**P1-3 验收证据2026-07-22**
- **4 个页面模板组件**[src/shared/components/page-templates/](file:///e:/Desktop/Edu/apps/portal-shell/src/shared/components/page-templates/)
- [list-page.tsx](file:///e:/Desktop/Edu/apps/portal-shell/src/shared/components/page-templates/list-page.tsx)`ListPageShell` + `ListPageSkeleton`,结构 = PageHeader + FilterBar + 主内容 + Pagination三态 = loading/empty/errorNode 优先级链
- [detail-page.tsx](file:///e:/Desktop/Edu/apps/portal-shell/src/shared/components/page-templates/detail-page.tsx)`DetailPageShell` + `DetailSection` + `DetailField` + `DetailPageSkeleton`,结构 = PageHeader含 backHref + 分区 + 字段表
- [form-page.tsx](file:///e:/Desktop/Edu/apps/portal-shell/src/shared/components/page-templates/form-page.tsx)`FormPageShell` + `FormPageSkeleton`,结构 = PageHeader + form + errorSummary + 提交/取消按钮
- [workbench-page.tsx](file:///e:/Desktop/Edu/apps/portal-shell/src/shared/components/page-templates/workbench-page.tsx)`WorkbenchPageShell` + `WorkbenchPanel` + `WorkbenchPageSkeleton`,结构 = PageHeader + 三栏(左树/中画布/右属性),左右栏宽度可配置
- [index.ts](file:///e:/Desktop/Edu/apps/portal-shell/src/shared/components/page-templates/index.ts)barrel 导出
- **4 个 dev 示例页**(仅 dev 可见,生产环境 `notFound()` 兜底):
- [/shell/dev/templates](file:///e:/Desktop/Edu/apps/portal-shell/src/app/shell/dev/templates/page.tsx):索引页,列出 4 张模板
- [/shell/dev/templates/list](file:///e:/Desktop/Edu/apps/portal-shell/src/app/shell/dev/templates/list/page.tsx):列表页示例,支持 `?state=loading|empty|success` 切换三态
- [/shell/dev/templates/detail](file:///e:/Desktop/Edu/apps/portal-shell/src/app/shell/dev/templates/detail/page.tsx):详情页示例
- [/shell/dev/templates/form](file:///e:/Desktop/Edu/apps/portal-shell/src/app/shell/dev/templates/form/page.tsx):表单页示例
- [/shell/dev/templates/workbench](file:///e:/Desktop/Edu/apps/portal-shell/src/app/shell/dev/templates/workbench/page.tsx):工作台页示例
- **路径命名修正**:原 ARCHITECTURE.md 写 `/shell/_dev/templates/*`,但 Next.js 将下划线开头的文件夹视为"私有文件夹"(不参与路由),实测 `/shell/_dev/templates``[[...route]]/page.tsx` catch-all 兜底接管ClientShell 微内核渲染)。改用 `dev` 命名后显式路由优先匹配catch-all 不再触发。route-permissions.ts 同步登记 `PREFIX /shell/dev/`(空 config = 仅校验登录身份)
- **三态规范验证**HTTP 200 + 内容断言):
- `GET /shell/dev/templates/list?state=loading` → 200HTML 含 `animate-pulse` 骨架,无表格数据
- `GET /shell/dev/templates/list?state=empty` → 200HTML 含"暂无数据"空态,无表格数据
- `GET /shell/dev/templates/list`(默认 success→ 200HTML 含表格行"考试 A"
- **单测**`vitest run --reporter=verbose page-templates` → 19/19 passed覆盖 4 个模板的三态、字段渲染、提交按钮禁用、errorSummary alert 等)
- **质量校验**`tsc --noEmit` 通过;`eslint src/shared/components/page-templates src/app/shell/dev src/shared/lib/route-permissions.ts` 通过;`vitest run` 全量 21 test files / 231 tests 全部通过212 原有 + 19 新增)
### P2 · 教师域页面23 周,可与 P3 部分并行)
- 范围§9.1 全表(~50 页。顺序建议exams → homework → grades → lesson-plans → questions/textbooks → attendance/classes/students → diagnostic/error-book/analytics → elective/course-plans → ai-* → practice/schedule-changes/leave。