Files
Edu/docs/architecture/issues/contracts/parent-portal_contract.md

14 KiB
Raw Blame History

parent-portal 对接契约

负责人ai15 关联:matrix.mdparent-bff_contract.mdiam_contract.mdpush-gateway_contract.md 依据ARB-001BFF GraphQL、ARB-002MF Shell 暴露清单)、port-allocation.md §4 待仲裁ISSUE-001 ~ ISSUE-010objections/parent-portal_issue.md),仲裁前本契约按 ARB-001 GraphQL 方向编写


§1 我提供什么(对外接口)

1.1 gRPC 接口(如有)

无。parent-portal 是前端微前端 Remote不提供 gRPC。

1.2 HTTP 端点(如有)

无对外 HTTP API 端点。parent-portal 是 Next.js 前端应用MF Remote不对外暴露 REST API。

说明ISSUE-006parent-portal 的页面路由(/parent/dashboard/parent/grades 等)是前端 SSR/CSR 路由,不是 HTTP API 端点。页面路由清单见 01-understanding.md §8 L2 路由表

parent-portal 仅提供两个内部健康检查端点(非业务 API

Method Path 用途 认证
GET /api/health Dockerfile HEALTHCHECK
GET /api/ready K8s readinessProbe

1.3 GraphQL schema如 BFF

不适用。parent-portal 消费 parent-bff GraphQL自身不提供 schema。

1.4 Kafka 事件发布(如有)

无。前端不发布 Kafka 事件。

1.5 错误码前缀

parent-portal 不产生错误码前缀(前端不定义错误码)。消费侧错误码前缀见 §2.5。

1.6 微前端架构

角色 说明
MF 角色 RemoteShell = teacher-portal :4000
Remote name parent_app
remoteEntry 路径 static/chunks/remoteEntry.js
暴露模块 ./pages(家长场景页面)、./ChildSwitcher(多子女切换组件)
MF 配置文件 apps/parent-portal/next.config.jsNextFederationPlugin02-architecture-design §1.2
MF sharedsingleton react / react-dom / urql / graphql / @tanstack/react-query / zustand / nuqs / @edu/ui-tokens / @edu/ui-components / @edu/hooksARB-002
dev/prod 端口 4002port-allocation.md §4
feature flag NEXT_PUBLIC_MF_ENABLEDARB-002P4 默认开)

ISSUE-007MF 配置文件统一为 next.config.js,不使用 module-federation.config.ts(与 02-architecture-design + teacher-portal Shell 一致)。


§2 我消费什么(依赖上游)

2.1 gRPC 调用(同步)

无。前端不直接调 gRPC。

2.2 Kafka 事件订阅(异步)

无。前端不直接订阅 Kafka。

2.3 HTTP 调用(非 GraphQL

被调用方 Method.Path 用途 mock 策略
api-gateway (ai01) POST /api/v1/iam/login 家长登录 api-gateway 就绪前 MSW 返回固定 JWTparent 角色)

