Files
Edu/apps/portal-shell/docs/needtodo/admin-NeedTodo.md
SpecialX 062d9e9582 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
2026-07-24 23:07:20 +08:00

583 lines
48 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 管理域Admin待完成功能分析
> 参考项目:`e:\desktop\CICD\src\app\(dashboard)\admin\`41 个 page.tsx
> 当前项目:`e:\Desktop\Edu\apps\portal-shell\src\app\shell\admin\`1 个 page.tsx
> 规划依据:`apps\portal-shell\ARCHITECTURE.md` §9.4(管理域 24 页B5 批次)
> 分析日期2026-07-24
> 分析方式:逐页面对比 CICD 实现 vs portal-shell 实现,逐个读取 CICD page.tsx + ARCH §9.4 契约
---
## 〇、方法论与对比基线
1. CICD 单体Next.js App Router + Server Actions + Drizzle作为**功能基线**,反映"老版单体已实现"的管理员功能完整态。
2. portal-shell 作为**目标态**,遵循 ARCH §9.4 的契约与批次规划B524 页)。
3. CICD admin/layout.tsx 仅为 `<>{children}</>` passthrough无独立侧边栏/权限逻辑(权限由各 page.tsx 调 `requirePermission` 完成)。
4. ARCH §9.4 规划 24 页 = 1 仪表盘 + 23 管理子页portal-shell 仅完成 `/shell/admin/page.tsx`(仪表盘),其余 23 页全部缺失。
5. CICD 中存在但 ARCH §9.4 **未规划**的页面course-plans/curriculum-map/elective/questions/lesson-plans/error-book/scheduling/attendance 等 21 页CICD 历史已实现portal-shell 缺失但**不违反 ARCH §9.4**;这些页面是教师域在管理员视角的"全局只读 + 跨班聚合"版本,可作为 B5 后期/补充批次候选。
6. ARCH §9.4 中存在但 CICD **无对应**的页面4 页):`students``teachers``organization``viewports``plugins`,属 ARCH 新规划,需在 portal-shell 中独立设计。
---
## 一、页面完成度总览
| 状态 | 数量 | 说明 |
| --------------------------------- | ---- | ---------------------------------------------------------------------------------------------- |
| ✅ 已完成且功能完整 | 1 | `/shell/admin/page.tsx`仪表盘4 StatCard + 预警 + AI 用量,已接 `adminDashboard` 真实契约) |
| ❌ 完全缺失ARCH §9.4 规划内) | 23 | 见 §二,按 ARCH 规划口径的 23 个缺失页面 |
| CICD 已实现但 ARCH §9.4 未规划 | 21 | 见 §五,作为补充批次参考 |
| 🆕 ARCH §9.4 规划但 CICD 无源 | 4 | `students``teachers``organization``viewports`+ `plugins` 已有契约 ✅) |
### ✅ 已完成且功能完整1 页)
| 模块 | 页面 | 备注 |
| --------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| dashboard | `/shell/admin/page.tsx` | 客户端组件,`useAdminDashboard` hook 接 data-ana `adminDashboard` 真实契约4 StatCard教师/学生/班级/全校平均分)+ 近期预警 + AI 用量;含 loading/error 兜底;引用 ARCH §7.1 / §10 P1-2 |
---
## 二、缺失页面清单(按 ARCH §9.4 规划口径23 页)
### 2.1 dashboard 模块(无缺口)
`/shell` 已落地,对应 ARCH §9.4 第 1 行 `admin/dashboard``/shell`(动作为 R契约 ✅ `adminDashboard`)。
### 2.2 users 模块2 页缺失)
#### 2.2.1 `/shell/admin/users`(用户管理列表)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\users\page.tsx`
- **功能描述**:用户列表 + 角色 assignment 入口
- URL 参数:`page``search``role`(搜索/角色筛选 + 分页)
- 并行查询:`getAdminUsers({ page, search, role })` + `getAdminUserRoles()` + `getRoles()`
- 渲染 `AdminUsersView` 客户端组件,传入 users / roleOptions / 分页信息 / assignableRoles
- **技术栈**Server Component + `requirePermission(Permissions.USER_MANAGE)` + `force-dynamic` + `getSearchParam` 工具 + Drizzle data-access
- **ARCHITECTURE.md 契约**:❌ `users` 列表B5未就绪
- **CICD 关键代码片段**
```ts
await requirePermission(Permissions.USER_MANAGE);
const [result, roleOptions, roles] = await Promise.all([
getAdminUsers({ page, search, role }),
getAdminUserRoles(),
getRoles(),
]);
```
#### 2.2.2 `/shell/admin/users/import`(用户批量导入)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\users\import\page.tsx`
- **功能描述**:用户批量导入页面,包含
- 顶部 `UserImportDialog`(导入弹窗,触发上传 + Server Action 解析)
- 操作指引卡片4 步流程)
- 注意事项卡片6 条规则)
- 模板字段说明表5 列name/email/role/phone/inviteCode标注是否必填
- **技术栈**Server Component + `requirePermission(Permissions.USER_MANAGE)` + UI 基础组件Card / Table / Button+ next-intl
- **ARCHITECTURE.md 契约**:❌(未单独列,归 `users` 工单)
- **CICD 关键代码片段**:通过 `<UserImportDialog />` 客户端组件触发导入流程,模板字段固定 5 列。
### 2.3 roles + permissions 模块2 页缺失)
#### 2.3.1 `/shell/admin/roles`(角色管理列表)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\roles\page.tsx`
- **功能描述**:角色列表 + 创建/编辑入口
- 查询 `getRoles()` 拉取所有角色
- 渲染 `RoleManagementView` 客户端组件(含创建按钮、角色卡片/列表)
- **技术栈**Server Component + `requirePermission(Permissions.ROLE_READ)` + Drizzle `rbac/data-access`
- **ARCHITECTURE.md 契约**B5
- **CICD 关键代码片段**
```ts
await requirePermission(Permissions.ROLE_READ)
const roles = await getRoles()
return <RoleManagementView roles={roles} />
```
#### 2.3.2 `/shell/admin/permissions`(权限目录)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\permissions\page.tsx`
- **功能描述**:权限目录页(系统所有权限点列表,按模块分组)
- 查询 `getPermissionRoleCounts()` 获取每个权限点关联的角色数
- 渲染 `PermissionCatalogView` 客户端组件
- **技术栈**Server Component + `requirePermission(Permissions.PERMISSION_READ)` + Drizzle `rbac/data-access-permissions`
- **ARCHITECTURE.md 契约**B5
- **CICD 关键代码片段**
```ts
await requirePermission(Permissions.PERMISSION_READ)
const roleCountsByPermission = await getPermissionRoleCounts()
return <PermissionCatalogView roleCountsByPermission={roleCountsByPermission} />
```
> **附注**CICD 另有 `admin/roles/[id]/page.tsx`(角色详情,含 `RolePermissionMatrix` 权限矩阵 + `RoleDetailEditButton`),但 ARCH §9.4 仅规划 `/shell/admin/roles` 一页,未列详情子页。可作 B5 后期补强。
### 2.4 audit-logs 模块4 页缺失)
#### 2.4.1 `/shell/admin/audit-logs`(审计日志列表 + 导出)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\audit-logs\page.tsx`
- **功能描述**:审计日志列表 + 多维筛选 + CSV 导出
- URL 参数:`page`、`module`、`action`、`status`、`userId`、`startDate`、`endDate`
- 并行查询:`getAuditLogs({...})` + `getAuditModuleOptions()`
- `AuditLogExportButton` 触发 CSV 导出(按筛选条件)
- `SectionErrorBoundary` 错误兜底
- **技术栈**Server Component + `requirePermission(Permissions.AUDIT_LOG_READ)` + Drizzle `audit/data-access` + 类型守卫 `isValidAuditLogStatus`
- **ARCHITECTURE.md 契约**B5
- **CICD 关键代码片段**
```ts
const [result, moduleOptions] = await Promise.all([
getAuditLogs({ page, module, action, status, userId, startDate, endDate }),
getAuditModuleOptions(),
]);
```
#### 2.4.2 `/shell/admin/audit-logs/overview`(审计概览)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\audit-logs\overview\page.tsx`
- **功能描述**:审计概览页(统计/趋势/分布三件套)
- 并行查询:`getAuditOverviewStats()` + `getAuditTrend(7)` + `getDataChangeActionStats()`
- `AuditServiceProvider` 包裹 `adminAuditService` 注入服务上下文
- 渲染 `AuditOverviewView` 客户端组件(统计卡 + 7 天趋势图 + 动作分布饼图)
- **技术栈**Server Component + `requirePermission(Permissions.AUDIT_LOG_READ)` + 服务注入模式
- **ARCHITECTURE.md 契约**B5
- **CICD 关键代码片段**
```ts
const [stats, trend, distribution] = await Promise.all([
getAuditOverviewStats(),
getAuditTrend(7),
getDataChangeActionStats(),
]);
```
#### 2.4.3 `/shell/admin/audit-logs/login-logs`(登录日志)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\audit-logs\login-logs\page.tsx`
- **功能描述**:登录日志列表 + 筛选 + 导出
- URL 参数:`page`、`action`signin/signout/signup、`status`success/failure、`userId`、`startDate`、`endDate`
- 查询 `getLoginLogs({...})`
- `AuditLogExportButton exportType="login"` 触发导出
- 渲染 `LoginLogView` 客户端组件
- **技术栈**Server Component + `requirePermission(Permissions.AUDIT_LOG_READ)` + 类型守卫 `isValidLoginLogAction` / `isValidLoginLogStatus`
- **ARCHITECTURE.md 契约**B5
#### 2.4.4 `/shell/admin/audit-logs/data-changes`(数据变更日志)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\audit-logs\data-changes\page.tsx`
- **功能描述**:数据变更日志列表 + 筛选 + 导出 + 统计
- URL 参数:`page`、`tableName`、`action`create/update/delete、`userId`、`startDate`、`endDate`
- 并行查询:`getDataChangeLogs({...})` + `getDataChangeTableOptions()` + `getDataChangeStats()`
- 渲染 `DataChangeLogView` 客户端组件(含表选项下拉 + 变更统计卡)
- **技术栈**Server Component + `requirePermission(Permissions.AUDIT_LOG_READ)` + 类型守卫 `isValidDataChangeAction`
- **ARCHITECTURE.md 契约**B5
### 2.5 invitation-codes 模块1 页缺失)
#### 2.5.1 `/shell/admin/invitation-codes`(邀请码管理)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\invitation-codes\page.tsx`
- **功能描述**:邀请码列表 + 生成 + 删除
- SSR 查询 `listInvitationCodes(200, true)`200 条 + 含已用)
- 服务端计算 `now = new Date().getTime()` 传给客户端(避免 Client 端 render 阶段调用 `Date.now()`,符合 react-hooks/purity 规则)
- 生成/删除通过 Server Action + `router.refresh()` 触发更新
- 渲染 `InvitationCodesView` 客户端组件
- **技术栈**Server Component + `requirePermission(Permissions.USER_MANAGE)` + Drizzle `invitation-codes/data-access`
- **ARCHITECTURE.md 契约**B5
- **CICD 关键代码片段**
```ts
const codes = await listInvitationCodes(200, true)
const now = new Date().getTime()
return <InvitationCodesView initialCodes={codes} now={now} />
```
### 2.6 school 模块6 页缺失)
#### 2.6.1 `/shell/admin/school`学校首页redirect
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\school\page.tsx`
- **功能描述**:纯重定向页 `redirect("/admin/school/schools")`,无 UI
- **技术栈**`redirect()` from `next/navigation`
- **ARCHITECTURE.md 契约**B5
#### 2.6.2 `/shell/admin/school/schools`(学校列表)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\school\schools\page.tsx`
- **功能描述**:学校列表 + CRUD
- 查询 `getSchools()`
- 渲染 `SchoolsClient` 客户端组件
- `SectionErrorBoundary` 错误兜底
- **技术栈**Server Component + `requirePermission(Permissions.SCHOOL_MANAGE)` + Drizzle `school/data-access`
- **ARCHITECTURE.md 契约**B5
#### 2.6.3 `/shell/admin/school/classes`(班级管理)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\school\classes\page.tsx`
- **功能描述**:班级管理 + 跨数据聚合
- 并行查询:`getAdminClasses()` + `getTeacherOptions()` + `getSchools()` + `getGrades()`
- 渲染 `AdminClassesClient` 客户端组件(含班级 CRUD + 教师/学校/年级下拉)
- **技术栈**Server Component + `requirePermission(Permissions.SCHOOL_MANAGE)` + Drizzle `classes/data-access` + `school/data-access`
- **ARCHITECTURE.md 契约**B5
- **CICD 关键代码片段**
```ts
const [classes, teachers, schools, grades] = await Promise.all([
getAdminClasses(),
getTeacherOptions(),
getSchools(),
getGrades(),
]);
```
> **注**ARCH §9.4 第 7 行将 `admin/classes` 单列 1 页M与 `school/classes` 实际同源,建议合并到 `/shell/admin/school/classes`。
#### 2.6.4 `/shell/admin/school/departments`(部门管理)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\school\departments\page.tsx`
- **功能描述**:部门列表 + CRUD
- 查询 `getDepartments()`
- 渲染 `DepartmentsClient` 客户端组件
- **技术栈**Server Component + `requirePermission(Permissions.SCHOOL_MANAGE)` + Drizzle
- **ARCHITECTURE.md 契约**B5
#### 2.6.5 `/shell/admin/school/academic-year`(学年管理)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\school\academic-year\page.tsx`
- **功能描述**:学年列表 + CRUD
- 查询 `getAcademicYears()`
- 渲染 `AcademicYearClient` 客户端组件
- **技术栈**Server Component + `requirePermission(Permissions.SCHOOL_MANAGE)` + Drizzle
- **ARCHITECTURE.md 契约**B5
#### 2.6.6 `/shell/admin/school/grades`(年级管理)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\school\grades\page.tsx`
- **功能描述**:年级列表 + CRUD + 统计
- 并行查询:`getGrades()` + `getSchools()` + `getStaffOptions()` + `getGradeOverviewStats()`
- 渲染 `GradesClient` 客户端组件(年级 CRUD + 学校/教职工下拉 + 统计概览)
- **技术栈**Server Component + `requirePermission(Permissions.SCHOOL_MANAGE)` + Drizzle
- **ARCHITECTURE.md 契约**B5
> **附注**CICD 另有 `school/grades/insights/page.tsx`(年级洞察,含 `SchoolWideSummaryCard` 全校汇总 + ChipNav 年级筛选 + 作业表 + 班级排名表 + `getSchoolWideGradeSummary(ctx.dataScope)`),属管理员数据分析视角,**ARCH §9.4 未单独规划**,可作 B5 后期补强。
### 2.7 announcements 模块1 页缺失ARCH 口径)
#### 2.7.1 `/shell/admin/announcements`(公告管理列表)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\announcements\page.tsx`
- **功能描述**:公告列表 + 状态筛选
- URL 参数:`status`draft/published/archived
- 查询 `getAdminAnnouncementsPageData(status)`(一次性返回 announcements + grades + classes
- 渲染 `AdminAnnouncementsView` 客户端组件
- **技术栈**Server Component + `requirePermission(Permissions.ANNOUNCEMENT_MANAGE)` + Drizzle `announcements/data-access` + 类型守卫 `isValidStatus`
- **ARCHITECTURE.md 契约**B5
> **附注**CICD 另有 `announcements/[id]/page.tsx`(公告详情,含发布/归档/删除/置顶操作)+ `announcements/[id]/edit/page.tsx`(编辑表单 `AnnouncementForm mode="edit"` + grades 关联),**ARCH §9.4 仅规划 1 页**,建议合并到详情子页或工作流组件。
### 2.8 files 模块1 页缺失)
#### 2.8.1 `/shell/admin/files`(文件管理)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\files\page.tsx`
- **功能描述**:文件列表 + 统计
- 并行查询:`getFileAttachmentsWithFilters({ limit: 200 })` + `getFileStats()`
- 渲染 `AdminFilesView` 客户端组件(含统计卡 + 文件列表)
- **技术栈**Server Component + `requirePermission(Permissions.FILE_READ)` + Drizzle `files/data-access`
- **ARCHITECTURE.md 契约**B5
- **CICD 关键代码片段**
```ts
const [files, stats] = await Promise.all([
getFileAttachmentsWithFilters({ limit: 200 }),
getFileStats(),
]);
```
### 2.9 ai-settings 模块1 页缺失)
#### 2.9.1 `/shell/admin/ai-settings`AI 配置)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\ai-settings\page.tsx`
- **功能描述**AI Provider 配置 + Usage 仪表盘(取代旧 `/settings?tab=ai` 与考试页内嵌 AI 弹窗)
- 权限:`AI_CHAT`(普通用户可访问自己的 private provider管理员额外有 `AI_CONFIGURE`(管理 public provider 与他人 private provider
- 渲染 `AiProviderSettingsCard` 客户端组件(含 isAdmin 开关)
- 管理员额外渲染 `AiUsageDashboard`(用量统计)
- **技术栈**Server Component + `requirePermission(Permissions.AI_CHAT)` + 通过 `ctx.permissions.includes(Permissions.AI_CONFIGURE)` 区分管理员
- **ARCHITECTURE.md 契约**B5
### 2.10 system 模块1 页缺失)
#### 2.10.1 `/shell/admin/system`(系统设置)
- **CICD 参考实现**`e:\desktop\CICD\src\app\(dashboard)\admin\settings\page.tsx`
- **功能描述**:系统设置页
- 渲染 `AdminSettingsView` 客户端组件(具体配置项由组件内部决定)
- **技术栈**Server Component + `requirePermission(Permissions.SETTINGS_ADMIN)` + Drizzle
- **ARCHITECTURE.md 契约**B5对应 ARCH §9.4 第 13 行 `admin/system` → `/shell/admin/system`
### 2.11 viewports 模块1 页缺失ARCH 新建)
#### 2.11.1 `/shell/admin/viewports`(视口配置)
- **CICD 参考实现****无**CICD 未实现)
- **功能描述**:对齐 004 §5.4 视口配置BFF/Service 层 viewport 路由策略可视化)
- **技术栈**:未知,需依据 004 §5.4 设计
- **ARCHITECTURE.md 契约**B5
### 2.12 plugins 模块1 页,契约已就绪 ✅)
#### 2.12.1 `/shell/admin/plugins`(插件管理)
- **CICD 参考实现****无**CICD 未实现)
- **功能描述**:现有 portal-shell `plugin-manager` 升级整页
- **技术栈**:依据 portal-shell 已有 plugin-manager 演化
- **ARCHITECTURE.md 契约**:✅ `config-service`(已就绪,可优先实现)
### 2.13 ARCH §9.4 规划但 CICD 无源的"新建"页面3 页)
#### 2.13.1 `/shell/admin/students`(学生管理)
- **CICD 参考实现****无**
- **ARCHITECTURE.md 契约**B5
- **建议**:参照 CICD 中 `admin/school/classes` 等管理页设计,作学生维度聚合视图。
#### 2.13.2 `/shell/admin/teachers`(教师管理)
- **CICD 参考实现****无**
- **ARCHITECTURE.md 契约**B5
- **建议**:参照 CICD 中 `admin/users` + `getStaffOptions()` 演化。
#### 2.13.3 `/shell/admin/organization`(组织管理)
- **CICD 参考实现****无**
- **ARCHITECTURE.md 契约**B5
- **建议**:合并 `school/departments` + `school/grades` + 师生维度,作组织架构视图。
---
## 三、按 ARCH §9.4 模块汇总
| 模块 | ARCH 规划页数 | portal-shell 已完成 | 缺失 | 契约状态 |
| ---------------- | ---------------------------------------------------------------- | ------------------- | ------------------ | ------------------- |
| dashboard | 1 | 1 | 0 | ✅ `adminDashboard` |
| users | 1+1 import 子页) | 0 | 1+1 子页) | ❌ |
| roles | 1 | 0 | 1 | ❌ |
| permissions | 1 | 0 | 1 | ❌ |
| audit-logs | 4含 overview/login/data-changes | 0 | 4 | ❌ |
| invitation-codes | 1 | 0 | 1 | ❌ |
| school | 6schools/classes/departments/academic-year/grades + redirect | 0 | 6 | ❌ |
| classes | 1与 school/classes 同源) | 0 | 0合并到 school | ❌ |
| students | 1 | 0 | 1 | ❌ |
| teachers | 1 | 0 | 1 | ❌ |
| organization | 1 | 0 | 1 | ❌ |
| announcements | 1 | 0 | 1 | ❌ |
| files | 1 | 0 | 1 | ❌ |
| ai-settings | 1 | 0 | 1 | ❌ |
| system | 1 | 0 | 1 | ❌ |
| viewports | 1 | 0 | 1 | ❌ |
| plugins | 1 | 0 | 1 | ✅ `config-service` |
| **合计** | **~24** | **1** | **~23** | **2 ✅ / ~22 ❌** |
> **批次**:全部 B5契约就绪优先级`plugins` ✅ > `dashboard` ✅(已完成)> 其余 ❌ 需 MSW 兜底先行。
---
## 四、CICD 中存在但 ARCH §9.4 未规划的管理员页面21 页B5 后期候选)
> 这些页面在 CICD 中属于"管理员视角的跨班聚合/全局只读"功能是教师域功能在管理员层级的复用。ARCH §9.4 未将其纳入 24 页规划,但作为完整管理员工作台仍具迁移价值。建议作为 B5 末或 B6 补充批次候选,按需取用。
### 4.1 course-plans 模块4 页)
| CICD 路径 | 功能 | 技术栈 |
| --------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `admin/course-plans/page.tsx` | 课程计划列表admin 全局视角,`scope.isAdmin=true` | Server Component + `requirePermission(Permissions.COURSE_PLAN_READ)` + `getCoursePlans({ status }, { isAdmin: true })` |
| `admin/course-plans/create/page.tsx` | 创建课程计划 | Server Component + `requirePermission(Permissions.COURSE_PLAN_MANAGE)` + 并行查询 classes/subjects/teachers/academicYears + `CoursePlanForm mode="create"` |
| `admin/course-plans/[id]/page.tsx` | 课程计划详情 | Server Component + `getCoursePlanById(id, { userId, isAdmin: true })` + `CoursePlanDetail` |
| `admin/course-plans/[id]/edit/page.tsx` | 编辑课程计划 | Server Component + `requirePermission(Permissions.COURSE_PLAN_MANAGE)` + `CoursePlanForm mode="edit"` |
### 4.2 curriculum-map 模块1 页)
| CICD 路径 | 功能 | 技术栈 |
| ------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `admin/curriculum-map/page.tsx` | 课程地图(标准覆盖热图 + 5 张统计卡:教师/教案/已发布/已提交/已关联标准数) | Server Component + `requirePermission(Permissions.LESSON_PLAN_READ)` + `getStandardsCoverageHeatmapAction()` + `getGlobalLessonPlanStatsAction()` + `CurriculumMapView` |
### 4.3 elective 模块4 页)
| CICD 路径 | 功能 | 技术栈 |
| ----------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `admin/elective/page.tsx` | 选修课列表(`StatsCardsLoader` + `CourseListLoader` 双 Suspense 流式) | Server Component + `requirePermission(Permissions.ELECTIVE_READ)` + `ElectivePageLayout` |
| `admin/elective/create/page.tsx` | 创建选修课 | Server Component + `getSubjectOptions()/getGrades()/getStaffOptions()` + `ElectiveCourseForm mode="create"` |
| `admin/elective/[id]/page.tsx` | 选修课详情(含 `getCourseSelections` 选课记录) | Server Component + `requirePermission(Permissions.ELECTIVE_READ)` + `ElectiveCourseDetail` |
| `admin/elective/[id]/edit/page.tsx` | 编辑选修课 | Server Component + `ElectiveCourseForm mode="edit"` |
### 4.4 questions 模块1 页)
| CICD 路径 | 功能 | 技术栈 |
| -------------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `admin/questions/page.tsx` | 题库管理(筛选 + 导入导出 + 创建) | Server Component + `requirePermission(Permissions.QUESTION_READ)` + `getQuestions({...})` + `QuestionFilters`Suspense + `QuestionBankResultsClient` + `ImportExportButtons` + `CreateQuestionButton` |
### 4.5 lesson-plans 模块2 页)
| CICD 路径 | 功能 | 技术栈 |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `admin/lesson-plans/page.tsx` | 教案列表4 统计卡:总数/已发布/草稿/已归档 + `LessonPlanList viewMode="admin"` + `LessonPlanProviderSetup` 注入 ADMIN_ROLE_CONFIG | Server Component + `requirePermission(Permissions.LESSON_PLAN_READ)` + `getLessonPlans({}, ctx.dataScope, ctx.userId)` + `getLessonPlanStats()` |
| `admin/lesson-plans/[planId]/view/page.tsx` | 教案只读视图(含 textbook/chapter 标题解析) | Server Component + `getLessonPlanById(planId, ctx.userId)` + `getTextbookById/getChaptersByTextbookId` 并行 + `LessonPlanReadonlyView` |
### 4.6 error-book 模块1 页)
| CICD 路径 | 功能 | 技术栈 |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `admin/error-book/page.tsx` | 错题本分析5 统计卡 + 学科 Tab + 学科分布图 + 章节/知识点薄弱度并排 + Top 50 学生 + Top 10 高频错题;限 500 学生 + DataScope 校验 `type === "all"` | Server Component + `requirePermission(Permissions.ERROR_BOOK_ANALYTICS_READ)` + 多 data-access 并行 + `SubjectTabs/StatsGrid/SubjectDistributionChart/ChapterWeaknessChart/KnowledgePointWeaknessChart/GroupedStudentErrorTable/TopWrongQuestions` + `WidgetBoundary` |
### 4.7 scheduling 模块3 页)
| CICD 路径 | 功能 | 技术栈 |
| ----------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `admin/scheduling/auto/page.tsx` | 自动排课(`AutoSchedulePanel` + 跳转 rules 配置入口) | Server Component + `requirePermission(Permissions.SCHEDULE_AUTO)` + `getAdminClassesForScheduling()` |
| `admin/scheduling/changes/page.tsx` | 排课变更审批(变更列表 + 冲突检测 + 课表网格) | Server Component + `requirePermission(Permissions.SCHEDULE_ADJUST)` + 并行 `getAdminClassesForScheduling/getScheduleChanges/getScheduleEntriesForAdmin` + `ScheduleChangeList canApprove` + `ScheduleConflictsView` + `ScheduleGridView` |
| `admin/scheduling/rules/page.tsx` | 排课规则配置 | Server Component + `requirePermission(Permissions.SCHEDULE_ADJUST)` + `getSchedulingRules()` + `SchedulingRulesForm` |
### 4.8 attendance 模块1 页)
| CICD 路径 | 功能 | 技术栈 |
| --------------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `admin/attendance/page.tsx` | 考勤管理7 统计卡 + 班级对比卡 + 考勤-成绩关联分析卡 + 筛选器) | Server Component + `requirePermission(Permissions.ATTENDANCE_READ)` + 并行 `getAttendanceRecords/getAttendanceStats/getGrades/getClassComparison/getAttendanceGradeCorrelation` + `AdminAttendanceFilters`(含 class/status/date 筛选) |
> **附注**CICD `admin/attendance/admin-attendance-filters.tsx` 是页内私有 Client Component封装 `FilterBar + Select + Input`,使用 `ATTENDANCE_STATUS_OPTIONS` 常量。迁移时此类"页内 filters 组件"模式应保持。
### 4.9 announcements 详情/编辑2 页)
| CICD 路径 | 功能 | 技术栈 |
| ---------------------------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `admin/announcements/[id]/page.tsx` | 公告详情(`AnnouncementDetail canManage` + 跳转 edit + 发布/归档/删除/置顶操作入口) | Server Component + `requirePermission(Permissions.ANNOUNCEMENT_MANAGE)` + `getAdminAnnouncementDetailPageData(id)` + `AnnouncementsServiceProvider` |
| `admin/announcements/[id]/edit/page.tsx` | 公告编辑(`AnnouncementForm mode="edit"` + grades 关联) | Server Component + `requirePermission(Permissions.ANNOUNCEMENT_MANAGE)` + `getEditAnnouncementPageData(id)` |
### 4.10 users/import 子页1 页)
已在 §2.2.2 列入 ARCH 规划口径(与 `users` 工单合并),此处不重复。
### 4.11 roles/[id] 详情1 页)
| CICD 路径 | 功能 | 技术栈 |
| --------------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `admin/roles/[id]/page.tsx` | 角色详情(`RolePermissionMatrix` 权限矩阵 + `RoleDetailEditButton` + admin 角色锁定提示卡) | Server Component + `requirePermission(Permissions.ROLE_READ)` + `getRoleById(id)` + `notFound()` 兜底 + admin 角色强制锁定isLocked |
### 4.12 school/grades/insights1 页)
已在 §2.6 附注中提及,不重复。
---
## 五、迁移注意事项
### 5.1 架构迁移要点
1. **管理员权限校验**:所有 23 缺失页面均需 `requirePermission(Permissions.XXX)` 在 Server Component 入口校验。CICD 模式可直接复用,但需对齐 portal-shell 的 auth-guard004 §5 鉴权链路)。
2. **DataScope 上下文**`school/grades/insights`、`error-book`、`attendance` 等页面依赖 `ctx.dataScope`all / class_taught / class_members / childrenportal-shell 需在 BFF 层补齐数据范围上下文。
3. **Server Action + router.refresh 模式**`invitation-codes`、`announcements/[id]/edit` 等使用此模式portal-shell 需保持等价机制BFF API + 客户端 refetch
4. **导出功能**`audit-logs` 三页 + `questions` 导入导出按钮,需后端提供 CSV 导出端点。
5. **服务注入**`audit-logs/overview` 使用 `AuditServiceProvider + adminAuditService` 模式portal-shell 应在 BFF/Service 层保留服务抽象。
### 5.2 模块复杂度风险
| 模块 | 风险点 | 缓解建议 |
| ----------------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| **audit-logs**4 页) | 审计核心,多维筛选 + 导出 + 概览统计 + 数据变更统计 | 后端契约工单优先;前端可 MSW 先行 4 页 UI |
| **school**6 页) | 体系复杂6 子页 + 跨表关联schools/classes/departments/grades/academic-year/staff | 按 schools → grades → classes → departments → academic-year 顺序迁移insights 作 B5 末 |
| **scheduling**3 页,§四补充批次) | 涉及自动排课算法 + 冲突检测 + 审批流 | 算法侧需独立服务/工单;前端先做 changes 审批流auto/rules 后置 |
| **error-book**(§四补充批次) | 5 统计卡 + 4 图表 + Top 50 学生 + Top 10 错题;限 500 学生性能保护 | 复用教师域 error-book 组件,仅换 data-access 为 admin scope图表组件应已存在 |
| **attendance**(§四补充批次) | 7 统计 + 班级对比 + 考勤-成绩关联分析 | 后端需提供 `getClassComparison` + `getAttendanceGradeCorrelation` 两个分析端点 |
| **curriculum-map**(§四补充批次) | 标准覆盖热图 + 5 张统计卡 + `getStandardsCoverageHeatmapAction` Server Action | 依赖 lesson-preparation 模块的 actions-analytics需先迁移教师域 lesson-plans |
| **ai-settings** | 双权限AI_CHAT + AI_CONFIGURE+ Provider 配置 + Usage 仪表盘 | 后端需提供 provider CRUD + usage 聚合端点 |
### 5.3 契约就绪优先级建议
按 ARCH §9.4 节奏原则(契约就绪页先行,❌ 页用 MSW 先上 UI
1. **优先级 1契约 ✅,可立即实现真实查询)**
- `/shell/admin/plugins`(✅ `config-service`
- `/shell/admin`(已完成)
2. **优先级 2高价值 + 中等复杂度,需后端契约工单)**
- `/shell/admin/users` + `/shell/admin/users/import`(用户管理 + 批量导入)
- `/shell/admin/roles` + `/shell/admin/permissions`RBAC 核心)
- `/shell/admin/invitation-codes`(与 users 共享 USER_MANAGE 权限)
- `/shell/admin/announcements`(公告管理)
- `/shell/admin/files`(文件管理)
3. **优先级 3高复杂度建议 MSW 先行)**
- `/shell/admin/audit-logs/*`4 页,审计核心,多维筛选 + 导出)
- `/shell/admin/school/*`6 页,体系复杂)
4. **优先级 4ARCH 新建,需独立设计)**
- `/shell/admin/students`、`/shell/admin/teachers`、`/shell/admin/organization`、`/shell/admin/viewports`、`/shell/admin/system`
5. **优先级 5§四补充批次B5 末或 B6**
- course-plans/curriculum-map/elective/questions/lesson-plans/error-book/scheduling/attendance 共 16 页
### 5.4 CICD admin/layout.tsx 迁移说明
CICD `admin/layout.tsx` 仅 `return <>{children}</>`**无独立侧边栏/权限逻辑**(侧边栏由 `(dashboard)/layout.tsx` 统一处理,权限由各 page 调 `requirePermission`)。
portal-shell 同样无需在 `shell/admin/layout.tsx` 实现额外逻辑,保持 passthrough 即可;侧边栏与权限校验由 `shell/layout.tsx` 与各 page.tsx 分担。
---
## 六、附录CICD admin/page.tsx 完整清单41 个)
| # | CICD 路径 | ARCH §9.4 归属 | 缺失/已有 |
| --- | ------------------------------------------- | ----------------------------- | ------------------------------------------- |
| 1 | `admin/dashboard/page.tsx` | §9.4 第 1 行 ✅ | portal-shell `/shell/admin/page.tsx` 已完成 |
| 2 | `admin/users/page.tsx` | §9.4 第 2 行 ❌ | 缺失 |
| 3 | `admin/users/import/page.tsx` | §9.4 第 2 行 ❌(合并) | 缺失 |
| 4 | `admin/roles/page.tsx` | §9.4 第 3 行 ❌ | 缺失 |
| 5 | `admin/roles/[id]/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 6 | `admin/permissions/page.tsx` | §9.4 第 3 行 ❌ | 缺失 |
| 7 | `admin/audit-logs/page.tsx` | §9.4 第 4 行 ❌ | 缺失 |
| 8 | `admin/audit-logs/overview/page.tsx` | §9.4 第 4 行 ❌ | 缺失 |
| 9 | `admin/audit-logs/login-logs/page.tsx` | §9.4 第 4 行 ❌ | 缺失 |
| 10 | `admin/audit-logs/data-changes/page.tsx` | §9.4 第 4 行 ❌ | 缺失 |
| 11 | `admin/invitation-codes/page.tsx` | §9.4 第 5 行 ❌ | 缺失 |
| 12 | `admin/school/page.tsx`redirect | §9.4 第 6 行 ❌ | 缺失 |
| 13 | `admin/school/schools/page.tsx` | §9.4 第 6 行 ❌ | 缺失 |
| 14 | `admin/school/classes/page.tsx` | §9.4 第 6/7 行 ❌ | 缺失 |
| 15 | `admin/school/departments/page.tsx` | §9.4 第 6 行 ❌ | 缺失 |
| 16 | `admin/school/academic-year/page.tsx` | §9.4 第 6 行 ❌ | 缺失 |
| 17 | `admin/school/grades/page.tsx` | §9.4 第 6 行 ❌ | 缺失 |
| 18 | `admin/school/grades/insights/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 19 | `admin/announcements/page.tsx` | §9.4 第 10 行 ❌ | 缺失 |
| 20 | `admin/announcements/[id]/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 21 | `admin/announcements/[id]/edit/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 22 | `admin/files/page.tsx` | §9.4 第 11 行 ❌ | 缺失 |
| 23 | `admin/ai-settings/page.tsx` | §9.4 第 12 行 ❌ | 缺失 |
| 24 | `admin/settings/page.tsx` | §9.4 第 13 行 ❌(→ /system | 缺失 |
| 25 | `admin/course-plans/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 26 | `admin/course-plans/create/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 27 | `admin/course-plans/[id]/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 28 | `admin/course-plans/[id]/edit/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 29 | `admin/curriculum-map/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 30 | `admin/elective/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 31 | `admin/elective/create/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 32 | `admin/elective/[id]/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 33 | `admin/elective/[id]/edit/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 34 | `admin/questions/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 35 | `admin/lesson-plans/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 36 | `admin/lesson-plans/[planId]/view/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 37 | `admin/error-book/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 38 | `admin/scheduling/auto/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 39 | `admin/scheduling/changes/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 40 | `admin/scheduling/rules/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
| 41 | `admin/attendance/page.tsx` | §四补充批次 | 缺失(非 ARCH §9.4 规划) |
**ARCH §9.4 规划但 CICD 无源5 页)**
| # | ARCH 目标路由 | 说明 | 契约 |
| --- | --------------------------- | -------------------------------- | ------------------- |
| A | `/shell/admin/students` | ARCH 新建CICD 无 | ❌ |
| B | `/shell/admin/teachers` | ARCH 新建CICD 无 | ❌ |
| C | `/shell/admin/organization` | ARCH 新建CICD 无 | ❌ |
| D | `/shell/admin/viewports` | ARCH 新建,对齐 004 §5.4 | ❌ |
| E | `/shell/admin/plugins` | ARCH 新建plugin-manager 升级) | ✅ `config-service` |
---
## 七、关键结论
1. **portal-shell 管理域完成度1/24 ≈ 4%**(仅仪表盘),是各角色域中完成度最低的。
2. **缺失 23 页全部属 B5 批次**,节奏紧迫,建议立即启动契约工单。
3. **契约就绪仅 2 个**`adminDashboard`(已用)+ `config-service`plugins未实现
4. **CICD 有 21 页 ARCH §9.4 未规划**,是教师域功能在管理员视角的复用,建议作为 B5 末或 B6 补充批次,按需取用。
5. **高复杂度模块**audit-logs4 页 + 导出、school6 子页 + 跨表关联、scheduling算法、error-book多图表聚合
6. **CICD admin/layout.tsx 无独立逻辑**portal-shell 保持 passthrough 即可,侧边栏与权限由 shell/layout + 各 page.tsx 分担。
7. **建议实施顺序**:契约就绪的 `plugins` → 高价值低复杂度的 `users/roles/permissions/invitation-codes/announcements/files/ai-settings` → 高复杂度的 `audit-logs/*` + `school/*` → ARCH 新建的 `students/teachers/organization/viewports/system` → §四补充批次 16 页。