# 家长域(Parent)实现完整性核查报告
> 参考项目:`e:\Desktop\CICD\src\app\(dashboard)\parent\`
> 当前项目:`e:\Desktop\Edu\apps\portal-shell\src\app\shell\parent\`
> 规划依据:`apps/portal-shell/ARCHITECTURE.md` §9.3(24 页,B4 批次)
> 核查日期:2026-08-04
> 任务范围:仅核查与文档更新,不修改源代码
---
## 一、页面完成度总览
### 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 |
| 数据来源 | 直查 DB(Drizzle) | 走 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` 聚合。
### 1.4 portal-shell 家长域资产核查(features / lib/api / mocks,已实际读取源码确认)
#### 1.4.1 features/parent/ client 组件
**`src/features/parent/` 目录不存在**。当前 `src/features/` 下仅有:`admin` / `notifications` / `settings` / `shared` / `student` / `teacher`。
> **结论**:家长域**完全没有 features 层 client 组件**。CICD 中家长域依赖的模块组件(`ParentDashboard` / `ChildCard` / `ParentChildrenDataPage` / `ParentNoChildrenPage` / `ChildDetailHeader` / `SiblingSwitcher` / `StudentGradeSummary` / `GradeTrendCard` / `ReportCardView` / `ParentAttendanceCalendar` / `CoursePlanList` / `LessonPlanReadonlyView` / `StudentDiagnosticView` / `PracticeHistory` / `ParentSelectionView` / `LeaveRequestForm` 等)在 portal-shell 中**均未建立**,需在 B4 批次逐模块重建或下沉。
#### 1.4.2 lib/api/ 家长相关 API hooks
家长相关 hooks 分布在 2 个文件,共 **5 个 hooks**:
**`src/lib/api/dashboard.ts`(1 个 hook)**:
- `useParentDashboard()`:查询 `parentDashboard` 根字段,返回 `ParentDashboard | null`。operation:`GET_PARENT_DASHBOARD_DOC`,类型 `ParentDashboard` 字段 snake_case 对齐 data-ana 子图。
**`src/lib/api/parent.ts`(4 个 hooks + 领域模型)**:
- `useParentChildren()`:查询 `myChildren`(`GET_MY_CHILDREN_OVERVIEW_DOC`),返回 `ChildSummary[]`(含 `recentGrades` / `attendance` / `homeworkCompletion`)
- `useLeaveRequests(childId, status)`:查询 `leaveRequests`(`GET_LEAVE_REQUESTS_DOC`),按孩子 ID 与状态筛选
- `useApproveLeave()`:`APPROVE_LEAVE_DOC` mutation,失败抛 `ApiError`
- `useRejectLeave()`:`REJECT_LEAVE_DOC` mutation(需 reason),失败抛 `ApiError`
领域模型类型:`ChildSummary` / `ChildGrade` / `ChildAttendance` / `ChildHomeworkCompletion` / `LeaveRequest` / `LeaveType` / `LeaveStatus`
operations 文件:`src/lib/api/operations/parent.graphql.ts`(4 个 document)。导出:`src/lib/api/index.ts` 第 36 行 `export * from "./parent";`。
> **结论**:lib/api 层家长 hooks 已就绪 5 个(仪表盘 + 子女概览 + 请假审批链路)。§9.3 其余 18+ 页面所需 hooks(grades / report-card / exams / homework / attendance / classes / course-plans / lesson-plans / error-book / diagnostic / learning-path / practice / elective / preferences 等)**均未建立**。注:`lib/api/` 下虽有 `grades.ts` / `attendance.ts` 等同名文件,但属学生域 / 通用域 hooks,家长域多子女聚合 + 只读过滤尚未单独建模。
#### 1.4.3 src/mocks/graphql-data.ts 家长相关 mock 数据
| Mock 资产 | 位置 | 状态 | 服务对象 |
| -------------------------------- | ---------------------- | ----------------- | ----------------------------------------------------------------------------------------- |
| `mockParentDashboard` | `graphql-data.ts:84` | ✅ 存在 | `GetParentDashboard` 查询(仪表盘页) |
| `GetParentDashboard` case 分支 | `graphql-data.ts:5577` | ✅ 存在 | 仪表盘 hook 兜底 |
| `mockLeaveRequests` | `graphql-data.ts:4143` | 🟡 存在但属教师域 | `GetTeacherLeaveRequests`(教师域 B2) |
| `GetMyChildrenOverview` mock | — | ❌ **缺失** | `useParentChildren` 无兜底 |
| `GetLeaveRequests`(家长版)mock | — | ❌ **缺失** | `useLeaveRequests` 无兜底(教师版结构 `{ items, total }` 与家长版 `LeaveRequest[]` 不同) |
| `ApproveLeave` mock | — | ❌ **缺失** | `useApproveLeave` 无兜底 |
| `RejectLeave` mock | — | ❌ **缺失** | `useRejectLeave` 无兜底 |
> **结论**:家长域 mock **仅仪表盘 1 项就绪**,`useParentChildren` / `useLeaveRequests`(家长版)/ `useApproveLeave` / `useRejectLeave` 4 个 hook 在 dev 环境**无 MSW 兜底**(会触发 Apollo 错误或空态)。需在 B4 补齐 4 个 mock,否则 dev 环境无法演示。
---
## 二、缺失页面清单(按模块分组)
### 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 }
```
> ⚠️ **此页是家长域最核心页面**,是其他模块(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//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`(attendance,CICD 实际用 `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 中无源,需从零设计。**