ISSUE-004

  • 登录端点统一为 POST /api/v1/iam/login(与 matrix.md §5 /api/v1/iam/* + 01 §3.1 前缀一致)
  • 登录是 parent-portal 唯一走 REST非 GraphQL的端点登录前无 JWTGraphQL endpoint 需鉴权
  • 待 coord 确认登录是否走 REST其余走 GraphQL

2.4 GraphQL 查询域(经 api-gateway 代理到 parent-bff

依据ARB-001BFF GraphQL+ parent-bff_contract.md §1.3

端点POST /api/v1/parent/graphqlapi-gateway 代理 /api/v1/parent/* → parent-bff :3010 /graphql

ISSUE-001 / ISSUE-008

  • 01/02 文档描述为 REST 消费,与 ARB-001 冲突,待 coord 仲裁
  • 仲裁前本表按 GraphQL 方向编写(与 parent-bff contract + matrix.md 一致)
  • 路径前缀统一为 /api/v1/parent/graphql(与 matrix.md §5 一致,旧版缺 v1
Query/Mutation 类型 用途 对应 parent-bff 聚合 mock 策略
currentUser Query 当前家长信息 iam.GetUserInfo + GetEffectivePermissions + GetViewports MSW 返回固定家长parent-001 王家长)
myChildren Query 我的子女列表(核心) iam.GetChildrenByParentI3/ISSUE-047 裁决) MSW 返回固定 2 个子女student-001 + student-002
childSummary(childId) Query 子女仪表盘概览 data-ana.GetParentDashboard MSW 返回固定仪表盘
childGrades(childId) Query 子女成绩 core-edu.ListGradesByStudent MSW 返回固定 5 个成绩
childAttendance(childId) Query 子女考勤 core-edu.ListAttendanceByStudent MSW 返回固定 10 条考勤
childHomework(childId) Query 子女作业 core-edu.ListHomeworkByClass MSW 返回固定 3 个作业
childWeakness(childId) Query 子女薄弱点 data-ana.GetStudentWeakness MSW 返回固定 3 个 weak_points
childTrend(childId) Query 子女学习趋势 data-ana.GetLearningTrend MSW 返回固定趋势数据
myNotifications Query 通知列表P5 msg.ListNotifications MSW 返回固定 10 条通知
markAsRead(notificationId) Mutation 标记已读P5 msg.MarkAsRead MSW 返回 success=true
updateNotificationPreferences Mutation 更新通知偏好 msg待 ai05 确认) MSW 返回 success=true
switchChild(childId) Mutation 切换当前子女 待 ISSUE-009 仲裁确认 见 ISSUE-009

switchChild 说明ISSUE-009

  • parent-bff_contract.md §1.3 未列 switchChild Mutation
  • 待 coord 仲裁switchChild 是 GraphQL Mutation后端记录当前子女还是纯前端状态localStorage + Zustand
  • 若纯前端:本表移除 switchChild切换逻辑在 useChildSwitcher 内直接写 Zustand + localStorage

2.5 消费的错误码前缀(前端 i18n 路由)

parent-portal 不产生错误码,仅消费。前端 API 请求层根据 error.code 前缀路由到对应 i18n key

前缀 来源服务 i18n key 模式
IAM_ iam error.iam.{{code}}
CORE_EDU_ core-edu error.core_edu.{{code}}
BFF_PARENT_ parent-bff error.bff_parent.{{code}}
GW_ api-gateway error.gw.{{code}}
NETWORK_ 前端网络层 error.network.{{code}}

:与 matrix.md §6 错误码前缀矩阵对齐。BFF_PARENT_ 前缀由 parent-bff 定义(见 parent-bff_contract.md §1.5)。

2.6 WebSocket 推送P5

被调用方 协议 路径 用途 mock 策略
push-gateway (ai02) WebSocket /ws 实时推送 mock-socket 模拟 WS 推送(每 30s 1 条)
push-gateway (ai02) SSE降级 /sse SSE 降级

WebSocket 连接由 Shell 建立统一连接管理parent-portal 通过 Zustand ui-store 订阅事件流。

2.7 消费的 MF Shell 暴露ARB-002

暴露模块 来源 用途
AppShell teacher-portal Shell 左栏导航 + 主内容区布局
GraphQLProvider teacher-portal Shell urql client 单例ARB-002
useAuth packages/hooks 会话状态
usePermission packages/hooks 权限查询
useGraphQLClient packages/hooks urql client 获取
ErrorBoundary packages/ui-components React 渲染异常兜底
Loading / Empty packages/ui-components 骨架屏 / 空态
RequirePermission packages/ui-components L3 组件级视口控制

MF sharedsingletonreact / react-dom / urql / graphql / @tanstack/react-query / zustand / nuqs / @edu/ui-tokens / @edu/ui-components / @edu/hooksARB-002 裁决,见 coord.md §2


§3 就绪信号

3.1 我依赖的上游就绪标志

上游 就绪信号 提供方 状态
api-gateway HTTP :8080 启用 + JWT 验签 + /api/v1/parent/* 代理 ai01
parent-bff GraphQL POST /graphql :3010 + currentUser/myChildren/childSummary/childGrades Query ai05 P4
iam GetChildrenByParent gRPC 50052 + iam_student_guardiansI3/ISSUE-047 裁决) ai06 P3 补全
teacher-portal Shell MF exposesAppShell + GraphQLProvider + hooks + UI 组件)+ shared singleton ai13 P2
push-gateway WebSocket :8081/ws ai02 P5
msg gRPC 50056 + NotificationService ai10 P5
shared-ts / contracts ApiClient / Logger / Permissions 常量 coord
ui-tokens / ui-components / hooks 三层令牌 + shadcn + usePermission/useAuth ai07/ai13 P2 收尾

P0 阻塞ISSUE-010iam GetChildrenByParent 缺失,多子女场景无法落地。补全前用 mock固定 2 个子女 student-001 + student-002开发。

3.2 我的就绪标志(供下游消费)

matrix.md §8 就绪信号跟踪表对齐

信号 说明 阶段
parent-portal dev server :4002 启用 MF Remote 可被 Shell 加载 P4-1
MF Remote remoteEntry.js 可加载 Shell 端 remotes.parent = parent_app@http://localhost:4002/... 可解析 P4-1
独立壳渲染 首页 + 导航 + 路由守卫 P4-1
登录流程可用 POST /api/v1/iam/login 获取 JWT 存入 httpOnly cookie P4-2
GraphQL 查询可执行 currentUser / myChildren / childSummary 返回数据mock 或真实) P4-2
多子女切换可用 ChildSwitcher + invalidate 流程通过 P4-3
数据范围校验生效 前端路由守卫校验 childId 是否在 myChildren 返回列表中 P4-3
Dashboard 可访问 家长登录 → 看到 Dashboard含子女卡片 P4-4
健康检查通过 GET /api/health + GET /api/ready 200 P4-1
测试覆盖率达标 单元 ≥ 85% + 集成 ≥ 75% P4-9
Docker 镜像可构建 docker build 成功 P4-10
WebSocket 通知可接收 push-gateway WS 事件正确处理 P5-1

§4 Mock 策略

4.1 我提供的 mock

parent-portal 是前端,无下游消费方。但对开发体验提供:

  • Storybook:各组件独立 story
  • MSW handlersapps/parent-portal/src/mocks/handlers.ts,拦截所有 GraphQL/HTTP 请求

4.2 我消费的 mock

在真实上游就绪前parent-portal 使用以下 mockNEXT_PUBLIC_API_MOCKING=enabled 控制):

  • GraphQL mockMSW 拦截 POST /api/v1/parent/graphql
    • 按 operationName 返回对应 mock 响应(与 parent-bff mock 数据一致)
    • currentUser → 固定家长id="parent-001", name="王家长", roles=["parent"]
    • myChildren → 固定 2 个子女id="student-001" 李同学 + id="student-002" 李妹妹)
    • childSummary → 固定仪表盘child_avg_score=85.0, child_class_rank=5
    • childGrades → 固定 5 个成绩
    • childAttendance → 固定 10 条考勤
    • childHomework → 固定 3 个作业
    • myNotifications → 固定 10 条通知
    • 所有 mock 响应定义在 apps/parent-portal/src/mocks/fixtures/*.json
  • HTTP mockMSW 拦截 POST /api/v1/iam/login → 返回固定 JWT + UserInfoparent 角色)
  • WebSocket mockmock-socket 库,连接后每 30 秒推送 1 条 mock 通知
  • JWT mock:固定 mock JWT存入 httpOnly cookie
  • 环境切换NEXT_PUBLIC_API_MOCKING=enabled(开发)/ disabled(上游就绪后)
  • 数据一致性myChildren mock 必须返回固定 2 个孩子student-001 + student-002与所有 child* 查询的 student_id 一致(否则前端数据范围校验失败)

§5 待协调事项(指向 objections

以下事项已提请 coord 仲裁,仲裁结果可能影响本契约:

ISSUE 影响章节 当前处理
ISSUE-001REST vs GraphQL §2.4 按 GraphQL 编写(依 ARB-001待 coord 确认
ISSUE-004登录端点 §2.3 暂用 POST /api/v1/iam/login,待 coord 确认
ISSUE-006HTTP 端点分类) §1.2 已修正为"无对外 HTTP API"
ISSUE-007MF 配置文件名) §1.6 已修正为 next.config.js
ISSUE-008GraphQL 路径前缀) §2.4 已修正为 /api/v1/parent/graphql
ISSUE-009switchChild Mutation §2.4 列为待仲裁,标注两种方案
ISSUE-010iam GetChildrenByParent 缺失) §3.1 P0 阻塞,用 mock 开发

详见 objections/parent-portal_issue.md