feat(portal-shell): 管理域 §9.4 B5 全量迁移(24 + 21 补充批次共 44 页 + 42 features)

按 ARCHITECTURE.md §9.4 规划口径 + admin-NeedTodo.md §四补充批次完成管理域全量页面迁移:

【§9.4 规划 24 页(B5)】
- users(2) + roles(1) + permissions(1) + audit-logs(4) + invitation-codes(1)
- school(6: redirect/schools/classes/departments/academic-year/grades)
- announcements(1) + files(1) + ai-settings(1) + system(1) + viewports(1)
- students(1) + teachers(1) + organization(1) + plugins(1, config-service)
- 仪表盘已存在(/shell/admin/page.tsx)

【§四补充批次 21 页】
- course-plans(4) + elective(4) + questions(1) + lesson-plans(2) + error-book(1)
- scheduling(3: auto/changes/rules) + attendance(1) + curriculum-map(1)
- announcements 详情/编辑(2) + roles/[id] 详情(1) + users/import(1)

【实现要点】
- 全部使用 ListPageShell + loading/error/empty 三态规范(§11.3 DoD)
- 走 lib/api hooks;未就绪契约走 MSW + @contract-pending 注释(§11.4)
- 文案走 useTranslations(zh-CN + en 两份同步更新)
- 42 个 features/<domain>/transformations.ts 纯函数 + 配套 vitest 单测
- catch 块统一 notify.error;无空 catch;lint:tokens 通过
- 路由全部登记到 route-permissions.ts(39 EXACT + 8 PREFIX)

【验收】
- tsc --noEmit: 0 errors
- ESLint src: 0 errors (4 generated-files warnings, pre-existing)
- lint:tokens: 0 errors
- vitest: 1639/1639 passed (含 23 admin 测试文件 671 用例)
- check:routes: PASS (143 routes, 4 ghost entries pre-existing)
- check:pages: PASS (146 pages)
- check:codegen: PASS
- arch:scan: 24 modules, 8262 symbols

关联:ARCHITECTURE.md §9.4 / §10 P5 / §11.3 DoD / §11.6
This commit is contained in:
SpecialX
2026-07-24 23:07:20 +08:00
parent 5a9f652943
commit 062d9e9582
394 changed files with 60468 additions and 118 deletions

View File

