# 小程序后端接口输出规范 > **文档编号**:DS-API-OUTPUT-001 > **版本**:v1.0.0 > **适用范围**:NeoZQYY 小程序所有后端接口(HTTP JSON 响应体) > **最后更新**:2026-03-18 > **关联文档**: > - [DISPLAY-STANDARDS.md](./design-system/DISPLAY-STANDARDS.md) — 前端展示规范第 1~6 章 > - [DISPLAY-STANDARDS-2.md](./design-system/DISPLAY-STANDARDS-2.md) — 第 7~9 章(截止日期 / 评分 / 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`(0~100,整数或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`(0~10,0.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 } ``` - 统一 0~100 整数或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分" } ``` - 统一使用 **0~10 分制**,0.5 步长 - 0 表示「未评分」,前端展示 `--` - 前端调用 `scoreToHalfStar(score)` 转换为 0~5 星展示 ### 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`(橙) | | 1~7 | `还剩 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`:integer(0~100),关系进度百分比 - `deadline`:`YYYY-MM-DD`,前端调用 `formatDeadline()` 语义化 - `aiSuggestion`:string,AI 摘要文案,后端生成,前端直接展示 ### 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`:0~10 分制,0 表示未评分 - `serviceRecords.hours`、`hoursRaw`:number(小时),前端调用 `formatHours()` - `serviceRecords.income`、`serviceSummary.*`:integer(元),前端调用 `formatMoney()` - `isEstimate`:boolean,true 时前端展示「预估」标注 ### 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`:integer(0~100),前端调用 `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 数据(字段结构与接口保持一致)