chore: update book enabled status wiring
This commit is contained in:
@@ -2,53 +2,57 @@
|
||||
|
||||
## 适用范围
|
||||
|
||||
- 判断项目中的 `vo`、实体、接口入参、接口出参应该落在哪一层时,使用本文。
|
||||
- 新增或修改业务模块的 `model/<module>`、`model/<module>/request`、`model/<module>/response` 时,使用本文。
|
||||
- 判断某个 API 是直接复用实体,还是新增 `request/response` 结构时,使用本文。
|
||||
- 判断实体、API 入参、API 出参、`vo` 的落点时,使用本文。
|
||||
- 新增或修改 `model/<module>`、`model/<module>/request`、`model/<module>/response` 时,使用本文。
|
||||
|
||||
## 结论基线
|
||||
|
||||
- 本项目不单独维护顶层 `vo` 目录。
|
||||
- 项目里的数据载体统一归到 `model` 体系,不额外拆一套平行 `vo` 层。
|
||||
- 标准落点如下:
|
||||
- 不建顶层 `vo` 目录;所有数据载体统一归入 `model` 体系。
|
||||
- 实体只承载表结构和业务实体字段;禁止承载分页、筛选、排序、展示聚合字段。
|
||||
|
||||
| 场景 | 落点 | 说明 |
|
||||
| 类型 | 固定落点 | 用途 |
|
||||
|:---|:---|:---|
|
||||
| 数据库实体 / 业务实体 | `model/<module>` | 承载表结构映射、业务实体字段 |
|
||||
| API 入参 | `model/<module>/request` | 承载查询条件、分页条件、保存参数等 |
|
||||
| API 出参 | `model/<module>/response` | 承载详情包装、列表项包装、聚合展示结构等 |
|
||||
| 跨模块通用入参 | `model/common/request` | 例如 `PageInfo`、`GetById`、`IdsReq` |
|
||||
| 跨模块通用出参 | `model/common/response` | 例如统一响应壳、分页结果 |
|
||||
| 实体 | `model/<module>` | GORM 映射、业务实体 |
|
||||
| 入参 | `model/<module>/request` | 查询、分页、排序、保存、动作参数 |
|
||||
| 出参 | `model/<module>/response` | 详情包装、列表项、聚合字段、展示转换 |
|
||||
| 通用结构 | `model/common/request`、`model/common/response` | 跨模块稳定复用 |
|
||||
|
||||
## 判定规则
|
||||
|
||||
- 请求参数如果就是业务实体本身,且不会引入多余字段、敏感字段或语义歧义,可以直接复用 `model/<module>` 实体。
|
||||
- 请求参数如果只是“分页 + 条件筛选 + 排序”这类接口 contract,应定义到 `model/<module>/request`。
|
||||
- 返回结果如果只是直接返回实体本身,可以直接返回实体或列表,不强制为了“像 VO”再包一层空结构。
|
||||
- 返回结果如果需要额外包装、聚合字段、嵌套结构、展示字段转换,应定义到 `model/<module>/response`。
|
||||
- 多个 API 只要 contract 一致,可以共用同一个 `request` 或 `response` 结构;不是每个 API 都必须单独建一份。
|
||||
| 场景 | 结论 |
|
||||
|:---|:---|
|
||||
| 入参 = 可公开写入的实体字段,且无额外语义 | 可复用实体 |
|
||||
| 入参只开放部分字段,或需要屏蔽敏感/系统字段 | 必须使用 `request` |
|
||||
| 入参包含分页、筛选、排序、动作语义、组合参数 | 必须使用 `request` |
|
||||
| 返回实体原样或实体列表 | 可直接返回实体 |
|
||||
| 返回包含展示、聚合、联表、树、嵌套结构 | 必须使用 `response` |
|
||||
| 多个接口 contract 完全一致 | 复用同一个 `request/response` |
|
||||
| `admin/app` 字段、校验、分页、展示口径不同 | 按端拆分 `request/response` |
|
||||
|
||||
## 强制规则
|
||||
|
||||
- 新增业务模块时,实体统一放 `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` 是否仍一致。
|
||||
- 新增实体必须放 `model/<module>`;正式 API contract 必须放 `request` 或 `response`。
|
||||
- 禁止在 `API` 文件中长期维护正式 contract 的匿名结构体。
|
||||
- 新增 `request/response` 前,必须先检查同模块现有结构是否可复用。
|
||||
- `request/response` 只有字段、校验语义、返回语义明显不同,才允许新增。
|
||||
- 同一业务模块存在 `admin/app` 两套接口时,实体只保留一份;仅 `request/response` 按端拆分。
|
||||
- 改实体字段时,必须同步检查 `doc-sql`、`Service` 查询/写入、`API` 绑定/返回。
|
||||
- 改 `request/response` 或接口 contract 时,必须同步检查并更新 `doc-api`、`API`、`Service`。
|
||||
|
||||
## 推荐做法
|
||||
|
||||
- `Create`、`Update` 这类保存接口,如果直接面向实体字段,可优先复用实体。
|
||||
- `GetList`、搜索、筛选、排序接口,优先使用 `request` 结构,不要把分页筛选字段硬塞进实体。
|
||||
- `Find`、详情、聚合展示、树结构、联表结果等返回,优先使用 `response` 结构,不要把纯展示字段反向塞进数据库实体。
|
||||
- `response` 结构命名优先体现业务语义,例如 `BookDetailResponse`、`BookListItem`、`AuthorOption`;不要机械统一叫 `XxxVO`。
|
||||
| 对象 | 模板 | 示例 |
|
||||
|:---|:---|:---|
|
||||
| 列表查询入参 | `<StructName>Search` | `BookSearch` |
|
||||
| 动作入参 | `<Action><StructName>Req` | `ChangePasswordReq` |
|
||||
| 详情出参 | `<StructName>Response` | `BookResponse` |
|
||||
| 列表项出参 | `<StructName>ListItem` | `BookListItem` |
|
||||
| 选项出参 | `<StructName>Option` | `AuthorOption` |
|
||||
| 文件 | `model/<module>/<resource>.go`、`model/<module>/request/<resource>.go`、`model/<module>/response/<resource>.go` | `model/book/book.go` |
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 禁止单独新建顶层 `vo` 目录,与 `model` 并行维护两套数据结构体系。
|
||||
- 禁止为了“每个 API 都有专属 VO”而机械性给每个接口复制一份几乎相同的 `request/response`。
|
||||
- 禁止把分页、排序、筛选字段直接加进数据库实体,只为了省掉 `request` 结构。
|
||||
- 禁止把纯展示字段、聚合字段、临时返回字段长期塞进实体,只为了省掉 `response` 结构。
|
||||
- 禁止 `API`、`Service` 长期返回 `map[string]interface{}`、`gin.H` 充当正式业务出参,导致 contract 漂移。
|
||||
- 禁止新建顶层 `vo` 目录,与 `model` 并行维护数据结构。
|
||||
- 禁止为每个 API 机械复制字段几乎相同的 `request/response`。
|
||||
- 禁止把分页、排序、筛选、展示、聚合、临时返回字段塞进实体。
|
||||
- 禁止用 `map[string]interface{}`、`gin.H` 作为正式业务出参。
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
| 字段 | 类型 | 必填 | 规则 | 说明 |
|
||||
|:---|:---|:---:|:---|:---|
|
||||
| name | string | 是 | 非空,最大 `128` 字符,唯一 | 作者名称 |
|
||||
| authorStatus | string | 否 | `common_enabled_status`:`enabled`/`disabled`;默认 `enabled` | 作者启用状态 |
|
||||
| isEnabled | bool | 否 | 默认 `true` | 作者是否启用 |
|
||||
| intro | string | 否 | 可为空 | 作者简介 |
|
||||
| coverUrl | string | 否 | 可为空,最大 `500` 字符 | 作者头像或封面 URL |
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
- 创建请求禁止传服务端生成字段:`id/createdAt/updatedAt`。
|
||||
- `name` 必须唯一,对应唯一索引 `uk_book_author_name`。
|
||||
- `authorStatus` 为空时按数据库默认值 `enabled` 落库;传值时必须符合 `common_enabled_status`。
|
||||
- `isEnabled` 未传时按数据库默认值 `true` 落库。
|
||||
|
||||
### 删除书籍作者
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
|:---|:---|:---:|:---|:---|
|
||||
| id | uint | 是 | `> 0` | 作者 ID |
|
||||
| name | string | 是 | 非空,最大 `128` 字符,唯一 | 作者名称 |
|
||||
| authorStatus | string | 否 | `common_enabled_status`:`enabled`/`disabled` | 作者启用状态 |
|
||||
| isEnabled | bool | 否 | `true/false` | 作者是否启用 |
|
||||
| intro | string | 否 | 可为空 | 作者简介 |
|
||||
| coverUrl | string | 否 | 可为空,最大 `500` 字符 | 作者头像或封面 URL |
|
||||
|
||||
@@ -117,7 +117,6 @@
|
||||
- 更新请求禁止传服务端维护字段:`createdAt/updatedAt`。
|
||||
- 更新为实体全量保存,前端应传完整可编辑实体,避免字段被零值覆盖。
|
||||
- `name` 必须唯一,对应唯一索引 `uk_book_author_name`。
|
||||
- `authorStatus` 为空时会按空值保存;传值时必须符合 `common_enabled_status`。
|
||||
|
||||
### 查询书籍作者详情
|
||||
|
||||
@@ -142,7 +141,7 @@
|
||||
| bookAuthor.createdAt | time | 创建时间 |
|
||||
| bookAuthor.updatedAt | time | 更新时间 |
|
||||
| bookAuthor.name | string | 作者名称 |
|
||||
| bookAuthor.authorStatus | string | 作者启用状态,见 `common_enabled_status` |
|
||||
| bookAuthor.isEnabled | bool | 作者是否启用 |
|
||||
| bookAuthor.intro | string | 作者简介 |
|
||||
| bookAuthor.coverUrl | string | 作者头像或封面 URL |
|
||||
|
||||
@@ -162,7 +161,7 @@
|
||||
| pageSize | int | 否 | 默认 `10`,最大 `100` | 每页数量 |
|
||||
| keyword | string | 否 | 模糊匹配 `name` | 通用关键字 |
|
||||
| name | string | 否 | 模糊匹配 `name` | 作者名称 |
|
||||
| authorStatus | string | 否 | `common_enabled_status`:`enabled`/`disabled` | 作者启用状态 |
|
||||
| isEnabled | bool | 否 | `true/false` | 作者是否启用 |
|
||||
|
||||
#### Response `response.PageResult`
|
||||
|
||||
@@ -173,7 +172,7 @@
|
||||
| list[].createdAt | time | 创建时间 |
|
||||
| list[].updatedAt | time | 更新时间 |
|
||||
| list[].name | string | 作者名称 |
|
||||
| list[].authorStatus | string | 作者启用状态,见 `common_enabled_status` |
|
||||
| list[].isEnabled | bool | 作者是否启用 |
|
||||
| list[].intro | string | 作者简介 |
|
||||
| list[].coverUrl | string | 作者头像或封面 URL |
|
||||
| list[].authorName | string | 作者名称展示字段,来源于 `book_author.name AS author_name` |
|
||||
@@ -190,5 +189,5 @@
|
||||
|
||||
- admin 端书籍作者 CRUD 挂载到 `PrivateGroup`,需要 `JWT + Casbin`。
|
||||
- 写操作挂载 `middleware.OperationRecord()`;读操作不挂操作审计。
|
||||
- `authorStatus` 固定值域来自 `common_enabled_status`:`enabled`、`disabled`。
|
||||
- “是否启用”统一使用 `isEnabled` 布尔字段:`true` 表示启用,`false` 表示禁用。
|
||||
- 表结构、字段长度、唯一约束和索引以 `.ai-specs/doc-sql/book_author.sql` 为准。
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# 通用启用状态
|
||||
|
||||
- 模块:common
|
||||
- 字典编码:`common_enabled_status`
|
||||
- 字典类型:`固定值域字典`
|
||||
|
||||
| Label | Value | Sort | Status | Desc |
|
||||
|:---|:---|:---|:---|:---|
|
||||
| 启用 | `enabled` | 10 | true | 业务对象处于启用状态,可按对应业务规则正常使用 |
|
||||
| 禁用 | `disabled` | 20 | true | 业务对象处于禁用状态,不应再被新增业务关系使用 |
|
||||
@@ -7,7 +7,6 @@
|
||||
-- 模型:model/book/book_author.go
|
||||
-- 迁移接入:initialize/gorm_biz.go
|
||||
-- 删除策略:硬删表
|
||||
-- 启用状态字典:common_enabled_status
|
||||
-- 职责:承载书籍作者主体信息,用于作者资料展示、书籍作者关联和后台作者管理。
|
||||
|
||||
CREATE TABLE book_author (
|
||||
@@ -15,7 +14,7 @@ CREATE TABLE book_author (
|
||||
created_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
name varchar(128) NOT NULL,
|
||||
author_status varchar(32) NOT NULL DEFAULT 'enabled',
|
||||
is_enabled boolean NOT NULL DEFAULT true,
|
||||
intro text,
|
||||
cover_url varchar(500)
|
||||
);
|
||||
@@ -25,10 +24,10 @@ COMMENT ON COLUMN book_author.id IS '主键';
|
||||
COMMENT ON COLUMN book_author.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN book_author.updated_at IS '更新时间';
|
||||
COMMENT ON COLUMN book_author.name IS '作者名称';
|
||||
COMMENT ON COLUMN book_author.author_status IS '作者启用状态字典值,对应 common_enabled_status';
|
||||
COMMENT ON COLUMN book_author.is_enabled IS '作者是否启用';
|
||||
COMMENT ON COLUMN book_author.intro IS '作者简介';
|
||||
COMMENT ON COLUMN book_author.cover_url IS '作者封面图片 URL';
|
||||
|
||||
CREATE UNIQUE INDEX uk_book_author_name ON book_author (name);
|
||||
CREATE INDEX idx_book_author_author_status ON book_author (author_status);
|
||||
CREATE INDEX idx_book_author_is_enabled ON book_author (is_enabled);
|
||||
CREATE INDEX idx_book_author_created_at ON book_author (created_at);
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
### 书籍作者表
|
||||
- 名称:作者名称
|
||||
- 状态:字典 `common_enabled_status`
|
||||
- 是否启用:作者启停状态
|
||||
- 简介:作者简介
|
||||
- 封面图片URL:作者封面地址
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ CREATE INDEX idx_<table_name>_<field_2> ON <table_name> (<field_2>);
|
||||
- `硬删表` 按模板直接输出,不追加 `deleted_at`
|
||||
- 没有字典字段,就删除对应“字典”注释行
|
||||
- 没有唯一索引或普通索引,就删除对应 SQL 行
|
||||
- 如果字段默认值来自 `固定值域字典`,直接写字典项 `Value`,例如 `DEFAULT 'enabled'`
|
||||
- 如果字段默认值来自 `固定值域字典`,直接写字典项 `Value`,例如 `DEFAULT 'draft'`
|
||||
- 如果字段引用 `动态值域字典`,就删除默认值示例,按业务真实规则只保留结构约束和索引
|
||||
|
||||
## 复刻目标
|
||||
|
||||
Reference in New Issue
Block a user