From 4abbf558e461e424467e9e9a835c9a3a6b0807d6 Mon Sep 17 00:00:00 2001 From: huang Date: Tue, 20 Jan 2026 15:10:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=20DTO=20=E8=A7=84=E8=8C=83?= =?UTF-8?q?=EF=BC=9A=E7=BB=9F=E4=B8=80=20description=20=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E5=B9=B6=E6=B7=BB=E5=8A=A0=20AI=20=E5=8A=A9=E6=89=8B=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=A3=80=E6=9F=A5=E6=8C=87=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复所有 DTO 文件的 description 标签(10 个文件) - 枚举字段统一使用中文说明(用户类型、角色类型、权限类型等) - 状态字段明确说明 0/1 含义 - validate 标签与 OpenAPI 标签保持一致 - 在 AGENTS.md 和 CLAUDE.md 添加 DTO 规范章节 - AI 助手必须执行的 7 项检查清单 - 常见枚举字段标准值参考 - 确保未来 AI 助手自动遵循规范 - 创建规范文档 - docs/code-review-checklist.md(Code Review 检查清单) - docs/dto-improvement-summary.md(DTO 改进总结) - docs/ai-dto-guidelines-update.md(AI 指引更新说明) - 重新生成 OpenAPI 文档(375 个 description 标签) 影响:所有 API 字段现在都有清晰的中文说明,前端开发更友好 --- .gitignore | 4 +- AGENTS.md | 138 +++++++ CLAUDE.md | 40 ++ docs/admin-openapi.yaml | 61 +-- docs/ai-dto-guidelines-update.md | 265 ++++++++++++ docs/api/auth.md | 511 ++++++++++++++++++++++++ docs/code-review-checklist.md | 326 +++++++++++++++ docs/dto-improvement-summary.md | 215 ++++++++++ internal/model/account_dto.go | 12 +- internal/model/account_role_dto.go | 14 +- internal/model/auth_dto.go | 18 +- internal/model/enterprise_dto.go | 72 ++-- internal/model/permission_dto.go | 20 +- internal/model/personal_customer_dto.go | 34 +- internal/model/role_dto.go | 6 +- internal/model/role_permission_dto.go | 14 +- internal/model/shop_account_dto.go | 18 +- internal/model/shop_dto.go | 82 ++-- 18 files changed, 1677 insertions(+), 173 deletions(-) create mode 100644 docs/ai-dto-guidelines-update.md create mode 100644 docs/api/auth.md create mode 100644 docs/code-review-checklist.md create mode 100644 docs/dto-improvement-summary.md diff --git a/.gitignore b/.gitignore index 00fdd15..6f8137a 100644 --- a/.gitignore +++ b/.gitignore @@ -69,7 +69,7 @@ build/ .claude/settings.local.json cmd/api/api 2026-01-09-local-command-caveatcaveat-the-messages-below-w.txt -api .gitignore -worker ai-gateway.conf +__debug_bin1621385388 +docs/admin-openapi.yaml diff --git a/AGENTS.md b/AGENTS.md index 1d7d8a6..2d2a5f3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -93,6 +93,144 @@ Handler → Service → Store → Model - 接口命名: 使用 `-er` 后缀(Reader、Writer、Logger) - 缩写词: 全大写或全小写(URL、ID、HTTP 或 url、id、http) +## DTO 规范(重要!) + +**所有 DTO 文件必须遵循以下规范,这是 API 文档生成的基础。** + +### 必须项(MUST) + +#### 1. Description 标签规范 + +**所有字段必须使用 `description` 标签,禁止使用行内注释** + +❌ **错误**: +```go +type CreateUserRequest struct { + Username string `json:"username"` // 用户名 + Status int `json:"status"` // 状态 +} +``` + +✅ **正确**: +```go +type CreateUserRequest struct { + Username string `json:"username" description:"用户名"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` +} +``` + +#### 2. 枚举字段必须列出所有可能值(中文) + +**所有枚举类型字段必须在 `description` 中列出所有可能值和对应的中文含义** + +```go +// 用户类型 +UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + +// 角色类型 +RoleType int `json:"role_type" description:"角色类型 (1:平台角色, 2:客户角色)"` + +// 权限类型 +PermType int `json:"perm_type" description:"权限类型 (1:菜单, 2:按钮)"` + +// 状态字段 +Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + +// 适用端口 +Platform string `json:"platform" description:"适用端口 (all:全部, web:Web后台, h5:H5端)"` +``` + +❌ **禁止使用英文枚举值**: +```go +UserType int `json:"user_type" description:"用户类型 (1:SuperAdmin, 2:Platform)"` // 错误! +``` + +#### 3. 验证标签与 OpenAPI 标签一致 + +**所有验证约束必须同时在 `validate` 和 OpenAPI 标签中声明** + +```go +Username string `json:"username" validate:"required,min=3,max=50" required:"true" minLength:"3" maxLength:"50" description:"用户名"` +``` + +**标签对照表**: + +| validate 标签 | OpenAPI 标签 | 说明 | +|--------------|--------------|------| +| `required` | `required:"true"` | 必填字段 | +| `min=N,max=M` | `minimum:"N" maximum:"M"` | 数值范围 | +| `min=N,max=M` (字符串) | `minLength:"N" maxLength:"M"` | 字符串长度 | +| `len=N` | `minLength:"N" maxLength:"N"` | 固定长度 | +| `oneof=A B C` | `description` 中说明 | 枚举值 | + +#### 4. 请求参数类型标签 + +**Query 参数和 Path 参数必须添加对应标签** + +```go +// Query 参数 +type ListRequest struct { + Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码"` + UserType *int `json:"user_type" query:"user_type" validate:"omitempty,min=1,max=4" minimum:"1" maximum:"4" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` +} + +// Path 参数 +type IDReq struct { + ID uint `path:"id" description:"ID" required:"true"` +} +``` + +#### 5. 响应 DTO 完整性 + +**所有响应 DTO 的字段都必须有完整的 `description` 标签** + +```go +type AccountResponse struct { + ID uint `json:"id" description:"账号ID"` + Username string `json:"username" description:"用户名"` + UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + CreatedAt string `json:"created_at" description:"创建时间"` + UpdatedAt string `json:"updated_at" description:"更新时间"` +} +``` + +### AI 助手必须执行的检查 + +**在创建或修改任何 DTO 文件后,必须执行以下检查:** + +1. ✅ 检查所有字段是否有 `description` 标签 +2. ✅ 检查枚举字段是否列出了所有可能值(中文) +3. ✅ 检查状态字段是否说明了 0 和 1 的含义 +4. ✅ 检查 validate 标签与 OpenAPI 标签是否一致 +5. ✅ 检查是否禁止使用行内注释替代 description +6. ✅ 检查枚举值是否使用中文而非英文 +7. ✅ 重新生成 OpenAPI 文档验证:`go run cmd/gendocs/main.go` + +**详细检查清单**: 参见 `docs/code-review-checklist.md` + +### 常见枚举字段标准值 + +```go +// 用户类型 +description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)" + +// 角色类型 +description:"角色类型 (1:平台角色, 2:客户角色)" + +// 权限类型 +description:"权限类型 (1:菜单, 2:按钮)" + +// 适用端口 +description:"适用端口 (all:全部, web:Web后台, h5:H5端)" + +// 状态 +description:"状态 (0:禁用, 1:启用)" + +// 店铺层级 +description:"店铺层级 (1-7级)" +``` + ## Model 模型规范 **必须遵守的模型结构:** diff --git a/CLAUDE.md b/CLAUDE.md index e27d2d1..8435813 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -96,6 +96,46 @@ tests/ - Go 文档注释(doc comments for exported APIs)可以使用英文以保持生态兼容性,但中文注释更佳 - 变量名、函数名、类型名必须使用英文(遵循 Go 命名规范) +**DTO 规范(API 文档生成基础):** + +所有 DTO 文件必须严格遵循以下规范,这是 OpenAPI 文档自动生成的基础: + +1. **所有字段必须使用 `description` 标签**(禁止使用行内注释) + ```go + // ✅ 正确 + Username string `json:"username" description:"用户名"` + + // ❌ 错误 + Username string `json:"username"` // 用户名 + ``` + +2. **枚举字段必须列出所有可能值(使用中文)** + ```go + UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + ``` + +3. **validate 标签必须与 OpenAPI 标签一致** + ```go + Username string `json:"username" validate:"required,min=3,max=50" required:"true" minLength:"3" maxLength:"50" description:"用户名"` + ``` + +4. **Query 和 Path 参数必须添加对应标签** + ```go + Page int `json:"page" query:"page" description:"页码"` + ID uint `path:"id" description:"ID" required:"true"` + ``` + +5. **AI 助手在创建/修改 DTO 后必须执行以下检查**: + - ✅ 所有字段都有 `description` 标签 + - ✅ 枚举字段列出了所有可能值(中文) + - ✅ 状态字段说明了 0 和 1 的含义 + - ✅ validate 标签与 OpenAPI 标签一致 + - ✅ 禁止使用英文枚举值 + - ✅ 重新生成文档验证:`go run cmd/gendocs/main.go` + +详细规范参见:`docs/code-review-checklist.md` + **Go 代码风格要求:** - 必须使用 `gofmt` 格式化所有代码 diff --git a/docs/admin-openapi.yaml b/docs/admin-openapi.yaml index eea5b3b..09d2246 100644 --- a/docs/admin-openapi.yaml +++ b/docs/admin-openapi.yaml @@ -62,7 +62,7 @@ components: nullable: true type: integer status: - description: 状态 + description: 状态 (0:禁用, 1:启用) type: integer updated_at: description: 更新时间 @@ -72,7 +72,7 @@ components: minimum: 0 type: integer user_type: - description: 用户类型 + description: 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号) type: integer username: description: 用户名 @@ -131,7 +131,7 @@ components: nullable: true type: integer user_type: - description: 用户类型 (1:SuperAdmin, 2:Platform, 3:Agent, 4:Enterprise) + description: 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号) maximum: 4 minimum: 1 type: integer @@ -279,7 +279,7 @@ components: ModelPermissionResponse: properties: available_for_role_types: - description: 可用角色类型 + description: 可用角色类型 (1:平台角色, 2:客户角色) type: string created_at: description: 创建时间 @@ -304,16 +304,16 @@ components: description: 权限名称 type: string perm_type: - description: 权限类型 + description: 权限类型 (1:菜单, 2:按钮) type: integer platform: - description: 适用端口 + description: 适用端口 (all:全部, web:Web后台, h5:H5端) type: string sort: description: 排序值 type: integer status: - description: 状态 + description: 状态 (0:禁用, 1:启用) type: integer updated_at: description: 更新时间 @@ -329,7 +329,7 @@ components: ModelPermissionTreeNode: properties: available_for_role_types: - description: 可用角色类型 + description: 可用角色类型 (1:平台角色, 2:客户角色) type: string children: description: 子权限列表 @@ -347,10 +347,10 @@ components: description: 权限名称 type: string perm_type: - description: 权限类型 + description: 权限类型 (1:菜单, 2:按钮) type: integer platform: - description: 适用端口 + description: 适用端口 (all:全部, web:Web后台, h5:H5端) type: string sort: description: 排序值 @@ -426,10 +426,10 @@ components: description: 角色名称 type: string role_type: - description: 角色类型 + description: 角色类型 (1:平台角色, 2:客户角色) type: integer status: - description: 状态 + description: 状态 (0:禁用, 1:启用) type: integer updated_at: description: 更新时间 @@ -559,25 +559,34 @@ components: ModelUserInfo: properties: enterprise_id: + description: 企业ID minimum: 0 type: integer enterprise_name: + description: 企业名称 type: string id: + description: 用户ID minimum: 0 type: integer phone: + description: 手机号 type: string shop_id: + description: 店铺ID minimum: 0 type: integer shop_name: + description: 店铺名称 type: string user_type: + description: 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号) type: integer user_type_name: + description: 用户类型名称 type: string username: + description: 用户名 type: string type: object securitySchemes: @@ -622,20 +631,20 @@ paths: description: 手机号模糊查询 maxLength: 20 type: string - - description: 用户类型 + - description: 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号) in: query name: user_type schema: - description: 用户类型 + description: 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号) maximum: 4 minimum: 1 nullable: true type: integer - - description: 状态 + - description: 状态 (0:禁用, 1:启用) in: query name: status schema: - description: 状态 + description: 状态 (0:禁用, 1:启用) maximum: 1 minimum: 0 nullable: true @@ -1153,20 +1162,20 @@ paths: description: 权限编码模糊查询 maxLength: 100 type: string - - description: 权限类型 + - description: 权限类型 (1:菜单, 2:按钮) in: query name: perm_type schema: - description: 权限类型 + description: 权限类型 (1:菜单, 2:按钮) maximum: 2 minimum: 1 nullable: true type: integer - - description: 适用端口 + - description: 适用端口 (all:全部, web:Web后台, h5:H5端) in: query name: platform schema: - description: 适用端口 + description: 适用端口 (all:全部, web:Web后台, h5:H5端) type: string - description: 可用角色类型 (1:平台角色, 2:客户角色) in: query @@ -1185,11 +1194,11 @@ paths: minimum: 0 nullable: true type: integer - - description: 状态 + - description: 状态 (0:禁用, 1:启用) in: query name: status schema: - description: 状态 + description: 状态 (0:禁用, 1:启用) maximum: 1 minimum: 0 nullable: true @@ -1482,11 +1491,11 @@ paths: description: 手机号模糊查询 maxLength: 20 type: string - - description: 状态 + - description: 状态 (0:禁用, 1:启用) in: query name: status schema: - description: 状态 + description: 状态 (0:禁用, 1:启用) maximum: 1 minimum: 0 nullable: true @@ -2005,11 +2014,11 @@ paths: minimum: 1 nullable: true type: integer - - description: 状态 + - description: 状态 (0:禁用, 1:启用) in: query name: status schema: - description: 状态 + description: 状态 (0:禁用, 1:启用) maximum: 1 minimum: 0 nullable: true diff --git a/docs/ai-dto-guidelines-update.md b/docs/ai-dto-guidelines-update.md new file mode 100644 index 0000000..78b944f --- /dev/null +++ b/docs/ai-dto-guidelines-update.md @@ -0,0 +1,265 @@ +# AI 助手 DTO 规范指引更新 + +## 📋 更新概览 + +**更新日期**: 2026-01-20 +**目的**: 确保未来的 AI 助手在创建/修改 DTO 时自动遵循规范 + +--- + +## ✅ 已更新的文件 + +### 1. `AGENTS.md`(第 96 行) + +添加了完整的 **DTO 规范(重要!)** 章节,包括: + +- ✅ Description 标签规范 +- ✅ 枚举字段必须列出所有可能值(中文) +- ✅ 验证标签与 OpenAPI 标签一致 +- ✅ 请求参数类型标签 +- ✅ 响应 DTO 完整性 +- ✅ **AI 助手必须执行的检查清单** +- ✅ 常见枚举字段标准值 + +### 2. `CLAUDE.md`(第 99 行) + +添加了 **DTO 规范(API 文档生成基础)** 章节,包括: + +- ✅ 所有字段必须使用 `description` 标签 +- ✅ 枚举字段必须列出所有可能值(使用中文) +- ✅ validate 标签必须与 OpenAPI 标签一致 +- ✅ Query 和 Path 参数必须添加对应标签 +- ✅ **AI 助手在创建/修改 DTO 后必须执行的检查** + +--- + +## 🎯 AI 助手自动检查清单 + +未来的 AI 助手在创建或修改任何 DTO 文件后,会**自动执行**以下检查: + +### 必须执行的检查(来自 AGENTS.md) + +```markdown +1. ✅ 检查所有字段是否有 `description` 标签 +2. ✅ 检查枚举字段是否列出了所有可能值(中文) +3. ✅ 检查状态字段是否说明了 0 和 1 的含义 +4. ✅ 检查 validate 标签与 OpenAPI 标签是否一致 +5. ✅ 检查是否禁止使用行内注释替代 description +6. ✅ 检查枚举值是否使用中文而非英文 +7. ✅ 重新生成 OpenAPI 文档验证:`go run cmd/gendocs/main.go` +``` + +### 详细检查清单位置 + +- **完整清单**: `docs/code-review-checklist.md` +- **在线引用**: 两个文件都包含此引用 + +--- + +## 📚 标准枚举值参考 + +两个文件都包含了常见枚举字段的标准值: + +```go +// 用户类型 +description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)" + +// 角色类型 +description:"角色类型 (1:平台角色, 2:客户角色)" + +// 权限类型 +description:"权限类型 (1:菜单, 2:按钮)" + +// 适用端口 +description:"适用端口 (all:全部, web:Web后台, h5:H5端)" + +// 状态 +description:"状态 (0:禁用, 1:启用)" + +// 店铺层级 +description:"店铺层级 (1-7级)" +``` + +--- + +## 🔄 工作流程 + +### 1. AI 助手创建/修改 DTO 文件 + +```go +type CreateAccountRequest struct { + Username string `json:"username" validate:"required,min=3,max=50" required:"true" minLength:"3" maxLength:"50" description:"用户名"` + UserType int `json:"user_type" validate:"required,min=1,max=4" required:"true" minimum:"1" maximum:"4" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + Status int `json:"status" validate:"required,min=0,max=1" required:"true" minimum:"0" maximum:"1" description:"状态 (0:禁用, 1:启用)"` +} +``` + +### 2. AI 助手自动执行检查 + +根据 `AGENTS.md` 和 `CLAUDE.md` 中的指引,AI 会: + +- ✅ 验证所有字段都有 `description` 标签 +- ✅ 验证枚举字段包含完整的中文说明 +- ✅ 验证 validate 和 OpenAPI 标签一致性 +- ✅ 执行 `go run cmd/gendocs/main.go` 生成文档 + +### 3. AI 助手验证生成的文档 + +```bash +# 检查用户类型字段 +grep -A 3 "user_type:" docs/admin-openapi.yaml + +# 输出应该包含完整的中文枚举说明: +# description: 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号) +``` + +### 4. AI 助手报告检查结果 + +AI 会主动告知用户: +- ✅ 所有 DTO 字段都符合规范 +- ✅ OpenAPI 文档已重新生成 +- ✅ 所有枚举值使用中文说明 + +--- + +## 📊 对比:更新前 vs 更新后 + +### 更新前 ❌ + +**AI 助手行为**: +- ❌ 可能忘记添加 `description` 标签 +- ❌ 可能使用英文枚举值 +- ❌ 可能使用行内注释而非 `description` +- ❌ 不会自动验证文档生成 + +**开发者需要**: +- 🔧 手动检查每个 DTO 文件 +- 🔧 手动修复不符合规范的字段 +- 🔧 手动重新生成文档 + +### 更新后 ✅ + +**AI 助手行为**: +- ✅ **自动**为所有字段添加 `description` 标签 +- ✅ **自动**使用中文枚举值 +- ✅ **自动**确保 validate 和 OpenAPI 标签一致 +- ✅ **自动**重新生成并验证文档 + +**开发者只需**: +- 👀 Code Review 时参考 `docs/code-review-checklist.md` +- ✅ 信任 AI 已按规范执行 + +--- + +## 🎓 示例:AI 助手的标准操作流程 + +### 用户请求 +``` +"请创建一个企业管理的 DTO,包括创建、更新和列表查询" +``` + +### AI 助手执行步骤 + +1. **读取规范**(自动) + - 从 `AGENTS.md` 或 `CLAUDE.md` 读取 DTO 规范 + - 了解必须遵循的标签格式 + +2. **创建 DTO**(遵循规范) + ```go + type CreateEnterpriseRequest struct { + EnterpriseName string `json:"enterprise_name" validate:"required" required:"true" description:"企业名称"` + Status int `json:"status" validate:"required,min=0,max=1" required:"true" description:"状态 (0:禁用, 1:启用)"` + } + ``` + +3. **执行检查**(自动) + - ✅ 所有字段都有 `description` + - ✅ Status 字段说明了 0/1 含义 + - ✅ validate 和 OpenAPI 标签一致 + +4. **生成文档**(自动) + ```bash + go run cmd/gendocs/main.go + ``` + +5. **验证文档**(自动) + ```bash + grep "状态" docs/admin-openapi.yaml + # 确认输出包含: description: 状态 (0:禁用, 1:启用) + ``` + +6. **报告完成**(主动告知用户) + ``` + ✅ 已创建 enterprise_dto.go + ✅ 所有字段都符合 DTO 规范 + ✅ OpenAPI 文档已更新(docs/admin-openapi.yaml) + ✅ 所有枚举值使用中文说明 + ``` + +--- + +## 🔗 相关文档 + +| 文档 | 路径 | 说明 | +|------|------|------| +| AI 开发规范 | `AGENTS.md` | 包含 DTO 规范和检查清单(第 96 行) | +| Claude 规范 | `CLAUDE.md` | 包含 DTO 规范和检查清单(第 99 行) | +| Code Review 清单 | `docs/code-review-checklist.md` | 完整的检查清单 | +| DTO 改进总结 | `docs/dto-improvement-summary.md` | 本次修复的详细记录 | +| OpenAPI 文档 | `docs/admin-openapi.yaml` | 自动生成的 API 文档 | + +--- + +## 🎯 预期效果 + +### 对未来 AI 助手的影响 + +1. ✅ **自动合规**:所有新建的 DTO 自动符合规范 +2. ✅ **减少返工**:不再需要手动修复不规范的代码 +3. ✅ **文档同步**:代码即文档,文档永远是最新的 +4. ✅ **一致性**:所有枚举字段使用统一的中文说明格式 + +### 对开发团队的影响 + +1. ✅ **Code Review 简化**:只需对照 `docs/code-review-checklist.md` 快速检查 +2. ✅ **前端友好**:API 文档清晰,前端开发效率提升 +3. ✅ **新人友好**:规范明确,容易上手 +4. ✅ **维护成本降低**:规范统一,代码可读性强 + +--- + +## 📈 统计数据 + +### 文件更新统计 + +| 文件 | 添加行数 | 章节 | 位置 | +|------|---------|------|------| +| `AGENTS.md` | ~120 行 | DTO 规范(重要!) | 第 96 行 | +| `CLAUDE.md` | ~30 行 | DTO 规范(API 文档生成基础) | 第 99 行 | + +### 覆盖的检查项 + +- ✅ **7 个自动检查项**(AGENTS.md) +- ✅ **5 个核心规范点**(CLAUDE.md) +- ✅ **6 种标准枚举类型** + +--- + +## 🚀 下一步 + +### 立即生效 + +- ✅ 未来所有与此项目交互的 AI 助手都会自动读取这些规范 +- ✅ 新建或修改 DTO 时会自动执行检查 +- ✅ 文档生成和验证自动化 + +### 团队协作 + +- 📝 在 Code Review 时参考 `docs/code-review-checklist.md` +- 📝 在 PR 模板中添加"DTO 规范检查"项 +- 📝 定期运行 `go run cmd/gendocs/main.go` 确保文档最新 + +--- + +**最后更新**: 2026-01-20 +**维护者**: 开发团队 diff --git a/docs/api/auth.md b/docs/api/auth.md new file mode 100644 index 0000000..68c7ca9 --- /dev/null +++ b/docs/api/auth.md @@ -0,0 +1,511 @@ +# B 端认证 API 文档 + +本文档描述君鸿卡管系统 B 端认证接口(后台管理和 H5),包括登录、登出、Token 刷新、用户信息查询和密码修改功能。 + +--- + +## 概述 + +### 基础信息 + +- **后台 API 前缀**: `/api/admin` +- **H5 API 前缀**: `/api/h5` +- **认证方式**: Bearer Token (存储在 Redis) +- **Token 类型**: + - Access Token:24 小时有效期,用于 API 访问 + - Refresh Token:7 天有效期,用于刷新 Access Token + +### 用户类型限制 + +| 平台 | 允许的用户类型 | +|------|---------------| +| 后台 | SuperAdmin(1)、Platform(2)、Agent(3) | +| H5 | Agent(3)、Enterprise(4) | + +--- + +## 公开接口(无需认证) + +### 1. 用户登录 + +**后台**: `POST /api/admin/login` +**H5**: `POST /api/h5/login` + +使用用户名或手机号 + 密码登录,返回访问令牌。 + +#### 请求体 + +```json +{ + "username": "admin", + "password": "Admin@123456", + "device": "web" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| username | string | 是 | 用户名或手机号 | +| password | string | 是 | 密码 | +| device | string | 否 | 设备标识(web/ios/android) | + +#### 响应示例 + +**成功(200)**: +```json +{ + "code": 0, + "message": "操作成功", + "data": { + "access_token": "550e8400-e29b-41d4-a716-446655440000", + "refresh_token": "660f9500-f39c-52e5-b827-557766551111", + "expires_in": 86400, + "user": { + "id": 1, + "username": "admin", + "phone": "13800000000", + "user_type": 1, + "user_type_name": "超级管理员", + "shop_id": 0, + "enterprise_id": 0 + }, + "permissions": [ + "user:create", + "user:update", + "user:delete", + "role:manage" + ] + }, + "timestamp": "2026-01-15T16:05:00+08:00" +} +``` + +#### 错误码 + +| 错误码 | 消息 | 说明 | +|--------|------|------| +| 1001 | 参数验证失败 | 请求参数不完整或格式错误 | +| 1040 | 用户名或密码错误 | 凭证无效 | +| 1011 | 账号已禁用 | 账号被禁用,无法登录 | +| 1041 | 账号已锁定 | 账号被锁定 | + +#### cURL 示例 + +```bash +# 后台登录 +curl -X POST http://localhost:8080/api/admin/login \ + -H "Content-Type: application/json" \ + -d '{ + "username": "admin", + "password": "Admin@123456", + "device": "web" + }' + +# H5 登录 +curl -X POST http://localhost:8080/api/h5/login \ + -H "Content-Type: application/json" \ + -d '{ + "username": "agent001", + "password": "password123", + "device": "ios" + }' +``` + +--- + +### 2. 刷新访问令牌 + +**后台**: `POST /api/admin/refresh-token` +**H5**: `POST /api/h5/refresh-token` + +使用 Refresh Token 获取新的 Access Token。 + +#### 请求体 + +```json +{ + "refresh_token": "660f9500-f39c-52e5-b827-557766551111" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| refresh_token | string | 是 | 刷新令牌 | + +#### 响应示例 + +**成功(200)**: +```json +{ + "code": 0, + "message": "操作成功", + "data": { + "access_token": "770a0600-a40d-63f6-c938-668877662222", + "expires_in": 86400 + }, + "timestamp": "2026-01-15T16:06:00+08:00" +} +``` + +#### 错误码 + +| 错误码 | 消息 | 说明 | +|--------|------|------| +| 1001 | 参数验证失败 | refresh_token 缺失 | +| 1003 | 无效或过期的令牌 | Refresh Token 无效或已过期 | + +#### cURL 示例 + +```bash +curl -X POST http://localhost:8080/api/admin/refresh-token \ + -H "Content-Type: application/json" \ + -d '{ + "refresh_token": "660f9500-f39c-52e5-b827-557766551111" + }' +``` + +--- + +## 受保护接口(需要认证) + +所有受保护接口需在请求头中携带 Access Token: + +``` +Authorization: Bearer {access_token} +``` + +--- + +### 3. 用户登出 + +**后台**: `POST /api/admin/logout` +**H5**: `POST /api/h5/logout` + +撤销当前 Access Token 和 Refresh Token(如果提供)。 + +#### 请求头 + +``` +Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000 +``` + +#### 请求体(可选) + +```json +{ + "refresh_token": "660f9500-f39c-52e5-b827-557766551111" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| refresh_token | string | 否 | 如果提供,同时撤销 Refresh Token | + +#### 响应示例 + +**成功(200)**: +```json +{ + "code": 0, + "message": "操作成功", + "data": null, + "timestamp": "2026-01-15T16:07:00+08:00" +} +``` + +#### 错误码 + +| 错误码 | 消息 | 说明 | +|--------|------|------| +| 1002 | 缺失认证令牌 | 请求头未携带 Authorization | +| 1003 | 无效或过期的令牌 | Access Token 无效或已过期 | +| 1004 | 未授权访问 | Token 已被撤销 | + +#### cURL 示例 + +```bash +curl -X POST http://localhost:8080/api/admin/logout \ + -H "Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000" \ + -H "Content-Type: application/json" \ + -d '{ + "refresh_token": "660f9500-f39c-52e5-b827-557766551111" + }' +``` + +--- + +### 4. 获取当前用户信息 + +**后台**: `GET /api/admin/me` +**H5**: `GET /api/h5/me` + +获取当前登录用户的详细信息和权限列表。 + +#### 请求头 + +``` +Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000 +``` + +#### 响应示例 + +**成功(200)**: +```json +{ + "code": 0, + "message": "操作成功", + "data": { + "user": { + "id": 1, + "username": "admin", + "phone": "13800000000", + "user_type": 1, + "user_type_name": "超级管理员", + "shop_id": 0, + "enterprise_id": 0, + "status": 1, + "created_at": "2026-01-01T00:00:00+08:00" + }, + "permissions": [ + "user:create", + "user:update", + "user:delete", + "role:manage", + "permission:manage" + ] + }, + "timestamp": "2026-01-15T16:08:00+08:00" +} +``` + +#### 错误码 + +| 错误码 | 消息 | 说明 | +|--------|------|------| +| 1002 | 缺失认证令牌 | 请求头未携带 Authorization | +| 1003 | 无效或过期的令牌 | Access Token 无效或已过期 | +| 1004 | 未授权访问 | 用户信息查询失败 | + +#### cURL 示例 + +```bash +curl -X GET http://localhost:8080/api/admin/me \ + -H "Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000" +``` + +--- + +### 5. 修改密码 + +**后台**: `POST /api/admin/password` +**H5**: `POST /api/h5/password` + +修改当前用户密码,修改成功后所有旧 Token 将失效。 + +#### 请求头 + +``` +Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000 +``` + +#### 请求体 + +```json +{ + "old_password": "Admin@123456", + "new_password": "NewPassword@2026" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| old_password | string | 是 | 当前密码 | +| new_password | string | 是 | 新密码(6-20 位,包含字母和数字) | + +#### 响应示例 + +**成功(200)**: +```json +{ + "code": 0, + "message": "操作成功", + "data": null, + "timestamp": "2026-01-15T16:09:00+08:00" +} +``` + +#### 错误码 + +| 错误码 | 消息 | 说明 | +|--------|------|------| +| 1001 | 参数验证失败 | 密码格式不符合要求 | +| 1002 | 缺失认证令牌 | 请求头未携带 Authorization | +| 1003 | 无效或过期的令牌 | Access Token 无效或已过期 | +| 1043 | 旧密码错误 | 提供的旧密码不正确 | + +#### cURL 示例 + +```bash +curl -X POST http://localhost:8080/api/admin/password \ + -H "Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000" \ + -H "Content-Type: application/json" \ + -d '{ + "old_password": "Admin@123456", + "new_password": "NewPassword@2026" + }' +``` + +--- + +## 错误码对照表 + +### 认证相关错误(1000-1099) + +| 错误码 | 消息 | HTTP 状态码 | 说明 | +|--------|------|-------------|------| +| 1001 | 参数验证失败 | 400 | 请求参数不完整或格式错误 | +| 1002 | 缺失认证令牌 | 401 | Authorization 请求头缺失 | +| 1003 | 无效或过期的令牌 | 401 | Token 无效或已过期 | +| 1004 | 未授权访问 | 401 | 无权访问该资源 | +| 1005 | 禁止访问 | 403 | 用户类型不允许访问 | +| 1040 | 用户名或密码错误 | 401 | 登录凭证错误 | +| 1011 | 账号已禁用 | 403 | 账号被管理员禁用 | +| 1041 | 账号已锁定 | 403 | 账号因安全原因被锁定 | +| 1042 | 密码已过期 | 403 | 需要更新密码 | +| 1043 | 旧密码错误 | 400 | 修改密码时提供的旧密码不正确 | + +### 服务端错误(2000-2999) + +| 错误码 | 消息 | HTTP 状态码 | 说明 | +|--------|------|-------------|------| +| 2001 | 内部服务器错误 | 500 | 服务器内部错误 | +| 2002 | 数据库错误 | 500 | 数据库操作失败 | +| 2003 | Redis 错误 | 500 | Redis 操作失败 | +| 2004 | 服务不可用 | 503 | 服务暂时不可用 | + +--- + +## 使用场景示例 + +### 场景 1:完整登录流程 + +```bash +# 1. 用户登录 +curl -X POST http://localhost:8080/api/admin/login \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"Admin@123456"}' \ + | jq + +# 响应获取 access_token 和 refresh_token +# { +# "code": 0, +# "data": { +# "access_token": "550e8400-...", +# "refresh_token": "660f9500-..." +# } +# } + +# 2. 使用 access_token 访问受保护接口 +curl -X GET http://localhost:8080/api/admin/me \ + -H "Authorization: Bearer 550e8400-..." \ + | jq + +# 3. Access Token 过期后,使用 Refresh Token 刷新 +curl -X POST http://localhost:8080/api/admin/refresh-token \ + -H "Content-Type: application/json" \ + -d '{"refresh_token":"660f9500-..."}' \ + | jq + +# 4. 登出 +curl -X POST http://localhost:8080/api/admin/logout \ + -H "Authorization: Bearer 550e8400-..." \ + -H "Content-Type: application/json" \ + -d '{"refresh_token":"660f9500-..."}' \ + | jq +``` + +### 场景 2:修改密码 + +```bash +# 1. 登录获取 token +TOKEN=$(curl -s -X POST http://localhost:8080/api/admin/login \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"Admin@123456"}' \ + | jq -r '.data.access_token') + +# 2. 修改密码 +curl -X POST http://localhost:8080/api/admin/password \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "old_password": "Admin@123456", + "new_password": "NewPassword@2026" + }' \ + | jq + +# 3. 旧 token 失效,需要重新登录 +curl -X POST http://localhost:8080/api/admin/login \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"NewPassword@2026"}' \ + | jq +``` + +--- + +## 安全注意事项 + +1. **Token 存储**: + - 前端应将 Token 存储在安全位置(如 HttpOnly Cookie 或 secure storage) + - 不要将 Token 暴露在 URL 中 + +2. **Token 传输**: + - 始终使用 HTTPS 传输 Token + - Token 仅在 Authorization 请求头中传递 + +3. **密码要求**: + - 长度:6-20 位 + - 必须包含字母和数字 + - 建议包含特殊字符 + +4. **Token 生命周期**: + - Access Token:24 小时自动过期 + - Refresh Token:7 天自动过期 + - 修改密码后所有旧 Token 立即失效 + +5. **并发登录**: + - 系统支持同一用户多设备同时登录 + - 每个设备拥有独立的 Token 对 + - 登出只撤销当前设备的 Token + +--- + +## 常见问题 + +**Q: 如何判断 Access Token 是否过期?** +A: 接口返回 `1003` 错误码时表示 Token 过期,应使用 Refresh Token 刷新。 + +**Q: Refresh Token 过期后怎么办?** +A: Refresh Token 过期后需要重新登录。 + +**Q: 修改密码后需要重新登录吗?** +A: 是的,修改密码后所有设备的 Token 都会失效,需要重新登录。 + +**Q: 后台用户可以使用 H5 接口吗?** +A: 不可以。后台和 H5 有不同的用户类型限制,使用错误的端点会返回 `1005` 错误。 + +**Q: 如何撤销所有设备的登录状态?** +A: 调用 `/api/admin/password` 修改密码,所有设备的 Token 会自动失效。 + +--- + +## 相关文档 + +- [使用指南](../auth-usage-guide.md) - 如何在代码中集成认证 +- [架构说明](../auth-architecture.md) - 认证系统架构设计 +- [错误处理指南](../003-error-handling/使用指南.md) - 统一错误处理 + +--- + +**文档版本**: v1.0 +**最后更新**: 2026-01-15 +**维护者**: 君鸿卡管系统开发团队 diff --git a/docs/code-review-checklist.md b/docs/code-review-checklist.md new file mode 100644 index 0000000..74f05b4 --- /dev/null +++ b/docs/code-review-checklist.md @@ -0,0 +1,326 @@ +# Code Review 检查清单 + +## 📋 DTO 规范检查清单 + +在提交 Pull Request 前,请确保所有 DTO 文件遵循以下规范。 + +--- + +## ✅ 必须项(MUST) + +### 1. Description 标签规范 + +**所有字段必须使用 `description` 标签,禁止使用行内注释** + +❌ **错误示例**: +```go +type CreateUserRequest struct { + Username string `json:"username"` // 用户名 + Status int `json:"status"` // 状态 +} +``` + +✅ **正确示例**: +```go +type CreateUserRequest struct { + Username string `json:"username" description:"用户名"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` +} +``` + +--- + +### 2. 枚举字段必须列出所有可能值(中文说明) + +**所有枚举类型字段必须在 `description` 中列出所有可能值和对应的中文含义** + +#### 用户类型 +```go +UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` +``` + +#### 角色类型 +```go +RoleType int `json:"role_type" description:"角色类型 (1:平台角色, 2:客户角色)"` +``` + +#### 权限类型 +```go +PermType int `json:"perm_type" description:"权限类型 (1:菜单, 2:按钮)"` +``` + +#### 状态字段 +```go +Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` +``` + +#### 适用端口 +```go +Platform string `json:"platform" description:"适用端口 (all:全部, web:Web后台, h5:H5端)"` +``` + +--- + +### 3. 验证标签与 OpenAPI 标签一致 + +**所有验证约束必须同时在 `validate` 和 OpenAPI 标签中声明** + +✅ **正确示例**: +```go +Username string `json:"username" validate:"required,min=3,max=50" required:"true" minLength:"3" maxLength:"50" description:"用户名"` +``` + +**标签对照表**: + +| validate 标签 | OpenAPI 标签 | 说明 | +|--------------|--------------|------| +| `required` | `required:"true"` | 必填字段 | +| `min=N,max=M` | `minimum:"N" maximum:"M"` | 数值范围 | +| `min=N,max=M` (字符串) | `minLength:"N" maxLength:"M"` | 字符串长度 | +| `len=N` | `minLength:"N" maxLength:"N"` | 固定长度 | +| `oneof=A B C` | `description` 中说明 | 枚举值 | + +--- + +### 4. 请求参数类型标签 + +**Query 参数和 Path 参数必须添加对应标签** + +#### Query 参数 +```go +type ListRequest struct { + Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码"` + UserType *int `json:"user_type" query:"user_type" validate:"omitempty,min=1,max=4" minimum:"1" maximum:"4" description:"用户类型"` +} +``` + +#### Path 参数 +```go +type IDReq struct { + ID uint `path:"id" description:"ID" required:"true"` +} +``` + +--- + +### 5. 响应 DTO 完整性 + +**所有响应 DTO 的字段都必须有完整的 `description` 标签** + +✅ **正确示例**: +```go +type AccountResponse struct { + ID uint `json:"id" description:"账号ID"` + Username string `json:"username" description:"用户名"` + UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + CreatedAt string `json:"created_at" description:"创建时间"` + UpdatedAt string `json:"updated_at" description:"更新时间"` +} +``` + +--- + +## 🔍 推荐项(SHOULD) + +### 6. 字段顺序规范 + +建议按以下顺序组织字段: + +1. 主键字段(ID) +2. 业务核心字段(名称、编号等) +3. 关联字段(外键) +4. 状态字段 +5. 审计字段(Creator、Updater、CreatedAt、UpdatedAt) + +--- + +### 7. 中文注释完整性 + +**所有导出的结构体、方法、常量必须有中文 godoc 注释** + +✅ **正确示例**: +```go +// CreateAccountRequest 创建账号请求 +type CreateAccountRequest struct { + // ... +} + +// AccountResponse 账号响应 +type AccountResponse struct { + // ... +} +``` + +--- + +### 8. 必填字段和可选字段区分 + +**使用指针类型标识可选字段** + +```go +type UpdateRequest struct { + Username *string `json:"username" description:"用户名(可选)"` // 可选 + Status *int `json:"status" description:"状态(可选)"` // 可选 +} + +type CreateRequest struct { + Username string `json:"username" required:"true" description:"用户名"` // 必填 + Status int `json:"status" required:"true" description:"状态"` // 必填 +} +``` + +--- + +## 🚫 禁止项(MUST NOT) + +### 9. 禁止使用英文枚举值说明 + +❌ **错误**: +```go +UserType int `json:"user_type" description:"用户类型 (1:SuperAdmin, 2:Platform, 3:Agent, 4:Enterprise)"` +``` + +✅ **正确**: +```go +UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` +``` + +--- + +### 10. 禁止缺失枚举值说明 + +❌ **错误**: +```go +Status int `json:"status" description:"状态"` +``` + +✅ **正确**: +```go +Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` +``` + +--- + +### 11. 禁止不一致的 description + +**同一字段在不同 DTO 中必须使用一致的 description** + +✅ **正确示例**: +```go +// CreateAccountRequest +UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + +// AccountListRequest +UserType *int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + +// AccountResponse +UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` +``` + +--- + +## 📝 常见枚举字段参考 + +### 用户类型(UserType) +```go +description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)" +``` + +### 角色类型(RoleType) +```go +description:"角色类型 (1:平台角色, 2:客户角色)" +``` + +### 权限类型(PermType) +```go +description:"权限类型 (1:菜单, 2:按钮)" +``` + +### 适用端口(Platform) +```go +description:"适用端口 (all:全部, web:Web后台, h5:H5端)" +``` + +### 状态(Status) +```go +description:"状态 (0:禁用, 1:启用)" +``` + +### 店铺层级(Level) +```go +description:"店铺层级 (1-7级)" +``` + +--- + +## 🔧 检查工具 + +### 手动检查 + +在提交前运行以下命令检查 DTO 文件: + +```bash +# 查找没有 description 标签的 json 字段 +grep -rn 'json:"[^"]*"' internal/model/*_dto.go | grep -v 'description:' + +# 查找使用行内注释的字段(应该改为 description 标签) +grep -rn '`json:.*`.*//\s' internal/model/*_dto.go + +# 查找可能缺少枚举值说明的 status 字段 +grep -rn 'Status.*json:"status".*description:"状态"$' internal/model/*_dto.go +``` + +### 自动生成文档验证 + +```bash +# 生成 OpenAPI 文档 +go run cmd/gendocs/main.go + +# 检查生成的文档中是否包含完整的枚举值说明 +grep -A 3 "user_type:" docs/admin-openapi.yaml +grep -A 3 "status:" docs/admin-openapi.yaml +``` + +--- + +## 📚 相关文档 + +- [项目开发规范](../AGENTS.md) +- [OpenAPI 文档生成说明](../README.md#openapi-文档) +- [RBAC 用户类型定义](../pkg/constants/constants.go) + +--- + +## ✅ Code Review 检查清单(用于审查者) + +在审查 Pull Request 时,请逐项检查: + +- [ ] 所有新增/修改的 DTO 字段都有 `description` 标签 +- [ ] 所有枚举字段的 description 包含完整的可能值和中文说明 +- [ ] 所有状态字段明确说明了 0 和 1 的含义 +- [ ] validate 标签与 OpenAPI 标签(required、minLength、maximum 等)一致 +- [ ] Query 参数添加了 `query` 标签 +- [ ] Path 参数添加了 `path` 标签 +- [ ] 响应 DTO 的所有字段都有完整说明 +- [ ] 同一字段在不同 DTO 中使用一致的 description +- [ ] 所有枚举值使用中文说明,禁止使用英文 +- [ ] 没有使用行内注释替代 description 标签 +- [ ] 所有导出的结构体有中文 godoc 注释 + +--- + +## 🎯 完成标准 + +当所有检查项都通过时,才能合并 PR。 + +**文档生成验证**: +```bash +go run cmd/gendocs/main.go +# 检查 docs/admin-openapi.yaml 中所有字段都有清晰的中文说明 +``` + +--- + +**最后更新**: 2026-01-20 +**维护者**: 开发团队 diff --git a/docs/dto-improvement-summary.md b/docs/dto-improvement-summary.md new file mode 100644 index 0000000..041b261 --- /dev/null +++ b/docs/dto-improvement-summary.md @@ -0,0 +1,215 @@ +# DTO 规范完善总结 + +## 📊 修复概览 + +**修复日期**: 2026-01-20 +**修复范围**: 所有 DTO 文件的 `description` 标签规范化 + +--- + +## ✅ 已修复的文件清单 + +### 1. 账号模块 +- ✅ `internal/model/account_dto.go` + - 修复 `CreateAccountRequest.UserType` - 添加完整中文枚举说明 + - 修复 `AccountListRequest.UserType` - 添加完整中文枚举说明 + - 修复 `AccountListRequest.Status` - 添加 0/1 含义 + - 修复 `AccountResponse.UserType` - 添加完整中文枚举说明 + - 修复 `AccountResponse.Status` - 添加 0/1 含义 + - 修复 `PlatformAccountListRequest.Status` - 添加 0/1 含义 + +### 2. 认证模块 +- ✅ `internal/model/auth_dto.go` + - 为 `UserInfo` 所有字段添加完整的 `description` 标签 + - `UserType` 使用完整中文枚举说明 + +### 3. 角色模块 +- ✅ `internal/model/role_dto.go` + - 修复 `RoleListRequest.Status` - 添加 0/1 含义 + - 修复 `RoleResponse.RoleType` - 添加完整中文枚举说明 + - 修复 `RoleResponse.Status` - 添加 0/1 含义 + +### 4. 权限模块 +- ✅ `internal/model/permission_dto.go` + - 修复 `PermissionListRequest.PermType` - 添加完整中文枚举说明 + - 修复 `PermissionListRequest.Platform` - 添加完整中文枚举说明 + - 修复 `PermissionListRequest.Status` - 添加 0/1 含义 + - 修复 `PermissionResponse.PermType` - 添加完整中文枚举说明 + - 修复 `PermissionResponse.Platform` - 添加完整中文枚举说明 + - 修复 `PermissionResponse.Status` - 添加 0/1 含义 + - 修复 `PermissionTreeNode` - 所有字段添加完整说明 + +### 5. 店铺模块 +- ✅ `internal/model/shop_dto.go` + - 从无 `description` 标签 → 所有字段添加完整的 `description` 标签 + - 添加 validate 对应的 OpenAPI 标签(required、minLength、maxLength 等) + - `Status` 字段添加 0/1 含义说明 + - `Level` 字段说明店铺层级范围 + +### 6. 企业模块 +- ✅ `internal/model/enterprise_dto.go` + - 从行内注释 → 改为 `description` 标签 + - `Status` 字段添加 0/1 含义说明 + - 所有字段添加清晰的中文说明 + +### 7. 个人客户模块 +- ✅ `internal/model/personal_customer_dto.go` + - 从行内注释 → 改为 `description` 标签 + - `Status` 字段添加 0/1 含义说明 + - 所有字段添加清晰的中文说明 + +### 8. 代理商账号模块 +- ✅ `internal/model/shop_account_dto.go` + - 从行内注释 → 改为 `description` 标签 + - `UserType` 和 `Status` 字段添加完整枚举说明 + +### 9. 角色-权限关联模块 +- ✅ `internal/model/role_permission_dto.go` + - 从无 `description` 标签 → 所有字段添加完整说明 + - `Status` 字段添加 0/1 含义说明 + +### 10. 账号-角色关联模块 +- ✅ `internal/model/account_role_dto.go` + - 从无 `description` 标签 → 所有字段添加完整说明 + - `Status` 字段添加 0/1 含义说明 + +--- + +## 📈 修复前后对比 + +### 修复前 ❌ + +**问题 1**: 枚举值使用英文 +```go +UserType int `json:"user_type" description:"用户类型 (1:SuperAdmin, 2:Platform, 3:Agent, 4:Enterprise)"` +``` + +**问题 2**: 缺少枚举值说明 +```go +Status int `json:"status" description:"状态"` +``` + +**问题 3**: 使用行内注释而非 description 标签 +```go +EnterpriseName string `json:"enterprise_name"` // 企业名称 +``` + +**问题 4**: 完全没有 description 标签 +```go +type ShopResponse struct { + ID uint `json:"id"` + ShopName string `json:"shop_name"` + Status int `json:"status"` +} +``` + +### 修复后 ✅ + +**所有枚举值使用完整中文说明** +```go +UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` +``` + +**状态字段明确说明 0/1 含义** +```go +Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` +``` + +**统一使用 description 标签** +```go +EnterpriseName string `json:"enterprise_name" description:"企业名称"` +``` + +**所有字段都有完整说明** +```go +type ShopResponse struct { + ID uint `json:"id" description:"店铺ID"` + ShopName string `json:"shop_name" description:"店铺名称"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` +} +``` + +--- + +## 📊 统计数据 + +### 生成的 OpenAPI 文档 + +- **文件路径**: `docs/admin-openapi.yaml` +- **Description 字段数量**: **375 个** +- **覆盖的 DTO 文件**: **10 个** +- **修复的字段**: **100+ 个** + +### 枚举字段标准化 + +| 枚举类型 | 标准 Description | 使用次数 | +|---------|-----------------|---------| +| 用户类型 | `用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)` | 6 处 | +| 角色类型 | `角色类型 (1:平台角色, 2:客户角色)` | 3 处 | +| 权限类型 | `权限类型 (1:菜单, 2:按钮)` | 3 处 | +| 适用端口 | `适用端口 (all:全部, web:Web后台, h5:H5端)` | 5 处 | +| 状态 | `状态 (0:禁用, 1:启用)` | 15+ 处 | + +--- + +## 🎯 达成的效果 + +### 1. 前端开发友好 +- ✅ 所有 API 字段都有清晰的中文说明 +- ✅ 枚举字段明确列出所有可能值 +- ✅ 导入 Swagger UI/Apifox 后可直接使用 + +### 2. 文档自动生成 +- ✅ OpenAPI 文档完全自动生成,无需手动编写 +- ✅ 字段说明与代码同步,避免文档过期 + +### 3. 代码可维护性 +- ✅ 统一的规范,新人容易上手 +- ✅ Code Review 有明确的检查标准 + +--- + +## 📋 后续维护 + +### 新增 DTO 时必须遵循 + +1. ✅ 所有字段添加 `description` 标签 +2. ✅ 枚举字段列出所有可能值(中文) +3. ✅ validate 标签与 OpenAPI 标签保持一致 +4. ✅ 使用 `query` 和 `path` 标签标记参数类型 + +### Code Review 检查清单 + +详见:[docs/code-review-checklist.md](./code-review-checklist.md) + +### 验证方法 + +```bash +# 生成文档 +go run cmd/gendocs/main.go + +# 检查特定字段的说明 +grep -A 3 "user_type:" docs/admin-openapi.yaml +grep -A 3 "status:" docs/admin-openapi.yaml + +# 统计 description 数量 +grep -c "description:" docs/admin-openapi.yaml +``` + +--- + +## 🔗 相关文档 + +- [Code Review 检查清单](./code-review-checklist.md) +- [项目开发规范](../AGENTS.md) +- [README](../README.md) + +--- + +## 👥 贡献者 + +- 开发团队 + +--- + +**最后更新**: 2026-01-20 diff --git a/internal/model/account_dto.go b/internal/model/account_dto.go index 3623533..da86ac2 100644 --- a/internal/model/account_dto.go +++ b/internal/model/account_dto.go @@ -5,7 +5,7 @@ type CreateAccountRequest struct { Username string `json:"username" validate:"required,min=3,max=50" required:"true" minLength:"3" maxLength:"50" description:"用户名"` Phone string `json:"phone" validate:"required,len=11" required:"true" minLength:"11" maxLength:"11" description:"手机号"` Password string `json:"password" validate:"required,min=8,max=32" required:"true" minLength:"8" maxLength:"32" description:"密码"` - UserType int `json:"user_type" validate:"required,min=1,max=4" required:"true" minimum:"1" maximum:"4" description:"用户类型 (1:SuperAdmin, 2:Platform, 3:Agent, 4:Enterprise)"` + UserType int `json:"user_type" validate:"required,min=1,max=4" required:"true" minimum:"1" maximum:"4" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` ShopID *uint `json:"shop_id" description:"关联店铺ID(代理账号必填)"` EnterpriseID *uint `json:"enterprise_id" description:"关联企业ID(企业账号必填)"` } @@ -24,8 +24,8 @@ type AccountListRequest struct { PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"` Username string `json:"username" query:"username" validate:"omitempty,max=50" maxLength:"50" description:"用户名模糊查询"` Phone string `json:"phone" query:"phone" validate:"omitempty,max=20" maxLength:"20" description:"手机号模糊查询"` - UserType *int `json:"user_type" query:"user_type" validate:"omitempty,min=1,max=4" minimum:"1" maximum:"4" description:"用户类型"` - Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态"` + UserType *int `json:"user_type" query:"user_type" validate:"omitempty,min=1,max=4" minimum:"1" maximum:"4" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态 (0:禁用, 1:启用)"` } // AccountResponse 账号响应 @@ -33,10 +33,10 @@ type AccountResponse struct { ID uint `json:"id" description:"账号ID"` Username string `json:"username" description:"用户名"` Phone string `json:"phone" description:"手机号"` - UserType int `json:"user_type" description:"用户类型"` + UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` ShopID *uint `json:"shop_id,omitempty" description:"关联店铺ID"` EnterpriseID *uint `json:"enterprise_id,omitempty" description:"关联企业ID"` - Status int `json:"status" description:"状态"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` Creator uint `json:"creator" description:"创建人ID"` Updater uint `json:"updater" description:"更新人ID"` CreatedAt string `json:"created_at" description:"创建时间"` @@ -78,7 +78,7 @@ type PlatformAccountListRequest struct { PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"` Username string `json:"username" query:"username" validate:"omitempty,max=50" maxLength:"50" description:"用户名模糊查询"` Phone string `json:"phone" query:"phone" validate:"omitempty,max=20" maxLength:"20" description:"手机号模糊查询"` - Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态"` + Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态 (0:禁用, 1:启用)"` } // UpdatePasswordParams 修改密码参数(用于 OpenAPI 生成) diff --git a/internal/model/account_role_dto.go b/internal/model/account_role_dto.go index e59fdea..0b2ad8f 100644 --- a/internal/model/account_role_dto.go +++ b/internal/model/account_role_dto.go @@ -2,15 +2,15 @@ package model // AccountRoleResponse 账号-角色关联响应 type AccountRoleResponse struct { - ID uint `json:"id"` - AccountID uint `json:"account_id"` - RoleID uint `json:"role_id"` - Status int `json:"status"` - CreatedAt string `json:"created_at"` + ID uint `json:"id" description:"关联ID"` + AccountID uint `json:"account_id" description:"账号ID"` + RoleID uint `json:"role_id" description:"角色ID"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + CreatedAt string `json:"created_at" description:"创建时间"` } // AccountRolesResponse 账号的角色列表响应 type AccountRolesResponse struct { - AccountID uint `json:"account_id"` - Roles []*RoleResponse `json:"roles"` + AccountID uint `json:"account_id" description:"账号ID"` + Roles []*RoleResponse `json:"roles" description:"角色列表"` } diff --git a/internal/model/auth_dto.go b/internal/model/auth_dto.go index 2a5afd6..db6cfdc 100644 --- a/internal/model/auth_dto.go +++ b/internal/model/auth_dto.go @@ -15,15 +15,15 @@ type LoginResponse struct { } type UserInfo struct { - ID uint `json:"id"` - Username string `json:"username"` - Phone string `json:"phone"` - UserType int `json:"user_type"` - UserTypeName string `json:"user_type_name"` - ShopID uint `json:"shop_id,omitempty"` - ShopName string `json:"shop_name,omitempty"` - EnterpriseID uint `json:"enterprise_id,omitempty"` - EnterpriseName string `json:"enterprise_name,omitempty"` + ID uint `json:"id" description:"用户ID"` + Username string `json:"username" description:"用户名"` + Phone string `json:"phone" description:"手机号"` + UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + UserTypeName string `json:"user_type_name" description:"用户类型名称"` + ShopID uint `json:"shop_id,omitempty" description:"店铺ID"` + ShopName string `json:"shop_name,omitempty" description:"店铺名称"` + EnterpriseID uint `json:"enterprise_id,omitempty" description:"企业ID"` + EnterpriseName string `json:"enterprise_name,omitempty" description:"企业名称"` } type RefreshTokenRequest struct { diff --git a/internal/model/enterprise_dto.go b/internal/model/enterprise_dto.go index f3584da..0c174a7 100644 --- a/internal/model/enterprise_dto.go +++ b/internal/model/enterprise_dto.go @@ -2,48 +2,48 @@ package model // CreateEnterpriseRequest 创建企业请求 type CreateEnterpriseRequest struct { - EnterpriseName string `json:"enterprise_name" validate:"required"` // 企业名称 - EnterpriseCode string `json:"enterprise_code"` // 企业编号 - OwnerShopID *uint `json:"owner_shop_id"` // 归属店铺ID - LegalPerson string `json:"legal_person"` // 法人代表 - ContactName string `json:"contact_name"` // 联系人姓名 - ContactPhone string `json:"contact_phone"` // 联系人电话 - BusinessLicense string `json:"business_license"` // 营业执照号 - Province string `json:"province"` // 省份 - City string `json:"city"` // 城市 - District string `json:"district"` // 区县 - Address string `json:"address"` // 详细地址 + EnterpriseName string `json:"enterprise_name" validate:"required" required:"true" description:"企业名称"` + EnterpriseCode string `json:"enterprise_code" description:"企业编号"` + OwnerShopID *uint `json:"owner_shop_id" description:"归属店铺ID(可不填则归属平台)"` + LegalPerson string `json:"legal_person" description:"法人代表"` + ContactName string `json:"contact_name" description:"联系人姓名"` + ContactPhone string `json:"contact_phone" description:"联系人电话"` + BusinessLicense string `json:"business_license" description:"营业执照号"` + Province string `json:"province" description:"省份"` + City string `json:"city" description:"城市"` + District string `json:"district" description:"区县"` + Address string `json:"address" description:"详细地址"` } // UpdateEnterpriseRequest 更新企业请求 type UpdateEnterpriseRequest struct { - EnterpriseName *string `json:"enterprise_name"` // 企业名称 - EnterpriseCode *string `json:"enterprise_code"` // 企业编号 - LegalPerson *string `json:"legal_person"` // 法人代表 - ContactName *string `json:"contact_name"` // 联系人姓名 - ContactPhone *string `json:"contact_phone"` // 联系人电话 - BusinessLicense *string `json:"business_license"` // 营业执照号 - Province *string `json:"province"` // 省份 - City *string `json:"city"` // 城市 - District *string `json:"district"` // 区县 - Address *string `json:"address"` // 详细地址 + EnterpriseName *string `json:"enterprise_name" description:"企业名称"` + EnterpriseCode *string `json:"enterprise_code" description:"企业编号"` + LegalPerson *string `json:"legal_person" description:"法人代表"` + ContactName *string `json:"contact_name" description:"联系人姓名"` + ContactPhone *string `json:"contact_phone" description:"联系人电话"` + BusinessLicense *string `json:"business_license" description:"营业执照号"` + Province *string `json:"province" description:"省份"` + City *string `json:"city" description:"城市"` + District *string `json:"district" description:"区县"` + Address *string `json:"address" description:"详细地址"` } // EnterpriseResponse 企业响应 type EnterpriseResponse struct { - ID uint `json:"id"` - EnterpriseName string `json:"enterprise_name"` - EnterpriseCode string `json:"enterprise_code"` - OwnerShopID *uint `json:"owner_shop_id,omitempty"` - LegalPerson string `json:"legal_person"` - ContactName string `json:"contact_name"` - ContactPhone string `json:"contact_phone"` - BusinessLicense string `json:"business_license"` - Province string `json:"province"` - City string `json:"city"` - District string `json:"district"` - Address string `json:"address"` - Status int `json:"status"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + ID uint `json:"id" description:"企业ID"` + EnterpriseName string `json:"enterprise_name" description:"企业名称"` + EnterpriseCode string `json:"enterprise_code" description:"企业编号"` + OwnerShopID *uint `json:"owner_shop_id,omitempty" description:"归属店铺ID"` + LegalPerson string `json:"legal_person" description:"法人代表"` + ContactName string `json:"contact_name" description:"联系人姓名"` + ContactPhone string `json:"contact_phone" description:"联系人电话"` + BusinessLicense string `json:"business_license" description:"营业执照号"` + Province string `json:"province" description:"省份"` + City string `json:"city" description:"城市"` + District string `json:"district" description:"区县"` + Address string `json:"address" description:"详细地址"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + CreatedAt string `json:"created_at" description:"创建时间"` + UpdatedAt string `json:"updated_at" description:"更新时间"` } diff --git a/internal/model/permission_dto.go b/internal/model/permission_dto.go index cc729da..d444020 100644 --- a/internal/model/permission_dto.go +++ b/internal/model/permission_dto.go @@ -34,11 +34,11 @@ type PermissionListRequest struct { PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"` PermName string `json:"perm_name" query:"perm_name" validate:"omitempty,max=50" maxLength:"50" description:"权限名称模糊查询"` PermCode string `json:"perm_code" query:"perm_code" validate:"omitempty,max=100" maxLength:"100" description:"权限编码模糊查询"` - PermType *int `json:"perm_type" query:"perm_type" validate:"omitempty,min=1,max=2" minimum:"1" maximum:"2" description:"权限类型"` - Platform string `json:"platform" query:"platform" validate:"omitempty,oneof=all web h5" description:"适用端口"` + PermType *int `json:"perm_type" query:"perm_type" validate:"omitempty,min=1,max=2" minimum:"1" maximum:"2" description:"权限类型 (1:菜单, 2:按钮)"` + Platform string `json:"platform" query:"platform" validate:"omitempty,oneof=all web h5" description:"适用端口 (all:全部, web:Web后台, h5:H5端)"` AvailableForRoleType *int `json:"available_for_role_type" query:"available_for_role_type" validate:"omitempty,min=1,max=2" minimum:"1" maximum:"2" description:"可用角色类型 (1:平台角色, 2:客户角色)"` ParentID *uint `json:"parent_id" query:"parent_id" description:"父权限ID"` - Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态"` + Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态 (0:禁用, 1:启用)"` } // PermissionResponse 权限响应 @@ -46,13 +46,13 @@ type PermissionResponse struct { ID uint `json:"id" description:"权限ID"` PermName string `json:"perm_name" description:"权限名称"` PermCode string `json:"perm_code" description:"权限编码"` - PermType int `json:"perm_type" description:"权限类型"` - Platform string `json:"platform" description:"适用端口"` - AvailableForRoleTypes string `json:"available_for_role_types" description:"可用角色类型"` + PermType int `json:"perm_type" description:"权限类型 (1:菜单, 2:按钮)"` + Platform string `json:"platform" description:"适用端口 (all:全部, web:Web后台, h5:H5端)"` + AvailableForRoleTypes string `json:"available_for_role_types" description:"可用角色类型 (1:平台角色, 2:客户角色)"` URL string `json:"url,omitempty" description:"请求路径"` ParentID *uint `json:"parent_id,omitempty" description:"父权限ID"` Sort int `json:"sort" description:"排序值"` - Status int `json:"status" description:"状态"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` Creator uint `json:"creator" description:"创建人ID"` Updater uint `json:"updater" description:"更新人ID"` CreatedAt string `json:"created_at" description:"创建时间"` @@ -72,9 +72,9 @@ type PermissionTreeNode struct { ID uint `json:"id" description:"权限ID"` PermName string `json:"perm_name" description:"权限名称"` PermCode string `json:"perm_code" description:"权限编码"` - PermType int `json:"perm_type" description:"权限类型"` - Platform string `json:"platform" description:"适用端口"` - AvailableForRoleTypes string `json:"available_for_role_types" description:"可用角色类型"` + PermType int `json:"perm_type" description:"权限类型 (1:菜单, 2:按钮)"` + Platform string `json:"platform" description:"适用端口 (all:全部, web:Web后台, h5:H5端)"` + AvailableForRoleTypes string `json:"available_for_role_types" description:"可用角色类型 (1:平台角色, 2:客户角色)"` URL string `json:"url,omitempty" description:"请求路径"` Sort int `json:"sort" description:"排序值"` Children []*PermissionTreeNode `json:"children,omitempty" description:"子权限列表"` diff --git a/internal/model/personal_customer_dto.go b/internal/model/personal_customer_dto.go index b6fd571..664c528 100644 --- a/internal/model/personal_customer_dto.go +++ b/internal/model/personal_customer_dto.go @@ -2,29 +2,29 @@ package model // CreatePersonalCustomerRequest 创建个人客户请求 type CreatePersonalCustomerRequest struct { - Phone string `json:"phone" validate:"required"` // 手机号 - Nickname string `json:"nickname"` // 昵称 - AvatarURL string `json:"avatar_url"` // 头像URL - WxOpenID string `json:"wx_open_id"` // 微信OpenID - WxUnionID string `json:"wx_union_id"` // 微信UnionID + Phone string `json:"phone" validate:"required" required:"true" description:"手机号"` + Nickname string `json:"nickname" description:"昵称"` + AvatarURL string `json:"avatar_url" description:"头像URL"` + WxOpenID string `json:"wx_open_id" description:"微信OpenID"` + WxUnionID string `json:"wx_union_id" description:"微信UnionID"` } // UpdatePersonalCustomerRequest 更新个人客户请求 type UpdatePersonalCustomerRequest struct { - Phone *string `json:"phone"` // 手机号 - Nickname *string `json:"nickname"` // 昵称 - AvatarURL *string `json:"avatar_url"` // 头像URL + Phone *string `json:"phone" description:"手机号"` + Nickname *string `json:"nickname" description:"昵称"` + AvatarURL *string `json:"avatar_url" description:"头像URL"` } // PersonalCustomerResponse 个人客户响应 type PersonalCustomerResponse struct { - ID uint `json:"id"` - Phone string `json:"phone"` - Nickname string `json:"nickname"` - AvatarURL string `json:"avatar_url"` - WxOpenID string `json:"wx_open_id"` - WxUnionID string `json:"wx_union_id"` - Status int `json:"status"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + ID uint `json:"id" description:"客户ID"` + Phone string `json:"phone" description:"手机号"` + Nickname string `json:"nickname" description:"昵称"` + AvatarURL string `json:"avatar_url" description:"头像URL"` + WxOpenID string `json:"wx_open_id" description:"微信OpenID"` + WxUnionID string `json:"wx_union_id" description:"微信UnionID"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + CreatedAt string `json:"created_at" description:"创建时间"` + UpdatedAt string `json:"updated_at" description:"更新时间"` } diff --git a/internal/model/role_dto.go b/internal/model/role_dto.go index e013190..ae4599d 100644 --- a/internal/model/role_dto.go +++ b/internal/model/role_dto.go @@ -26,7 +26,7 @@ type RoleListRequest struct { PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"` RoleName string `json:"role_name" query:"role_name" validate:"omitempty,max=50" maxLength:"50" description:"角色名称模糊查询"` RoleType *int `json:"role_type" query:"role_type" validate:"omitempty,min=1,max=2" minimum:"1" maximum:"2" description:"角色类型 (1:平台角色, 2:客户角色)"` - Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态"` + Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态 (0:禁用, 1:启用)"` } // RoleResponse 角色响应 @@ -34,8 +34,8 @@ type RoleResponse struct { ID uint `json:"id" description:"角色ID"` RoleName string `json:"role_name" description:"角色名称"` RoleDesc string `json:"role_desc" description:"角色描述"` - RoleType int `json:"role_type" description:"角色类型"` - Status int `json:"status" description:"状态"` + RoleType int `json:"role_type" description:"角色类型 (1:平台角色, 2:客户角色)"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` Creator uint `json:"creator" description:"创建人ID"` Updater uint `json:"updater" description:"更新人ID"` CreatedAt string `json:"created_at" description:"创建时间"` diff --git a/internal/model/role_permission_dto.go b/internal/model/role_permission_dto.go index 9001a90..f6e7893 100644 --- a/internal/model/role_permission_dto.go +++ b/internal/model/role_permission_dto.go @@ -2,15 +2,15 @@ package model // RolePermissionResponse 角色-权限关联响应 type RolePermissionResponse struct { - ID uint `json:"id"` - RoleID uint `json:"role_id"` - PermID uint `json:"perm_id"` - Status int `json:"status"` - CreatedAt string `json:"created_at"` + ID uint `json:"id" description:"关联ID"` + RoleID uint `json:"role_id" description:"角色ID"` + PermID uint `json:"perm_id" description:"权限ID"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + CreatedAt string `json:"created_at" description:"创建时间"` } // RolePermissionsResponse 角色的权限列表响应 type RolePermissionsResponse struct { - RoleID uint `json:"role_id"` - Permissions []*PermissionResponse `json:"permissions"` + RoleID uint `json:"role_id" description:"角色ID"` + Permissions []*PermissionResponse `json:"permissions" description:"权限列表"` } diff --git a/internal/model/shop_account_dto.go b/internal/model/shop_account_dto.go index 470470a..29c710f 100644 --- a/internal/model/shop_account_dto.go +++ b/internal/model/shop_account_dto.go @@ -36,13 +36,13 @@ type UpdateShopAccountStatusRequest struct { // ShopAccountResponse 代理商账号响应 type ShopAccountResponse struct { - ID uint `json:"id"` - ShopID uint `json:"shop_id"` - ShopName string `json:"shop_name,omitempty"` // 关联查询时填充 - Username string `json:"username"` - Phone string `json:"phone"` - UserType int `json:"user_type"` - Status int `json:"status"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + ID uint `json:"id" description:"账号ID"` + ShopID uint `json:"shop_id" description:"店铺ID"` + ShopName string `json:"shop_name,omitempty" description:"店铺名称"` + Username string `json:"username" description:"用户名"` + Phone string `json:"phone" description:"手机号"` + UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + CreatedAt string `json:"created_at" description:"创建时间"` + UpdatedAt string `json:"updated_at" description:"更新时间"` } diff --git a/internal/model/shop_dto.go b/internal/model/shop_dto.go index ee9957d..14b5428 100644 --- a/internal/model/shop_dto.go +++ b/internal/model/shop_dto.go @@ -1,55 +1,55 @@ package model type ShopListRequest struct { - Page int `json:"page" query:"page" validate:"omitempty,min=1"` - PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100"` - ShopName string `json:"shop_name" query:"shop_name" validate:"omitempty,max=100"` - ShopCode string `json:"shop_code" query:"shop_code" validate:"omitempty,max=50"` - ParentID *uint `json:"parent_id" query:"parent_id" validate:"omitempty,min=1"` - Level *int `json:"level" query:"level" validate:"omitempty,min=1,max=7"` - Status *int `json:"status" query:"status" validate:"omitempty,oneof=0 1"` + Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码"` + PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"` + ShopName string `json:"shop_name" query:"shop_name" validate:"omitempty,max=100" maxLength:"100" description:"店铺名称模糊查询"` + ShopCode string `json:"shop_code" query:"shop_code" validate:"omitempty,max=50" maxLength:"50" description:"店铺编号模糊查询"` + ParentID *uint `json:"parent_id" query:"parent_id" validate:"omitempty,min=1" minimum:"1" description:"上级店铺ID"` + Level *int `json:"level" query:"level" validate:"omitempty,min=1,max=7" minimum:"1" maximum:"7" description:"店铺层级 (1-7级)"` + Status *int `json:"status" query:"status" validate:"omitempty,oneof=0 1" description:"状态 (0:禁用, 1:启用)"` } type CreateShopRequest struct { - ShopName string `json:"shop_name" validate:"required,min=1,max=100"` - ShopCode string `json:"shop_code" validate:"required,min=1,max=50"` - ParentID *uint `json:"parent_id" validate:"omitempty,min=1"` - ContactName string `json:"contact_name" validate:"omitempty,max=50"` - ContactPhone string `json:"contact_phone" validate:"omitempty,len=11"` - Province string `json:"province" validate:"omitempty,max=50"` - City string `json:"city" validate:"omitempty,max=50"` - District string `json:"district" validate:"omitempty,max=50"` - Address string `json:"address" validate:"omitempty,max=255"` - InitPassword string `json:"init_password" validate:"required,min=8,max=32"` - InitUsername string `json:"init_username" validate:"required,min=3,max=50"` - InitPhone string `json:"init_phone" validate:"required,len=11"` + ShopName string `json:"shop_name" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"店铺名称"` + ShopCode string `json:"shop_code" validate:"required,min=1,max=50" required:"true" minLength:"1" maxLength:"50" description:"店铺编号"` + ParentID *uint `json:"parent_id" validate:"omitempty,min=1" minimum:"1" description:"上级店铺ID(一级店铺可不填)"` + ContactName string `json:"contact_name" validate:"omitempty,max=50" maxLength:"50" description:"联系人姓名"` + ContactPhone string `json:"contact_phone" validate:"omitempty,len=11" minLength:"11" maxLength:"11" description:"联系人电话"` + Province string `json:"province" validate:"omitempty,max=50" maxLength:"50" description:"省份"` + City string `json:"city" validate:"omitempty,max=50" maxLength:"50" description:"城市"` + District string `json:"district" validate:"omitempty,max=50" maxLength:"50" description:"区县"` + Address string `json:"address" validate:"omitempty,max=255" maxLength:"255" description:"详细地址"` + InitPassword string `json:"init_password" validate:"required,min=8,max=32" required:"true" minLength:"8" maxLength:"32" description:"初始账号密码"` + InitUsername string `json:"init_username" validate:"required,min=3,max=50" required:"true" minLength:"3" maxLength:"50" description:"初始账号用户名"` + InitPhone string `json:"init_phone" validate:"required,len=11" required:"true" minLength:"11" maxLength:"11" description:"初始账号手机号"` } type UpdateShopRequest struct { - ShopName string `json:"shop_name" validate:"required,min=1,max=100"` - ContactName string `json:"contact_name" validate:"omitempty,max=50"` - ContactPhone string `json:"contact_phone" validate:"omitempty,len=11"` - Province string `json:"province" validate:"omitempty,max=50"` - City string `json:"city" validate:"omitempty,max=50"` - District string `json:"district" validate:"omitempty,max=50"` - Address string `json:"address" validate:"omitempty,max=255"` - Status int `json:"status" validate:"required,oneof=0 1"` + ShopName string `json:"shop_name" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"店铺名称"` + ContactName string `json:"contact_name" validate:"omitempty,max=50" maxLength:"50" description:"联系人姓名"` + ContactPhone string `json:"contact_phone" validate:"omitempty,len=11" minLength:"11" maxLength:"11" description:"联系人电话"` + Province string `json:"province" validate:"omitempty,max=50" maxLength:"50" description:"省份"` + City string `json:"city" validate:"omitempty,max=50" maxLength:"50" description:"城市"` + District string `json:"district" validate:"omitempty,max=50" maxLength:"50" description:"区县"` + Address string `json:"address" validate:"omitempty,max=255" maxLength:"255" description:"详细地址"` + Status int `json:"status" validate:"required,oneof=0 1" required:"true" description:"状态 (0:禁用, 1:启用)"` } // ShopResponse 店铺响应 type ShopResponse struct { - ID uint `json:"id"` - ShopName string `json:"shop_name"` - ShopCode string `json:"shop_code"` - ParentID *uint `json:"parent_id,omitempty"` - Level int `json:"level"` - ContactName string `json:"contact_name"` - ContactPhone string `json:"contact_phone"` - Province string `json:"province"` - City string `json:"city"` - District string `json:"district"` - Address string `json:"address"` - Status int `json:"status"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + ID uint `json:"id" description:"店铺ID"` + ShopName string `json:"shop_name" description:"店铺名称"` + ShopCode string `json:"shop_code" description:"店铺编号"` + ParentID *uint `json:"parent_id,omitempty" description:"上级店铺ID"` + Level int `json:"level" description:"店铺层级 (1-7级)"` + ContactName string `json:"contact_name" description:"联系人姓名"` + ContactPhone string `json:"contact_phone" description:"联系人电话"` + Province string `json:"province" description:"省份"` + City string `json:"city" description:"城市"` + District string `json:"district" description:"区县"` + Address string `json:"address" description:"详细地址"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + CreatedAt string `json:"created_at" description:"创建时间"` + UpdatedAt string `json:"updated_at" description:"更新时间"` }