# Model / Request / Response 组织规范

## 适用范围

- 判断项目中的 `vo`、实体、接口入参、接口出参应该落在哪一层时，使用本文。
- 新增或修改业务模块的 `model/<module>`、`model/<module>/request`、`model/<module>/response` 时，使用本文。
- 判断某个 API 是直接复用实体，还是新增 `request/response` 结构时，使用本文。

## 结论基线

- 本项目不单独维护顶层 `vo` 目录。
- 项目里的数据载体统一归到 `model` 体系，不额外拆一套平行 `vo` 层。
- 标准落点如下：

| 场景 | 落点 | 说明 |
|:---|:---|:---|
| 数据库实体 / 业务实体 | `model/<module>` | 承载表结构映射、业务实体字段 |
| API 入参 | `model/<module>/request` | 承载查询条件、分页条件、保存参数等 |
| API 出参 | `model/<module>/response` | 承载详情包装、列表项包装、聚合展示结构等 |
| 跨模块通用入参 | `model/common/request` | 例如 `PageInfo`、`GetById`、`IdsReq` |
| 跨模块通用出参 | `model/common/response` | 例如统一响应壳、分页结果 |

## 判定规则

- 请求参数如果就是业务实体本身，且不会引入多余字段、敏感字段或语义歧义，可以直接复用 `model/<module>` 实体。
- 请求参数如果只是“分页 + 条件筛选 + 排序”这类接口 contract，应定义到 `model/<module>/request`。
- 返回结果如果只是直接返回实体本身，可以直接返回实体或列表，不强制为了“像 VO”再包一层空结构。
- 返回结果如果需要额外包装、聚合字段、嵌套结构、展示字段转换，应定义到 `model/<module>/response`。
- 多个 API 只要 contract 一致，可以共用同一个 `request` 或 `response` 结构；不是每个 API 都必须单独建一份。

## 强制规则

- 新增业务模块时，实体统一放 `model/<module>`；禁止把实体落到 `api`、`service`、`router`。
- `API` 层入参、出参需要独立结构时，统一放 `model/<module>/request`、`model/<module>/response`；禁止在 `API` 文件里长期维护临时匿名结构体当正式 contract。
- 跨模块都能稳定复用的分页、主键、统一响应、分页结果等结构，统一复用 `model/common/request`、`model/common/response`；不要每个模块各复制一份。
- 同一业务模块如果同时存在 `admin/app` 两套接口，实体仍统一放 `model/<module>`；只有 `request/response` 按 `admin` / `app` 分文件区分。
- 新增 `request/response` 前，先检查同模块现有结构是否可复用；只有接口字段、校验语义、返回语义明显不同，才新增结构。
- 改实体字段时，必须同步检查 `service` 查询/写入、`API` 绑定/返回、`doc-sql` 是否仍一致。
- 改 `request/response` 时，必须同步检查 `API` 绑定、`Service` 方法签名、`doc-api` 是否仍一致。

## 推荐做法

- `Create`、`Update` 这类保存接口，如果直接面向实体字段，可优先复用实体。
- `GetList`、搜索、筛选、排序接口，优先使用 `request` 结构，不要把分页筛选字段硬塞进实体。
- `Find`、详情、聚合展示、树结构、联表结果等返回，优先使用 `response` 结构，不要把纯展示字段反向塞进数据库实体。
- `response` 结构命名优先体现业务语义，例如 `BookDetailResponse`、`BookListItem`、`AuthorOption`；不要机械统一叫 `XxxVO`。

## 禁止事项

- 禁止单独新建顶层 `vo` 目录，与 `model` 并行维护两套数据结构体系。
- 禁止为了“每个 API 都有专属 VO”而机械性给每个接口复制一份几乎相同的 `request/response`。
- 禁止把分页、排序、筛选字段直接加进数据库实体，只为了省掉 `request` 结构。
- 禁止把纯展示字段、聚合字段、临时返回字段长期塞进实体，只为了省掉 `response` 结构。
- 禁止 `API`、`Service` 长期返回 `map[string]interface{}`、`gin.H` 充当正式业务出参，导致 contract 漂移。
