docs: 目录布局改为扁平结构,与 chis_upload 对齐

按团队 AGENTS.md 的扁平偏好,弃用 internal/+cmd/,改为顶层平铺包 +
单 main.go(-mode server|deliver)。同步更新 docs/03 目录结构图与 §4.4、
docs/05 路线图措辞、CLAUDE.md 目录职责表。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ila
2026-05-30 13:10:18 +08:00
co-authored by Claude Opus 4.8
parent e1fe1a92e6
commit 6204da871e
3 changed files with 50 additions and 48 deletions
+10 -8
View File
@@ -24,7 +24,7 @@
把上游 PHIS(公卫系统)数据转换并投递到省基卫平台。 把上游 PHIS(公卫系统)数据转换并投递到省基卫平台。
- **当前阶段**:设计完成、待编码(脚手架尚未建立,见路线图阶段 0) - **当前阶段**:设计完成、待编码(脚手架尚未建立,见路线图阶段 0)
- **语言/运行**:Go 1.24,单二进制双子命令(`cmd/server` 同步 API、`cmd/deliver` 投递 worker) - **语言/运行**:Go 1.24,单二进制 + 子命令(`main.go -mode server|deliver`,沿用 chis_upload 风格)
- **团队定位**:默认由初级程序员维护,所有改动优先保证可读、可理解、可接手,避免过度抽象 - **团队定位**:默认由初级程序员维护,所有改动优先保证可读、可理解、可接手,避免过度抽象
- **核心链路**:PHIS(拉取)→ 字段映射 → MD5 签名 + 统一信封 → CHIS OSI(POST `/osi/api/...`)→ 状态回写 - **核心链路**:PHIS(拉取)→ 字段映射 → MD5 签名 + 统一信封 → CHIS OSI(POST `/osi/api/...`)→ 状态回写
@@ -41,15 +41,17 @@ OSI 是**无状态服务端接口**,鉴权 = 请求头 MD5 签名(`password=
> 以下为**目标**结构(见 `docs/03-目标架构设计.md` 第 3 节),多数目录尚未创建,按路线图阶段逐步建立。 > 以下为**目标**结构(见 `docs/03-目标架构设计.md` 第 3 节),多数目录尚未创建,按路线图阶段逐步建立。
> 采用**扁平布局**(顶层平铺包,不用 `internal/`/`cmd/`),与 `chis_upload` 同款形状。
| 目录 | 说明 | | 目录 | 说明 |
|------|------| |------|------|
| `cmd/server/` `cmd/deliver/` | 双入口:同步投递 API / 定时投递 worker | | `main.go` | 单入口:`-mode server\|deliver`(同步投递 API / 定时投递 worker) |
| `internal/osi/` | ★ 薄客户端:签名、传输、`Call`、各业务域调用方法 | | `osi/` | ★ 薄客户端:签名、传输、`Call`、各业务域调用方法 |
| `internal/contract/` | ★ 校验后的接口契约(结构体 + serviceId 常量),docx 坑点的唯一修正点 | | `contract/` | ★ 校验后的接口契约(结构体 + serviceId 常量),docx 坑点的唯一修正点 |
| `internal/mapping/` | ★ PHIS→OSI 字段/字典映射 + checkId 生成(本项目核心) | | `mapping/` | ★ PHIS→OSI 字段/字典映射 + checkId 生成(本项目核心) |
| `internal/source/phis/` | PHIS 拉取客户端 + 任务模型 + 状态回写 | | `source/` | PHIS 拉取客户端 + 任务模型 + 状态回写 |
| `internal/pipeline/` | 投递编排:校验→映射→调用→分类重试→幂等→熔断→报告 | | `pipeline/` | 投递编排:校验→映射→调用→分类重试→幂等→熔断→报告 |
| `internal/observ/` `internal/store/` | report log(redis 优先、文件降级)/ redis(可选)+文件存储 | | `observ/` `store/` | report log(redis 优先、文件降级)/ redis(可选)+文件存储 |
| `handler/` `router/` | server 模式对外 HTTP 接口与路由 | | `handler/` `router/` | server 模式对外 HTTP 接口与路由 |
| `config/` | viper 读取配置(osi / phis / redis / proxy) | | `config/` | viper 读取配置(osi / phis / redis / proxy) |
| `docs/` | 所有设计文档,与代码同等重要 | | `docs/` | 所有设计文档,与代码同等重要 |
+37 -37
View File
@@ -39,48 +39,48 @@
## 3. 目录结构 ## 3. 目录结构
采用**扁平布局**(顶层平铺包、单 `main.go` + `-mode` 子命令),与参考项目 `chis_upload` 保持同款形状,降低团队接手成本。
与 `chis_upload` 的差别只在"内容"——无 `chis/`(逆向)、无 `middleware/`(cookie)、无 SM2,新增 `osi/`/`mapping/`/`pipeline/`。
``` ```
chis_osi/ chis_osi/
├── cmd/ ├── main.go 入口:-mode server|deliver(沿用 chis_upload 的单入口 + flag 风格)
│ ├── server/ main:HTTP 服务入口 ├── config/ viper 配置(osi/phis/redis/proxy)
│ └── deliver/ main:投递 worker 入口 ├── osi/ ★ 薄客户端:与平台的全部交互
├── config/ viper 配置(osi/phis/redis/log/proxy) │ ├── sign.go MD5 签名(ts + password)
├── internal/ │ ├── transport.go HTTP 发送、超时、SOCKS5
│ ├── osi/ ★ 薄客户端:与平台的全部交互 │ ├── client.go Call(ctx, serviceId, body, &out):注入头+信封+发送+判码
│ │ ├── sign.go MD5 签名(ts + password) │ ├── codes.go 返回码常量与成功/可重试判定
│ │ ├── transport.go HTTP 发送、超时、SOCKS5 │ ├── jkda.go 档案:Create/Update/Find/FindRqbj
│ │ ├── client.go Call(ctx, serviceId, body, &out):注入头+信封+发送+判码 │ ├── jktj.go 体检:Create/Update/Query/List/Last
│ │ ├── codes.go 返回码常量与成功/可重试判定 │ ├── lnr.go 老年人:自理评估、中医体质辨识
│ │ ├── jkda.go 档案:Create/Update/Find/FindRqbj │ ├── zyjkzd.go 中医健康指导
│ │ ├── jktj.go 体检:Create/Update/Query/List/Last │ └── public.go 网格/责任医生/药品/机构 字典查询
│ │ ├── lnr.go 老年人:自理评估、中医体质辨识 ├── contract/ ★ 校验后的接口契约(请求/响应结构体 + serviceId 常量)
│ │ ├── zyjkzd.go 中医健康指导 │ ├── envelope.go 通用信封:{serviceId, uploadinfo|baseInfo, manageInfo}
│ │ └── public.go 网格/责任医生/药品/机构 字典查询 │ └── jkda.go / jktj.go / lnr.go / ...
│ ├── contract/ ★ 校验后的接口契约(请求/响应结构体 + serviceId 常量) ├── mapping/ ★ PHIS→OSI 映射(本项目核心)
│ │ ├── envelope.go 通用信封:{serviceId, uploadinfo|baseInfo, manageInfo} │ ├── dict.go 码表:性别/民族/血型/职业/文化程度/婚姻/医保...(双向)
│ │ ├── jkda.go / jktj.go / lnr.go / ... │ ├── health_record.go 档案字段映射 + 校验
│ ├── mapping/ ★ PHIS→OSI 映射(本项目核心) │ ├── health_check.go 体检字段映射
│ │ ├── dict.go 码表:性别/民族/血型/职业/文化程度/婚姻/医保...(双向) │ ├── elderly.go 老年人映射
│ │ ├── health_record.go 档案字段映射 + 校验 │ └── checkid.go checkId 生成(确定性,幂等键来源)
│ │ ├── health_check.go 体检字段映射 ├── source/ PHIS 拉取客户端 + 任务模型 + 状态回写
│ │ ├── elderly.go 老年人映射 ├── pipeline/ 投递编排:校验→映射→调用→分类→重试→幂等→报告
│ │ └── checkid.go checkId 生成(确定性,幂等键来源) │ ├── deliver.go 单条投递
│ ├── source/phis/ PHIS 拉取客户端 + 任务模型 + 状态回写 │ ├── retry.go 重试与错误分类
│ ├── pipeline/ 投递编排:校验→映射→调用→分类→重试→幂等→报告 │ ├── idempotency.go 基于 checkId 的去重存储(redis|file)
│ │ ├── deliver.go 单条投递 │ ├── circuit.go 熔断
│ │ ├── retry.go 重试与错误分类 │ └── report.go 批次报告
│ │ ├── idempotency.go 基于 checkId 的去重存储(redis|file) ├── observ/ report log(redis 优先,文件降级)+ 快照 + trace
│ │ ├── circuit.go 熔断 ├── store/ redis 客户端封装(可选)+ 文件存储
│ │ └── report.go 批次报告
│ ├── observ/ report log(redis 优先,文件降级)+ 快照 + trace
│ └── store/ redis 客户端封装(可选)+ 文件存储
├── handler/ HTTP handlers(server 模式对外接口) ├── handler/ HTTP handlers(server 模式对外接口)
├── router/ 路由 ├── router/ 路由
├── docs/ ├── docs/
└── AGENTS.md 沿用旧项目协作规范 └── AGENTS.md / CLAUDE.md 协作规范
``` ```
> `internal/` 用于约束包边界,避免被外部误用;若团队更习惯扁平结构,可去掉 `internal/` 层级,保持包名不变。 > 不使用 `internal/` 与 `cmd/`:团队 `AGENTS.md` 偏好扁平、避免过度抽象,且 `chis_upload` 已是单 `main.go`+`-mode` 形态,保持一致优先于"标准 Go 布局"。
--- ---
@@ -142,7 +142,7 @@ type ManageInfo struct { DSFMC, OperateUnit, OperateUser string }
> 完整度(completeLevel/perfection):默认**不本地计算**,按文档字段如实上送,依赖平台计算。 > 完整度(completeLevel/perfection):默认**不本地计算**,按文档字段如实上送,依赖平台计算。
> 若联调发现平台要求接入方计算,再把旧项目 `health_record_complete_level.go`/`health_check_perfection.go` 移植进 `mapping/`(开放问题,见第 8 节)。 > 若联调发现平台要求接入方计算,再把旧项目 `health_record_complete_level.go`/`health_check_perfection.go` 移植进 `mapping/`(开放问题,见第 8 节)。
### 4.4 `source/phis` —— 任务源 ### 4.4 `source` —— 任务源
- 拉取待上送明细(替代旧项目的本地 mock 文件)。 - 拉取待上送明细(替代旧项目的本地 mock 文件)。
- 任务模型:`{taskId, dataType, payload(PHIS原始), ...}`。 - 任务模型:`{taskId, dataType, payload(PHIS原始), ...}`。
@@ -177,7 +177,7 @@ type ManageInfo struct { DSFMC, OperateUnit, OperateUser string }
## 5. 关键时序:一条体检记录的投递 ## 5. 关键时序:一条体检记录的投递
``` ```
deliver-worker source/phis mapping osi.Client CHIS OSI deliver-worker source mapping osi.Client CHIS OSI
│ 拉取任务 │ │ │ │ │ 拉取任务 │ │ │ │
│ ───────────────────▶│ │ │ │ │ ───────────────────▶│ │ │ │
│ ◀─ task(原始体检) │ │ │ │ │ ◀─ task(原始体检) │ │ │ │
+3 -3
View File
@@ -6,7 +6,7 @@
## 阶段 0 · 脚手架与契约骨架 ## 阶段 0 · 脚手架与契约骨架
- [ ] 初始化 Go module、`cmd/server`、`cmd/deliver` 双入口、`config/`(viper)。 - [ ] 初始化 Go module、单 `main.go`(`-mode server|deliver`)、`config/`(viper)。
- [ ] 落地 `osi/sign.go`(MD5 签名)+ 单测:用文档约定的 `ts/ask` 校验 `password` 形态(32 位小写)。 - [ ] 落地 `osi/sign.go`(MD5 签名)+ 单测:用文档约定的 `ts/ask` 校验 `password` 形态(32 位小写)。
- [ ] 移植旧项目 `transport.go`/`http_client.go` → `osi/transport.go`(保留 SOCKS5/超时,去 cookiejar 与拟态头)。 - [ ] 移植旧项目 `transport.go`/`http_client.go` → `osi/transport.go`(保留 SOCKS5/超时,去 cookiejar 与拟态头)。
- [ ] `osi/client.go` 的 `Call(serviceId, body, out)`:注入头+信封+发送+判码(`code=="1"`/`405`)。 - [ ] `osi/client.go` 的 `Call(serviceId, body, out)`:注入头+信封+发送+判码(`code=="1"`/`405`)。
@@ -32,7 +32,7 @@
- [ ] `pipeline`:`deliver.go`/`retry.go`/`idempotency.go`(checkId)/`circuit.go`/`report.go`。 - [ ] `pipeline`:`deliver.go`/`retry.go`/`idempotency.go`(checkId)/`circuit.go`/`report.go`。
- [ ] `observ`:一套 report log(redis 优先、文件降级)+ 快照 + trace。 - [ ] `observ`:一套 report log(redis 优先、文件降级)+ 快照 + trace。
- [ ] `cmd/deliver`:定时驱动(先用本地任务文件 mock,对齐旧项目可跑形态)。 - [ ] `main.go -mode deliver`:定时驱动(先用本地任务文件 mock,对齐旧项目可跑形态)。
- **验收**:批量任务跑完出批次报告(total/success/failed/skipped/retry + 失败 Top);网络不可达触发熔断且行为符合预期。 - **验收**:批量任务跑完出批次报告(total/success/failed/skipped/retry + 失败 Top);网络不可达触发熔断且行为符合预期。
## 阶段 4 · 其余业务线 ## 阶段 4 · 其余业务线
@@ -43,7 +43,7 @@
## 阶段 5 · PHIS 真实接入与状态回写 ## 阶段 5 · PHIS 真实接入与状态回写
- [ ] `source/phis`:真实拉取接口替换 mock;任务模型对齐。 - [ ] `source`:真实拉取接口替换 mock;任务模型对齐。
- [ ] 投递结果回写 PHIS(done/retry/failed),trace_id 用 PHIS 任务号贯穿。 - [ ] 投递结果回写 PHIS(done/retry/failed),trace_id 用 PHIS 任务号贯穿。
- **验收**:PHIS→chis_osi→CHIS 全链路自动跑通,状态可回查。 - **验收**:PHIS→chis_osi→CHIS 全链路自动跑通,状态可回查。