gwy-exam/deliverables/architecture/架构交付说明.md
2026-08-26 16:20:55 +08:00

89 lines
4.5 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.

# 备考中枢 · 架构交付说明(垂直切片最终形态)
> 汇编:项目总监 大湾区靓仔 · 2026-08-26
> 产出:首席架构师 高见远
> 版本v2.0(垂直切片最终形态)· 已通过门禁核验
> 门禁结论:无 emoji / 无 any 类型声明 / 无"原来→改为"对照措辞 / 目录为最终形态
---
## 一、这套架构长什么样
采用**垂直切片Vertical Slice**组织方式,而非按层堆放大目录。一个资源被"纵向切透"——从 HTTP 入口到数据落盘端到端归属一个切片,切片内按职责分 **3 层**,层与层之间依赖只向下。
### 3 层结构
| 层 | 职责 | 落地位置 |
|----|------|----------|
| **Handler 层** | 路由注册 + zod 请求校验 + 调 service + 组装 `ApiResponse<T>` | `routes/*.routes.ts`(校验/编排/响应全在一个文件) |
| **Service 层** | 跨实体业务:抽题 / 判定 / 错题入本 / 增量聚合 / 备份还原 | `services/*.service.ts`(不碰 req/res |
| **数据访问 + 领域类型层** | 读 JSON(zod 校验) + 原子写 + 写队列 + 领域类型 | `data/store.ts` + `packages/shared/schemas` |
> 领域类型不手写 interface由 `packages/shared/src/schemas/*.schema.ts` 的 zod schema 经 `z.infer` 产出,前后端共用。
---
## 二、为什么改一个接口不再"跳来跳去"
一个资源 = **一个 route 文件(内含 handler+ 一个 service 文件**。跨切片的实体业务(如答错同时写 answer-record、wrong-question 并增量更新统计)统一交给 service 层承载——这正是 service 层在该架构中不可替代的价值。
**改一个典型接口的落点**
| 改动 | 落点 | 数量 |
|------|------|:---:|
| 改某个字段 / 新增字段 | 改 `shared/schemas/*.schema.ts` 的 zod schema + 对应 `route` handler | **~2 处** |
| 改一段业务逻辑 | 对应 `service` 文件 | **1 处** |
| 类型 / OpenAPI 契约 / 请求校验 | 由 zod schema 自动跟随(`z.infer` 产类型、`zod-openapi` 反推契约) | **0 处(自动)** |
**单一契约源**是这套架构的灵魂:同一份 zod schema 同时驱动三处——请求运行时校验、TS 类型(`z.infer`、OpenAPI 契约(`zod-openapi` 自动反推),三者永不失同步,杜绝手写契约导致的漂移。
---
## 三、关键工程化要点
| 项 | 说明 |
|----|------|
| **单一契约源** | zod schema 唯一来源 → `z.infer` 产类型 + `zod-openapi` 自动反推 OpenAPI 契约 + 同一 schema 做请求校验,三者同步 |
| **无 any** | tsconfig strict 全家桶noImplicitAny / strictNullChecks / exactOptionalPropertyTypes / noUncheckedIndexedAccess / useUnknownInCatchVariables+ `ApiResponse<T>` 泛型 + catch 用 unknown 窄化 + zod 收窄 |
| **JSON 数据层三重防护** | zod 运行时校验(文件是不可信输入)+ 临时文件 rename 原子替换 + 写队列串行,保证数据资产永不损坏 |
| **数据资产** | `APP_DATA_DIR` 可配置 + Docker volume 挂载 + 导出 JSON/CSV / 备份 / 还原接口(还原前自动备份,坏备份不覆盖好数据) |
| **AI 扩展位** | 二期 P1 前置但本期零实现:`services/ai/` 占位 + `providers/` 接口 + `aiEnabled` 恒 false |
---
## 四、8 个领域实体
`Question / AnswerRecord / WrongQuestion / MockExam / ShenLunEssay / StudyTask / StatsSnapshot / AppSettings`,全部由 `packages/shared/src/schemas/*.schema.ts` 的 zod schema 经 `z.infer` 产出具名类型。
---
## 五、版本锚定
| 技术 | 版本锚定 |
|------|----------|
| Node.js | 24.xLTS |
| Express | 5.2.x |
| Vue | 3.5.x / Vite 6.x |
| TypeScript | 5.8.x |
| zod | 4.x若落 3.xzod-to-openapi 须降级 v7.3.4 |
| @asteasolutions/zod-to-openapi | 8.x |
> Phase 2 安装后需把 `package.json`/`pnpm-lock.yaml` 精确版本回写锚定表,使规格与实现同步。
---
## 六、交付物清单(全部在 `deliverables/architecture/`
| 文件 | 说明 |
|------|------|
| `architecture.md` | 核心架构文档v2.0,垂直切片最终形态) |
| `openapi.yaml` | OpenAPI 契约(标注由 zod-openapi 自动反推生成,勿手改) |
| `params.md` | 技术约束清单 + 8 实体 scha + 枚举 + 错误码 |
| `decisions/ADR-001~006` | 6 份架构决策记录(新增 ADR-006 垂直切片 + 单一契约源) |
---
## 七、下一步
架构已确定为垂直切片最终形态,随时可进入 **Phase 1.5 Spec 生成** 或直接进入 **Phase 2 设计细化 + 开发**。确认后我将推进。