Files
0451meishi/docs/API.md
2026-01-15 11:37:22 +08:00

341 lines
9.1 KiB
Markdown
Raw 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.
# API 使用说明(中文)
## Base URL
- 后端:`http://localhost:8080`
- Swagger推荐看这个字段更全`http://localhost:8081`(加载 `docs/openapi.yaml`
## 统一响应结构
后端所有接口统一返回:
```json
{ "code": 0, "message": "ok", "data": {}, "meta": {} }
```
- `code=0` 表示成功
- `code!=0` 表示失败(通常等于 HTTP 状态码)
## 必须携带的请求头
本项目所有 `/api/**` 接口都需要 APIKey
- `X-API-Key: <你的apikey>`
管理端接口(`/api/admin/**`,除登录外)还需要管理员 JWT
- `Authorization: Bearer <admin_token>`
用户端需要登录的接口(`/api/user/**` 的部分接口)需要用户 JWT
- `Authorization: Bearer <user_token>`
默认开发环境(可在 `backend/.env` 修改):
- `API_KEY=dev-api-key-change-me`
## PowerShell / curl 提示Windows
- Windows PowerShell 里的 `curl` 可能是 `Invoke-WebRequest` 的别名;建议用 `curl.exe``Invoke-RestMethod`
## 验证码Captcha
用户注册/登录 **必须先获取验证码**,再把 `captcha_id` + `captcha_code` 带到接口里。
### 获取验证码SVG
`GET /api/captcha/new`
```bash
curl.exe "http://localhost:8080/api/captcha/new" -H "X-API-Key: dev-api-key-change-me"
```
返回示例:
```json
{
"code": 0,
"message": "ok",
"data": {
"captcha_id": "c180df303849ea6dc75c670c4f1062b0",
"svg": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><svg ...>XHSXY</svg>"
}
}
```
说明:
- `captcha_id` 有效期 5 分钟
- 校验成功后删除(一次性使用)
- `svg` 是字符串:前端可用 `v-html` 渲染,或转成 `data:image/svg+xml` 显示在 `<img>`
PowerShell 测试(从 SVG 中提取验证码文本,仅用于本地调试):
```powershell
$apiKey='dev-api-key-change-me'
$cap = Invoke-RestMethod -Method Get -Uri http://localhost:8080/api/captcha/new -Headers @{"X-API-Key"=$apiKey}
$id = $cap.data.captcha_id
$svg = $cap.data.svg
$code = [regex]::Match($svg,'>([0-9A-Z]{5})<').Groups[1].Value
```
## 用户侧Web/小程序)
### 用户注册
`POST /api/user/register`
请求示例:
```bash
curl.exe -X POST "http://localhost:8080/api/user/register" `
-H "X-API-Key: dev-api-key-change-me" `
-H "Content-Type: application/json" `
-d "{\"username\":\"u1\",\"password\":\"pass123456\",\"captcha_id\":\"$CAPTCHA_ID\",\"captcha_code\":\"$CAPTCHA_CODE\"}"
```
请求结构体JSON
```json
{
"username": "u1",
"password": "pass123456",
"captcha_id": "xxxx",
"captcha_code": "ABCDE"
}
```
返回:
- `data.token`:用户 JWT
- `data.user`:用户信息
### 用户登录
`POST /api/user/login`
请求结构体JSON
```json
{
"username": "u1",
"password": "pass123456",
"captcha_id": "xxxx",
"captcha_code": "ABCDE"
}
```
返回:
- `data.token`:用户 JWT
- `data.user`:用户信息(简化字段)
### 当前用户
`GET /api/user/me`(需要 `Authorization: Bearer <user_token>`
### 我的评论记录
`GET /api/user/reviews?page=1&page_size=20`(需要 `Authorization: Bearer <user_token>`
### 提交评论(进入待审核)
`POST /api/user/stores/:id/reviews`
图片上传说明:
- 评论的 `image_urls` 需要先上传拿到图片 URL
- 用户上传接口:`POST /api/user/upload``multipart/form-data`,字段名 `file`
请求结构体JSON
```json
{
"rating": 5,
"content": "太好吃了",
"image_urls": ["http://localhost:8080/static/upload/2025/12/xx.jpg"],
"recommend_dishes": [
{ "name": "锅包肉", "image_url": "http://...", "like": true }
]
}
```
返回示例:
```json
{ "code": 0, "message": "ok", "data": { "id": 1, "status": "pending" } }
```
### 点赞店铺toggle
`POST /api/user/stores/:id/like`
返回示例:
```json
{ "code": 0, "message": "ok", "data": { "liked": true } }
```
### 店铺搜索 / 热榜(公开)
- 搜索:`GET /api/stores/search?keyword=锅包肉&page=1&page_size=20`(会累积热度)
- 热榜:`GET /api/stores/hot?by=hotness&limit=20`
### 公共读取接口(前端可直接调用)
- 分类列表:`GET /api/categories`(只返回 enabled=true
- 店铺列表:`GET /api/stores?page=1&page_size=20&category_id=1&keyword=xx`(只返回 active
- 店铺详情:`GET /api/stores/:id`(只返回 active
- 店铺评论:`GET /api/stores/:id/reviews?page=1&page_size=20`(只返回 approved
- 店铺排行:`GET /api/rankings/stores?by=hotness&page=1&page_size=20`
## 商家入驻(公开提交)
`POST /api/merchant/apply`
请求结构体JSON
```json
{
"store_name": "示例店铺",
"category_id": 1,
"address": "哈尔滨市xx路",
"open_hours": "10:00-22:00",
"phone": "13000000000",
"cover_url": "",
"image_urls": [],
"description": "商家描述",
"contact_name": "张三",
"contact_phone": "13000000000"
}
```
返回示例:
```json
{ "code": 0, "message": "ok", "data": { "id": 1, "status": "pending" } }
```
## 管理后台Admin
### 管理员登录
`POST /api/admin/login`
说明:
- 管理员登录也需要验证码(防止暴力破解)
- 先调用 `GET /api/captcha/new` 获取 `captcha_id` + `svg`,再提交到登录接口
```bash
curl.exe -X POST "http://localhost:8080/api/admin/login" `
-H "X-API-Key: dev-api-key-change-me" `
-H "Content-Type: application/json" `
-d "{\"username\":\"admin\",\"password\":\"admin123456\",\"captcha_id\":\"$CAPTCHA_ID\",\"captcha_code\":\"$CAPTCHA_CODE\"}"
```
返回:
- `data.token`:管理员 JWT
### CORS 跨域设置(可视化配置)
- 获取:`GET /api/admin/settings/cors`
- 保存:`PUT /api/admin/settings/cors`
保存 payload
```json
{ "origins": ["http://localhost:5173", "https://admin.example.com"] }
```
### 上传图片
`POST /api/admin/upload``multipart/form-data`,字段名 `file`
```bash
curl.exe -X POST "http://localhost:8080/api/admin/upload" `
-H "X-API-Key: dev-api-key-change-me" `
-H "Authorization: Bearer <admin_token>" `
-F "file=@./test.jpg"
```
返回:
- `data.url`:可访问 URL例如 `http://localhost:8080/static/upload/2025/12/xx.jpg`
### 用户上传图片(用于评论)
`POST /api/user/upload``multipart/form-data`,字段名 `file`,需要用户 JWT
```bash
curl.exe -X POST "http://localhost:8080/api/user/upload" `
-H "X-API-Key: dev-api-key-change-me" `
-H "Authorization: Bearer <user_token>" `
-F "file=@./test.jpg"
```
### 分类管理
- 列表:`GET /api/admin/categories?page=1&page_size=20&keyword=xxx`
- 新增:`POST /api/admin/categories`
- 编辑:`PUT /api/admin/categories/:id`
- 删除:`DELETE /api/admin/categories/:id`
新增/编辑 payload
```json
{ "name": "烧烤", "icon_url": "", "sort_order": 10, "enabled": true }
```
### 店铺管理
- 列表:`GET /api/admin/stores?page=1&page_size=20&keyword=xx&status=active&category_id=1`
- 详情:`GET /api/admin/stores/:id`
- 新增:`POST /api/admin/stores`
- 编辑:`PUT /api/admin/stores/:id`
- 上下架:`PATCH /api/admin/stores/:id/status``{"status":"active|inactive"}`
- 删除:`DELETE /api/admin/stores/:id`
新增/编辑 payload
```json
{
"name": "示例店铺",
"category_id": 1,
"address": "哈尔滨市xx路",
"open_hours": "10:00-22:00",
"phone": "13000000000",
"cover_url": "http://localhost:8080/static/upload/2025/12/cover.jpg",
"description": "描述",
"status": "active",
"images": [{ "url": "http://...", "sort_order": 0 }],
"dishes": [{ "name": "锅包肉", "description": "必点", "image_url": "http://...", "sort_order": 0 }]
}
```
### 评论管理(审核/删除)
- 列表:`GET /api/admin/reviews?page=1&page_size=20&status=pending&store_id=1&user_id=2`
- 审核:`PATCH /api/admin/reviews/:id/status``{"status":"pending|approved|blocked"}`
- 删除:`DELETE /api/admin/reviews/:id`
### 商家入驻审核
- 列表:`GET /api/admin/merchant/applications?status=pending&page=1&page_size=20`
- 审核:`PATCH /api/admin/merchant/applications/:id/review`
审核 payload
- 通过:`{ "action": "approve" }`
- 拒绝:`{ "action": "reject", "reject_reason": "资料不完整" }`
### 排行管理
- 查看排行:`GET /api/admin/rankings/stores?by=hotness&page=1&page_size=20`
- `by=hotness|likes|search|reviews`
- 重算综合分:`POST /api/admin/rankings/stores/recalc`
### APIKey 管理
- 列表:`GET /api/admin/apikeys?page=1&page_size=20`
- 创建:`POST /api/admin/apikeys`(创建成功会返回一次性明文 `data.key`,请立即保存)
- 撤销:`PATCH /api/admin/apikeys/:id/revoke`
### 用户管理(管理端)
- 列表:`GET /api/admin/users?keyword=xx&status=active&page=1&page_size=20`
- 详情:`GET /api/admin/users/:id`
- 启用/禁用:`PATCH /api/admin/users/:id/status``{"status":"active|disabled"}`
### 管理员管理
- 列表:`GET /api/admin/admins?keyword=xx&page=1&page_size=20`
- 新增:`POST /api/admin/admins`
- 重置密码:`PATCH /api/admin/admins/:id/password`
- 启用/禁用:`PATCH /api/admin/admins/:id/enabled`
新增 payload
```json
{ "username": "ops", "password": "StrongPass123", "enabled": true }
```
## OpenAPI
- 文件:`docs/openapi.yaml`
- Swagger UI`http://localhost:8081`