This commit is contained in:
2026-07-05 14:43:34 +08:00
commit 17a8027b20
277 changed files with 63794 additions and 0 deletions
+113
View File
@@ -0,0 +1,113 @@
# Lead · 意向客户(Phase 3)
> 自主问卷用户信息采集的统一入口,落到 `leads` 表,供管理后台跟进。
## 接口表
| Method | Path | 鉴权 | 说明 |
|---|---|---|---|
| POST | `/api/v1/leads` | - | 提交(小程序自测问卷、首页落地等) |
| GET | `/api/v1/leads/stats` | ✅ | 统计:总数 / 24h / 按 source 分组 |
| GET | `/api/v1/admin/leads` | ✅ | 列表,支持 phone / source / keyword / 时间过滤 |
| GET | `/api/v1/admin/leads/:id` | ✅ | 详情 |
| PUT | `/api/v1/admin/leads/:id/remark` | ✅ | 修改备注 |
| DELETE | `/api/v1/admin/leads/:id` | ✅ | 删除 |
## POST /api/v1/leads
**请求体**
```json
{
"name": "张三",
"phone": "13800138000",
"symptom": "便血近 1 周,伴有肛门坠胀",
"questionnaire": {
"total": 5,
"answers": { "0": "sometimes", "1": "no" },
"createdAt": "2026-06-14T08:30:00.000Z"
},
"source": "self-test",
"score": 5
}
```
**校验规则**
- `name` 必填,1-20 字符
- `phone` 必填,匹配 `^1[3-9]\d{9}$`
- `symptom` 可选,≤ 500 字
- `questionnaire` 必填,任意 JSON 对象
- `source` 可选,枚举 `self-test` / `home` / `appointment` / `other`,默认 `self-test`
- `score` 可选,0-100
**响应**
```json
{ "code": 0, "message": "提交成功", "data": { "id": "lead-1781398800000", "createdAt": "2026-06-14 16:30:00" } }
```
**错误码**
| HTTP | code | message |
|---|---|---|
| 400 | 1 | 姓名必填 / 姓名长度需在 1-20 字符 |
| 400 | 1 | 手机号必填 / 手机号格式不正确 |
| 400 | 1 | 症状描述不超过 500 字 |
| 400 | 1 | 问卷答案 questionnaire 必填且为对象 |
| 400 | 1 | source 仅支持:self-test / home / appointment / other |
| 400 | 1 | 该手机号在同渠道已提交过,请勿重复 |
| 500 | 500 | 服务器内部错误 |
## GET /api/v1/admin/leads
**Query**
- `phone` 手机号精确匹配
- `source` 渠道
- `keyword` 姓名模糊匹配
- `startDate` / `endDate` 时间范围(`YYYY-MM-DD`)
- `limit` 默认 50,最大 200
- `offset` 默认 0
**响应**
```json
{
"code": 0,
"message": "ok",
"data": {
"list": [
{
"id": "lead-1781398800000",
"name": "张三",
"phone": "13800138000",
"symptom": "便血近 1 周",
"questionnaire": { "total": 5, "answers": {} },
"source": "self-test",
"score": 5,
"remark": "",
"createdAt": "2026-06-14 16:30:00",
"updatedAt": "2026-06-14 16:30:00"
}
],
"total": 1,
"limit": 50,
"offset": 0
}
}
```
## 数据表
```sql
CREATE TABLE leads (
id VARCHAR(32) PRIMARY KEY,
name VARCHAR(50) NOT NULL,
phone VARCHAR(20) NOT NULL,
symptom TEXT,
questionnaire JSON NOT NULL,
source VARCHAR(20) NOT NULL DEFAULT 'self-test',
score INT DEFAULT 0,
remark VARCHAR(500),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uniq_phone_source (phone, source)
);
```
唯一约束 `(phone, source)`:同手机号在同一渠道只保留一条。