小程序迁移 静态页面完成!!!

This commit is contained in:
Neo
2026-03-18 05:14:35 +08:00
parent 72bb11b34f
commit 075caf067f
124 changed files with 10407 additions and 2738 deletions

View File

@@ -0,0 +1,545 @@
# 小程序后端接口输出规范
> **文档编号**DS-API-OUTPUT-001
> **版本**v1.0.0
> **适用范围**NeoZQYY 小程序所有后端接口HTTP JSON 响应体)
> **最后更新**2026-03-18
> **关联文档**
> - [DISPLAY-STANDARDS.md](./design-system/DISPLAY-STANDARDS.md) — 前端展示规范第 16 章
> - [DISPLAY-STANDARDS-2.md](./design-system/DISPLAY-STANDARDS-2.md) — 第 79 章(截止日期 / 评分 / Mock
> - [DATETIME-DISPLAY-STANDARD.md](./design-system/DATETIME-DISPLAY-STANDARD.md) — 时间展示规范
---
## 目录
1. [总体约定](#1-总体约定)
2. [响应体结构](#2-响应体结构)
3. [字段类型规范(核心规则)](#3-字段类型规范核心规则)
4. [各业务字段细则](#4-各业务字段细则)
5. [枚举值规范](#5-枚举值规范)
6. [分页规范](#6-分页规范)
7. [接口端点命名规范](#7-接口端点命名规范)
8. [各页面接口字段对照表](#8-各页面接口字段对照表)
9. [禁止事项速查](#9-禁止事项速查)
---
## 1. 总体约定
| 项目 | 规范 |
|------|------|
| 协议 | HTTPS REST JSON |
| 编码 | UTF-8 |
| Content-Type | `application/json` |
| 时区 | **后端统一输出 UTC前端负责本地化展示** |
| 数值精度 | 金额为整数(元),课时为 0.5 步长浮点 |
| 空值 | 字段不存在时输出 `null`**不得省略字段** |
| 布尔值 | `true` / `false`,不用 `0/1` |
| 字符串编码格式 | 纯数据,**不含展示单位**¥、h、%、笔等) |
---
## 2. 响应体结构
### 2.1 成功响应
```json
{
"code": 0,
"message": "success",
"data": { ... }
}
```
### 2.2 失败响应
```json
{
"code": 40001,
"message": "参数错误:缺少 customerId",
"data": null
}
```
### 2.3 分页列表响应
```json
{
"code": 0,
"message": "success",
"data": {
"list": [ ... ],
"total": 32,
"page": 1,
"pageSize": 20,
"hasMore": true
}
}
```
---
## 3. 字段类型规范(核心规则)
> **核心原则:后端输出原始语义数值,前端负责格式化展示。**
> 后端不拼接 `¥`、`h`、`%`、`笔` 等展示字符,也不做千分位格式化。
### 3.1 类型对照表
| 字段类型 | 后端输出类型 | 示例 | 前端处理函数 | 禁止输出 |
|----------|-------------|------|-------------|----------|
| **金额** | `number`(元,整数) | `12680` | `formatMoney()` | `"¥12,680"` `"12680.00"` |
| **课时** | `number`小时0.5步长) | `2.5` | `formatHours()` | `"2.5h"` `"2h30min"` |
| **计数** | `number`(整数) | `32` | `formatCount()` | `"32笔"` `"32次"` |
| **百分比** | `number`0100整数或1位小数 | `85.5` | `formatPercent()` | `"85.5%"` `"0.855"` |
| **日期** | `string``YYYY-MM-DD` | `"2026-03-18"` | `formatDeadline()` | `"2026/03/18"` `1742256000000` |
| **时间戳** | `string`ISO 8601含时区 | `"2026-03-18T08:30:00+08:00"` | `formatRelativeTime()` | Unix 毫秒整数 |
| **等级 key** | `string`(英文 key | `"star"` | 查 `LEVEL_MAP` | `"星级"` `"gold"` |
| **状态 key** | `string`(英文 key | `"pending"` | 查枚举映射 | `"待处理"` |
| **评分** | `number`0100.5步长) | `8.5` | `scoreToHalfStar()` | `"8.5分"` `4` (5分制) |
| **布尔** | `boolean` | `true` | 直接使用 | `1` `"true"` |
| **空值** | `null` | `null` | 展示 `--` | `""` `0`(有语义时除外) |
---
## 4. 各业务字段细则
### 4.1 金额字段
```json
// 正确
{ "balance": 2000, "income": 510, "salary": 12680 }
// 错误
{ "balance": "¥2,000", "income": "¥510", "salary": "¥12,680" }
```
- 统一以「元」为单位,**不含分**
- 负数直接输出负整数:`-368`
- 零值输出 `0`,不输出 `null`
- 前端调用 `formatMoney(value)` 展示
### 4.2 课时字段
```json
// 正确
{ "hours": 2.5, "hoursRaw": 3.0 }
// 错误
{ "hours": "2.5h", "deduct": "(折0.5h)" }
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `hours` | `number` | 折算后实际计入课时(小时) |
| `hoursRaw` | `number \| null` | 折算前原始小时数;无折算时输出 `null` |
- 前端仅在 `hoursRaw !== null && hoursRaw !== hours` 时展示折算备注
- 步长为 0.5,如 `1.0``1.5``2.0``2.5`
### 4.3 计数字段
```json
// 正确
{ "totalCount": 32, "serviceCount": 18 }
// 错误
{ "totalCount": "32笔", "serviceCount": "18次" }
```
- 前端调用 `formatCount(value, '笔')` 展示,单位由页面层决定
### 4.4 百分比字段
```json
// 正确(进度/完成率)
{ "filledPct": 85, "completionRate": 72.5 }
// 错误
{ "filledPct": "85%", "completionRate": 0.725 }
```
- 统一 0100 整数或1位小数**不用小数形式**
- 允许超过 100如完成率 120%
### 4.5 日期与时间
| 场景 | 格式 | 示例 |
|------|------|------|
| 纯日期(截止日、生日等) | `YYYY-MM-DD` | `"2026-03-18"` |
| 精确时间(备注时间、服务记录) | ISO 8601 含时区 | `"2026-03-18T08:30:00+08:00"` |
| 时间区间service timeRange | 直接拼接字符串 | `"20:00-22:00"` |
- **禁止** 输出 Unix 毫秒时间戳整数
- **禁止** 输出 `YYYY/MM/DD` 格式
- 前端截止日期调用 `formatDeadline(date)` 语义化
- 前端相对时间调用 `formatRelativeTime(iso)` 展示
### 4.6 评分字段
```json
// 正确
{ "heartScore": 8.5, "noteScore": 7.0 }
// 错误
{ "heartScore": 4, "noteScore": "7.5分" }
```
- 统一使用 **010 分制**0.5 步长
- 0 表示「未评分」,前端展示 `--`
- 前端调用 `scoreToHalfStar(score)` 转换为 05 星展示
### 4.7 等级字段
```json
// 正确
{ "level": "star" }
// 错误
{ "level": "星级" }
```
| 后端 key | 前端展示 |
|----------|----------|
| `star` | 星级助教 |
| `senior` | 高级助教 |
| `middle` | 中级助教 |
| `junior` | 初级助教 |
### 4.8 天数字段
```json
// 正确
{ "lastVisitDays": 23, "daysAbsent": 23 }
// 错误
{ "lastVisitDays": "23天前", "daysAbsent": "23天" }
```
- 统一输出整数天数,不含「天」「天前」等汉字
- 前端拼接文案时自行添加单位
---
## 5. 枚举值规范
所有枚举字段统一使用英文下划线 key前端维护映射表。
### 5.1 任务类型 `taskType`
| key | 展示文案 |
|-----|----------|
| `callback` | 回访 |
| `priority_recall` | 优先召回 |
| `high_priority` | 高优先召回 |
| `relationship` | 关系构建 |
### 5.2 任务状态 `status`
| key | 展示文案 |
|-----|----------|
| `pending` | 待处理 |
| `completed` | 已完成 |
| `abandoned` | 已放弃 |
### 5.3 助教等级 `level`
| key | 展示文案 |
|-----|----------|
| `star` | 星级助教 |
| `senior` | 高级助教 |
| `middle` | 中级助教 |
| `junior` | 初级助教 |
### 5.4 课程类型 `courseType`
| key | 展示文案 | 样式 key |
|-----|----------|----------|
| `basic` | 基础课 | `tag-basic` |
| `vip` | 包厢课 | `tag-vip` |
| `tip` | 打赏课 | `tag-tip` |
| `recharge` | 充值 | `tag-recharge` |
| `incentive` | 激励 | `tag-incentive` |
### 5.5 线索来源 `source`
| key | 展示文案 |
|-----|----------|
| `manual` | 助教手动录入 |
| `ai_consumption` | 系统自动(消费分析) |
| `ai_note` | 系统自动(备注分析) |
### 5.6 线索分类 `category`
| key | 展示文案 |
|-----|----------|
| `customer_basic` | 客户基础 |
| `consumption` | 消费习惯 |
| `play_pref` | 玩法偏好 |
| `promo_pref` | 促销偏好 |
| `social` | 社交偏好 |
| `feedback` | 重要反馈 |
### 5.7 截止日期语义化(前端计算,非接口字段)
后端只输出 `deadline: "YYYY-MM-DD"`,前端调用 `formatDeadline()` 计算:
| diff | 展示文案 | 样式 |
|------|----------|------|
| < 0 | `逾期 N 天` | `danger`(红) |
| = 0 | `今天到期` | `warning`(橙) |
| 17 | `还剩 N 天` | `normal` |
| > 7 | `MM-DD` | `muted`(灰) |
| null | `--` | `muted` |
---
## 6. 分页规范
```json
{
"list": [],
"total": 100,
"page": 1,
"pageSize": 20,
"hasMore": true
}
```
- `page` 从 1 开始计数
- `hasMore` 由后端根据 `total` 和当前 `page * pageSize` 计算
- `total` 为全量数据总条数(不是当前页条数)
---
## 7. 接口端点命名规范
```
GET /api/xcx/tasks 任务列表
GET /api/xcx/tasks/:id 任务详情
GET /api/xcx/tasks/:id/notes 任务备注列表
POST /api/xcx/tasks/:id/notes 新增备注
GET /api/xcx/tasks/:id/service-records 近期服务记录
GET /api/xcx/coaches 助教看板列表
GET /api/xcx/coaches/:id 助教详情
GET /api/xcx/performance 绩效概览
GET /api/xcx/performance/records 绩效记录列表(支持月份分页)
GET /api/xcx/retention-clues/:customerId 维客线索
```
- 资源名用复数小写连字符
- 路径参数用 `:id`,不用查询参数代替
- 月份筛选用 `?year=2026&month=2`
---
## 8. 各页面接口字段对照表
### 8.1 任务列表页 `GET /api/xcx/tasks`
```json
{
"id": "task-001",
"customerName": "王先生",
"taskType": "high_priority",
"taskTypeLabel": "高优先召回",
"deadline": "2026-03-20",
"heartScore": 8.5,
"isPinned": true,
"hasNote": true,
"status": "pending",
"lastVisitDays": 23,
"balance": 2000,
"filledPct": 85,
"aiSuggestion": "建议本周内回访,余额即将到期"
}
```
**说明:**
- `lastVisitDays`integer距上次到店天数null 表示从未到店
- `balance`integer余额null 表示无储值
- `filledPct`integer0100关系进度百分比
- `deadline``YYYY-MM-DD`,前端调用 `formatDeadline()` 语义化
- `aiSuggestion`stringAI 摘要文案,后端生成,前端直接展示
### 8.2 任务详情页 `GET /api/xcx/tasks/:id`
```json
{
"id": "task-001",
"customerName": "王先生",
"taskType": "high_priority",
"taskTypeLabel": "高优先召回",
"status": "pending",
"deadline": "2026-03-20",
"heartScore": 8.5,
"phone": "138****5678",
"lastVisitDate": "2026-03-01",
"lastSpendAmount": 380,
"daysAbsent": 23,
"callbackReason": "上次体验课后未续费,需跟进意向",
"churnRisk": "high",
"spendTrend": "down",
"aiAnalysis": {
"summary": "最近 3 个月每周均有 1-2 次课程互动",
"suggestions": ["询问近期是否有空", "告知会员专属活动"]
},
"talkingPoints": ["王哥好久不见..."],
"notes": [
{
"id": "note-001",
"content": "已通过微信联系王先生...",
"tagType": "customer",
"tagLabel": "客户:王先生",
"createdAt": "2026-03-10T16:30:00+08:00",
"score": 8.5
}
],
"serviceRecords": [
{
"table": "A12号台",
"type": "基础课",
"typeClass": "basic",
"recordType": "course",
"hours": 2.5,
"hoursRaw": 3.0,
"income": 200,
"isEstimate": true,
"drinks": "百威x2 红牛x1",
"date": "2026-02-07T21:30:00+08:00"
}
],
"serviceSummary": {
"totalHours": 6.0,
"totalIncome": 510,
"avgIncome": 170
}
}
```
**说明:**
- `phone`:后端已做脱敏处理(`138****5678`),或根据权限返回明文
- `score`010 分制0 表示未评分
- `serviceRecords.hours``hoursRaw`number小时前端调用 `formatHours()`
- `serviceRecords.income``serviceSummary.*`integer前端调用 `formatMoney()`
- `isEstimate`booleantrue 时前端展示「预估」标注
### 8.3 助教看板页 `GET /api/xcx/coaches`
```json
{
"id": "coach-001",
"name": "小燕",
"level": "star",
"storeName": "朗朗桌球",
"customerCount": 28,
"monthHours": 86.0,
"monthIncome": 18600,
"svAmount": 5000,
"filledPct": 92,
"taskCount": 6,
"urgentTaskCount": 2,
"aiSuggestion": "本月表现优秀,建议重点跟进 2 位高风险流失客户"
}
```
**说明:**
- `level`:英文 key前端查 `LEVEL_MAP` 展示中文
- `monthHours`number小时前端调用 `formatHours()`
- `monthIncome``svAmount`integer前端调用 `formatMoney()`
- `filledPct`integer0100前端调用 `formatPercent()``toProgressWidth()`
- `customerCount``taskCount``urgentTaskCount`integer前端调用 `formatCount()`
### 8.4 绩效记录页 `GET /api/xcx/performance/records`
请求参数:`?year=2026&month=2&page=1&pageSize=20`
```json
{
"summary": {
"totalCount": 32,
"totalHours": 59.0,
"totalIncome": 4720
},
"dateGroups": [
{
"date": "2026-02-07",
"totalHours": 6.0,
"totalIncome": 510,
"records": [
{
"id": "r1",
"customerName": "王先生",
"timeRange": "20:00-22:00",
"hours": 2.0,
"hoursRaw": null,
"courseType": "basic",
"location": "3号台",
"income": 160
}
]
}
],
"hasMore": false,
"page": 1,
"pageSize": 20
}
```
**说明:**
- `date``YYYY-MM-DD`前端格式化为「2月7日」
- `summary.*``dateGroups.totalIncome``records.income`integer
- `summary.totalHours``dateGroups.totalHours``records.hours`number小时
- `hoursRaw`null 表示无折算,有值时前端展示折算备注
- `courseType`:英文 key`basic`/`vip`/`tip`/`recharge`/`incentive`
### 8.5 备注接口 `GET /api/xcx/tasks/:id/notes`
```json
[
{
"id": "note-001",
"content": "已通过微信联系王先生...",
"tagType": "customer",
"tagLabel": "客户:王先生",
"createdAt": "2026-03-10T16:30:00+08:00",
"score": 8.5
}
]
```
- `tagType``customer` / `coach` / `system`
- `score`0 表示未评分0.5 步长,前端调用 `scoreToHalfStar()` 转 5 星制
- `createdAt`ISO 8601前端调用 `formatRelativeTime()` 展示相对时间
---
## 9. 禁止事项速查
| 禁止行为 | 正确做法 |
|----------|----------|
| 输出 `"¥12,680"` | 输出 `12680` |
| 输出 `"2.5h"` | 输出 `2.5` |
| 输出 `"32笔"` | 输出 `32` |
| 输出 `"85%"` | 输出 `85` |
| 输出 `"星级"` 作为等级 | 输出 `"star"` |
| 输出 `"待处理"` 作为状态 | 输出 `"pending"` |
| 省略值为 null 的字段 | 显式输出 `null` |
| 用 `0` 代替 `null` 表示「无」 | 用 `null`0 保留给有意义的零值) |
| 输出 Unix 毫秒时间戳 | 输出 ISO 8601 字符串 |
| 输出 `YYYY/MM/DD` 日期格式 | 输出 `YYYY-MM-DD` |
| 后端做 `toLocaleString()` 格式化 | 后端输出原始数值,前端格式化 |
| `hoursRaw` 输出 `"(折0.5h)"` | 输出 `3.0`(原始小时数) |
---
## 关联文档
- [DISPLAY-STANDARDS.md](./design-system/DISPLAY-STANDARDS.md) — 前端格式化规范
- [DISPLAY-STANDARDS-2.md](./design-system/DISPLAY-STANDARDS-2.md) — 截止日期 / 评分 / Mock 规范
- [DATETIME-DISPLAY-STANDARD.md](./design-system/DATETIME-DISPLAY-STANDARD.md) — 时间展示规范
- `utils/money.ts``formatMoney` / `formatCount` / `formatPercent` / `toProgressWidth`
- `utils/time.ts``formatHours` / `formatDeadline` / `formatRelativeTime`
- `utils/rating.ts``scoreToHalfStar` / `isUnrated`
- `utils/mock-data.ts` — Mock 数据(字段结构与接口保持一致)