feat(admin-portal): 完整实现 admin-portal 管理端微前端

包含 src 全部实现、Dockerfile、配置文件等
This commit is contained in:
SpecialX
2026-07-10 19:09:12 +08:00
parent 02d09c47fa
commit b3511910d1
69 changed files with 11955 additions and 693 deletions

View File

@@ -1,42 +1,66 @@
# 模块理解确认书 — admin-portal
> AIai07TS/React · 管理场景域前端 remote
> 阶段:阶段 1 交付物
> 日期2026-07-09
> 关联:[004 架构影响地图](../../../docs/architecture/004_architecture_impact_map.md) §1.1a/1.1b/§5.4、[AI 分配方案](../../../docs/architecture/ai-allocation.md) §5 ai07、[pending-features P6](../../../docs/architecture/roadmap/pending-features.md)、[known-issues §2.12](../../../docs/troubleshooting/known-issues.md)、[teacher-portal 阶段1](../../teacher-portal/docs/01-understanding.md)、[teacher-portal 阶段2](../../teacher-portal/docs/02-architecture-design.md)
> AIai16TS/React · 管理场景域前端 remote
> 阶段:阶段 1 交付物(仲裁后修订版 v2
> 日期2026-07-10
> 关联:
>
> - [004 架构影响地图](../../../docs/architecture/004_architecture_impact_map.md) §1.1a/1.1b/§5.4
> - [AI 分配方案](../../../docs/architecture/ai-allocation.md) §5 ai16
> - [总统最终裁决](../../../docs/architecture/president-final-rulings.md) §5.1-5.5ISSUE-044~048
> - [admin-portal 对接契约](../../architecture/issues/contracts/admin-portal_contract.md)
> - [admin-portal 工作线](../../architecture/issues/worklines/admin-portal_workline.md)
> - [known-issues §2.16](../../../docs/troubleshooting/known-issues.md)
---
## 0. 仲裁结果摘要ARB-001~006
| 编号 | 议题 | 裁决 |
| -------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| ARB-001 | BFF 归属ISSUE-044 | 复用 teacher-bff GraphQL endpoint不新建 admin-bffai03 预留 `admin.*` 命名空间 |
| ARB-002 | 错误码前缀ISSUE-045 | `ADMIN_` 前缀(合并 `SCHOOL_`/`ORG_``ADMIN_`i18n key `error.admin.*` |
| ARB-003 | 权限点命名ISSUE-046 | admin 自身资源用 `ADMIN_*`;跨服务资源保留原前缀(`IAM_USER_READ` 等) |
| ARB-004 | GraphQL 客户端ISSUE-047 | MF 模式复用 Shell 暴露的 GraphQL client 单例standalone 模式自建 urql client |
| ARB-005 | 审计日志归属ISSUE-048 | 审计事件归 iam 发布到 `edu.iam.audit.created`teacher-bff 消费聚合admin-portal 经 GraphQL `auditLogs` Query 消费 |
| ARB-006 | WebSocket 实时通知 | 接入 push-gateway `GET /ws`(审计告警/异常登录/系统异常),不再用轮询 |
| 端口分配 | admin-portal dev server | **4003**(非旧文档的 3003 |
---
## 1. 我在架构中的位置
- **层级**L2 微前端层004 §3.1 六层架构中的前端层)
- **MF 角色****Remote 子应用**,挂载到 teacher-portal Shell主应用
- **MF 角色****Remote 子应用**,挂载到 teacher-portal Shell主应用,端口 4000
- **上游(谁调用我)**:浏览器(系统管理员 / 校管理员)
- **下游(同步)**api-gatewayREST经 teacher-portal Shell 的 Next.js `rewrites` 代理 `/api/v1/*`
- **下游(推送)****不消费推送**,管理端用轮询
- **BFF 对接**teacher-bff 复用(`/admin/*` 聚合)+ iam 直连(`/iam/*` 用户/角色/权限/视口 CRUD
- **通信方式**HTTP/REST前端→Gateway
- **下游(同步)**api-gatewayGraphQL `POST /api/admin/graphql` + REST `/api/auth/login`
- **下游(推送)**push-gateway `GET /ws`WebSocket 实时通知ARB-006
- **BFF 对接**复用 teacher-bff GraphQL admin 命名空间ARB-001不新建 admin-bff
- **通信方式**GraphQL业务数据+ HTTP登录+ WebSocket实时通知
- **不直连**:前端不直连任何业务服务或 BFF 后端实例,全部经 api-gateway 代理
**说明**
- admin-portal 作为 Remote 子应用,挂载到 teacher-portal Shell 提供的 AppShell + 共享依赖react/react-dom/@tanstack/react-query/zustand/nuqs/ui-components/ui-tokens/contracts/hooks
- 路由前缀 `/admin/*` 由 teacher-portal Shell 动态加载 admin-portal Remote 模块
- 场景域 BFF 复用策略004 §5.4):系统/校管理员复用 teacher-portal Shell + teacher-bff`/admin/*` 视口)+ iam 直连,不单独建 portal 后端
- 全部业务请求经 api-gateway 代理admin-portal 本身不实现 rewrites依赖 Shell 的 rewrites
- admin-portal 作为 Remote 子应用,挂载到 teacher-portal Shell
- Shell 暴露 `GraphQLProvider` / `useGraphQLClient` / `AppShell` / `useAuth` / `usePermission`admin-portal MF 模式复用standalone 模式自建
- 路由前缀 `/admin/*` 由 teacher-portal Shell 动态加载 admin-portal Remote 模块(暴露 `./AdminApp`
- 场景域 BFF 复用策略004 §5.4 + ARB-001复用 teacher-bff GraphQL endpointadmin 命名空间(`admin.*` Query/Mutation
## 2. 我的限界上下文
### 2.1 我负责的聚合 / 实体(前端视图模型)
- 用户、角色、权限、视口(管理场景域前端视图)
- 用户、角色、权限、视口(管理场景域前端视图,调 iam 经 GraphQL
- 组织(学校/年级/班级层级)
- 平台监控(运行时指标、用户活动、错误统计
- 会话状态Session、视口Viewport、权限Permission与 teacher-portal 共享,引用 teacher-portal 文档
- 学校设置system 路由
- 班级/教师/学生全局管理admin 视角,只读 + 状态管理
- 审计日志(只读,经 teacher-bff GraphQL `auditLogs` Query 消费)
- 管理仪表盘(聚合统计 + 服务健康)
- 实时通知WebSocket 推送:审计告警/异常登录/系统异常)
### 2.2 业务领域
- **管理场景域**(前端场景域:管理场景域,对应后端 iam 限界上下文 + teacher-bff 管理视口
- **管理场景域**(前端场景域:管理场景域,对应后端 iam 限界上下文 + teacher-bff admin 命名空间
### 2.3 不负责
@@ -44,6 +68,7 @@
- 学生作答界面(归 student-portal
- 家长多子女切换(归 parent-portal
- 教师仪表盘(归 teacher-portaladmin-portal 仅有管理仪表盘)
- 审计事件发布(归 iamadmin-portal 仅消费)
### 2.4 数据范围
@@ -54,180 +79,206 @@
### 3.1 消费的后端 API经 api-gateway 代理)
| 路径前缀 | 下游 BFF/服务 | 关键端点 |
| ------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/api/v1/iam/*`(管理用) | iam | `GET /iam/users``POST /iam/users``PUT /iam/users/:id``GET /iam/roles``GET /iam/permissions``GET /iam/viewports``PUT /iam/viewports/:id` |
| `/api/v1/admin/*` | teacher-bff 复用 + iam 直连 | `GET /admin/dashboard``GET /admin/monitoring/metrics``GET /admin/stats/users``GET /admin/stats/active-sessions` |
| `/api/v1/notifications/*` | msg | 通知中心P5 |
| 路径 | Method | 下游 BFF/服务 | 用途 |
| ------------------------- | ------ | ----------------------------- | ------------------------------------------------- |
| `/api/admin/graphql` | POST | teacher-bffadmin 命名空间) | 全部业务 GraphQL 查询ARB-001 |
| `/api/auth/login` | POST | api-gateway → iam | 登录standalone 模式用MF 模式复用 Shell 登录) |
| `GET /ws`push-gateway | WS | push-gateway | 实时通知(审计告警/异常登录/系统异常ARB-006 |
### 3.2 统一响应契约
### 3.2 GraphQL Operationscontract §2.4
所有后端响应遵循 `ActionState` 结构(迁移指南 §7.5
admin-portal 消费 teacher-bff admin 命名空间的 18 个 GraphQL operations
```typescript
type ActionState<T> =
| { success: true; data: T }
| {
success: false;
error: { code: string; message: string; details?: unknown };
};
```
| Operation | 类型 | 用途 |
| ------------------------------------------------ | -------------- | ------------------------------- |
| `currentUser` | Query | 当前管理员信息 |
| `adminUsers` / `adminUser(id)` | Query | 用户列表 / 详情 |
| `createUser` / `updateUser` / `toggleUserStatus` | Mutation | 用户 CRUD |
| `adminRoles` | Query | 角色列表(含权限) |
| `createRole` / `updateRolePermissions` | Mutation | 角色 CRUD + 权限矩阵 |
| `adminPermissions` | Query | 全量权限点(按 resource |
| `adminViewports(scope)` | Query | 视口配置列表 |
| `updateViewport` | Mutation | 视口配置更新 |
| `adminOrganization(parentId)` | Query | 组织树 |
| `adminClasses` | Query | 班级管理(全局) |
| `adminTeachers` | Query | 教师管理 |
| `adminStudents` | Query | 学生管理 |
| `auditLogs(filter)` | Query | 审计日志(聚合 iam AuditEvent |
| `adminDashboard` | Query | 管理员仪表盘聚合 |
| `systemSettings` / `updateSystemSettings` | Query/Mutation | 学校设置 |
错误码前缀按服务名大写admin-portal 涉及:`IAM_``BFF_TEACHER_``GW_``NETWORK_`)。前端 API 请求层根据 `error.code` 前缀路由到对应的 i18n key。
### 3.3 推送契约ARB-006
### 3.3 推送契约
admin-portal 接入 push-gateway `GET /ws`,消费 3 类实时通知:
**— N/A**
| 通知类型 | severity | 用途 |
| ---------------- | -------- | ------------------------- |
| `audit_alert` | warning | 审计告警(敏感操作触发) |
| `abnormal_login` | error | 异常登录(异地/异常时段) |
| `system_error` | error | 系统异常(服务降级/宕机) |
admin-portal **不消费** WebSocket 推送或 SSE 流式响应。管理端场景对实时性要求低,采用**轮询**策略:
- 平台监控页60s 轮询 `GET /api/v1/admin/monitoring/metrics`
- 用户活动统计5min 轮询 `GET /api/v1/admin/stats/active-sessions`
- 通知中心P5HTTP 长轮询或定时拉取 `GET /api/v1/notifications`(不走 push-gateway
> 长期监控指标推荐用 `<iframe>` 嵌入 Grafana 面板PlatformMonitor 组件),不经过 BFF。
> **不再用轮询**:旧文档的"60s 轮询监控 + 5min 轮询统计"策略已被 ARB-006 替换为 WebSocket 实时推送。开发期用 mock-socket + 30s 定时器模拟推送。
### 3.4 proto 不直接消费
前端不调用 gRPCBFF 把 gRPC 聚合为 REST 暴露给前端。前端仅消费 `packages/contracts/src/permissions.ts` 中的权限点常量TS 文件,非 proto 生成)。
前端不调用 gRPCteacher-bff 把 gRPC 聚合为 GraphQL 暴露给前端。前端仅消费 `packages/contracts/src/permissions.ts` 中的权限点常量TS 文件,非 proto 生成)。
## 4. 我的技术栈
| 维度 | 选型 | 说明 |
| --------------------------- | -------------------------------------------------------- | ----------------------------------------------- |
| 框架 | Next.js 14+App Router | server components 默认client components 按需 |
| 语言 | TypeScript 5.5+strict | 沿用 tsconfig.base.json |
| 微前端 | Module Federation 2.0@module-federation/nextjs-mf | admin-portal = **Remote** |
| 样式 | Tailwind CSS 3.4+ | 配合设计令牌三层模型(与 teacher-portal 共享) |
| UI 组件库 | shadcn/ui迁移指南 §7.2 | 复用 Shell 暴露的 `packages/ui-components/` |
| 状态管理 L1 URL | nuqs | 可分享、可刷新状态 |
| 状态管理 L2 Server | TanStack Query v5 | 服务端数据缓存、重试、乐观更新 |
| 状态管理 L3 Client Business | Zustand slice | 客户端业务状态 |
| 状态管理 L4 Global UI | Zustand ui-store + ModalRoot复用 Shell | 全局 UI 状态 |
| 状态管理 L5 Form | react-hook-form + zodResolver | 表单状态 |
| 富文本 | — **不使用** | 管理端无富文本场景,不引入 Tiptap |
| 图表 | recharts | 管理仪表盘、用户活动统计 |
| i18n | next-intl | BFF/服务返回 i18n key + 参数,前端翻译 |
| A11y | eslint-plugin-jsx-a11yerror 级) | WCAG 2.2 AA |
| 字体 | Intersans/ Frauncesserif/ JetBrains Monomono | 复用 teacher-portal RootLayout 加载,不重复引入 |
| 维度 | 选型 | 说明 |
| ---------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| 框架 | Next.js 14+App Router | server components 默认client components 按需 |
| 语言 | TypeScript 5.5+strict | 沿用 tsconfig.base.json |
| 微前端 | Module Federation 2.0@module-federation/nextjs-mf | admin-portal = **Remote**,端口 4003 |
| 数据层 | urql GraphQL client | standalone 自建 / MF 复用 Shell 单例ARB-004 |
| 样式 | Tailwind CSS 3.4+ | 配合设计令牌三层(复用 Shell |
| UI 组件库 | shadcn/ui 风格(复用 Shell `@edu/ui-components` | admin-portal 内部 `ui.tsx` 封装 PaperCard/Button/Table 等纸面组件 |
| 表单 | react-hook-form + zod | 用户表单/学校设置 |
| 拖拽排序 | @dnd-kit/sortable | 视口配置拖拽排序 |
| 图表 | recharts | 仪表盘趋势表(实际以纯表格为主,纸面风格 |
| i18n | 轻量 i18n`messages` 字典 + `t()` 函数) | 命名空间 `admin.*`,不依赖 next-intl |
| Mock | MSWMock Service Worker+ mock-socket | 开发期拦截全部 GraphQL/HTTP + WebSocket mock |
| Web Vitals | web-vitals v4 | LCP/CLS/FCP/INP/TTFB 采集,`navigator.sendBeacon` 上报 |
| A11y | eslint-plugin-jsx-a11yerror 级) | WCAG 2.2 AA |
| 字体 | Intersans/ Frauncesserif/ JetBrains Monomono | RootLayout 加载standaloneMF 模式复用 Shell |
| 测试 | Vitest + @testing-library/react | jsdom 环境,覆盖率 ≥ 80% |
| ESLint | ESLint 9 flat config | jsx-a11y + tseslint + prettier`@next/eslint-plugin-next` 14.x 与 ESLint 9 不兼容,已移除) |
> 技术栈 teacher-portal **完全一致**差异仅在MF 角色Remote 而非 Shell、不使用 Tiptap、不消费 WebSocket/SSE 推送、数据范围 L3-L5。
> **技术栈差异**vs teacher-portalMF 角色Remote、GraphQL 为主(非 REST、消费 WebSocket 推送(非 SSE、纸面 UI 风格、数据范围 L3-L5。
## 5. 我的阶段归属
- **阶段**P6硬化阶段
- **当前状态** **全为待建**admin-portal 当前为空目录,无任何代码);📐 需设计(待全部业务服务稳定
- **依赖上游阶段**P6依赖 teacher-portal Shell 已就绪 + iam 已实现用户/角色/权限/视口 CRUD + teacher-bff 已实现 `/admin/*` 复用
- **阶段**P6硬化阶段,批次 5
- **当前状态** **已实现**P2-P6 全阶段交付完成,含 11 路由 + MSW mock + A11y + Web Vitals + Dockerfile
- **依赖上游阶段**P6依赖 teacher-portal Shell 已就绪 + teacher-bff GraphQL admin 命名空间 + iam 已实现用户/角色/权限/视口 CRUD + push-gateway WebSocket
## 6. 我需要对齐的黄金模板项(对照 classes 服务
## 6. 路由表11 路由contract §1.2
> 前端无 `@RequirePermission` 装饰器(后端概念),对齐项改造为前端等价物。
| 路由 | 页面 | 权限点 | 数据范围 |
| --------------------- | ---------------- | ---------------------- | -------- |
| `/admin/dashboard` | 管理员仪表盘 | `ADMIN_DASHBOARD_VIEW` | L3-L5 |
| `/admin/users` | 用户管理 | `IAM_USER_READ` | L3-L5 |
| `/admin/roles` | 角色权限管理 | `IAM_ROLE_READ` | L3-L5 |
| `/admin/permissions` | 权限点管理 | `IAM_PERMISSION_READ` | L5 |
| `/admin/viewports` | 视口配置 | `IAM_VIEWPORT_READ` | L5 |
| `/admin/organization` | 组织管理 | `ADMIN_ORG_MANAGE` | L3-L5 |
| `/admin/system` | 学校设置 | `ADMIN_SYSTEM_MANAGE` | L5 |
| `/admin/classes` | 班级管理(全局) | `ADMIN_CLASS_READ` | L3-L5 |
| `/admin/teachers` | 教师管理 | `ADMIN_TEACHER_READ` | L3-L5 |
| `/admin/students` | 学生管理 | `ADMIN_STUDENT_READ` | L3-L5 |
| `/admin/audit-logs` | 审计日志 | `ADMIN_AUDIT_READ` | L5 |
| 对齐项 | classes后端黄金模板 | admin-portal 前端等价 | 当前状态 |
| --------------------- | ------------------------------------- | ------------------------------------------------------------------------ | -------------------------- |
| 权限校验 | `@RequirePermission(Permissions.XXX)` | `usePermission().hasPermission("XXX")` Hook + `<RequirePermission>` 组件 | ❌ 待建(无现有代码) |
| 错误码前缀统一 | `CLASSES_*``IAM_*` | API 请求层根据 `error.code` 前缀路由 i18n | ❌ 待建 |
| logger | pino | 前端 console + SentryP6 | ❌ 待建 |
| metrics | prom-client `/metrics` | 前端 Web Vitals → Gateway 上报 | ❌ 待建 |
| tracer | OTel SDK | 前端 OTel browser SDKP6 | ❌ 待建 |
| /healthz + /readyz | `GET /healthz` `GET /readyz` | Next.js `/api/health` route + Dockerfile HEALTHCHECK | ❌ 待建 |
| 优雅关闭 | SIGTERM handler | Next.js 无长连接,无需 | ✅ N/A |
| 测试覆盖率 ≥ 80% | Vitest | Vitest + @testing-library/react + Playwright E2E | ❌ 待建0% |
| Dockerfile 多阶段构建 | builder + runtime | builder + runtime | ❌ 待建 |
| Zod 输入验证 | class-validator + Zod schema | react-hook-form + zodResolver | ❌ 待建 |
| GlobalErrorFilter | NestJS 全局异常过滤器 | React ErrorBoundary + API 请求层统一错误处理 | ❌ 待建 |
| 设计令牌三层 | — | primitive.css / semantic-light/dark.css / tailwind-theme.css复用 | ❌ 待建(复用 Shell 暴露) |
| A11y 工具集 | — | useA11yId / mergeA11yProps / describeInput / focus-trap复用 Shell | ❌ 待建(复用 Shell 暴露) |
> 权限点前缀规则ARB-003admin 自身资源用 `ADMIN_*`;跨服务资源保留原前缀(如 `IAM_USER_READ`)。`ADMIN_*` 常量由 coord 维护于 `packages/contracts/src/permissions.ts`admin-portal 引用 `src/lib/permissions.ts`,不硬编码。
## 7. 黄金模板对齐清单(前端等价)
| 对齐项 | 后端等价 | admin-portal 实现 | 状态 |
| --------------------- | ------------------------------------- | ------------------------------------------------------------- | ---- |
| 权限校验 | `@RequirePermission(Permissions.XXX)` | `usePermission().hasPermission("XXX")` Hook + `AuthGuard` | ✅ |
| 错误码前缀 | `IAM_*` / `ADMIN_*` | `CONSUMED_ERROR_PREFIXES` 常量 + i18n 路由 | ✅ |
| logger | pino | console + 结构化(生产 → 上报) | ✅ |
| metrics | prom-client `/metrics` | Web Vitals v4 → `navigator.sendBeacon` 上报 | |
| /health + /ready | `GET /healthz` `GET /readyz` | Next.js Route Handler `/api/health` + `/api/ready` | ✅ |
| 优雅关闭 | SIGTERM handler | N/ANext.js 无长连接) | |
| 测试覆盖率 ≥ 80% | Vitest | Vitest + @testing-library/react | ⚠️ |
| Dockerfile 多阶段构建 | builder + runtime | `node:22-alpine` 多阶段standalone 输出EXPOSE 4003 | ✅ |
| Zod 输入验证 | class-validator + Zod schema | react-hook-form + zod | ✅ |
| GlobalErrorFilter | NestJS 全局异常过滤器 | React ErrorBoundary + Toast 错误处理 | ✅ |
| 设计令牌三层 | — | `globals.css`primitive/semantic+ tailwind-theme | ✅ |
| A11y 工具集 | — | eslint-plugin-jsx-a11yerror 级)+ skip-link + focus-visible | ✅ |
| Module Federation | — | `next.config.js` Remote 角色,`NEXT_PUBLIC_MF_ENABLED` 控制 | ✅ |
| MSW mock | — | 18 GraphQL operation + `/api/auth/login` mock | ✅ |
---
## 附admin-portal 现状审计(对齐黄金模板
## 附admin-portal 实现清单v2仲裁后修订
### 审计表
| 维度 | 状态 | 说明 |
| ------------------------------------ | ------ | ------------------------------------------------------------------------- |
| 权限装饰器(前端等价 usePermission | ❌ | 待建,复用 Shell 暴露的 `usePermission` Hook + `<RequirePermission>` 组件 |
| 错误码前缀 | ❌ | 待建,复用 Shell 暴露的 ApiClient统一请求层 |
| logger | ❌ | 待建,复用 `packages/shared-ts/src/logger.ts` |
| metrics | ❌ | 待建Web Vitals 上报 `admin_portal_*` |
| tracer | ❌ | 待建OTel browser SDKP6 |
| /healthz | ❌ | 待建Next.js Route Handler |
| /readyz | ❌ | 待建Next.js Route Handler |
| 优雅关闭 | ✅ N/A | Next.js 无长连接 |
| 测试覆盖率 | ❌ | 待建,目标 ≥ 80% |
| Dockerfile 多阶段 | ❌ | 待建builder + runtime |
| Zod 输入验证 | ❌ | 待建react-hook-form + zodResolver |
| GlobalErrorFilterErrorBoundary | ❌ | 待建,复用 Shell 暴露的 ErrorBoundary |
| 设计令牌三层 | ❌ | 待建,复用 Shell 暴露的 `packages/ui-tokens/` |
| A11y 工具集 | ❌ | 待建,复用 Shell 暴露的 `packages/ui-components/` |
| Module Federation 配置 | ❌ | 待建next.config.js 配置 Remote 角色 |
| 5 层状态管理 | ❌ | 待建,复用 Shell 暴露的 nuqs/TanStack Query/Zustand |
| 共享组件库 | ❌ | 待建,复用 Shell 暴露 + admin 特有 4 个组件 |
| i18n | ❌ | 待建next-intl |
| API 请求层 | ❌ | 待建,复用 Shell 暴露的 ApiClient |
| ESLint flat config 自定义规则 | ❌ | 待建no-hardcoded-fonts / design-tokens 规则 |
### 现有文件清单
### 文件结构
```
apps/admin-portal/ # 空目录(待建)
apps/admin-portal/
├─ package.json # 依赖urql/msw/@dnd-kit/web-vitals/eslint-plugin-jsx-a11y
├─ next.config.js # MF Remote 配置 + rewritesGraphQL 代理)
├─ tsconfig.json # extends tsconfig.base.json
├─ tailwind.config.js # paper/ink/accent/rule 色板
├─ eslint.config.js # ESLint 9 flat configjsx-a11y + tseslint + prettier
├─ Dockerfile # 多阶段构建node:22-alpinestandalone
├─ vitest.config.ts # jsdom + coverage ≥80%
├─ .env.example # 环境变量模板
├─ public/mockServiceWorker.js # MSW worker
└─ src/
├─ app/
│ ├─ globals.css # 设计令牌 + A11y 样式
│ ├─ layout.tsx # RootLayout字体加载
│ ├─ page.tsx # 根页面redirect /admin/dashboard
│ ├─ admin-app.tsx # MF Remote 入口exposes ./AdminApp
│ ├─ login/page.tsx # 登录页standalone mock 登录)
│ ├─ admin/
│ │ ├─ layout.tsx # admin 路由组 layoutProvider 链 + AuthGuard + AdminShell
│ │ ├─ dashboard/page.tsx # 管理仪表盘
│ │ ├─ users/page.tsx # 用户管理
│ │ ├─ roles/page.tsx # 角色权限
│ │ ├─ permissions/page.tsx # 权限点管理
│ │ ├─ viewports/page.tsx # 视口配置(@dnd-kit 拖拽)
│ │ ├─ organization/page.tsx # 组织管理
│ │ ├─ system/page.tsx # 学校设置
│ │ ├─ classes/page.tsx # 班级管理
│ │ ├─ teachers/page.tsx # 教师管理
│ │ ├─ students/page.tsx # 学生管理
│ │ └─ audit-logs/page.tsx # 审计日志CSV 导出)
│ └─ api/
│ ├─ health/route.ts # Liveness 检查
│ └─ ready/route.ts # Readiness 检查
├─ components/
│ ├─ ui.tsx # 通用 UIPaperCard/Button/Input/Select/Badge/Table/Pagination
│ ├─ admin-shell.tsx # AdminShell左栏 11 项导航 + 主内容 + 跳过链接)
│ ├─ user-management-table.tsx # 用户管理表格
│ ├─ user-form-modal.tsx # 用户表单弹窗
│ ├─ role-permission-matrix.tsx# 角色权限矩阵
│ ├─ organization-tree.tsx # 组织树A11y treeitem
│ ├─ notification-panel.tsx # 通知面板WebSocket
│ ├─ msw-initializer.tsx # MSW 初始化
│ └─ web-vitals-initializer.tsx# Web Vitals 初始化
├─ hooks/
│ ├─ use-graphql.ts # useGraphQuery + useGraphMutation
│ ├─ use-users.ts # 用户 CRUD
│ ├─ use-roles.ts # 角色 CRUD
│ ├─ use-permissions.ts # 权限点查询
│ ├─ use-viewports.ts # 视口配置
│ ├─ use-organization.ts # 组织树
│ ├─ use-classes.ts # 班级
│ ├─ use-teachers.ts # 教师
│ ├─ use-students.ts # 学生
│ ├─ use-audit-logs.ts # 审计日志 + CSV 导出
│ ├─ use-dashboard.ts # 仪表盘
│ ├─ use-system-settings.ts # 学校设置
│ └─ use-websocket.ts # WebSocket 实时通知
├─ providers/
│ ├─ graphql-provider.tsx # GraphQLProviderstandalone 自建 urql client
│ ├─ auth-provider.tsx # AuthProvider + useAuth + usePermission
│ └─ toast-provider.tsx # ToastProvider + useToast
├─ lib/
│ ├─ graphql-client.ts # urql client + 18 个 GraphQL operations
│ ├─ auth.ts # 认证工具
│ ├─ permissions.ts # 权限常量ADMIN_ + IAM_
│ ├─ i18n.ts # 轻量 i18n
│ └─ web-vitals.ts # Web Vitals 采集
├─ types/
│ └─ view-models.ts # 视图模型类型定义
└─ mocks/
├─ browser.ts # MSW Browser Worker
├─ server.ts # MSW Node Servervitest
├─ fixtures.ts # mock 数据库
└─ handlers.ts # MSW handlers18 GraphQL + login
```
**说明**admin-portal 当前为空目录,所有维度均为 ❌ 待建状态。无现有文件、无现有代码、无现有违规点。P6 阶段从零开始搭建。
### 质量校验
### L1 导航菜单(视口
| 视口 key | 标签i18n key | 路由 | 权限 |
| -------------- | ------------------------ | --------------------- | ----------------------- |
| `dashboard` | `admin.nav.dashboard` | `/admin/dashboard` | `ADMIN_DASHBOARD_VIEW` |
| `users` | `admin.nav.users` | `/admin/users` | `IAM_USER_READ` |
| `roles` | `admin.nav.roles` | `/admin/roles` | `IAM_ROLE_READ` |
| `permissions` | `admin.nav.permissions` | `/admin/permissions` | `IAM_PERMISSION_READ` |
| `viewports` | `admin.nav.viewports` | `/admin/viewports` | `IAM_VIEWPORT_READ` |
| `organization` | `admin.nav.organization` | `/admin/organization` | `ORG_MANAGE` |
| `monitoring` | `admin.nav.monitoring` | `/admin/monitoring` | `ADMIN_MONITORING_VIEW` |
### L2 路由表
| 路由 | 页面 | 权限 |
| --------------------- | ---------- | ----------------------- |
| `/admin/dashboard` | 管理仪表盘 | `ADMIN_DASHBOARD_VIEW` |
| `/admin/users` | 用户管理 | `IAM_USER_READ` |
| `/admin/users/new` | 新建用户 | `IAM_USER_CREATE` |
| `/admin/users/:id` | 用户编辑 | `IAM_USER_UPDATE` |
| `/admin/roles` | 角色管理 | `IAM_ROLE_READ` |
| `/admin/permissions` | 权限管理 | `IAM_PERMISSION_READ` |
| `/admin/viewports` | 视口配置 | `IAM_VIEWPORT_READ` |
| `/admin/organization` | 组织管理 | `ORG_MANAGE` |
| `/admin/monitoring` | 平台监控 | `ADMIN_MONITORING_VIEW` |
### L3 组件级差异admin-portal 特有)
**复用 Shell 暴露的组件**AppShell、RequirePermission、ErrorBoundary、Loading、Empty、DataTable、Form、Chart、Toast、Modal、Button/Input/Select/Textarea、A11y 工具集
**admin-portal 特有组件**
| 组件 | 用途 | 来源 |
| ---------------------- | --------------------------------------- | ---- |
| `UserManagementTable` | 用户管理表格(列表/筛选/分页/批量操作) | 新建 |
| `RolePermissionMatrix` | 角色-权限矩阵编辑器checkbox 网格) | 新建 |
| `ViewportConfigEditor` | 视口配置编辑器(拖拽排序 + 权限绑定) | 新建 |
| `PlatformMonitor` | 平台监控Grafana iframe embed | 新建 |
**不使用的组件**RichTextEditorTiptap、ExamTaking、SSEViewer、ChildSwitcher 等(这些归 teacher-portal / student-portal / parent-portal
### L4 数据层差异
| 维度 | admin-portal | teacher-portal |
| ------------ | --------------------------------- | -------------------------------------- |
| 主要数据来源 | iam 直连 + teacher-bff 复用 | teacher-bff 聚合 + core-edu/content/ai |
| 缓存策略 | **5min 长缓存**(管理数据低频变) | 5min / 30s 混合(实时性差异) |
| 实时性要求 | 低(轮询 60s / 5min | 高WebSocket 推送 + SSE 流式) |
| 推送消费 | ❌ 不消费 | ✅ 消费 WebSocket + SSE |
- `pnpm run typecheck` → ✅ 通过0 errors
- `pnpm run lint` → ✅ 通过0 errors
---
**AI Agent**: ai07 (admin-portal remote)
**Branch**: docs/admin-portal-stage1-stage2-design-ai07
**AI Agent**: ai16 (admin-portal remote)
**Branch**: admin-portal-arbitration-done-TaFkyb
**Coordinator**: coord-ai