Files
cjyyzx/SUPER_OPS_API.md
T
xiaohei 428644e286
Revalidate Docs / Revalidate Docs (push) Failing after 2s
E2E CI / Check Duplicate Run (push) Failing after 5s
Test CI / Check Duplicate Run (push) Failing after 6s
E2E CI / Test Web App (push) Has been skipped
Test CI / Test Packages (push) Has been skipped
Test CI / Test App (shard 1/3) (push) Has been skipped
Test CI / Test App (shard 2/3) (push) Has been skipped
Test CI / Test App (shard 3/3) (push) Has been skipped
Test CI / Test Desktop App (push) Has been skipped
🔄 Branch Synchronization / sync-branches (push) Failing after 11s
Test CI / Test Database (push) Has been skipped
Test CI / Merge and Upload App Coverage (push) Has been skipped
Database Schema Visualization CI / build (push) Failing after 4m14s
Enterprise AI Workspace prototype: LobeChat (de-branded) + Enterprise Gateway + Postgres/Redis stack
2026-04-21 12:58:00 +08:00

314 lines
8.6 KiB
Markdown

# 超级运营中心对接文档 (xiaoshou → super-ops)
> 本文档描述 **销售系统 (xiaoshou) 对超级运营中心暴露的只读 API**。所有接口在 `/api/external/*`,独立于面向前端的 `/api/*` 与面向云管的 `/api/internal/*`,凭证可独立轮换。
## 基本信息
| 项 | 值 |
|---|---|
| **Base URL (生产)** | `https://xiaoshou-api.braveglacier-e1a32a70.eastasia.azurecontainerapps.io/api/external` |
| **Base URL (本地)** | `http://localhost:8000/api/external` |
| **鉴权方式** | 请求头 `X-Api-Key: <SUPER_OPS_API_KEY>` |
| **编码** | 请求/响应 UTF-8, Content-Type `application/json` |
| **速率限制** | 暂无,建议自行节流 < 100 req/s |
| **时区** | 所有 ISO 8601 时间戳均为 **服务器本地时区 (Asia/Shanghai, +08:00)**,无 tz 后缀时按此解释 |
| **版本策略** | 无版本前缀,向后兼容新增字段;如破坏性变更会单独沟通 |
### 如何拿到 `SUPER_OPS_API_KEY`
在 Azure Container App `xiaoshou-api` 的 secret 里以 `super-ops-api-key` 命名存储,环境变量 `SUPER_OPS_API_KEY` 引用。由销售系统管理员分发给超运中心负责人。
本地开发在 `.env` 里设 `SUPER_OPS_API_KEY=<随便一串>` 即可。
### 活性检查
```bash
curl https://xiaoshou-api.braveglacier-e1a32a70.eastasia.azurecontainerapps.io/api/external/meta/ping
# => {"ok":true,"service":"xiaoshou-external","ts":"2026-04-15T23:55:00.000000"}
```
注意:`meta/ping` **不校验 X-Api-Key**(只用于可达性嗅探)。**所有业务端点都必须带 `X-Api-Key`**。
### 鉴权失败
```
HTTP/1.1 401 Unauthorized
{"detail": "invalid X-Api-Key"}
```
---
## 端点清单
| Method | Path | 说明 |
|---|---|---|
| GET | `/meta/ping` | 活性检查 (免鉴权) |
| GET | `/customers` | 客户列表 (分页 + 过滤) |
| GET | `/customers/{id}` | 客户详情 |
| GET | `/customers/{id}/assignment-log` | 客户分配历史 |
| GET | `/customers/{id}/insight/runs` | AI 洞察运行列表 |
| GET | `/customers/{id}/insight/facts` | AI 洞察事实库 |
| GET | `/allocations` | 分配记录列表 |
| GET | `/allocations/{id}/history` | 分配变更流水 |
| GET | `/resources` | 货源列表 |
| GET | `/sales/users` | 销售成员 |
| GET | `/sales/rules` | 分配规则 |
---
## 详细接口
### GET `/customers`
客户列表。
**Query 参数**
| 名 | 类型 | 默认 | 说明 |
|---|---|---|---|
| page | int | 1 | 页码 |
| page_size | int | 50 | 每页, 最大 500 |
| industry | string | - | 精确匹配 |
| region | string | - | 精确匹配 |
| customer_status | string | - | active / inactive / frozen / prospect |
| sales_user_id | int | - | 所属销售 id |
| only_unassigned | bool | false | true → 只返回未分配给任何销售的客户 |
| updated_since | ISO8601 | - | 仅返回 updated_at ≥ since (用于增量同步) |
**响应示例**
```json
{
"total": 18,
"page": 1,
"page_size": 50,
"items": [
{
"id": 2,
"customer_code": "CUST-68A38417",
"customer_name": "会伴",
"industry": "科研服务",
"region": null,
"customer_level": null,
"customer_status": "active",
"sales_user_id": 2,
"operation_user_id": null,
"current_resource_count": 0,
"current_month_consumption": 0.0,
"source_system": "gongdan",
"source_id": "u-xxxx",
"last_follow_time": null,
"created_at": "2026-04-15T10:15:04.001354",
"updated_at": "2026-04-15T15:49:08.431617"
}
]
}
```
### GET `/customers/{id}`
单客户详情,字段同上单条。404 时返回 `{"detail":"客户不存在"}`。
### GET `/customers/{id}/assignment-log`
该客户的商机分配/再分配/回收历史。按 id 升序。
```json
{
"customer_id": 2,
"items": [
{
"id": 1,
"from_user_id": null,
"to_user_id": 2,
"trigger": "auto",
"rule_id": 2,
"reason": "auto-assign via rule '兜底'",
"at": "2026-04-15T15:49:08.431617"
}
]
}
```
`trigger` 枚举:`manual` / `auto` / `recycle` / `import`。
`to_user_id=null` 且 `trigger=recycle` 代表该次回收退回商机池。
### GET `/customers/{id}/insight/runs`
该客户的 AI 洞察 agent 运行列表 (降序)。
```json
{
"customer_id": 2,
"items": [
{
"id": 3,
"status": "completed",
"steps_total": 12,
"steps_done": 4,
"started_at": "2026-04-15T15:27:48.728656",
"completed_at": "2026-04-15T15:28:43.998691",
"summary": "# 会伴 洞察速览\n..."
}
]
}
```
### GET `/customers/{id}/insight/facts`
该客户 agent 抓出来的所有事实。可选 `?category=` 过滤 (`basic` / `people` / `tech` / `news` / `event` / `other`)。
```json
{
"customer_id": 2,
"items": [
{
"id": 1,
"category": "basic",
"content": "会伴定位为信息技术最新国际会议和期刊列表平台...",
"source_url": "https://www.myhuiban.com/",
"fingerprint": "94396740b5d60f8c7cfd505fa04a95c4ea139a33",
"run_id": 2,
"discovered_at": "2026-04-15T15:18:12.123456"
}
]
}
```
fingerprint = `sha1(category::normalized_content)`,同客户同指纹不会重复。
### GET `/allocations`
分配记录。
**Query 参数**
| 名 | 类型 | 默认 | 说明 |
|---|---|---|---|
| page | int | 1 | |
| page_size | int | 50 | 最大 500 |
| include_cancelled | bool | false | true 时包含 allocation_status=CANCELLED 的记录 |
| customer_id | int | - | 按客户过滤 |
| updated_since | ISO8601 | - | 增量同步 |
```json
{
"total": 35,
"page": 1,
"page_size": 50,
"items": [
{
"id": 1,
"allocation_code": "ALLOC-20260415120000",
"customer_id": 2,
"resource_id": 7,
"allocated_quantity": 10,
"unit_cost": 120.50,
"unit_price": 180.00,
"total_cost": 1205.00,
"total_price": 1800.00,
"profit_amount": 595.00,
"allocation_status": "PENDING",
"created_at": "...",
"updated_at": "..."
}
]
}
```
### GET `/allocations/{id}/history`
该分配的字段级变更流水。从创建后发生过的每次 `quantity/unit_price/status/...` 改动一行。
```json
{
"allocation_id": 1,
"items": [
{"id": 3, "field": "cancel", "old_value": "PENDING", "new_value": "CANCELLED", "reason": "客户退单", "at": "..."},
{"id": 2, "field": "allocated_quantity", "old_value": "10", "new_value": "5", "reason": null, "at": "..."},
{"id": 1, "field": "unit_price", "old_value": "200.00", "new_value": "180.00", "reason": null, "at": "..."}
]
}
```
### GET `/resources`
货源列表。分页同上。
### GET `/sales/users`
销售成员。`active_only` 默认 true,传 `false` 返回全部含停用。
### GET `/sales/rules`
分配规则,按 priority 升序。`sales_user_ids` 非空表示轮询模式,`cursor` 表示下次派给列表的 `cursor % len` 位。
```json
{
"items": [
{
"id": 1, "name": "华东能源",
"industry": "能源", "region": "华东", "customer_level": null,
"sales_user_id": 3, "sales_user_ids": null, "cursor": 0,
"priority": 10, "is_active": true
},
{
"id": 2, "name": "AI 轮询",
"industry": "AI", "region": null, "customer_level": null,
"sales_user_id": null, "sales_user_ids": [5, 6, 7], "cursor": 42,
"priority": 20, "is_active": true
}
]
}
```
---
## 推荐消费模式
### 1. 增量同步客户到超运侧
```
每 10 分钟:
last = localStorage.get("xiaoshou.customers.last_sync") or "1970-01-01"
page = 1
while True:
resp = GET /customers?updated_since={last}&page={page}&page_size=500
upsert resp.items to super-ops.customers
if page * 500 >= resp.total: break
page += 1
localStorage.set("xiaoshou.customers.last_sync", now_iso())
```
### 2. 实时拉单客户 AI 洞察展示
```
当超运看客户 X:
runs = GET /customers/X/insight/runs
facts = GET /customers/X/insight/facts
render(runs[0].summary, facts grouped by category)
```
### 3. 对账分配审计
```
每日 00:30:
allocs = GET /allocations?updated_since=yesterday&include_cancelled=true
for a in allocs.items:
hist = GET /allocations/{a.id}/history
archive to super-ops.audit_trail
```
---
## 错误码
| HTTP | 含义 |
|---|---|
| 200 | OK |
| 400 | 参数错误 (格式不对, updated_since 不是合法 ISO8601, 等) |
| 401 | X-Api-Key 缺失或错误 |
| 404 | 资源 (客户/分配/货源) 不存在或已软删 |
| 5xx | 服务端错误,业务端请带 exponential backoff 重试 |
---
## 变更日志
- **2026-04-15** 首版:`/customers`, `/allocations`, `/resources`, `/sales/users`, `/sales/rules`, `/customers/{id}/assignment-log`, `/customers/{id}/insight/{runs,facts}`, `/allocations/{id}/history`, `/meta/ping`。