Files
2026-10-25 23:18:44 +08:00

386 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# portal-mini-go 后台管理接口文档
> 基于 Go + gin 的中后台管理后端服务。本文档描述**后台管理(`/api/admin`)**相关接口。小程序端接口见 `miniapp-api.md`。
## 1. 概述
- **基础路径**:`/api/admin`
- **服务地址**:由 `configs/config.yaml` 中 `server.port` 决定(默认 `8080`),例如 `http://localhost:8080`。
- **统一响应**:所有接口均返回 `HTTP 200`,业务结果通过响应体中的 `code` 字段判断(见 §2.4)。
- **鉴权方式**:后台接口需在请求头携带 `Authorization: Bearer <JWT>`,由 `AdminAuth` 中间件校验(登录接口除外)。
- **全局接口**:`GET /healthz` 为健康检查,无需鉴权,返回 `{"code":0,"msg":"ok","data":{"status":"ok"}}`。
## 2. 公共约定
### 2.1 请求头
| Header | 必填 | 说明 |
| --- | --- | --- |
| `Content-Type` | 是(POST/PUT) | 固定为 `application/json`。 |
| `Authorization` | 是(登录除外) | 后台登录后下发的 JWT,格式 `Bearer <token>`。 |
### 2.2 统一响应结构
```json
{
"code": 0,
"msg": "ok",
"data": { }
}
```
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `code` | int | 业务码。`0` 表示成功;非 `0` 表示失败(见 §2.4)。 |
| `msg` | string | 结果描述。`0` 时为 `ok`,失败时为人可读信息。 |
| `data` | object/null | 业务数据,成功时有内容,失败时通常省略。 |
### 2.3 鉴权中间件
| 中间件 | 校验逻辑 |
| --- | --- |
| `AdminAuth` | 校验 `Authorization: Bearer <JWT>`(HS256)。校验通过后将 `admin_id` 注入上下文;登录接口 `POST /api/admin/login` 不挂载此中间件。 |
> 全局还挂载 `Recovery`(panic 恢复)、`Trace`(注入 trace_id)、`ErrorHandler`(统一错误转换)。错误由中间件转换,handler 内不直接散落 `c.JSON` 处理错误。
### 2.4 错误码
| 业务码 | 常量 | 含义 |
| --- | --- | --- |
| `0` | — | 成功 |
| `40000` | `ErrBadRequest` | 请求参数错误 / 非法输入(`ext` 非合法 JSON、用户状态非法等) |
| `40100` | `ErrUnauthorized` | 未认证 / 登录失败 / token 无效或过期 |
| `40300` | `ErrForbidden` | 禁止访问 |
| `40400` | `ErrNotFound` | 资源不存在(如小程序 / 用户 ID 不存在) |
| `50000` | `ErrServer` | 服务内部错误(含 token 签发等) |
> 非 `BizError` 的未知错误一律归为 `50000`。
## 3. 接口列表
### 3.1 `POST /api/admin/login`
后台管理员登录,签发 JWT。无需 `Authorization` 头。
**请求体**
```json
{
"username": "admin",
"password": "admin123"
}
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `username` | string | 是 | 管理员账号(当前示例固定 `admin`)。 |
| `password` | string | 是 | 密码(当前示例固定 `admin123`;生产应接 DB + 密码哈希)。 |
**响应**
```json
{ "code": 0, "msg": "ok", "data": { "token": "<JWT>" } }
```
**curl 示例**
```bash
curl -X POST http://localhost:8080/api/admin/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
```
### 3.2 `GET /api/admin/info`
受保护接口示例,需有效 JWT,返回当前管理员 ID。
**请求头**:`Authorization: Bearer <JWT>`
**响应**
```json
{ "code": 0, "msg": "ok", "data": { "admin_id": "1" } }
```
### 3.3 `POST /api/admin/miniapps`
新建被纳管小程序。
**请求头**:`Authorization: Bearer <JWT>`
**请求体**
```json
{
"name": "示例小程序",
"description": "用于演示",
"app_id": "wx1234567890",
"app_secret": "secret-xxxx",
"status": 1,
"ext": "{\"k\":\"v\"}"
}
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `name` | string | 是 | 小程序名称。 |
| `description` | string | 否 | 描述。 |
| `app_id` | string | 是 | 微信 AppID,全局唯一。 |
| `app_secret` | string | 是 | 微信 AppSecret(**不会在响应中返回**)。 |
| `status` | int8 | 否 | 状态:`0` 停用,`1` 启用。缺省为 `1`。 |
| `ext` | string | 否 | 扩展字段,必须为合法 JSON 字符串(允许空串)。 |
**响应**:返回创建后的 `MiniProgram` 对象(见 §4.1),`app_secret` 字段不返回。
### 3.4 `PUT /api/admin/miniapps/:id`
按 ID 局部更新小程序。
**请求头**:`Authorization: Bearer <JWT>`
**路径参数**
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| `id` | uint64 | 小程序主键。 |
**请求体**(所有字段均为可选,仅在提供时更新;`ext` 若提供需为合法 JSON)
```json
{
"name": "新名称",
"description": "新描述",
"app_secret": "new-secret",
"status": 0,
"ext": "{\"theme\":\"dark\"}"
}
```
> 字段以指针区分「未提供」与「置空」;若全部为空则不更新,直接返回原记录。
**响应**:返回更新后的 `MiniProgram` 对象。
### 3.5 `GET /api/admin/miniapps/:id`
查询单个小程序。
**请求头**:`Authorization: Bearer <JWT>`
**路径参数**:`id`(uint64)。
**响应**:返回 `MiniProgram` 对象;不存在返回 `40400`。
### 3.6 `GET /api/admin/miniapps`
分页列表查询小程序。
**请求头**:`Authorization: Bearer <JWT>`
**查询参数**
| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `status` | int8 | `-1`(全部) | 按状态筛选:`0` 停用,`1` 启用,`-1` 全部。 |
| `page` | int | `1` | 页码,从 1 开始。 |
| `size` | int | `20` | 每页条数。 |
**响应**
```json
{
"code": 0,
"msg": "ok",
"data": {
"list": [ { "id": 1, "name": "示例小程序", "app_id": "wx123...", "status": 1 } ],
"total": 1,
"page": 1,
"size": 20
}
}
```
**curl 示例**
```bash
curl "http://localhost:8080/api/admin/miniapps?status=1&page=1&size=20" \
-H "Authorization: Bearer <JWT>"
```
### 3.7 `DELETE /api/admin/miniapps/:id`
软删除小程序(置 `deleted_at`)。
**请求头**:`Authorization: Bearer <JWT>`
**路径参数**:`id`(uint64)。
**响应**
```json
{ "code": 0, "msg": "ok" }
```
### 3.8 `GET /api/admin/users`
分页列表查询小程序端用户,支持按小程序与关键字(昵称 / OpenID)过滤。
**请求头**:`Authorization: Bearer <JWT>`
**查询参数**
| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `mini_id` | uint64 | `0`(全部) | 按所属小程序筛选;`0` 表示不限小程序。 |
| `keyword` | string | 空 | 模糊匹配 `nickname` 或 `openid`(前后自动加 `%`)。 |
| `page` | int | `1` | 页码,从 1 开始。 |
| `size` | int | `20` | 每页条数。 |
**响应**
```json
{
"code": 0,
"msg": "ok",
"data": {
"list": [
{
"id": 1,
"mini_id": 10,
"openid": "oABC...",
"union_id": "",
"nickname": "张三",
"avatar": "https://...",
"status": 1,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:00:00Z"
}
],
"total": 1,
"page": 1,
"size": 20
}
}
```
**curl 示例**
```bash
curl "http://localhost:8080/api/admin/users?mini_id=10&keyword=张三&page=1&size=20" \
-H "Authorization: Bearer <JWT>"
```
### 3.9 `GET /api/admin/users/:id`
查询单个用户详情(后台视角,不限小程序)。
**请求头**:`Authorization: Bearer <JWT>`
**路径参数**
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| `id` | uint64 | 用户主键。 |
**响应**:返回 `User` 对象(见 §4.2);不存在返回 `40400`。
### 3.10 `PUT /api/admin/users/:id`
编辑用户资料(昵称 / 头像 / 状态)。字段均为可选,仅在提供时更新。
**请求头**:`Authorization: Bearer <JWT>`
**路径参数**:`id`(uint64)。
**请求体**
```json
{
"nickname": "新昵称",
"avatar": "https://new-avatar.png",
"status": 0
}
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `nickname` | string | 否 | 昵称,提供即更新。 |
| `avatar` | string | 否 | 头像 URL,提供即更新。 |
| `status` | int8 | 否 | 状态:`0` 禁用,`1` 正常;非法值返回 `40000`。 |
> 所有字段以指针区分「未提供」与「置空」;若全部为空则不更新,直接返回原记录。
**响应**:返回更新后的 `User` 对象。
### 3.11 `POST /api/admin/users/:id/status`
禁用 / 启用用户。
**请求头**:`Authorization: Bearer <JWT>`
**路径参数**:`id`(uint64)。
**请求体**
```json
{ "status": 0 }
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `status` | int8 | 是(binding:`required`) | `0` 禁用,`1` 正常;非法值返回 `40000`。 |
**响应**:返回更新后的 `User` 对象。
## 4. 数据模型
### 4.1 MiniProgram(被纳管小程序)
| 字段 | 类型 | JSON | 说明 |
| --- | --- | --- | --- |
| `ID` | uint64 | `id` | 主键,自增。 |
| `Name` | string | `name` | 名称。 |
| `Description` | string | `description` | 描述。 |
| `AppID` | string | `app_id` | 微信 AppID,全局唯一。 |
| `AppSecret` | string | `app_secret` | **不返回**(json `-`)。 |
| `Status` | int8 | `status` | `0` 停用,`1` 启用。 |
| `Ext` | string | `ext` | 扩展 JSON 文本。 |
| `CreatedAt` | time | `created_at` | 创建时间。 |
| `UpdatedAt` | time | `updated_at` | 更新时间。 |
### 4.2 User(小程序端用户)
| 字段 | 类型 | JSON | 说明 |
| --- | --- | --- | --- |
| `ID` | uint64 | `id` | 主键,自增。 |
| `MiniID` | uint64 | `mini_id` | 所属小程序(`mini_programs.id`)。 |
| `OpenID` | string | `openid` | 微信 OpenID,与 `mini_id` 共同唯一。 |
| `UnionID` | string | `union_id` | 微信 UnionID(可能为空)。 |
| `Nickname` | string | `nickname` | 昵称。 |
| `Avatar` | string | `avatar` | 头像 URL。 |
| `Status` | int8 | `status` | `0` 禁用,`1` 正常(默认 `1`)。 |
| `CreatedAt` | time | `created_at` | 创建时间。 |
| `UpdatedAt` | time | `updated_at` | 更新时间。 |
## 5. 配置说明(后台相关)
配置由 `configs/config.yaml` + 环境变量(支持 `${ENV}` 占位符)加载。敏感信息(DB 密码、JWT Secret)应通过环境变量注入,禁止硬编码。
| 配置项 | 说明 |
| --- | --- |
| `server.port` / `server.mode` | 服务端口、运行模式(`release` 时 gin 进入 ReleaseMode)。 |
| `mysql.*` | MySQL 连接与连接池参数,拼装为 DSN。 |
| `logging.level` / `logging.format` | 日志级别与格式(text/json)。 |
| `admin.jwt_secret` | 后台 JWT 签名密钥。 |
| `admin.token_ttl` | 后台 JWT 有效期(如 `24h`)。 |
## 6. 备注
- **后台账号**:`POST /api/admin/login` 当前为固定示例账号,生产环境需接入数据库与密码哈希校验。
- **小程序管理**:本分组下的 `miniapps` 接口用于纳管微信小程序配置(增删改查),是小程序端 `X-App-ID` 鉴权的数据来源。新增/修改这些接口时须同步更新本文档。
- **用户管理**:`/api/admin/users` 下的接口用于后台管理各小程序端用户(列表、详情、编辑、禁用/启用)。`User` 模型新增的 `status` 字段需手动在数据库中加列后方可生效(因项目未开启 AutoMigrate):
```sql
ALTER TABLE users ADD COLUMN status TINYINT NOT NULL DEFAULT 1;
```
新增/修改这些接口时须同步更新本文档。
- **RBAC 管理**:后台管理员、角色、权限的增删改查及关联分配接口见 [admin-rbac.md](./admin-rbac.md)(路由前缀 `/api/admin/rbac`,受 `admin:manage` / `role:manage` / `perm:manage` 守卫)。