- 根目录 project_rules.md 损坏(72 字节乱码),已删除 - 从 CICD 项目迁移完整版至 .trae/rules/project_rules.md(17881 字节) - 更新 MIGRATION_GUIDE/README/coding-standards 引用至 .trae/rules/ - P0 紧急修复,影响所有 AI 工作流程
30 KiB
迁移指南:CICD → Edu
版本:1.0 日期:2026-07-07 状态:基线发布 维护者:架构组 关联文档:
目录
一、迁移背景
1.1 迁移动机
原始项目 CICD 是基于 Next.js 16 的单应用架构,承载 K12 智慧教务系统 35 个业务模块。随着业务规模扩张与团队增长,单应用架构在以下方面暴露瓶颈:
| 维度 | 单应用瓶颈 | 微服务目标 |
|---|---|---|
| 团队协作 | 35 模块挤在同一仓库,合并冲突频繁 | 按领域拆分,6 领域团队独立迭代 |
| 部署节奏 | 全量构建发布,单模块变更牵动全站 | 服务粒度独立部署,故障爆炸半径缩小 |
| 技术选型 | TypeScript 单语言,AI/分析场景受限 | TS(业务)+ Go(网关)+ Python(AI/分析)各取所长 |
| 数据规模 | 单 MySQL,跨模块联表与读放大 | 读写分离 + CQRS,ClickHouse 承载分析负载 |
| 可演进性 | 模块间隐式耦合,重构成本高 | DDD 限界上下文显式契约,演化可控 |
1.2 迁移原则
- 契约先行:服务间通信先定 protobuf 契约,再写实现,禁止"先实现再补契约"
- 资产复用:设计令牌、权限模型、缓存策略、UI 组件模式等优质资产尽量平移,不重复造轮子
- ** strangler fig**:不一次性切流,按阶段灰度迁移,旧系统与新系统在过渡期并存
- 数据自治:每个微服务独占自身数据库,跨服务查询走 BFF 聚合或读模型
- 可观测优先:迁移同步建立 tracing/metrics/logging 三件套,禁止"先上线后补监控"
二、原始项目说明(CICD)
2.1 基本概况
| 属性 | 值 |
|---|---|
| 仓库路径 | e:\Desktop\CICD |
| 技术栈 | Next.js 16 + React 19 + Tailwind v4 + Drizzle ORM |
| 语言 | TypeScript(全栈) |
| 架构 | 单应用 + 严格模块化(app → modules → shared 三层) |
| 业务模块数 | 35 个 |
| 数据库 | MySQL(单库) |
| 认证 | NextAuth.js |
| 部署 | Gitea Actions + Docker standalone |
2.2 模块清单(按领域归类)
| 领域 | 模块 |
|---|---|
| 身份与权限 | auth、users、onboarding、settings、permissions |
| 教学组织 | classes、teachers、students、parents、subjects |
| 教学核心 | courses、lessons、schedule、attendance、leave-requests |
| 考试评价 | exams、questions、grading、scores、analytics |
| 作业内容 | homework、textbooks、resources |
| 沟通通知 | messaging、notifications、announcements |
| 智能辅助 | ai(备课/出题/分析)、search |
| 系统支撑 | audit-logs、reports、dashboard、layout |
2.3 已沉淀的工程资产
- arch.db 架构元数据库:通过
npm run arch:scan扫描得到模块、函数、调用关系、依赖关系、技术标签的结构化数据 - 设计令牌体系:primitive / semantic-light / semantic-dark / 模块命名空间 / Tailwind 暴露 五层分层
- 权限模型:
requirePermission()服务端校验 +usePermission().hasPermission()客户端校验,权限点常量集中维护 - 缓存策略:
cacheFn(Reactcache()+ 自定义缓存层),权限数据不跨请求缓存 - ActionState 模式:Server Action 统一返回
{ success, message, errors, data }结构 - 5 层状态模型:URL(nuqs)→ Server(TanStack Query)→ Client Business(Zustand)→ Global UI(Zustand)→ Form(react-hook-form)
- A11y 工具集:
useA11yId、mergeA11yProps、describeInput、loadingAria、aria-live Hook、focus-trap 组件 - CI/CD 流水线:CI + 安全扫描 + 灾备演练三套 Gitea Actions 工作流
- 审计日志三件套:
login-logger、change-logger、audit-logger
三、新项目说明(Edu)
3.1 基本概况
| 属性 | 值 |
|---|---|
| 仓库路径 | e:\Desktop\Edu |
| 远程仓库 | https://git.eazygame.cn/xiner/Edu.git |
| 架构范式 | DDD + EDA + CQRS 微服务 |
| 语言 | TypeScript(NestJS 10)+ Go(Gin 网关)+ Python(FastAPI 分析/AI) |
| 前端 | React + Next.js + Module Federation(4 微前端) |
| monorepo 策略 | pnpm workspace + go.work + pyproject.toml (uv) |
| 事件总线 | Kafka + Debezium CDC |
| 契约 | protobuf + buf |
| 存储 | MySQL / Redis / ClickHouse / Neo4j / Elasticsearch |
3.2 整体架构
flowchart TB
subgraph Client[客户端]
WEB[Web 浏览器]
APP[移动端]
end
subgraph Gateway[网关层 Go Gin]
GW[API Gateway<br/>路由/鉴权/限流/熔断]
end
subgraph BFF[聚合层 BFF]
BFF1[Admin BFF]
BFF2[Teacher BFF]
BFF3[Student/Parent BFF]
end
subgraph Services[业务微服务 NestJS]
S1[identity 身份]
S2[org 教学组织]
S3[teaching 教学核心]
S4[content 内容分析]
S5[comm 沟通]
S6[insight 智能洞察]
end
subgraph Infra[基础设施服务]
I1[auth 认证授权]
I2[notification 通知]
end
subgraph EventBus[事件总线]
K[Kafka]
DBZ[Debezium CDC]
end
subgraph Storage[存储]
MY[(MySQL)]
RD[(Redis)]
CH[(ClickHouse)]
NEO[(Neo4j)]
ES[(Elasticsearch)]
end
Client --> GW
GW --> BFF
BFF --> Services
Services --> Infra
Services <--> K
DBZ --> K
Services --> Storage
Infra --> Storage
3.3 微前端与领域服务映射
| 微前端 | 路由前缀 | 对接 BFF | 主要消费的服务 |
|---|---|---|---|
| Admin Shell | /admin |
Admin BFF | identity、org、insight |
| Teacher Shell | /teacher |
Teacher BFF | teaching、content、comm |
| Student Shell | /student |
Student/Parent BFF | teaching、content |
| Parent Shell | /parent |
Student/Parent BFF | teaching、comm |
| 微服务 | 原始模块映射 | 主存储 | 对外契约 |
|---|---|---|---|
| identity | auth、users、onboarding、settings、permissions | MySQL + Redis | identity.proto |
| org | classes、teachers、students、parents、subjects | MySQL | org.proto |
| teaching | courses、lessons、schedule、attendance、leave-requests、exams、homework | MySQL | teaching.proto |
| content | textbooks、resources、questions、grading | MySQL + Elasticsearch | content.proto |
| comm | messaging、notifications、announcements | MySQL + Redis | comm.proto |
| insight | scores、analytics、ai、search、reports、dashboard | ClickHouse + Neo4j | insight.proto |
| auth(基础设施) | NextAuth 逻辑下沉 | MySQL + Redis | auth.proto |
| notification(基础设施) | notifications channel 抽离 | MySQL + Redis | notification.proto |
四、迁移策略矩阵
按"直接迁移 / 调整迁移 / 重写 / 新建"四档分类。
4.1 规范类资产
| 资产 | 策略 | 说明 |
|---|---|---|
| 项目规则(project_rules) | 调整 | 架构图优先保留,分层规则从三层改为微服务分层,新增 DDD/契约/事件驱动规则 |
| 编码规范(coding-standards) | 调整 | TS 部分保留并补充 NestJS 装饰器/DI 规则,新增 Go、Python、protobuf 章节 |
| Git 工作流 | 调整 | trunk-based 替代分支策略,scope 改为服务/包名,新增多语言 monorepo 提交规则 |
| 提交规范(Conventional Commits) | 直接迁移 | 类型与格式完全沿用 |
| 设计令牌规范 | 调整 | 分层模型保留,分布位置从 src/app/styles/tokens/ 改为微前端共享包 |
| 安全规范 | 直接迁移 | Cookie 策略、env 校验、XSS 防护、权限校验规则全部沿用 |
| 问题记录规则 | 直接迁移 | known-issues.md 索引式速查手册模式沿用 |
| A11y 规范 | 直接迁移 | WCAG 2.2 AA 目标与工具集沿用 |
4.2 代码类资产
| 资产 | 策略 | 说明 |
|---|---|---|
| Zod schema 定义 | 直接迁移 | 各模块 schema.ts 平移至对应微服务,复用验证规则 |
| 权限点常量(Permissions) | 直接迁移 | 集中迁入 identity 服务共享包 |
| Drizzle schema(表结构) | 调整 | 按领域拆分到各微服务独占库,关系型字段保持不变 |
| ActionState 类型 | 直接迁移 | 升级为 protobuf message,结构不变 |
| Server Actions | 重写 | 改写为 NestJS Controller + Service + Application Service 三层 |
| data-access 层 | 重写 | 改写为 NestJS Repository + Domain Entity |
| UI 组件(shared/components) | 直接迁移 | 平移至微前端共享包,保持 PascalCase 命名 |
| Hook(useAuth、usePermission) | 调整 | 改为通过 BFF/gRPC client 获取,接口签名保持不变 |
| 缓存层(cacheFn) | 重写 | 改为 NestJS Cache 模块 + Redis,去除 React cache() |
| arch:scan 工具 | 调整 | 扫描器扩展为多语言(TS+Go+Python),数据库结构保持 |
| 审计日志三件套 | 直接迁移 | 平移至 notification 服务,日志结构保持 |
| CI/CD 流水线 | 重写 | Gitea Actions 改为多服务并行流水线,新增契约校验阶段 |
4.3 文档类资产
| 资产 | 策略 | 说明 |
|---|---|---|
| 架构影响地图(004) | 重写 | 从单应用模块图改为微服务限界上下文图 |
| K12 功能清单(006) | 直接迁移 | 功能清单与架构无关,直接平移 |
| 差距审计报告(007) | 调整 | 重新审计各微服务的功能完成度 |
| 模块角色映射(008) | 直接迁移 | 角色权限矩阵不变 |
| 路线图(roadmap/) | 重写 | 6 阶段微服务路线图 |
| known-issues.md | 直接迁移 | 经验日志平移,新增"微服务"分区 |
| 各模块 README | 重写 | 改为各微服务 README,按 DDD 上下文描述 |
五、文档体系映射表
| CICD 文档 | Edu 对应文档 | 关系 |
|---|---|---|
.trae/rules/project_rules.md |
project_rules.md |
调整(微服务版) |
docs/standards/coding-standards.md |
docs/standards/coding-standards.md |
调整(多语言版) |
| —(散落在 project_rules) | docs/standards/git-workflow.md |
新建 |
docs/architecture/004_architecture_impact_map.md |
docs/architecture/001_architecture_overview.md |
重写 |
docs/architecture/006_k12_feature_checklist.md |
docs/architecture/feature_checklist.md |
直接迁移 |
docs/architecture/007_gap_audit_report.md |
docs/architecture/gap_audit.md |
调整 |
docs/architecture/008_module_role_mapping.md |
docs/architecture/role_mapping.md |
直接迁移 |
docs/architecture/roadmap/README.md |
docs/architecture/roadmap/README.md |
重写 |
docs/architecture/roadmap/tech-debt.md |
docs/architecture/roadmap/tech-debt.md |
重写 |
docs/architecture/roadmap/decoupling.md |
docs/architecture/roadmap/migration_phases.md |
重写(迁移阶段化) |
docs/troubleshooting/known-issues.md |
docs/troubleshooting/known-issues.md |
直接迁移 + 新分区 |
src/modules/[module]/README.md |
services/[service]/README.md |
重写 |
docs/standards/coding-standards.md §A11y |
docs/standards/accessibility.md |
拆分独立 |
六、六阶段路线图概览
6.1 阶段总览
gantt
title Edu 微服务迁移六阶段路线图
dateFormat YYYY-MM-DD
axisFormat %m月
section P1 地基
仓库结构/契约/CI/可观测 :p1, 2026-07-01, 30d
section P2 身份
identity/auth/notification :p2, after p1, 30d
section P3 核心教学
org/teaching/content :p3, after p2, 45d
section P4 内容分析
insight+CQRS读模型/ES :p4, after p3, 30d
section P5 沟通AI
comm/AI增强 :p5, after p4, 30d
section P6 硬化
安全/灾备/性能/混沌 :p6, after p5, 30d
6.2 各阶段目标
| 阶段 | 名称 | 目标 | 关键交付物 | 验收信号 |
|---|---|---|---|---|
| P1 | 地基 | 仓库骨架、契约工具链、CI、可观测平台 | monorepo 结构、buf 配置、Kafka 集群、OpenTelemetry | 契约生成 + 一次端到端 trace |
| P2 | 身份 | identity + auth + notification 三服务打通 | JWT 颁发、RBAC、邮件/短信/站内通知 | 用户注册→登录→收到通知 |
| P3 | 核心教学 | org + teaching + content | 班级/课表/作业/题库/考试 | 教师创建作业→学生提交→批改闭环 |
| P4 | 内容分析 | insight + CQRS 读模型 + ES 全文检索 | ClickHouse 报表、ES 搜索、Neo4j 知识图谱 | 多维分析报表 + 全文搜索可用 |
| P5 | 沟通AI | comm + AI 辅助 | 站内信/通知中心、AI 备课/出题/答疑 | 教师用 AI 出题并发布到班级 |
| P6 | 硬化 | 安全加固、灾备、性能、混沌工程 | WAF、定期备份、压测报告、混沌演练 | RPO≤15min、RTO≤30min、P99≤500ms |
6.3 阶段交付门槛
每个阶段进入下一阶段前必须满足:
- 契约稳定:本阶段涉及服务的 protobuf 契约冻结,breaking change 走 deprecation 流程
- 可观测完整:tracing 覆盖率 ≥ 95%,关键业务指标(QPS/延迟/错误率)接入 Grafana
- 测试覆盖:单元测试 ≥ 80%,关键流程 E2E 通过
- 文档同步:服务 README + 004 架构图 + known-issues 已更新
- arch.db 同步:
pnpm run arch:scan已扫描最新代码状态
七、原始项目可复用资产清单
7.1 设计令牌思路
复用方式:将 CICD 的 src/app/styles/tokens/ 五层分层模型平移至微前端共享包。
| CICD 位置 | Edu 位置 | 调整 |
|---|---|---|
src/app/styles/tokens/primitive.css |
packages/ui-tokens/primitive.css |
直接平移 |
src/app/styles/tokens/semantic-light.css |
packages/ui-tokens/semantic-light.css |
直接平移 |
src/app/styles/tokens/semantic-dark.css |
packages/ui-tokens/semantic-dark.css |
直接平移 |
src/app/styles/tokens/lesson-preparation.css |
packages/ui-tokens/lesson-preparation.css |
直接平移 |
src/app/styles/tokens/tailwind-theme.css |
packages/ui-tokens/tailwind-theme.css |
直接平移 |
强制规则保持不变:
- 禁止硬编码颜色(
#hex) - 禁止硬编码字体(
'Inter'/'Fraunces'/'JetBrains Mono') - 禁止硬编码字号(
font-size: Npx) - 禁止 Tailwind 任意值(
w-[Npx]) - ESLint
no-restricted-syntax+design-tokens/no-hardcoded-fonts规则沿用
7.2 UI 组件模式
复用方式:将 CICD 的 src/shared/components/ui/ 平移至 packages/ui-components/,作为 Module Federation 共享依赖。
| 组件类别 | CICD 路径 | Edu 路径 | 复用要点 |
|---|---|---|---|
| 基础组件(Button/Input/Dialog) | shared/components/ui/ |
packages/ui-components/ |
全部平移,保持 PascalCase 命名 |
| A11y 组件 | shared/components/a11y/ |
packages/ui-components/a11y/ |
skip-link、visually-hidden、focus-trap、aria-status 全部平移 |
| 图表组件 | 各模块内 | packages/ui-components/charts/ |
收集 recharts 封装,统一暴露 |
| 表单组件 | react-hook-form 封装 | packages/ui-components/form/ |
与 zod resolver 一同平移 |
复用规则:
- 组件必须为纯函数,使用
function声明 - 不使用
React.FC,直接用函数声明 + 显式标注 props 类型 - 默认服务端组件(微前端 host),需要交互时才添加
"use client" - 组件行数 ≤ 500 行(复杂表单/大型表格可放宽至 800 行)
7.3 权限模型
复用方式:将 CICD 的 requirePermission() + usePermission().hasPermission() 模式平移至 identity 服务 + auth 基础设施服务。
| CICD 资产 | Edu 位置 | 调整 |
|---|---|---|
shared/lib/auth-guard.ts(requirePermission) |
services/auth/src/guards/permission.guard.ts(NestJS Guard) |
改为 NestJS Guard 装饰器 |
shared/types/permissions.ts(权限点常量) |
packages/contracts/src/permissions.ts |
集中到 contracts 包,多服务共享 |
usePermission Hook |
packages/ui-components/hooks/use-permission.ts |
通过 BFF 拉取权限,Hook 接口不变 |
| 角色权限矩阵(008) | docs/architecture/role_mapping.md |
直接平移 |
强制规则保持不变:
- 每个 Controller/Action 必须调用
requirePermission()等价物 - 前端组件禁止使用
role === "xxx"硬编码,统一使用usePermission().hasPermission()
7.4 缓存策略
复用方式:CICD 的 cacheFn(React cache() + 自定义缓存层)改为 NestJS Cache 模块 + Redis,权限数据不跨请求缓存的规则沿用。
| CICD 模式 | Edu 模式 | 备注 |
|---|---|---|
cacheFn(React cache) |
NestJS @UseInterceptors(CacheInterceptor) + Redis |
单请求内缓存改为 NestJS REQUEST scope |
unstable_cache |
禁用 | CICD 已禁用,Edu 沿用禁用决策 |
| 权限数据缓存 | 仅在 auth 服务内部缓存,TTL ≤ 60s | 跨服务不缓存权限 |
| 静态资源缓存 | CDN + 短缓存 | 配置不变 |
7.5 Server Action 模式 → Application Service 模式
复用方式:CICD 的 Server Action 编排模式(权限 + Zod 验证 + 调用 data-access + revalidate)平移为 NestJS Application Service 编排模式。
| CICD Server Action 步骤 | NestJS Application Service 对应 |
|---|---|
requirePermission(perm) |
@RequirePermission(perm) 装饰器 + Guard |
Zod safeParse |
ValidationPipe + DTO class-validator |
调用 data-access |
调用 Domain Service / Repository |
revalidatePath |
发布领域事件触发读模型更新 |
返回 ActionState<T> |
返回 protobuf message(结构同 ActionState) |
7.6 状态管理 5 层模型
复用方式:CICD 的 5 层状态模型平移至微前端 host 应用。
| 层级 | CICD 方案 | Edu 方案 | 备注 |
|---|---|---|---|
| L1 URL | nuqs | nuqs | 直接平移 |
| L2 Server | TanStack Query | TanStack Query | 直接平移 |
| L3 Client Business | Zustand slice | Zustand slice | 直接平移 |
| L4 Global UI | Zustand ui-store + ModalRoot | Zustand ui-store + ModalRoot | 直接平移 |
| L5 Form | react-hook-form + zodResolver | react-hook-form + zodResolver | 直接平移 |
7.7 A11y 工具集
复用方式:全部平移至 packages/ui-components/a11y/。
useA11yId:自动生成唯一 ARIA IDmergeA11yProps:合并 ARIA propsdescribeInput:关联 input 与描述loadingAria:加载状态 ARIA 属性useAriaLive:aria-live 区域管理 Hookskip-link、visually-hidden、focus-trap、aria-status组件
目标:WCAG 2.2 AA 合规,eslint-plugin-jsx-a11y 设为 error。
7.8 审计日志三件套
复用方式:平移至 notification 服务,日志结构保持。
| CICD 资产 | Edu 位置 | 备注 |
|---|---|---|
shared/lib/login-logger.ts |
services/notification/src/loggers/login-logger.ts |
登录尝试日志 |
shared/lib/change-logger.ts |
services/notification/src/loggers/change-logger.ts |
数据变更日志(监听领域事件) |
shared/lib/audit-logger.ts |
services/notification/src/loggers/audit-logger.ts |
关键业务操作日志 |
7.9 CI/CD 流水线模式
复用方式:三套工作流模式沿用(CI + 安全扫描 + 灾备演练),但执行方式改为多服务并行。
| CICD 工作流 | Edu 工作流 | 调整 |
|---|---|---|
ci.yml |
.gitea/workflows/ci.yml |
单体改为矩阵并行(每个服务一个 job) |
security.yml |
.gitea/workflows/security.yml |
新增 Trivy 扫描 Docker 镜像 |
dr-drill.yml |
.gitea/workflows/dr-drill.yml |
灾备演练改为多服务恢复顺序演练 |
CI 必须包含(沿用 CICD 规则):
- 安装依赖(多语言:pnpm install / go mod download / uv sync)
- Lint 检查(ESLint + golangci-lint + ruff)
- 类型检查(tsc --noEmit + go vet + mypy)
- 契约校验(buf lint + buf breaking)
- 单元测试 + 覆盖率
- 构建(多服务并行)
- 安全审计(npm audit + Snyk + Trivy)
- E2E 测试(仅主分支)
八、迁移验收标准
8.1 阶段验收清单
每个阶段完成时必须勾选所有项:
- 本阶段服务的 protobuf 契约已冻结并通过
buf breaking校验 - 服务 README 已编写,包含限界上下文图与依赖关系
docs/architecture/001_architecture_overview.md已同步更新docs/troubleshooting/known-issues.md已追加本阶段经验日志pnpm run arch:scan已扫描最新代码状态(含 TS+Go+Python)- 单元测试覆盖率 ≥ 80%
- tracing 覆盖率 ≥ 95%,关键指标已接入 Grafana
pnpm run lint与pnpm run typecheck零错误- 安全扫描无高危漏洞
8.2 整体迁移完成标准
- 6 阶段全部交付且验收通过
- CICD 35 个业务模块全部在对应微服务中找到归宿
- 旧系统流量完全切流至新系统(strangler fig 完成)
- RPO ≤ 15min,RTO ≤ 30min
- P99 延迟 ≤ 500ms
- 全链路追踪可用,任意请求可一键定位调用链
- 文档体系完整:架构图、契约、README、known-issues 全部同步
8.3 回滚预案
每个阶段均需准备回滚方案:
- P1 地基:基础设施回滚(Kafka/可观测平台降级)
- P2 身份:双写期间保留 CICD NextAuth 作为 fallback
- P3 核心教学:双写 + 读流量按比例切流,异常即回切
- P4 内容分析:CQRS 读模型失败时降级为直查 MySQL
- P5 沟通AI:AI 服务降级为兜底响应,不影响主流程
- P6 硬化:混沌演练发现问题后回滚至上一稳定版本
附录:迁移过程中的关键决策点
| 决策点 | 选择 | 理由 |
|---|---|---|
| 服务拆分粒度 | 6 业务 + 2 基础设施 | 平衡团队规模与拆分收益,避免过细导致 RPC 开销 |
| 通信协议 | gRPC(内部)+ REST(BFF 对外) | 内部高性能,外部兼容性 |
| 事件总线 | Kafka + Debezium CDC | CDC 减少业务代码侵入,Outbox 模式保证一致性 |
| 契约工具 | protobuf + buf | 多语言代码生成,breaking change 检测 |
| 前端架构 | Module Federation | 微前端独立部署,运行时共享依赖 |
| 状态管理 | 沿用 5 层模型 | 团队熟悉度高,迁移成本低 |
| 数据库拆分 | 每服务独占库 | 杜绝跨服务联表,强制契约化通信 |
| 缓存策略 | NestJS Cache + Redis | 替代 React cache(),规则(权限不跨请求缓存)沿用 |
| 迁移方式 | strangler fig | 风险可控,渐进式切换 |
| arch.db | 多语言扫描扩展 | 复用 CICD 元数据库思路,扩展 Go/Python 扫描器 |