From 5cd8f0f551f1d76535e984fa9f781a68dbcfdc3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E7=8A=80=E9=BA=9F?= Date: Mon, 24 Aug 2026 18:07:33 +0800 Subject: [PATCH] =?UTF-8?q?refactor(api):=20=E5=A5=91=E7=BA=A6=E6=96=87?= =?UTF-8?q?=E4=BB=B6=20index.go=20=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20.go?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - tools/{uuid,md5,random,time,ip}/index.go → 对应 <功能名>.go(git mv 保留历史) - 目录名=包名=文件名三一致,扩展时目录内按功能加文件(ocr.go → + idcard.go + invoice.go) - doc.go / AGENTS.md / PROJECT_STRUCTURE.md 同步规则说明 - 冒烟测试 5 端点全部通过 --- AGENTS.md | 6 ++--- PROJECT_STRUCTURE.md | 2 +- api/open/v1/tools/doc.go | 20 +++++++++------ api/open/v1/tools/ip/{index.go => ip.go} | 0 api/open/v1/tools/md5/{index.go => md5.go} | 0 .../v1/tools/random/{index.go => random.go} | 0 api/open/v1/tools/time/{index.go => time.go} | 0 api/open/v1/tools/uuid/{index.go => uuid.go} | 0 docs/change-log/2026-08-24.md | 25 +++++++++++++++++++ 9 files changed, 41 insertions(+), 12 deletions(-) rename api/open/v1/tools/ip/{index.go => ip.go} (100%) rename api/open/v1/tools/md5/{index.go => md5.go} (100%) rename api/open/v1/tools/random/{index.go => random.go} (100%) rename api/open/v1/tools/time/{index.go => time.go} (100%) rename api/open/v1/tools/uuid/{index.go => uuid.go} (100%) diff --git a/AGENTS.md b/AGENTS.md index 3ed19ae..0d034a3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,7 +26,7 @@ service.xpcool.com/ │ ├── user/v1/ # /api/v1 用户端 API(登录公开,其余走 UserAuth) │ ├── admin/v1/ # /admin/v1 管理端 API(AdminAuth + X-Permission) │ └── open/v1/ # /api/open/v1 开放接口(给前端调用,公开无鉴权) -│ └── tools/ # 工具子功能契约,每子功能一目录:tools//index.go +│ └── tools/ # 工具子功能契约,每子功能一目录:tools//.go ├── common/ # 公共可复用模块(不依赖 internal,可独立抽取成库) │ └── tools/ # 工具模块,按子功能分包(见下文) ├── internal/ @@ -48,9 +48,9 @@ service.xpcool.com/ - **命名决策**:公共接口前缀用 **open**(不用 common)。理由:`common` 语义偏"内部公共代码",`open` 是开放接口业界惯例(支付宝 /open/api 等),更能表达"对外暴露、无鉴权"。同属"公开"语义的备选还有 `public`。 - 路由前缀 `/api/open/v1`,**公开、无鉴权**,实现于 `internal/controller/open`。 -- **tools 子功能目录规则**:`api/open/v1/tools/<子功能名>/index.go` 定义该子功能的 Req/Res 契约(index.go 内 `package <子功能名>`);控制器 `internal/controller/open/<子功能名>.go` 放对应方法(controller 统一 `package open`)。 +- **tools 子功能目录规则**:`api/open/v1/tools/<子功能名>/<子功能名>.go` 定义该子功能的 Req/Res 契约(目录名=包名=文件名三一致);控制器 `internal/controller/open/<子功能名>.go` 放对应方法(controller 统一 `package open`)。子功能变大后按端点/子领域在目录内**加文件**(如 ocr 目录下 `ocr.go` → `ocr.go + idcard.go + invoice.go`),不要堆在一个文件里。 - 当前端点:`GET/POST /tools/*`(uuid、md5、random、time、ip),底层复用 `common/tools` Go 包。 -- **新增子功能三步**:① `api/open/v1/tools//index.go` 写 Req/Res(g.Meta 带 path/method);② `internal/controller/open/.go` 加方法;③ 路由自动绑定,无需改 cmd.go。 +- **新增子功能三步**:① `api/open/v1/tools//.go` 写 Req/Res(g.Meta 带 path/method);② `internal/controller/open/.go` 加方法;③ 路由自动绑定,无需改 cmd.go。 ## 公共工具模块 common/tools diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md index 0e46967..4ee1f41 100644 --- a/PROJECT_STRUCTURE.md +++ b/PROJECT_STRUCTURE.md @@ -6,7 +6,7 @@ service.xpcool.com/ │ ├── user/v1/ # /api/v1 - client-facing API │ ├── admin/v1/ # /admin/v1 - administration API │ └── open/v1/ # /api/open/v1 - open API for frontends (no auth) -│ └── tools/ # one dir per sub-feature: tools//index.go +│ └── tools/ # one dir per sub-feature: tools//.go ├── common/ # public reusable module (no internal/ deps) │ └── tools/ # utility toolbox: md5, cryptox, uuid, random, │ # timex, convertx, strx, slicex, ip, filex diff --git a/api/open/v1/tools/doc.go b/api/open/v1/tools/doc.go index 6154071..b9ec226 100644 --- a/api/open/v1/tools/doc.go +++ b/api/open/v1/tools/doc.go @@ -1,14 +1,18 @@ // Package tools hosts the open API tool endpoints (GET/POST /tools/*). // -// Naming rule: every sub-feature gets its own directory under tools/, and the -// Req/Res contracts live in an index.go inside that directory, e.g. +// Naming rule: every sub-feature gets its own directory under tools/, named +// after the feature (dir name = package name), and the Req/Res contracts live +// in a file named after the feature inside that directory, e.g. // -// api/open/v1/tools/uuid/index.go - GET /tools/uuid -// api/open/v1/tools/md5/index.go - POST /tools/md5 -// api/open/v1/tools/random/index.go - GET /tools/random -// api/open/v1/tools/time/index.go - GET /tools/time -// api/open/v1/tools/ip/index.go - GET /tools/ip +// api/open/v1/tools/uuid/uuid.go - GET /tools/uuid +// api/open/v1/tools/md5/md5.go - POST /tools/md5 +// api/open/v1/tools/random/random.go - GET /tools/random +// api/open/v1/tools/time/time.go - GET /tools/time +// api/open/v1/tools/ip/ip.go - GET /tools/ip // -// Add a new feature by creating tools//index.go and a matching method +// As a feature grows, add more files inside its directory (e.g. idcard.go, +// invoice.go under ocr/) instead of bloating the starting file. +// +// Add a new feature by creating tools//.go and a matching method // in internal/controller/open/.go; the router binds it automatically. package tools diff --git a/api/open/v1/tools/ip/index.go b/api/open/v1/tools/ip/ip.go similarity index 100% rename from api/open/v1/tools/ip/index.go rename to api/open/v1/tools/ip/ip.go diff --git a/api/open/v1/tools/md5/index.go b/api/open/v1/tools/md5/md5.go similarity index 100% rename from api/open/v1/tools/md5/index.go rename to api/open/v1/tools/md5/md5.go diff --git a/api/open/v1/tools/random/index.go b/api/open/v1/tools/random/random.go similarity index 100% rename from api/open/v1/tools/random/index.go rename to api/open/v1/tools/random/random.go diff --git a/api/open/v1/tools/time/index.go b/api/open/v1/tools/time/time.go similarity index 100% rename from api/open/v1/tools/time/index.go rename to api/open/v1/tools/time/time.go diff --git a/api/open/v1/tools/uuid/index.go b/api/open/v1/tools/uuid/uuid.go similarity index 100% rename from api/open/v1/tools/uuid/index.go rename to api/open/v1/tools/uuid/uuid.go diff --git a/docs/change-log/2026-08-24.md b/docs/change-log/2026-08-24.md index 47dbd2b..725e950 100644 --- a/docs/change-log/2026-08-24.md +++ b/docs/change-log/2026-08-24.md @@ -128,3 +128,28 @@ - 前端若已联调旧 `/api/common/v1` 路径需同步改 `/api/open/v1`(当前无线上前端,风险低)。 - 新增子功能记得更新 `api/open/v1/tools/doc.go` 的示例清单。 + +--- + +## 追加(18:08):契约文件 index.go → <功能名>.go + +### 请求 + +用户咨询"子功能目录内用 index.go 还是 <功能名>.go 更易扩展维护",确认推荐后执行改动。 + +### 变更 + +- `git mv` 重命名 5 个契约文件:`tools/{uuid,md5,random,time,ip}/index.go` → `tools/{uuid,md5,random,time,ip}/{uuid,md5,random,time,ip}.go`(包内容不变) +- `api/open/v1/tools/doc.go` — 规则说明改为「目录名=包名=文件名三一致」,补充"功能变大后目录内加文件"的扩展指引 +- `AGENTS.md` / `PROJECT_STRUCTURE.md` — 同步 index.go 引用为 .go + +验证:`go build ./...`、`go vet` 通过;冒烟测试 5 端点全部正常。 + +### 决策与理由 + +- **选 <功能名>.go 而非 index.go**:① 目录名=包名=文件名三一致,导航直观;② index.go 是"入口"语义,功能膨胀后出现 `index.go + idcard.go` 混排会失去入口意义,而 `.go + idcard.go` 自然;③ 符合 Go 生态主流(strings/strings.go)与 GoFrame 官方模板(api/user/v1/user.go)。 +- **扩展路径已定型**:子功能从 1 个端点到多个端点,只需在目录内加文件(如 ocr 目录 `ocr.go → + idcard.go + invoice.go`),无需重构文件名。 + +### 待办与风险 + +- 无新增风险;后续新增子功能统一按 `tools//.go` 建文件。