Files
Neo-ZQYY/apps/backend/docs/API-REFERENCE.md

634 lines
17 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 参考手册
后端 API 基于 FastAPI 构建,所有端点均以 `/api/` 为前缀。
在线文档:启动后访问 `http://localhost:8000/docs`Swagger UI`/redoc`ReDoc
## 全局响应格式RNS1.0
所有 JSON 成功响应HTTP 2xx自动包装为统一格式
```json
{ "code": 0, "data": { ... } }
```
异常响应格式:
```json
{ "code": 401, "message": "未认证" }
```
规则:
- `code=0` 表示成功,`data` 为业务数据
- `code≠0` 表示错误,`code` 为 HTTP 状态码,`message` 为错误描述
- SSE 流式端点(`text/event-stream`)和非 JSON 响应不包装,直接透传
- 所有小程序 API 响应字段名为 camelCase`userId``storeName`
---
## 1. 管理后台认证 `/api/auth`
### POST `/api/auth/login`
管理后台用户名密码登录。
请求体:
```json
{ "username": "admin", "password": "..." }
```
响应:
```json
{ "access_token": "...", "refresh_token": "...", "token_type": "bearer" }
```
### POST `/api/auth/refresh`
刷新访问令牌。
请求体:
```json
{ "refresh_token": "..." }
```
---
## 2. 小程序认证 `/api/xcx-auth`
小程序用户的完整生命周期:微信登录 → 提交申请 → 管理员审批 → 正式使用。
### POST `/api/xcx-auth/login`
微信登录。用 `wx.login()` 获取的 code 换取 JWT。
请求体:
```json
{ "code": "微信临时登录凭证" }
```
响应:
```json
{
"access_token": "...",
"refresh_token": "...",
"token_type": "bearer",
"user_status": "pending | approved | rejected | disabled",
"user_id": 1
}
```
说明:
- 首次登录自动创建 `auth.users` 记录status=new前端引导至申请页
- new/pending/rejected 用户获得受限令牌(`limited=True`),仅可访问申请相关端点
- approved 用户获得完整令牌,包含 `site_id``roles`
### POST `/api/xcx-auth/apply`
提交入驻申请。需受限令牌或完整令牌。
请求体:
```json
{
"site_code": "AB123",
"applied_role_text": "助教",
"phone": "13800138000",
"employee_number": "E001",
"nickname": "张三"
}
```
说明:
- `site_code` 格式2 字母 + 3 数字(如 `AB123`),映射到 `auth.site_code_mapping`
- 后端自动进行人员匹配(`matching.py`),在 ETL 库中查找助教/员工记录
### GET `/api/xcx-auth/status`
查询当前用户状态和申请记录。需受限令牌或完整令牌。
响应:
```json
{
"user_id": 1,
"status": "approved",
"nickname": "张三",
"applications": [
{
"id": 1,
"site_code": "AB123",
"applied_role_text": "助教",
"status": "approved",
"review_note": null,
"created_at": "2026-02-25T10:00:00",
"reviewed_at": "2026-02-25T11:00:00"
}
]
}
```
### GET `/api/xcx-auth/sites`
获取当前用户关联的门店列表。需完整令牌。
### POST `/api/xcx-auth/switch-site`
切换当前门店,返回新的令牌对。需完整令牌。
请求体:
```json
{ "site_id": 2 }
```
### POST `/api/xcx-auth/refresh`
刷新令牌。
请求体:
```json
{ "refresh_token": "..." }
```
### POST `/api/xcx-auth/dev-login`
开发模式 mock 登录(仅 `WX_DEV_MODE=true` 时注册)。
请求体:
```json
{ "openid": "模拟openid", "status": "approved" }
```
说明:
- `status` 可选,为空时保留已有用户当前状态,新用户默认 `new`
- 仅开发/测试环境可用
---
## 3. 任务配置 `/api/tasks`
所有端点需 JWT 认证。
### GET `/api/tasks/registry`
按业务域分组的 ETL 任务列表。
响应示例:
```json
{
"groups": {
"会员": [
{
"code": "DWD_LOAD_FROM_ODS",
"name": "ODS → DWD 加载",
"domain": "会员",
"layer": "DWD",
"requires_window": true,
"is_ods": false,
"is_dimension": false,
"default_enabled": true,
"is_common": true
}
]
}
}
```
### GET `/api/tasks/dwd-tables`
按业务域分组的 DWD 表定义。
### GET `/api/tasks/flows`
返回 7 种 Flow 定义和 4 种处理模式。
Flow 列表:
| ID | 名称 | 层级 |
|----|------|------|
| `api_ods` | API → ODS | ODS |
| `api_ods_dwd` | API → ODS → DWD | ODS, DWD |
| `api_full` | API → ODS → DWD → DWS → INDEX | ODS, DWD, DWS, INDEX |
| `ods_dwd` | ODS → DWD | DWD |
| `dwd_dws` | DWD → DWS汇总 | DWS |
| `dwd_dws_index` | DWD → DWS → INDEX | DWS, INDEX |
| `dwd_index` | DWD → DWS指数 | INDEX |
处理模式:
| ID | 名称 | 说明 |
|----|------|------|
| `increment_only` | 仅增量处理 | 只处理新增和变更的数据 |
| `verify_only` | 仅校验修复 | 校验现有数据并修复不一致 |
| `increment_verify` | 增量 + 校验修复 | 先增量处理,再校验并修复 |
| `full_window` | 全窗口处理 | 用 API 返回数据的实际时间范围处理全部层 |
### POST `/api/tasks/validate`
验证任务配置并返回 CLI 命令预览。`store_id` 从 JWT 自动注入。
### GET `/api/tasks/sync-check`
对比后端硬编码任务列表与 ETL 真实注册表,返回差异。
---
## 4. 任务执行 `/api/execution`
所有端点需 JWT 认证,`site_id` 从 JWT 提取。
### POST `/api/execution/run`
直接执行任务(不经过队列)。异步启动 ETL CLI 子进程。
请求体:`TaskConfigSchema`flow、tasks、window 等)
响应:
```json
{ "execution_id": "uuid", "message": "任务已提交执行" }
```
### GET `/api/execution/queue`
获取当前门店的待执行队列。
### POST `/api/execution/queue`
将任务配置添加到执行队列。
### PUT `/api/execution/queue/reorder`
调整队列中任务的执行顺序。
### DELETE `/api/execution/queue/{task_id}`
从队列中删除待执行任务(仅 pending 状态)。
### POST `/api/execution/{execution_id}/cancel`
取消正在执行的任务。
### GET `/api/execution/history`
执行历史记录(按 `started_at` 降序,默认 50 条,最多 200 条)。
### GET `/api/execution/{execution_id}/logs`
获取指定执行的完整日志。优先从内存缓冲区读取(执行中),否则从数据库读取(已完成)。
---
## 5. 调度管理 `/api/schedules`
所有端点需 JWT 认证。
### GET `/api/schedules`
列出当前门店的所有调度任务。
### POST `/api/schedules`
创建调度任务,自动计算 `next_run_at`
### PUT `/api/schedules/{schedule_id}`
更新调度任务(部分更新,仅更新请求中提供的字段)。
### DELETE `/api/schedules/{schedule_id}`
删除调度任务。
### PATCH `/api/schedules/{schedule_id}/toggle`
切换启用/禁用状态。禁用时 `next_run_at` 置 NULL启用时重新计算。
---
## 6. 数据库查看器 `/api/db`
所有端点需 JWT 认证。使用 ETL 只读连接 + RLS 门店隔离。
### GET `/api/db/schemas`
返回 ETL 数据库中的 Schema 列表。
### GET `/api/db/schemas/{name}/tables`
返回指定 Schema 下所有表的名称和行数统计。
### GET `/api/db/tables/{schema}/{table}/columns`
返回指定表的列定义(列名、数据类型、是否可空、默认值)。
### POST `/api/db/query`
只读 SQL 执行。
安全措施:
- 拦截写操作关键词INSERT / UPDATE / DELETE / DROP / TRUNCATE
- 返回行数上限 1000 行
- 查询超时 30 秒
- 连接级 `read_only` 保护
请求体:
```json
{ "sql": "SELECT * FROM dwd.member_info LIMIT 10" }
```
---
## 7. ETL 状态 `/api/etl-status`
### GET `/api/etl-status/cursors`
返回各 ODS 表的最新数据游标(查询 `meta.etl_cursor`)。
### GET `/api/etl-status/recent-runs`
返回最近 50 条任务执行记录。
---
## 8. 环境配置 `/api/env-config`
### GET `/api/env-config`
读取根 `.env` 文件内容(敏感值脱敏显示)。
### PUT `/api/env-config`
更新 `.env` 文件中的配置项。
---
## 9. 运维面板 `/api/ops`
### GET `/api/ops/system`
服务器系统资源概况CPU、内存、磁盘、启动时间
### GET `/api/ops/services`
所有环境test/prod的服务运行状态PID、端口、内存、CPU、运行时长
### POST `/api/ops/services/{env}/start`
启动指定环境的后端服务。
### POST `/api/ops/services/{env}/stop`
停止指定环境的后端服务。
### POST `/api/ops/services/{env}/restart`
重启指定环境的后端服务。
### GET `/api/ops/git`
所有环境的 Git 状态(分支、最新提交、是否有本地修改)。
### POST `/api/ops/git/{env}/pull`
对指定环境执行 `git pull --ff-only`
### POST `/api/ops/git/{env}/sync-deps`
对指定环境执行 `uv sync --all-packages`
### GET `/api/ops/env-file/{env}`
读取指定环境的 `.env` 文件(敏感值脱敏)。
---
## 10. 其他端点
### GET `/health`
健康检查。返回 `{"status": "ok"}`
### GET `/api/xcx-test`
MVP 全链路验证端点,从 `test."xcx-test"` 表读取数据。
### GET/POST `/api/wx-callback`
微信消息推送回调。GET 用于签名验证POST 用于接收消息。
---
## 11. 管理端申请审核 `/api/admin/applications`
### GET `/api/admin/applications`
获取待审核申请列表。需管理后台 JWT。
### POST `/api/admin/applications/{id}/approve`
批准申请。
### POST `/api/admin/applications/{id}/reject`
拒绝申请。
---
## 12. 营业日配置 `/api/business-day`
### GET `/api/business-day/config`
获取营业日分割点配置(`BUSINESS_DAY_START_HOUR`)。
---
## 13. 小程序任务 `/api/xcx/tasks`
所有端点需 JWTapproved 状态)。
### GET `/api/xcx/tasks`
获取当前助教的活跃任务列表。
响应:`TaskListItem[]`
### POST `/api/xcx/tasks/{id}/pin`
置顶任务。
### POST `/api/xcx/tasks/{id}/unpin`
取消置顶。
### POST `/api/xcx/tasks/{id}/abandon`
放弃任务(需填写原因)。
请求体:
```json
{ "reason": "放弃原因" }
```
### POST `/api/xcx/tasks/{id}/restore`
取消放弃,恢复为活跃状态。
### GET `/api/xcx/tasks/{id}`
获取任务详情TASK-2。返回单个任务的完整信息含服务记录、备注、AI 分析、维客线索。
响应包含 `customerId` 字段,供前端跳转客户详情/对话页面使用。
---
## 14. 小程序绩效 `/api/xcx/performance`
所有端点需 JWTapproved 状态)。
### GET `/api/xcx/performance`
绩效概览PERF-1。返回指定月份的收入档位、DateGroup 分组记录、新客/常客列表。
查询参数:
- `month`:月份(格式 `YYYY-MM`,默认当月)
响应包含:`currentTier`/`nextTier`/`upgradeHoursNeeded`/`upgradeBonus`(收入档位)、`thisMonthRecords`DateGroup 分组)、`lastMonthIncome``incomeItems`(含 desc`newCustomers`/`regularCustomers`
### GET `/api/xcx/performance/records`
绩效明细PERF-2。返回指定月份的服务记录明细按日期分组支持分页。
查询参数:
- `month`:月份(格式 `YYYY-MM`,默认当月)
- `page`:页码(默认 1
- `page_size`:每页条数(默认 20
---
## 15. 小程序备注 `/api/xcx/notes`
所有端点需 JWTapproved 状态)。
### POST `/api/xcx/notes`
创建备注(含星星评分,可选关联任务)。
请求体:
```json
{
"target_type": "member",
"target_id": 1,
"content": "备注内容",
"task_id": null,
"rating_service_willingness": 4,
"rating_revisit_likelihood": 3
}
```
### GET `/api/xcx/notes`
查询某目标的备注列表(按创建时间倒序)。
查询参数:
- `target_type`:目标类型(默认 `member`
- `target_id`:目标 ID必填
### DELETE `/api/xcx/notes/{id}`
删除备注(验证归属后硬删除)。
---
## 16. 小程序配置 `/api/xcx/config`
所有端点需 JWTapproved 状态)。
### GET `/api/xcx/config/skill-types`
项目类型筛选器配置CONFIG-1。返回前端筛选器选项列表。
数据源:`app.v_cfg_area_category`(基于 `dws.cfg_area_category` 去重到 category 级别,排除 SPECIAL/OTHER按 sort_order 排序)。
响应头部自动插入"不限"选项key=ALL不存储在数据库中。
响应:`SkillTypeItem[]`
```json
[
{ "key": "ALL", "label": "不限", "emoji": "🔍", "cls": "" },
{ "key": "BILLIARD", "label": "🎱 中式/追分", "emoji": "🎱", "cls": "" },
{ "key": "SNOOKER", "label": "斯诺克", "emoji": "斯", "cls": "" },
{ "key": "MAHJONG", "label": "🀄 麻将/棋牌", "emoji": "🀄", "cls": "" },
{ "key": "KTV", "label": "🎤 团建/K歌", "emoji": "🎤", "cls": "" }
]
```
降级行为:查询失败时返回空数组 `[]`
---
## 17. 小程序三看板 `/api/xcx/board`
所有端点需 JWT + 对应权限。
### GET `/api/xcx/board/coaches`
助教看板BOARD-1。返回助教列表支持排序×技能×时间三重筛选。
查询参数:
- `sort`:排序维度(`perf_desc`/`perf_asc`/`salary_desc`/`salary_asc`/`sv_desc`/`task_desc`,默认 `perf_desc`
- `skill`:技能筛选(`ALL`/`BILLIARD`/`SNOOKER`/`MAHJONG`/`KTV`,默认 `ALL`
- `time`:时间范围(`month`/`quarter`/`last_month`/`last_3m`/`last_quarter`/`last_6m`,默认 `month`
约束:`time=last_6m` + `sort=sv_desc` 互斥,返回 400。
权限:`view_board_coach`
响应:`CoachBoardResponse`(含 `items` + `dimType`
### GET `/api/xcx/board/customers`
客户看板BOARD-2。返回客户列表支持维度×项目筛选 + 分页。
查询参数:
- `dimension`:客户维度(`recall`/`potential`/`balance`/`recharge`/`recent`/`spend60`/`freq60`/`loyal`,默认 `recall`
- `project`:项目筛选(`ALL`/`BILLIARD`/`SNOOKER`/`MAHJONG`/`KTV`,默认 `ALL`
- `page`:页码(默认 1
- `page_size`:每页条数(默认 20最大 100
权限:`view_board_customer`
响应:`CustomerBoardResponse`(含 `items`/`total`/`page`/`pageSize`
### GET `/api/xcx/board/finance`
财务看板BOARD-3。返回 6 大板块(经营一览/预收资产/营收结构/现金流/支出/助教分析)。
查询参数:
- `time`:时间范围(`month`/`lastMonth`/`week`/`lastWeek`/`quarter3`/`quarter`/`lastQuarter`/`half6`,默认 `month`
- `area`:区域筛选(`all`/`hall`/`hallA`/`hallB`/`hallC`/`mahjong`/`teamBuilding`,默认 `all`
- `compare`环比开关0=关闭/1=开启,默认 0
约束:`area≠all``recharge` 板块为 null`compare=0` 时响应不含环比字段。
权限:`view_board_finance`
响应:`FinanceBoardResponse`(含 `overview`/`recharge`/`revenue`/`cashflow`/`expense`/`coachAnalysis`
---
## 18. 小程序 CHAT `/api/xcx/chat`
所有端点需 JWTapproved 状态)。替代原 `xcx_ai_chat``/api/ai/*`),统一迁移到 `/api/xcx/chat/*` 路径。
### GET `/api/xcx/chat/history`
对话历史列表CHAT-1。返回当前用户的对话列表按最后消息时间倒序。
查询参数:
- `page`:页码(默认 1
- `page_size`:每页条数(默认 20最大 100
响应:`ChatHistoryResponse`(含 `items`/`total`/`page`/`pageSize`
每条对话包含:`id`(对话 ID`title`(对话标题)、`customerName`(关联客户姓名,可选)、`lastMessage`(最后消息摘要)、`timestamp`(最后消息时间)、`unreadCount`(未读数)。
### GET `/api/xcx/chat/messages`
通过上下文查询消息CHAT-2b。根据 `contextType` + `contextId` 自动查找或创建对话。
查询参数:
- `contextType`:上下文类型(`task`/`customer`/`coach`/`general`,必填)
- `contextId`:上下文 ID必填
- `page`:页码(默认 1
- `page_size`:每页条数(默认 50最大 100
对话复用规则:`task` 始终复用(无时限);`customer`/`coach` ≤ 3 天复用、> 3 天新建;`general` 始终新建。
响应:`ChatMessagesResponse`(含 `chatId`/`items`/`total`/`page`/`pageSize`
### GET `/api/xcx/chat/{chat_id}/messages`
通过 chatId 查询消息CHAT-2a。消息按 `created_at` 正序。
路径参数:
- `chat_id`:对话 ID
查询参数:
- `page`:页码(默认 1
- `page_size`:每页条数(默认 50最大 100
响应:`ChatMessagesResponse`
每条消息包含:`id``role``user`/`assistant`)、`content``createdAt``referenceCard`(可选,含 `type`/`title`/`summary`/`data` 键值对)。
### POST `/api/xcx/chat/{chat_id}/messages`
发送消息并获取同步 AI 回复CHAT-3。chatId 归属验证:不属于当前用户返回 403。
请求体:
```json
{ "content": "消息内容" }
```
响应:`SendMessageResponse`(含 `userMessage``aiReply`,各含 `id`/`content`/`createdAt`
AI 失败降级:用户消息仍保存,`aiReply.content` 返回错误提示HTTP 200。
### POST `/api/xcx/chat/stream`
SSE 流式对话端点CHAT-4。chatId 归属验证在流开始前完成。
请求体:
```json
{ "chatId": 1, "content": "消息内容" }
```
响应:`text/event-stream`(不经过 ResponseWrapper 包装)
SSE 事件类型:
- `event: message``data: {"token": "文本片段"}`
- `event: done``data: {"messageId": 123, "createdAt": "ISO8601"}`
- `event: error``data: {"message": "错误描述"}`
---
## 15. 维客线索 `/api/member-retention-clue`
替代原 `member-birthday` 端点,提供维客线索管理能力。
### WebSocket `/ws/logs/{execution_id}`
实时日志推送。连接后自动接收指定执行的日志流。
---
## 错误码约定
| HTTP 状态码 | 含义 |
|-------------|------|
| 200 | 成功 |
| 201 | 创建成功 |
| 400 | 请求参数错误 / SQL 执行错误 |
| 401 | 未认证 / 令牌无效 / 受限令牌 |
| 404 | 资源不存在 |
| 408 | 查询超时 |
| 409 | 状态冲突(如删除非 pending 任务) |
| 422 | 请求体验证失败 |
| 500 | 服务器内部错误 |