@@ -0,0 +1,725 @@
# 家长域Parent待完成功能分析
> 参考项目:`e:\desktop\CICD\src\app\(dashboard)\parent\`
> 当前项目:`e:\Desktop\Edu\apps\portal-shell\src\app\shell\parent\`
> 规划依据:`apps/portal-shell/ARCHITECTURE.md` §9.324 页B4 批次)
> 分析日期2026-07-24
> 任务范围:仅分析,不写代码
---
## 一、页面完成度总览
### 1.1 portal-shell 家长域现状
当前 `apps/portal-shell/src/app/shell/parent/` 下**仅有 1 个页面**
| 路径 | 状态 | 说明 |
| ------------------------ | --------- | ------------------------------------------------ |
| `/shell/parent/page.tsx` | ✅ 已完成 | 家长仪表盘(仅基础版,缺 trend/weakness 详情页) |
### 1.2 完成度统计
| 状态 | 数量 | 说明 |
| ------------ | ------ | ----------------------------------------------------------------------- |
| ✅ 已完成 | 1 | `/shell/parent/page.tsx`(仪表盘基础版,仍缺 2 个详情页) |
| 🟡 部分完成 | 1 | dashboard 模块基础页有trend/weakness 详情页缺) |
| ❌ 缺失 | 22 | 见下方模块清单 |
| **规划总数** | **24** | ARCHITECTURE.md §9.3 B4 批次(含 notifications/settings 共享路由 2 页) |
### 1.3 portal-shell 仪表盘与 CICD 仪表盘的技术差异(关键架构差异)
| 维度 | CICD 仪表盘 | portal-shell 仪表盘 |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| 渲染模式 | Server Component`async function` | Client Component`"use client"` |
| 数据获取 | Server Action `getParentDashboardAction()` + React `use()` 流式渲染 | `useParentDashboard()` Hook`@/lib/api`,走 BFF |
| 国际化 | `next-intl` `getTranslations` | 无(硬编码中文) |
| 权限校验 | `getAuthContext` + dataScope 类型守卫 | 无 |
| 视图组件 | `ParentDashboard` / `ChildCard` / `ParentAttentionBanner` / `AiChildSummary`(拆分到 `@/modules/dashboard/components` / `@/modules/parent/components` / `@/modules/ai/components` | 直接内联在 page.tsx |
| 数据来源 | 直查 DBDrizzle | 走 data-ana 微服务聚合(`parentDashboard` 契约) |
| 多子女支持 | ✅ 子女卡片网格 + AI 学情摘要(每子女一张) | ❌ 仅展示 `child_avg_score` / `child_class_rank` 等单值字段 |
> **重要提示**portal-shell 已转向微服务 + BFF 架构,迁移时**不能照搬 CICD 的 Server Action + Drizzle 直查模式**。家长页面应通过 `teacher-bff` / `data-ana` 等服务的 gRPC/HTTP API 获取数据,前端通过 hooks 消费。家长域多为**只读视图**,重点在 `myChildren` 契约 + `child-overview` 聚合。
---
## 二、缺失页面清单(按模块分组)
### 2.1 dashboard 模块3 页规划1 已完成2 缺失)
#### 2.1.1 ✅ `/shell/parent/page.tsx`(已完成)
- **portal-shell 实现**:基础仪表盘,显示孩子平均分 / 班级排名 / 薄弱知识点 / 预警通知
- **技术栈**Client Component + `useParentDashboard()` Hook + `DashboardShell` / `StatCard` 共享组件
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\dashboard\page.tsx`
- **CICD 技术栈**Server Component + `getParentDashboardAction()` Server Action + `ParentDashboard` 视图组件 + React `use()` 流式渲染 + `generateMetadata`
- **CICD 关键功能**
- 无子女时显示 `ParentNoChildrenPage` 空态
- 子女卡片列表(移动端水平滑动 + 桌面端网格,响应式)
- AI 学情摘要区域(`AiChildSummary`,每子女一张,客户端组件,由 `AiClientProvider` 注入数据服务)
- 家长关注横幅(`ParentAttentionBanner`
- 传入 `homeworkCompletionRate` 等"已知安全字段"给 AI
- **ARCHITECTURE.md 契约**:✅ `parentDashboard`
#### 2.1.2 ❌ `/shell/parent/trend`(学习趋势详情页,缺失)
- **CICD 参考实现**CICD 无独立 `/trend` 页面(融合在 dashboard 与 grades 中以趋势卡片呈现)
- **功能描述**:家长视角的学习趋势详情页,应展示:
- 多子女学习趋势对比
- 历史成绩趋势、知识点掌握趋势、对比基线
- 跨学年/学期聚合
- **技术栈建议**:复用 `parentDashboard` 契约扩展字段 + 趋势图组件Recharts/Echarts多子女对比布局参考 `ParentChildrenDataPage`
- **ARCHITECTURE.md 契约**:✅ `parentDashboard`(需扩展 trend 子契约)
- **CICD 关键代码片段**dashboard 中仅有 `ParentAttentionBanner`grades 页面中 `GradeTrendCard` + `GrowthArchiveChart` 是趋势相关参考
#### 2.1.3 ❌ `/shell/parent/weakness`(薄弱知识点详情页,缺失)
- **CICD 参考实现**CICD 无独立 `/weakness` 页面(融合在 dashboard / error-book 中以 `weakKps` / `child_weak_points` 呈现)
- **功能描述**:家长视角的薄弱知识点详情页,应展示:
- 多子女薄弱知识点汇总
- 按学科分组、关联错题、推荐练习
- 掌握率进度条
- **技术栈建议**:复用 `error-book` 模块的 `getKnowledgePointWeakness` 模式 + `Progress` 组件
- **ARCHITECTURE.md 契约**:✅ `parentDashboard`(需扩展 weakness 子契约)
- **CICD 关键代码片段**`error-book/page.tsx``weakKps.map` 渲染 `Progress` 进度条 + `kp.knowledgePointName` + `kp.errorCount` + `kp.masteryRate` 是直接参考
---
### 2.2 children 模块1 页规划0 已完成1 缺失)⚠️ 重点
#### 2.2.1 ❌ `/shell/parent/children/[studentId]`(子女详情页,缺失)⚠️ 重要
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\children\[studentId]\page.tsx`
- **功能描述**
- **单个子女的完整详情视图**(家长域最核心页面)
- **双重权限校验**
1. `verifyParentChildRelationAction(studentId)` 校验家长与子女存在关系防跨家庭信息泄露G4-002 审计修复)
2. dataScope 二次校验:`ctx.dataScope.type === "all"``childrenIds.includes(studentId)`
- 校验失败显示 `EmptyState` + `ShieldAlert` 图标("访问被拒绝"
- **头部**`ChildDetailHeader`(子女基本信息)
- **主体面板**`ChildDetailPanel`(多 Tab 切换视图,`initialTab` 来自 searchParams
- **兄弟姐妹切换器**`SiblingSwitcher`(在多子女家庭中快速切换查看不同子女)
- 并行拉取:`getChildDashboardDataAction(studentId)` + `getChildNameListAction()`
- `notFound()` 兜底(子女不存在)
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`verifyParentChildRelationAction` / `getChildDashboardDataAction` / `getChildNameListAction`(均来自 `@/modules/parent/actions`
- `requireAuth()` + `getAuthContext()` 双重身份校验
- 组件:`ChildDetailHeader` / `ChildDetailPanel` / `SiblingSwitcher` / `EmptyState`
- 路由参数:`studentId`
- searchParams`tab`(初始 Tab
- 工具:`getSearchParam`
- **ARCHITECTURE.md 契约**:❌ `myChildren`(需新建,是家长域核心契约)
- **CICD 关键代码片段**
```tsx
const relation = await verifyParentChildRelationAction(studentId)
const isInScope = ctx.dataScope.type === "all" ||
(ctx.dataScope.type === "children" && ctx.dataScope.childrenIds.includes(studentId))
if (!relation || !isInScope) { return <EmptyState icon={ShieldAlert} ... /> }
```
> ⚠️ **此页是家长域最核心页面**是其他模块grades/attendance/homework 等)子女切换的"枢纽"。`myChildren` 契约必须在 B4 首位补齐。
---
### 2.3 grades 模块2 页规划0 已完成2 缺失)
#### 2.3.1 ❌ `/shell/parent/grades`(子女成绩列表,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\grades\page.tsx`
- **功能描述**
- **多子女成绩对比视图**(家长域特色)
- 每个子女一块:姓名标题 + **导出按钮**`ParentExportButton`,按 studentId 导出)
- **成绩趋势卡片**`GradeTrendCard`含班级平均对比线v3-P2-8 补齐)
- **纵向成长档案图**`GrowthArchiveChart`P3-4 新增,跨学年/学期聚合)
- 学生成绩汇总(`StudentGradeSummary`
- 使用 `Promise.allSettled` 容错:单个子女查询失败不影响其他子女展示
- 用循环 + 类型守卫替代 `as` 断言P1-8 修复)
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getStudentGradeSummary(id, ctx.dataScope)` / `getClassAverageTrend(id, undefined, undefined, ctx.dataScope)` / `getStudentGrowthArchive(id, ctx.dataScope)`
- `requirePermission(Permissions.GRADE_RECORD_READ)`
- dataScope 校验:`ctx.dataScope.type === "children"` 且 `childrenIds.length > 0`,否则显示 `ParentNoChildrenPage`
- 组件:`ParentChildrenDataPage` / `ParentNoChildrenPage` / `ParentExportButton` / `GradeTrendCard` / `GrowthArchiveChart` / `StudentGradeSummary`
- 类型:`ClassAverageTrendResult` / `StudentGrowthArchiveResult`
- **ARCHITECTURE.md 契约**:❌(列表,未定义)
#### 2.3.2 ❌ `/shell/parent/grades/report-card`(子女成绩报告卡,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\grades\report-card\page.tsx`
- **功能描述**
- 学年 / 学期可切换的成绩报告卡(家长视角)
- **必填查询参数**`studentId`(必须在家长子女范围内)
- 可选参数:`academicYearId` / `semester`"1" | "2"
- 缺少 `studentId` 时显示提示空态 + 返回按钮
- 报告卡视图(`ReportCardView`,子女维度聚合)
- **打印操作**`ReportCardPrintAction`
- 返回成绩列表的面包屑(`ArrowLeft` + Link
- 学年数量提示
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getReportCardData(studentId, ctx.dataScope, { academicYearId, semester })` + `getAcademicYears()`
- `requirePermission(Permissions.GRADE_RECORD_READ)`
- 组件:`ReportCardView` / `ReportCardPrintAction` / `Button` / `EmptyState`
- 工具:`getParam` / `SearchParams` 类型
- searchParams`studentId` / `academicYearId` / `semester`
- dataScope 在 data-access 层校验子女归属(防跨家庭泄露)
- **ARCHITECTURE.md 契约**:❌(未单独定义)
---
### 2.4 exams 模块2 页规划0 已完成2 缺失)⚠️ CICD 无源
> **CICD 参考项目无 exams 模块家长页面**。家长考试相关功能需 portal-shell 从零设计。
#### 2.4.1 ❌ `/shell/parent/exams`(子女考试列表,缺失)
- **CICD 参考实现**:❌ CICD 无对应源页面
- **功能描述**:家长视角的子女考试列表,应展示:
- 多子女考试汇总(每个子女一块)
- 即将到来的考试(含倒计时、考场、座位号)
- 已结束考试(含成绩、查看结果入口)
- 按学科 / 状态过滤
- **技术栈建议**:参考 CICD `parent/grades/page.tsx` 的 `ParentChildrenDataPage` 多子女布局模式 + `parent/practice/page.tsx` 的单/多子女分支渲染
- **ARCHITECTURE.md 契约**:🟡(部分,需补充)
#### 2.4.2 ❌ `/shell/parent/exams/[id]/result`(子女考试结果页,缺失)
- **CICD 参考实现**:❌ CICD 无对应源页面(可参考 `parent/grades/report-card/page.tsx` 的 searchParams + 权限校验模式)
- **功能描述**
- 子女考试得分、排名、班级均分对比
- 题目作答详情(每题对错、参考答案、子女答案)
- 知识点掌握情况
- 错题一键加入错题本入口
- **技术栈建议**:参考 CICD `parent/grades/report-card/page.tsx` 的 `verifyParentChildRelationAction` + dataScope 双重校验模式
- **ARCHITECTURE.md 契约**:🟡(部分,需补充)
---
### 2.5 homework 模块1 页规划0 已完成1 缺失)⚠️ CICD 无源
#### 2.5.1 ❌ `/shell/parent/homework`(子女作业查看,缺失)⚠️ CICD 无源
- **CICD 参考实现**:❌ CICD 无对应源页面
- **功能描述**:家长视角查看子女作业,应展示:
- 多子女作业汇总(每个子女一块)
- 作业列表(标题、状态徽章、截止时间、剩余尝试次数、最新得分、逾期提示)
- 按学科分组 + 状态过滤all/pending/submitted/graded
- **只读视图**(家长不能提交作业,仅查看)
- **技术栈建议**:参考 CICD `parent/practice/page.tsx` 的 `ParentChildrenDataPage` + 单/多子女分支 + `StatsGrid` 统计模式;状态徽章参考学生域 `StatusBadge` + `variantMap`
- **ARCHITECTURE.md 契约**:❌
---
### 2.6 attendance 模块1 页规划0 已完成1 缺失)
#### 2.6.1 ❌ `/shell/parent/attendance`(子女考勤,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\attendance\page.tsx`
- **功能描述**
- **多子女考勤对比视图**(家长域特色)
- 顶部 `headerExtra`:出勤率卡片(`ParentAttendanceRateCard`+ 考勤预警(`ParentAttendanceWarning`
- 每个子女一块:姓名标题 + **考勤日历**`ParentAttendanceCalendar`+ **考勤明细**`ParentStudentAttendanceDetail`
- 使用 `Promise.allSettled` 容错
- **类型映射解耦**:将 attendance 模块的 `StudentAttendanceSummary` 映射为 parent 模块的 `ParentStudentAttendanceSummary`P1-2 解耦parent 模块仅消费自身类型)
- 通过接口抽象消费 attendance 数据P1-2 修复:不再直接 import data-access
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`createAttendanceReadService(ctx.dataScope).getStudentSummary(id)`(接口抽象)
- `getAuthContext()`(注意:未用 `requirePermission`,直接取 ctx
- dataScope 校验:`ctx.dataScope.type === "children"` 且 `childrenIds.length > 0`,否则显示 `ParentNoChildrenPage`
- 组件:`ParentChildrenDataPage` / `ParentNoChildrenPage` / `ParentAttendanceWarning` / `ParentAttendanceRateCard` / `ParentAttendanceCalendar` / `ParentStudentAttendanceDetail`
- 类型:`ParentStudentAttendanceSummary` / `AttendanceReadService`
- 映射函数:`toParentSummary`(手动字段映射)
- **ARCHITECTURE.md 契约**:❌
---
### 2.7 classes 模块1 页规划0 已完成1 缺失)⚠️ CICD 无源
#### 2.7.1 ❌ `/shell/parent/classes`(子女班级信息,缺失)⚠️ CICD 无源
- **CICD 参考实现**:❌ CICD 无对应源页面CICD 仅在 `course-plans` 中通过 `getStudentActiveClassId` 间接消费班级数据)
- **功能描述**:家长视角的子女班级信息,应展示:
- 多子女班级列表(每个子女一块)
- 班级基本信息(班名、班主任、任课教师、教室)
- 班级近期动态(作业、考试、公告)
- **技术栈建议**:参考 CICD `parent/course-plans/page.tsx` 的 `getStudentActiveClassId(sid)` 多子女并行查询模式 + `ParentChildrenDataPage` 布局
- **ARCHITECTURE.md 契约**:❌
---
### 2.8 course-plans 模块2 页规划0 已完成2 缺失)
#### 2.8.1 ❌ `/shell/parent/course-plans`(课程计划列表,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\course-plans\page.tsx`
- **功能描述**
- 家长视角:解析**所有孩子的班级 ID**,用于过滤课程计划
- 并行查询每个子女的活跃班级 ID`getStudentActiveClassId`
- 仅查询 `status: "active"` 的课程计划
- 使用 `CoursePlanList` 组件渲染(`detailBaseHref="/parent/course-plans"`
- 权限上下文:`{ userId, isAdmin: false, classIds }`(家长非管理员,仅限指定班级)
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getCoursePlans({ status: "active" }, { userId, isAdmin: false, classIds })` + `getStudentActiveClassId(sid)`(并行 `Promise.all`
- `requirePermission(Permissions.COURSE_PLAN_READ)`
- dataScope 类型守卫:`ctx.dataScope.type === "children"` 且 `childrenIds.length > 0`
- 组件:`CoursePlanList`
- 类型守卫:`filter((id): id is string => id !== null)`
- **ARCHITECTURE.md 契约**:❌
#### 2.8.2 ❌ `/shell/parent/course-plans/[id]`(课程计划详情,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\course-plans\[id]\page.tsx`
- **功能描述**
- 家长视角:仅允许查看**孩子所在班级**的课程计划
- 解析所有孩子的班级 ID传入权限上下文
- 若计划不在子女班级范围内,`notFound()` 兜底
- 使用 `CoursePlanDetail` 组件渲染(`backHref` / `successHref` 均指向 `/parent/course-plans`
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getCoursePlanById(id, { userId, isAdmin: false, classIds })` + `getStudentActiveClassId(sid)`(并行)
- `requirePermission(Permissions.COURSE_PLAN_READ)`
- 组件:`CoursePlanDetail`
- 路由参数:`id`
- `notFound()` 兜底
- **ARCHITECTURE.md 契约**:❌
---
### 2.9 lesson-plans 模块2 页规划0 已完成2 缺失)
#### 2.9.1 ❌ `/shell/parent/lesson-plans`(教案列表,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\lesson-plans\page.tsx`
- **功能描述**
- 家长视角:仅查看**已发布**教案(`status: "published"`
- 学科选项并行加载(`getSubjectOptions`
- **角色配置注入**`LessonPlanProviderSetup` 包裹,传入 `PARENT_ROLE_CONFIG`使筛选功能生效P0-13 修复)
- `LessonPlanList` 以 `viewMode="parent"` 渲染(只读模式)
- `Suspense` 流式渲染 + Skeleton 占位6 个 `h-[180px]` 卡片骨架)
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getLessonPlans({ status: "published" }, ctx.dataScope, ctx.userId)` + `getSubjectOptions()`
- `requirePermission(Permissions.LESSON_PLAN_READ)`V4 P0-2 修复:页面层补齐权限校验)
- 组件:`LessonPlanList` / `LessonPlanProviderSetup` / `Skeleton`
- Provider 配置:`PARENT_ROLE_CONFIG`(来自 `@/modules/lesson-preparation/providers/lesson-plan-provider`
- `viewMode="parent"` 标识家长只读视图
- **ARCHITECTURE.md 契约**:❌
#### 2.9.2 ❌ `/shell/parent/lesson-plans/[planId]/view`(教案只读详情,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\lesson-plans\[planId]\view\page.tsx`
- **功能描述**
- 家长视角:仅可查看**孩子所在年级**的已发布课案V4 P0-1 修复,防跨年级信息泄露)
- **scope 校验**`assertPlanInScope(plan, ctx)`,失败 `notFound()`
- 未发布计划显示提示卡片(`readonly.notPublished`
- 教材标题 + 章节标题并行查询V4 P2-1 修复,`Promise.all` 并行)
- `LessonPlanReadonlyView` 渲染计划内容
- 全屏布局(`h-[calc(100vh-4rem)]`
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getLessonPlanById(planId, ctx.userId)` + `getTextbookById(plan.textbookId)` + `getChaptersByTextbookId(plan.textbookId)` + `findChapterById(chapters, plan.chapterId)`
- `requirePermission(Permissions.LESSON_PLAN_READ)`
- scope 校验:`assertPlanInScope(plan, ctx)`lib/scope-check
- 组件:`LessonPlanReadonlyView` / `Skeleton`
- 路由参数:`planId`
- `notFound()` 兜底(计划不存在或越权)
- **ARCHITECTURE.md 契约**:❌
---
### 2.10 error-book 模块1 页规划0 已完成1 缺失)
#### 2.10.1 ❌ `/shell/parent/error-book`(子女错题本,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\error-book\page.tsx`
- **功能描述**
- **单/多子女分支渲染**(家长域特色):
- **单子女**:直接展示 `StatsGrid` 5 列统计卡片(总数 / 新增 / 学习中 / 已掌握 / 待复习)
- **多子女**:每个子女一张 `Card`,含姓名 + 掌握率徽章 + 4 项统计 + `Progress` 进度条
- 汇总所有子女的错题:**Top 错题**`TopWrongQuestions`,前 5+ **薄弱知识点**`getKnowledgePointWeakness`,前 5
- 薄弱知识点:每条含知识点名称 + 错误次数 + 掌握率 + `Progress` 进度条
- 待复习数 > 0 时高亮(`highlight: stats.dueReviewCount > 0`
- `WidgetBoundary` 降级容错
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getErrorBookStats(id)` + `getStudentNameMap(childrenIds)` + `getTopWrongQuestionsByStudentIds(childrenIds, 5)` + `getKnowledgePointWeakness(childrenIds, 5)`
- `requirePermission(Permissions.ERROR_BOOK_READ)`
- 组件:`StatsGrid` / `TopWrongQuestions` / `WidgetBoundary` / `Card` / `Badge` / `Progress` / `EmptyState`
- 工具:`formatNumber`
- icons`BookX` / `Clock` / `GraduationCap` / `Repeat` / `Sparkles` / `Users`
- **ARCHITECTURE.md 契约**:✅
---
### 2.11 diagnostic 模块1 页规划0 已完成1 缺失)
#### 2.11.1 ❌ `/shell/parent/diagnostic`(子女学情诊断,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\diagnostic\page.tsx`
- **功能描述**
- **多子女诊断对比视图**v4-P1-9 容错增强)
- 预先查询所有子女姓名(`getUserNamesByIds`),用于错误卡片展示
- **allSettled 容错但保留 rejected 项**rejected 项不再静默丢弃,渲染错误卡片(`AlertCircle` + 学生姓名 + "数据加载失败"提示)
- 每个子女:诊断摘要(`getStudentMasterySummary`+ **已发布诊断报告**`getDiagnosticReports`v4-P1-3 修复:家长仅可见 `status: "published"` 报告,避免草稿泄露)
- `StudentDiagnosticView` 渲染(`role="parent"`
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getStudentMasterySummary(id)` + `getDiagnosticReports({ studentId: id, status: "published" }, ctx.dataScope)` + `getUserNamesByIds(childrenIds)`
- `requirePermission(Permissions.DIAGNOSTIC_READ)`
- 组件:`ParentChildrenDataPage` / `ParentNoChildrenPage` / `StudentDiagnosticView` / `Card` / `CardContent`
- 类型:`ChildDiagnosticSuccessItem` / `ChildDiagnosticErrorItem`(联合类型 `ChildDiagnosticItem`
- icons`Stethoscope` / `AlertCircle`
- **ARCHITECTURE.md 契约**:✅
---
### 2.12 learning-path 模块1 页规划0 已完成1 缺失)⚠️ CICD 无源
#### 2.12.1 ❌ `/shell/parent/learning-path`(子女学习路径,缺失)⚠️ CICD 无源
- **CICD 参考实现**:❌ CICD 无对应源页面(学生域有 `learning/study-path`,但家长域无对应页)
- **功能描述**:家长视角查看子女的 AI 学习路径,应展示:
- 多子女学习路径汇总(每个子女一块)
- AI 生成的个性化学习路径(参考学生域 `AiStudyPath` 组件)
- 路径进度、节点完成情况
- **技术栈建议**:参考 CICD 学生域 `learning/study-path/page.tsx` 的 `AiStudyPath` + `AiClientProvider` 模式 + `requirePermission(Permissions.AI_CHAT)`;家长域需扩展为多子女布局
- **ARCHITECTURE.md 契约**:❌
---
### 2.13 practice 模块1 页规划0 已完成1 缺失)
#### 2.13.1 ❌ `/shell/parent/practice`(子女练习查看,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\practice\page.tsx`
- **功能描述**
- **单/多子女分支渲染**(家长域特色):
- **单子女**:直接展示 4 列 `StatsGrid`(总练习次数 / 已完成 / 总答题数 / 正确率)+ `PracticeHistory` 历史列表
- **多子女**:每个子女一块 `WidgetBoundary`,含姓名标题 + 4 列统计 + 历史列表
- **家长无会话详情页**,仅展示只读卡片(注释明确:`家长无会话详情页,仅展示只读卡片`
- `PracticeServiceProvider` 包裹(注入练习服务)
- `Promise.allSettled` 容错 + 循环 + 类型守卫(非 `as` 断言)
- 姓名映射并行启动(`nameMapPromise` 与 `childResults` 并行,但类型分离以利类型收窄)
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getPracticeStats(id)` + `getPracticeSessions(id, { pageSize: 20 })` + `getUserNamesByIds(childrenIds)`
- `requirePermission(Permissions.ADAPTIVE_PRACTICE_READ)`
- 组件:`PracticeServiceProvider` / `StatsGrid` / `PracticeHistory` / `WidgetBoundary` / `EmptyState`
- 类型:`PracticeSessionSummary` / `PracticeStats` / `ChildPracticeItem`
- icons`Target` / `Users` / `CheckCircle2` / `TrendingUp` / `Award`
- `valueClassName: "tabular-nums"` 数字对齐
- **ARCHITECTURE.md 契约**:❌
---
### 2.14 elective 模块1 页规划0 已完成1 缺失)
#### 2.14.1 ❌ `/shell/parent/elective`(子女选课查看,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\elective\page.tsx`
- **功能描述**
- **多子女选课记录查看**(只读,家长不能选课)
- 每个子女一块:`ParentSelectionView`(子女姓名 + 选课记录列表)
- **双重校验**`getChildrenAction()` 获取关系 + `getChildBasicInfoAction(r.studentId, r.relation)` 二次校验防跨家庭信息泄露G4-002 审计修复)
- `Promise.allSettled` 容错
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getStudentSelections(r.studentId)` + `getChildrenAction()` + `getChildBasicInfoAction(r.studentId, r.relation)`
- `requirePermission(Permissions.ELECTIVE_READ)`
- 组件:`ParentChildrenDataPage` / `ParentNoChildrenPage` / `ParentSelectionView`
- 类型:`ChildSelectionData`
- **ARCHITECTURE.md 契约**:❌
---
### 2.15 leave 模块1 页规划0 已完成1 缺失)
#### 2.15.1 ❌ `/shell/parent/leave`(家长在线请假,缺失)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\parent\leave\page.tsx`
- **功能描述**
- **家长域少有的"写"操作页面**(其他多为只读)
- 顶部:**在线请假表单**`LeaveRequestForm`,下拉选择子女,自动写入 classId
- 底部:该家长**所有子女**的请假申请列表(`LeaveRequestList`,按 dataScope=children 过滤)
- 子女选项构造:遍历关系列表,查询每个子女的 `basicInfo`,仅包含有活跃班级的子女(`basic.classId && basic.className`
- 返回仪表盘的面包屑(`ArrowLeft` + Link to `/parent/dashboard`
- 无关联子女时显示提示卡片
- **技术栈**
- Server Component + `force-dynamic`
- Server Actions`getChildrenAction()` + `getLeaveRequests({ scope, currentUserId, page: 1, pageSize: 50 })` + `getChildBasicInfoAction(r.studentId, r.relation)`
- `getAuthContext()`(注意:未用 `requirePermission`,直接取 ctx
- 组件:`LeaveRequestForm` / `LeaveRequestList` / `Card` / `Button`
- 类型:`ChildOption`(含 `id` / `name` / `classId` / `className`
- icons`ArrowLeft` / `CalendarDays`
- scope 处理:家长 scope 为 `children``getLeaveRequests` 按 scope 过滤所有子女记录
- **ARCHITECTURE.md 契约**:❌
---
### 2.16 notifications + settings + preferences 模块(共享 2 页 + 家长专属 1 页0 已完成1 缺失 + 2 共享)
#### 2.16.1 ❌ `/shell/parent/preferences`(家长偏好设置,缺失)
- **CICD 参考实现**:❌ CICD 无对应源页面
- **功能描述**:家长专属偏好设置,可能包括:
- 通知偏好(哪些子女事件需推送:成绩、考勤、作业、预警)
- AI 摘要偏好(摘要频率、详细程度)
- 隐私偏好(是否共享数据给 AI
- **技术栈建议**:参考共享 settings 页面模式 + 家长域专属字段
- **ARCHITECTURE.md 契约**:❌
- **批次**B4
#### 2.16.2 ❌ `/shell/notifications`(通知中心,缺失,共享)
- **CICD 参考实现**:❌ CICD `parent/` 下无对应源页面
- **功能描述**:通知中心(家长可见范围)
- **ARCHITECTURE.md 契约**:✅(共享,已就绪)
- **批次**B1/B3共享路由
#### 2.16.3 ❌ `/shell/settings`(系统设置,缺失,共享)
- **CICD 参考实现**:❌ CICD `parent/` 下无对应源页面
- **功能描述**:系统设置(通用)
- **ARCHITECTURE.md 契约**:✅(共享,已就绪)
- **批次**B1/B3共享路由
> **注**portal-shell 当前 `/shell/notifications` / `/shell/settings` 路由是否存在需在共享层确认。家长域仅需补充 `/shell/parent/preferences`。
---
## 三、按模块汇总
| 模块 | 规划页数 | 已完成 | 缺失 | 备注 |
| --------------------- | -------- | ------ | ------ | --------------------------------------- |
| dashboard | 3 | 1 | 2 | 仪表盘基础页有trend/weakness 详情页缺 |
| children | 1 | 0 | 1 | ⚠️ 家长域核心页,需 `myChildren` 契约 |
| grades | 2 | 0 | 2 | 多子女对比 + 报告卡 |
| exams | 2 | 0 | 2 | ⚠️ CICD 无源页面,全新设计 |
| homework | 1 | 0 | 1 | ⚠️ CICD 无源页面,全新设计 |
| attendance | 1 | 0 | 1 | 多子女考勤对比 |
| classes | 1 | 0 | 1 | ⚠️ CICD 无源页面,全新设计 |
| course-plans | 2 | 0 | 2 | 列表 + 详情,按子女班级过滤 |
| lesson-plans | 2 | 0 | 2 | 列表 + 只读详情scope 校验 |
| error-book | 1 | 0 | 1 | 单/多子女分支,契约 ✅ |
| diagnostic | 1 | 0 | 1 | 多子女诊断,契约 ✅ |
| learning-path | 1 | 0 | 1 | ⚠️ CICD 无源页面,全新设计 |
| practice | 1 | 0 | 1 | 单/多子女分支,只读 |
| elective | 1 | 0 | 1 | 多子女选课查看 |
| leave | 1 | 0 | 1 | 家长域少有的"写"操作 |
| preferences | 1 | 0 | 1 | 家长专属偏好 |
| notifications共享 | 1 | 0 | 1 | 共享路由,契约 ✅ |
| settings共享 | 1 | 0 | 1 | 共享路由,契约 ✅ |
| **合计** | **23** | **1** | **22** | 不含 dashboard 的 2 个详情页已计入缺失 |
> ARCHITECTURE.md §9.3 规划 24 页(含 notifications/settings 共享路由 2 页。portal-shell 当前 1 页已完成22 页缺失1 页为 dashboard 详情页(部分完成)。
---
## 四、关键技术差异 & 迁移注意事项
### 4.1 架构模式差异(最重要)
| 维度 | CICD参考 | portal-shell目标 |
| ------------- | ---------------------------------------------------------- | ------------------------------------------------------------------- |
| 渲染模式 | Server Component 为主 | 当前仪表盘是 Client Component需确定后续页面模式 |
| 数据获取 | Server Action + Drizzle 直查 DB | **必须改为** BFF / 微服务 API`teacher-bff` / `data-ana` 等) |
| 权限校验 | `requirePermission` + `getAuthContext` + dataScope | 需通过 Gateway + BFF 鉴权,前端用 `usePermission().hasPermission()` |
| 国际化 | `next-intl` `getTranslations` | portal-shell 当前仪表盘硬编码中文,需统一策略 |
| 共享 UI | `@/shared/components/ui/*` | `@/shared/components/ui/*`(已迁移部分) |
| 模块组件 | `@/modules/<domain>/components/*` | 需在 portal-shell 重建或下沉到 BFF |
| 多子女布局 | `ParentChildrenDataPage` + `ParentNoChildrenPage` 通用容器 | 需在 portal-shell 重建(家长域核心模式) |
| 单/多子女分支 | error-book / practice 中 `isSingleChild` 分支 | 需保留此模式(家长域特色) |
### 4.2 路由路径对齐
| CICD 路径 | ARCHITECTURE.md §9.3 目标路径 | 备注 |
| ----------------------------------- | ------------------------------------------ | ----------------------------------------------- |
| `parent/dashboard` | `/shell/parent`(家长仪表盘) | 提升到 `/shell/parent/page.tsx` |
| `parent/dashboard/trend` | `/shell/parent/trend` | CICD 无独立页,需新建 |
| `parent/dashboard/weakness` | `/shell/parent/weakness` | CICD 无独立页,需新建 |
| `parent/children/[studentId]` | `/shell/parent/children/[studentId]` | 路径一致 |
| `parent/grades` | `/shell/parent/grades` | 路径一致 |
| `parent/grades/report-card` | `/shell/parent/grades/report-card` | 路径一致 |
| `(无)` | `/shell/parent/exams` | 全新设计 |
| `(无)` | `/shell/parent/exams/[id]/result` | 全新设计 |
| `(无)` | `/shell/parent/homework` | 全新设计 |
| `parent/attendance` | `/shell/parent/attendance` | 路径一致 |
| `(无)` | `/shell/parent/classes` | 全新设计 |
| `parent/course-plans` | `/shell/parent/course-plans` | 路径一致 |
| `parent/course-plans/[id]` | `/shell/parent/course-plans/[id]` | 路径一致 |
| `parent/lesson-plans` | `/shell/parent/lesson-plans` | 路径一致 |
| `parent/lesson-plans/[planId]/view` | `/shell/parent/lesson-plans/[planId]/view` | 路径一致 |
| `parent/error-book` | `/shell/parent/error-book` | 路径一致 |
| `parent/diagnostic` | `/shell/parent/diagnostic` | 路径一致 |
| `(无)` | `/shell/parent/learning-path` | 全新设计(学生域有 `learning/study-path` 参考) |
| `parent/practice` | `/shell/parent/practice` | 路径一致 |
| `parent/elective` | `/shell/parent/elective` | 路径一致 |
| `parent/leave` | `/shell/parent/leave` | 路径一致 |
| `(无)` | `/shell/parent/preferences` | 全新设计 |
| 共享 | `/shell/notifications` | 共享路由 |
| 共享 | `/shell/settings` | 共享路由 |
> **注**:家长域路由迁移**压力较小**14 个 CICD 页面中有 13 个路径完全一致(仅 dashboard 从子路径提升到 `/shell/parent/page.tsx`)。需新建的 6 个页面exams×2、homework、classes、learning-path、preferences在 CICD 中无源。
### 4.3 权限点映射
CICD 中家长页面用到的权限点(迁移时需在 portal-shell `Permissions` 常量中对应):
- `GRADE_RECORD_READ`grades / report-card
- `ATTENDANCE_READ`attendanceCICD 实际用 `getAuthContext` 而非 `requirePermission`,需统一)
- `COURSE_PLAN_READ`course-plans 列表 + 详情)
- `LESSON_PLAN_READ`lesson-plans 列表 + 详情)
- `ERROR_BOOK_READ`error-book
- `DIAGNOSTIC_READ`diagnostic
- `ADAPTIVE_PRACTICE_READ`practice
- `ELECTIVE_READ`elective
- leave 用 `getAuthContext` 而非 `requirePermission`(需统一)
- children 详情用 `requireAuth` + `verifyParentChildRelationAction` + dataScope 二次校验(**双重校验模式**
- dashboard 用 `getParentDashboardAction`(内部封装权限)
### 4.4 共享组件清单(需在 portal-shell 补齐或确认已有)
**家长域通用容器(核心,必须重建)**
- `ParentChildrenDataPage`(多子女数据页通用容器,含 `renderItem` + `headerExtra` + 空态)
- `ParentNoChildrenPage`(无关联子女空态)
**dashboard 模块**
- `ParentDashboard` / `ChildCard` / `ParentAttentionBanner` / `AiChildSummary` / `ParentNoChildrenPage` / `ParentChildrenDataPage`
**children 模块**
- `ChildDetailHeader` / `ChildDetailPanel` / `SiblingSwitcher`
**grades 模块**
- `StudentGradeSummary` / `GradeTrendCard` / `GrowthArchiveChart` / `ReportCardView` / `ReportCardPrintAction` / `ParentExportButton`
**attendance 模块**
- `ParentAttendanceWarning` / `ParentAttendanceRateCard` / `ParentAttendanceCalendar` / `ParentStudentAttendanceDetail`
**course-plans 模块**
- `CoursePlanList` / `CoursePlanDetail`
**lesson-plans 模块**
- `LessonPlanList` / `LessonPlanReadonlyView` / `LessonPlanProviderSetup` + `PARENT_ROLE_CONFIG`
**error-book 模块**
- `StatsGrid` / `TopWrongQuestions` / `WidgetBoundary` / `Progress`
**diagnostic 模块**
- `StudentDiagnosticView``role="parent"`
**practice 模块**
- `PracticeServiceProvider` / `StatsGrid` / `PracticeHistory` / `WidgetBoundary`
**elective 模块**
- `ParentSelectionView`
**leave 模块**
- `LeaveRequestForm` / `LeaveRequestList` + `ChildOption` 类型
**基础 UI共享**
- `Card` / `CardContent` / `CardHeader` / `CardTitle` / `Button` / `Badge` / `EmptyState` / `Skeleton` / `Progress`
### 4.5 B4 实施优先级建议
按用户价值 + 实现复杂度 + 契约就绪度排序:
1. **P0必做家长域核心闭环**
- `children/[studentId]` 子女详情页(⚠️ 核心,需先补 `myChildren` 契约)
- `dashboard/trend` + `dashboard/weakness` 详情页(契约 ✅ `parentDashboard` 已就绪)
2. **P1高频查看契约 ✅)**
- `error-book`(契约 ✅)
- `diagnostic`(契约 ✅)
3. **P2学习数据查看**
- `grades` 列表 + `grades/report-card`
- `attendance`
- `practice`
4. **P3学习资源**
- `course-plans` 列表 + 详情
- `lesson-plans` 列表 + `lesson-plans/[planId]/view`
- `elective`
5. **P4写操作 + 偏好)**
- `leave`(家长域少有的"写"操作)
- `preferences`
6. **P5全新设计CICD 无源)**
- `exams` 列表 + `exams/[id]/result`
- `homework`
- `classes`
- `learning-path`
7. **共享**`notifications` / `settings`B1/B3 共享路由,非 B4 专属)
---
## 五、CICD 与 ARCHITECTURE.md §9.3 对照表
| ARCH §9.3 源路由 | ARCH §9.3 目标路由 | CICD 是否有源页面 | portal-shell 是否已有 | 契约状态 | 备注 |
| ----------------------------------- | ------------------------------------------ | ---------------------- | --------------------- | -------------------- | -------------------- |
| `parent/dashboard` | `/shell`(家长仪表盘) | ✅ | ✅ | ✅ `parentDashboard` | 已完成基础版 |
| `/trend` | `/shell/parent/trend` | ❌(融合在 dashboard | ❌ | ✅ `parentDashboard` | 需新建详情页 |
| `/weakness` | `/shell/parent/weakness` | ❌(融合在 dashboard | ❌ | ✅ `parentDashboard` | 需新建详情页 |
| `parent/children/[studentId]` | `/shell/parent/children/[studentId]` | ✅ | ❌ | ❌ `myChildren` | ⚠️ 核心,双重校验 |
| `parent/grades` | `/shell/parent/grades` | ✅ | ❌ | ❌ | 多子女对比 |
| `parent/grades/report-card` | `/shell/parent/grades/report-card` | ✅ | ❌ | ❌ | 打印支持 |
| `parent/exams` | `/shell/parent/exams` | ❌ | ❌ | 🟡 | CICD 无,全新设计 |
| `parent/exams/[id]/result` | `/shell/parent/exams/[id]/result` | ❌ | ❌ | 🟡 | CICD 无,全新设计 |
| `parent/homework` | `/shell/parent/homework` | ❌ | ❌ | ❌ | CICD 无,全新设计 |
| `parent/attendance` | `/shell/parent/attendance` | ✅ | ❌ | ❌ | 多子女考勤对比 |
| `parent/classes` | `/shell/parent/classes` | ❌ | ❌ | ❌ | CICD 无,全新设计 |
| `parent/course-plans` | `/shell/parent/course-plans` | ✅ | ❌ | ❌ | 按子女班级过滤 |
| `parent/course-plans/[id]` | `/shell/parent/course-plans/[id]` | ✅ | ❌ | ❌ | scope 校验 |
| `parent/lesson-plans` | `/shell/parent/lesson-plans` | ✅ | ❌ | ❌ | 已发布 + 只读 |
| `parent/lesson-plans/[planId]/view` | `/shell/parent/lesson-plans/[planId]/view` | ✅ | ❌ | ❌ | scope 校验 + 全屏 |
| `parent/error-book` | `/shell/parent/error-book` | ✅ | ❌ | ✅ | 单/多子女分支 |
| `parent/diagnostic` | `/shell/parent/diagnostic` | ✅ | ❌ | ✅ | 多子女 + 错误容错 |
| `parent/learning-path` | `/shell/parent/learning-path` | ❌ | ❌ | ❌ | CICD 无,全新设计 |
| `parent/practice` | `/shell/parent/practice` | ✅ | ❌ | ❌ | 单/多子女分支,只读 |
| `parent/elective` | `/shell/parent/elective` | ✅ | ❌ | ❌ | 多子女选课查看 |
| `parent/leave` | `/shell/parent/leave` | ✅ | ❌ | ❌ | 家长域少有的"写"操作 |
| `parent/preferences` | `/shell/parent/preferences` | ❌ | ❌ | ❌ | CICD 无,全新设计 |
| `notifications`、`settings` | 共享路由 | — | ❌ | ✅ | B1/B3共享路由 |
| `preferences` | `/shell/parent/preferences` | ❌ | ❌ | ❌ | 家长专属 |
---
## 六、风险与建议
### 6.1 高风险点
1. **`myChildren` 契约缺失**:家长域核心契约未就绪,`children/[studentId]` 子女详情页无法启动。**必须在 B4 首位补齐**,建议参考 CICD `getChildDashboardDataAction` 的数据结构定义契约
2. **6 个页面 CICD 无源**`exams`×2、`homework`、`classes`、`learning-path`、`preferences` 需从零设计,参考学生域同构页面(如 `exams` 参考学生域 `exams`、`homework` 参考学生域 `learning/assignments`、`learning-path` 参考学生域 `learning/study-path`
3. **架构模式转变**portal-shell 已转向 BFF + 微服务,**不能照搬 CICD 的 Server Action + Drizzle 直查模式**每个页面都需重新设计数据获取链路BFF → data-ana / core-edu 等服务)
4. **多子女布局是家长域核心模式**`ParentChildrenDataPage` + `ParentNoChildrenPage` 通用容器需优先重建13 个页面复用此模式
5. **单/多子女分支渲染**error-book / practice 中的 `isSingleChild` 分支需保留(单子女家庭体验更紧凑)
6. **双重权限校验**children 详情页的 `verifyParentChildRelationAction` + dataScope 二次校验是防跨家庭信息泄露的关键,迁移时必须保留
7. **国际化缺失**当前仪表盘硬编码中文22 页全部完成后需补 i18n建议从一开始就用 `next-intl`
8. **权限校验缺失**:当前仪表盘无 `requirePermission`,需建立 portal-shell 家长域权限校验中间件/装饰器
9. **leave 是少有的"写"操作**:家长域多为只读视图,`leave` 页面涉及表单提交,需重点设计 BFF 写接口 + 事务保证
### 6.2 建议
1. **先建契约**:开工前先在 `shared-proto` 中补齐 §9.3 标 ❌ / 🟡 的契约,特别是 `myChildren`(核心)、`parentDashboard` 扩展trend/weakness 子契约、exams 系列、homework、classes、learning-path、preferences
2. **统一渲染模式**:建议家长页面统一采用 Server Component + BFF 数据获取(与 CICD 一致),避免当前仪表盘的 Client Component 模式
3. **统一权限模型**:建立 portal-shell 家长域 `RequirePermission` 装饰器/中间件,覆盖所有页面;统一 `getAuthContext` 与 `requirePermission` 的使用CICD 中 attendance / leave 用 `getAuthContext`,需统一)
4. **共享容器下沉**`ParentChildrenDataPage` / `ParentNoChildrenPage` 是家长域核心容器,建议下沉到 `@/shared/components/parent/` 或 BFF 返回结构化数据
5. **复用学生域组件**:家长域多为只读视图,大量组件(`StudentGradeSummary` / `GradeTrendCard` / `ReportCardView` / `StudentDiagnosticView` / `PracticeHistory` / `CoursePlanList` / `LessonPlanReadonlyView`)可复用学生域实现,仅需传入 `role="parent"` 标识
6. **CICD 无源页面决策**6 个 CICD 无源页面需产品确认功能范围,建议参考学生域同构页面 + 家长域多子女布局组合设计
7. **分批推进**:按本报告 §4.5 的 P0→P5 优先级分批实施,每批完成后跑 `pnpm run arch:scan` 同步 arch.db
---
**分析完成。共发现 23 个待完成页面(含 2 个 dashboard 详情页 + 1 个 preferences 家长专属页 + 2 个共享路由页 + 18 个其他模块页),其中 22 个完全缺失、1 个为 dashboard 详情页缺失。最关键的 `children/[studentId]` 子女详情页需 `myChildren` 契约先行。6 个页面exams×2、homework、classes、learning-path、preferences在 CICD 中无源,需从零设计。**