Files
Neo-ZQYY/docs/prd/Neo_Specs/storyboard-walkthrough-assistant-view.md

827 lines
46 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.
# 小程序 Storyboard 走查报告 — 助教视角(小燕)
> 走查日期2026-03-18
> 走查角色:助教"小燕"已登录status=approved
> 对照文档:`docs/miniprogram-dev/API-contract.md`(契约)、`docs/prd/Neo_Specs/NS1-xcx-backend-api.md`spec
> 目标:提取 spec 未记录的接口需求细节
---
## 场景 1登录 → 任务列表app.ts
### API 调用
- `checkAuthStatus()``GET /api/xcx/me` → 返回 `ApiUserInfo`
- 参数来源token 从 `wx.getStorageSync('token')` 读取
- 成功后根据 `data.status` 路由:`approved``reLaunch('/pages/task-list/task-list')`
### 前端期望字段(/api/xcx/me 响应)
| 字段 | 类型 | 说明 | 契约定义 |
|------|------|------|---------|
| `user_id` | number | 用户 ID | ✅ |
| `status` | enum | `new/pending/approved/rejected/disabled` | ✅ |
| `nickname` | string | 昵称 | ✅ |
| `role` | string | 角色 | ✅ REQ-4 |
| `store_name` | string | 门店名 | ✅ REQ-4 |
| `coach_level` | string? | 助教等级 | ✅ REQ-4 |
| `avatar` | string? | 头像 URL | ✅ REQ-4 |
### globalData 结构
```typescript
globalData: {
token?: string
refreshToken?: string
authUser?: { userId: number, status: string, nickname: string }
}
```
### spec 未记录的 Gap
- **GAP-01**`globalData.authUser` 未存储 `role``store_name``coach_level``avatar`但下游页面task-list banner、performance banner、performance-records banner需要这些字段。前端需扩展 `globalData.authUser` 或各页面单独请求 `/me`
---
## 场景 2任务列表页task-list.ts
### API 调用
- `fetchTasks(params?)``GET /api/xcx/tasks?status=&page=&pageSize=`
- 返回:`{ tasks: Task[], performance: PerformanceData, total: number, hasMore: boolean }`
- 页面加载时无参数调用(获取全部任务)
### 前端期望字段 — Task任务卡片
| 字段 | 类型 | 说明 | 契约 TASK-1 |
|------|------|------|------------|
| `id` | string | 任务 ID | ✅ |
| `customerName` | string | 客户姓名 | ✅ |
| `customerAvatar` | string | 客户头像 | ✅ |
| `taskType` | enum | `callback/priority_recall/relationship/high_priority` | ✅ |
| `taskTypeLabel` | string | 类型中文标签 | ✅ |
| `deadline` | string | 截止日期 ISO 8601 | ✅ |
| `heartScore` | number | 爱心评分 0-10 | ✅ |
| `hobbies` | string[] | 爱好标签 | ✅ |
| `isPinned` | boolean | 是否置顶 | ✅ |
| `hasNote` | boolean | 是否有备注 | ✅ |
| `status` | enum | `pending/completed/abandoned` | ✅ |
### 前端期望字段 — PerformanceData绩效概览卡片
| 字段 | 类型 | 说明 | 契约 TASK-1 performance | 前端实际使用 |
|------|------|------|------------------------|-------------|
| `monthlyIncome` | number | 月收入 | ❌ 契约仅有 `total_income` | `buildPerfData()` 用 |
| `incomeChange` | number | 收入变化百分比 | ❌ 契约无 | `incomeTrend` 展示 |
| `currentTier` | string | 当前档位名称 | ❌ 契约无 | `bannerTitle` |
| `nextTierGap` | number | 距下一档差距 | ❌ 契约无 | `remainHours` |
| `todayServiceCount` | number | 今日服务次数 | ❌ 契约无 | 未使用 |
| `weekServiceCount` | number | 本周服务次数 | ❌ 契约无 | 未使用 |
| `monthServiceCount` | number | 本月服务次数 | ❌ 契约无 | 未使用 |
### 前端期望字段 — buildPerfData() 需要后端返回的绩效字段
| 字段 | 类型 | 说明 | 契约/spec 定义 |
|------|------|------|---------------|
| `tierNodes` | number[] | 档位节点数组,如 `[0,100,130,160,190,220]` | ❌ 未定义 |
| `totalHours` | number | 当月总工时(折算后) | 契约有 `total_hours` |
| `basicHours` | number | 基础课时 | ❌ 未定义 |
| `bonusHours` | number | 激励课时 | ❌ 未定义 |
| `currentTier` | number | 当前档位索引 | ❌ 未定义 |
| `nextTierHours` | number | 下一档位工时阈值 | ❌ 未定义 |
| `tierCompleted` | boolean | 是否已达标(满档) | ❌ 未定义 |
| `bonusMoney` | number | 升档奖金 | ❌ 未定义 |
| `incomeFormatted` | string | 格式化收入 | 契约有 `total_income` |
| `incomeTrend` | string | 收入趋势(如 `↓368` | ❌ 未定义 |
| `incomeTrendDir` | enum | `up/down` | ❌ 未定义 |
| `incomeMonth` | string | 当前月份标签 | 契约有 `month_label` |
| `prevMonth` | string | 上月标签 | ❌ 未定义 |
### enrichTask() 需要后端返回的扩展字段
| 字段 | 类型 | 说明 | 契约/spec 定义 |
|------|------|------|---------------|
| `lastVisitDays` | number | 距上次到店天数 | ❌ 前端 mock 计算,后端需返回 |
| `balance` | number | 客户余额 | ❌ 未定义在 TASK-1 |
| `aiSuggestion` | string | AI 建议摘要 | ❌ 未定义在 TASK-1 |
### 页面跳转
| 操作 | 目标 | 参数 |
|------|------|------|
| 点击任务卡片 | `/pages/task-detail/task-detail` | `?id={taskId}` |
| 点击绩效卡片 | `/pages/performance/performance` | 无参数 |
| 长按→AI助手 | `/pages/ai-chat/ai-chat` | `?taskId={id}&customerName={name}` |
### 写操作
| 操作 | API | 请求体 | 成功后行为 |
|------|-----|--------|-----------|
| 长按→置顶/取消置顶 | `POST /tasks/{id}/pin``/unpin` | 无 | 本地更新 `isPinned`,重新分组 |
| 长按→放弃 | `POST /tasks/{id}/abandon` | `{ reason: string }` | 本地移至 abandonedTasks |
| 长按→取消放弃 | `POST /tasks/{id}/restore` | 无 | 本地移至 normalTasks |
| 长按→添加备注 | `POST /notes` | `{ content, taskId?, customerId? }` | Toast 提示 |
### spec 未记录的 Gap
- **GAP-02**:契约 TASK-1 `performance` 仅有 4 个字段(`total_hours/total_income/total_customers/month_label`),但前端 `buildPerfData()` 需要 15+ 个字段(`tierNodes``basicHours``bonusHours``currentTier``nextTierHours``tierCompleted``bonusMoney``incomeTrend``incomeTrendDir``prevMonth` 等)。这是最大的 Gap。
- **GAP-03**`enrichTask()` 需要 `lastVisitDays`(距上次到店天数)、`balance`(客户余额)、`aiSuggestion`AI 建议),这 3 个字段在 TASK-1 契约中未定义。后端需在任务列表 item 中附带这些字段,或前端改为进入详情页后再加载。
- **GAP-04**`pin/unpin` 操作的 API 端点在契约中未定义。spec 提到已实现 `pin/unpin`,但 `api.ts` 中无对应函数,前端仅做本地状态更新。需确认 API 路径(`POST /tasks/{id}/pin``POST /tasks/{id}/unpin`)。
- **GAP-05**`createNote``score` 参数 — 前端备注弹窗 `onNoteConfirm` 传递 `{ score, content }`,但 `api.ts``createNote` 签名仅有 `{ content, taskId?, customerId? }`,缺少 `score` 字段。
---
## 场景 3任务详情页task-detail.ts
### API 调用
- `fetchTaskDetail(taskId)``GET /api/xcx/tasks/{taskId}`
- 参数来源:`options.id`(从 task-list 跳转传入)
- `deleteNote(noteId)``DELETE /api/xcx/notes/{noteId}`
### 前端期望字段 — TaskDetail完整清单
#### 基础信息(继承 Task
同 TASK-1 item 字段,契约已覆盖。
#### 维客线索 retentionClues内联 mock8 条)
| 字段 | 类型 | 说明 | 契约 TASK-2 |
|------|------|------|------------|
| `tag` | string | 线索大类标签(如 `"客户\n基础"` | ❌ 契约用 `tag` 但格式不同 |
| `tagColor` | enum | `primary/success/purple/error` | ✅ `tag_color` |
| `emoji` | string | 表情符号 | ✅ |
| `text` | string | 线索摘要 | ✅ |
| `source` | string | 来源(如 `"By:系统"``"By:小燕"` | ⚠️ 契约有 `source` 但格式不同 |
| `desc` | string? | 详细描述(展开后显示) | ✅ |
| `expanded` | boolean | 展开状态(前端本地) | — |
#### 话术参考 talkingPoints内联 mock5 条)
| 字段 | 类型 | 说明 | 契约 TASK-2 |
|------|------|------|------------|
| `talkingPoints` | string[] | 话术文本数组 | ✅ |
#### 服务记录 serviceRecords内联 mock4 条)
| 字段 | 类型 | 说明 | 契约 TASK-2 |
|------|------|------|------------|
| `table` | string | 台桌号 | ✅ |
| `type` | string | 课程类型标签 | ✅ |
| `typeClass` | enum | `basic/vip/tip/recharge/incentive` | ✅ `type_class` |
| `recordType` | enum? | `course/recharge` | ✅ `record_type` |
| `duration` | number | 折算后课时(小时) | ✅ |
| `durationRaw` | number? | 折算前课时(小时) | ✅ `duration_raw` |
| `income` | number | 收入(元) | ✅ |
| `isEstimate` | boolean? | 是否预估金额 | ✅ `is_estimate` |
| `drinks` | string | 酒水描述 | ✅ |
| `date` | string | 日期(格式化后) | ✅ |
#### 服务汇总 serviceSummary
| 字段 | 类型 | 说明 | 契约 TASK-2 |
|------|------|------|------------|
| `totalHours` | number | 总工时 | ✅ |
| `totalIncome` | number | 总收入 | ✅ |
| `avgIncome` | number | 平均收入 | ✅ |
#### AI 分析 aiAnalysis
| 字段 | 类型 | 说明 | 契约 TASK-2 |
|------|------|------|------------|
| `summary` | string | AI 分析摘要 | ✅ |
| `suggestions` | string[] | AI 建议列表 | ✅ |
#### 备注 notes内联 mock5 条)
| 字段 | 类型 | 说明 | 契约 TASK-2 |
|------|------|------|------------|
| `id` | string | 备注 ID | ✅ |
| `content` | string | 备注内容 | ✅ |
| `tagType` | enum | `customer/coach/system` | ✅ `tag_type` |
| `tagLabel` | string | 标签文案 | ✅ `tag_label` |
| `createdAt` | string | 创建时间 | ✅ `created_at` |
| `score` | number? | 满意度评分 0-10 | ✅ |
### 页面跳转
| 操作 | 目标 | 参数 |
|------|------|------|
| 问问助手 | `/pages/chat/chat` | `?customerId={detail.id}` |
| 查看全部服务记录 | `/pages/customer-service-records/customer-service-records` | `?customerId={detail.id}` |
### 写操作
| 操作 | API | 请求体 | 成功后行为 |
|------|-----|--------|-----------|
| 添加备注 | `POST /notes` | `{ content }` | 本地 prepend 到 sortedNotes |
| 删除备注 | `DELETE /notes/{noteId}` | 无 | 本地 filter 移除 |
| 放弃任务 | `POST /tasks/{id}/abandon` | `{ reason }` | 更新 `detail.status='abandoned'` |
| 取消放弃 | `POST /tasks/{id}/restore` | 无 | 更新 `detail.status='pending'` |
### spec 未记录的 Gap
- **GAP-06**:维客线索的 `tag` 字段格式不一致 — 前端内联 mock 使用 `"客户\n基础"` 格式(含换行符),契约定义为普通 string。后端需明确 tag 的取值枚举和格式。
- **GAP-07**:维客线索的 `source` 字段格式不一致 — 前端显示 `"By:系统"``"By:小燕"`,但 mock-data.ts 中 `RetentionClue.source` 定义为 `'manual' | 'ai_consumption' | 'ai_note'`。前端内联 mock 与类型定义不匹配,后端需明确返回格式。
- **GAP-08**`aiAnalysis` 数据来源 — spec §3.2 提到来自 `biz.ai_cache`app4/app5/app6/app7但契约未说明 `cache_type` 映射关系。需明确:`ai_analysis.summary` 来自哪个 `cache_type``talking_points` 来自哪个 `cache_type`
- **GAP-09**task-detail 跳转 chat 时传 `customerId={detail.id}`,但 `detail.id` 实际是 **taskId** 不是 customerId。前端需要一个 `customerId` 字段TASK-2 响应中需包含 `customer_id`)。
- **GAP-10**task-detail 跳转 customer-service-records 时同样传 `customerId={detail.id}`,存在同样的 taskId/customerId 混淆问题。TASK-2 响应需包含 `customer_id`
- **GAP-11**`storageLevel`(储值等级,如"非常多")和 `relationLevel/relationLevelText/relationColor`(关系等级)在前端本地计算,但后端未定义这些字段。后端是否需要返回,还是前端根据 `heartScore` 自行计算?
---
## 场景 4绩效概览页performance.ts
### API 调用
- `fetchPerformanceOverview({ year, month })``GET /api/xcx/performance?year=&month=`
- 参数来源:`new Date()` 取当前年月
- 返回类型:`PerformanceData`mock-data.ts 定义)
### 前端期望字段 — 完整清单(对比契约 PERF-1
#### Banner 数据(内联 mock非 API 返回)
| 字段 | 类型 | 说明 | 契约 PERF-1 | 数据源 |
|------|------|------|------------|--------|
| `coachName` | string | 助教姓名 `'小燕'` | ❌ 未定义 | 应从 globalData.authUser 或 /me |
| `coachRole` | string | 角色 `'助教'` | ❌ 未定义 | 同上 |
| `storeName` | string | 门店名 `'广州朗朗桌球'` | ❌ 未定义 | 同上 |
| `monthlyIncome` | string | 本月收入 `'¥6,206'` | ⚠️ 契约有 `total_income` 但是 number | 需格式化 |
| `lastMonthIncome` | string | 上月收入 `'¥16,880'` | ❌ 未定义 | 需后端额外返回 |
#### 收入档位(内联 mock
| 字段 | 类型 | 说明 | 契约 PERF-1 |
|------|------|------|------------|
| `currentTier.basicRate` | number | 当前档基础费率 80 | ❌ 未定义 |
| `currentTier.incentiveRate` | number | 当前档激励费率 95 | ❌ 未定义 |
| `nextTier.basicRate` | number | 下一档基础费率 90 | ❌ 未定义 |
| `nextTier.incentiveRate` | number | 下一档激励费率 114 | ❌ 未定义 |
| `upgradeHoursNeeded` | number | 距升档所需工时 15 | ❌ 未定义 |
| `upgradeBonus` | number | 升档奖金 800 | ❌ 未定义 |
#### 收入明细 incomeItems内联 mock4 项)
| 项目 | icon | desc 格式 | 契约 PERF-1 |
|------|------|----------|------------|
| 基础课 | 🎱 | `80元/h × 75h` | ⚠️ 契约有 `income_items` 但字段不同 |
| 激励课 | ⭐ | `95.05元/h × 10h` | 同上 |
| 充值激励 | 💰 | `客户充值返佣` | 同上 |
| TOP3 销冠奖 | 🏆 | `全店业绩前三名奖励` | 同上 |
契约 `income_items` 定义:`Array<{ label, amount, icon }>`,缺少 `desc` 字段。
#### 服务记录 thisMonthRecords内联 mock按日期分组
| 字段 | 类型 | 说明 | 契约 PERF-1 |
|------|------|------|------------|
| `date` | string | 日期标签 `'2月7日'` | ❌ 契约 `this_month_records` 结构完全不同 |
| `totalHours` | string | 当日总工时 `'4.0h'` | ❌ |
| `totalIncome` | string | 当日总收入 `'¥350'` | ❌ |
| `records[].customerName` | string | 客户名 | ⚠️ 契约有 `customer_name` |
| `records[].avatarChar` | string | 头像首字 | ❌ |
| `records[].avatarColor` | string | 头像颜色 | ❌ |
| `records[].timeRange` | string | 时间段 `'20:00-22:00'` | ❌ |
| `records[].hours` | string | 工时 `'2.0h'` | ⚠️ 契约有 `hours` 但是 number |
| `records[].courseType` | string | 课程类型 | ❌ |
| `records[].courseTypeClass` | string | 样式类 | ❌ |
| `records[].location` | string | 台号 | ❌ |
| `records[].income` | string | 收入 `'¥160'` | ⚠️ 契约有 `income` 但是 number |
#### 新客列表 newCustomers
| 字段 | 类型 | 说明 | 契约 PERF-1 |
|------|------|------|------------|
| `name` | string | 客户名 | ✅ |
| `avatarChar` | string | 头像首字 | ❌ 契约有 `avatar_char` |
| `avatarColor` | string | 头像颜色 | ❌ 未定义 |
| `lastService` | string | 最后服务日期 | ❌ 未定义 |
| `count` | number | 服务次数 | ❌ 未定义 |
#### 常客列表 regularCustomers
| 字段 | 类型 | 说明 | 契约 PERF-1 |
|------|------|------|------------|
| `name` | string | 客户名 | ✅ |
| `avatarChar` | string | 头像首字 | ❌ 契约有 `avatar_char` |
| `avatarColor` | string | 头像颜色 | ❌ 未定义 |
| `hours` | number | 总工时 | ❌ 未定义 |
| `income` | string | 总收入 | ❌ 未定义 |
| `count` | number | 到店次数 | ⚠️ 契约有 `visits` |
### 页面跳转
| 操作 | 目标 | 参数 |
|------|------|------|
| 查看全部记录 | `/pages/performance-records/performance-records` | 无参数 |
| 点击客户卡片 | `/pages/task-detail/task-detail` | `?customerName={name}` |
| 点击服务记录 | `/pages/task-detail/task-detail` | `?customerName={name}&taskId={taskId}` |
| 点击收入概览 | `/pages/performance-records/performance-records` | 无参数 |
### spec 未记录的 Gap
- **GAP-12**:契约 PERF-1 `this_month_records` 是扁平数组 `Array<{ customer_name, hours, income, date }>`,但前端需要 **按日期分组的 DateGroup 结构**(含 `date``totalHours``totalIncome``records[]`),且每条记录需要 `timeRange``courseType``courseTypeClass``location` 等字段。契约需大幅扩展。
- **GAP-13**:收入档位数据(`currentTier``nextTier``upgradeHoursNeeded``upgradeBonus`)在契约 PERF-1 中完全未定义。这些数据来自 `dws_assistant_salary_calc`,后端需返回。
- **GAP-14**`lastMonthIncome`(上月收入)在契约中未定义,前端 Banner 需要展示。
- **GAP-15**`incomeItems``desc` 字段(如 `"80元/h × 75h"`)在契约中未定义。后端需返回费率和工时的拆分数据,或直接返回格式化的 desc 字符串。
- **GAP-16**`newCustomers` 缺少 `lastService`(最后服务日期)和 `count`(服务次数)字段;`regularCustomers` 缺少 `hours`(总工时)和 `income`(总收入)字段。
- **GAP-17**:跳转 task-detail 时传 `customerName` 而非 `taskId`,但 task-detail 页面 `onLoad` 读取的是 `options.id`。参数传递不匹配,联调时会导致页面无法加载正确数据。
- **GAP-18**页面无月份切换功能F8API 支持 `year/month` 参数但页面固定当前月。
---
## 场景 5绩效明细页performance-records.ts
### API 调用
- `fetchPerformanceRecords({ year, month })``GET /api/xcx/performance/records?year=&month=&page=&pageSize=`
- 参数来源:`currentYear`/`currentMonth`(页面 data支持月份切换
- Banner 数据从 `getApp().globalData.authUser` 读取
### 前端期望字段 — summary
| 字段 | 类型 | 说明 | 契约 PERF-2 |
|------|------|------|------------|
| `totalCount` | number | 总笔数 32 | ✅ `total_count` |
| `totalHours` | number | 总工时 59.0 | ✅ `total_hours` |
| `totalHoursRaw` | number | 折算前总工时 63.5 | ✅ `total_hours_raw` |
| `totalIncome` | number | 总收入 4720 | ✅ `total_income` |
### 前端期望字段 — dateGroups按日期分组
| 字段 | 类型 | 说明 | 契约 PERF-2 |
|------|------|------|------------|
| `date` | string | 日期标签 `'2月7日'` | ✅ |
| `totalHours` | number | 当日总工时 | ✅ |
| `totalIncome` | number | 当日总收入 | ✅ |
| `records[].id` | string | 记录 ID | ✅ |
| `records[].customerName` | string | 客户名 | ✅ |
| `records[].avatarChar` | string | 头像首字 | ❌ 未定义 |
| `records[].avatarColor` | string | 头像颜色 | ❌ 未定义 |
| `records[].timeRange` | string | 时间段 | ✅ |
| `records[].hours` | number | 折算后工时 | ✅ |
| `records[].hoursRaw` | number? | 折算前工时 | ✅ |
| `records[].courseType` | string | 课程类型 | ✅ |
| `records[].courseTypeClass` | string | 样式类 | ✅ |
| `records[].location` | string | 台号 | ✅ |
| `records[].income` | number | 收入 | ✅ |
### courseTypeClass 完整枚举
前端使用的样式类:`tag-basic`(基础课)、`tag-vip`(包厢课)、`tag-tip`(打赏课)。
契约定义的 `course_type_class`:未明确枚举值。
### spec 未记录的 Gap
- **GAP-19**`avatarChar`(头像首字)和 `avatarColor`(头像颜色)在契约 PERF-2 中未定义。前端通过 `nameToAvatarColor()` 工具函数从姓名生成,但后端是否需要返回?建议前端自行计算。
- **GAP-20**`courseTypeClass` 的完整枚举值未在契约中明确。前端使用 `tag-basic`/`tag-vip`/`tag-tip`,但后端返回的是 `basic`/`vip`/`tip` 还是带 `tag-` 前缀?需统一。
- **GAP-21**月份切换时未重置分页F9 bug`switchMonth()``page` 未重置为 1。
- **GAP-22**Banner 字段 `coachName`/`coachLevel`/`storeName``globalData.authUser` 读取,但 `authUser` 当前未存储 `coachLevel``storeName`(见 GAP-01
---
## 场景 6客户详情页customer-detail.ts
### API 调用
- `fetchCustomerDetail(customerId)``GET /api/xcx/customers/{customerId}`
- 参数来源:页面路由参数(但当前代码从 `__route__` 解析,有 bug
### 前端期望字段 — 完整清单
#### 客户基本信息(内联 mock
| 字段 | 类型 | 说明 | 契约 CUST-1 |
|------|------|------|------------|
| `id` | string | 客户 ID | ✅ |
| `name` | string | 客户名 | ✅ |
| `avatarChar` | string | 头像首字 | ❌ 未定义 |
| `phone` | string | 手机号(完整) | ⚠️ 契约有 `phone`(脱敏)和 `phone_full`(完整) |
| `balance` | string | 余额 `'8,600'` | ❌ 未定义 |
| `consumption60d` | string | 近60天消费 `'2,800'` | ❌ 未定义 |
| `idealInterval` | string | 理想到店间隔 `'7天'` | ❌ 未定义 |
| `daysSinceVisit` | string | 距上次到店 `'12天'` | ❌ 未定义 |
#### AI 洞察 aiInsight内联 mock
| 字段 | 类型 | 说明 | 契约 CUST-1 |
|------|------|------|------------|
| `summary` | string | AI 分析摘要 | ❌ 未定义 |
| `strategies` | Array<{color, text}> | 策略建议列表 | ❌ 未定义 |
#### 维客线索 clues内联 mock7 条)
| 字段 | 类型 | 说明 | 契约 CUST-1 |
|------|------|------|------------|
| `category` | string | 线索大类(含换行符) | ⚠️ 契约说"同 TASK-2 格式" |
| `categoryColor` | string | 颜色 | ⚠️ |
| `text` | string | 含 emoji 的摘要 | ⚠️ |
| `source` | string | 来源 `'系统'`/`'小燕'` | ⚠️ |
| `detail` | string? | 详细描述 | ⚠️ |
#### 关联助教 coachTasks内联 mock4 位助教)
| 字段 | 类型 | 说明 | 契约 CUST-1 |
|------|------|------|------------|
| `name` | string | 助教名 | ❌ 完全未定义 |
| `level` | string | 等级 `senior/middle/junior` | ❌ |
| `levelColor` | string | 等级颜色 | ❌ |
| `taskType` | string | 任务类型标签 | ❌ |
| `taskColor` | string | 任务颜色 | ❌ |
| `bgClass` | string | 背景样式类 | ❌ |
| `status` | string | 状态 `normal/pinned/abandoned` | ❌ |
| `lastService` | string | 最后服务 `'02-20 21:30 · 2.5h'` | ❌ |
| `metrics` | Array<{label,value,color}> | 指标近60天次数/总时长/次均时长) | ❌ |
#### 最亲密助教 favoriteCoaches内联 mock2 位)
| 字段 | 类型 | 说明 | 契约 CUST-1 |
|------|------|------|------------|
| `emoji` | string | 爱心 emoji | ❌ 完全未定义 |
| `name` | string | 助教名 | ❌ |
| `relationIndex` | string | 关系指数 `'9.2'` | ❌ |
| `indexColor` | string | 指数颜色 | ❌ |
| `bgClass` | string | 背景样式类 | ❌ |
| `stats` | Array<{label,value,color}> | 统计(基础/激励/上课/充值) | ❌ |
#### 消费记录 consumptionRecords内联 mock3 条3 种类型)
| 字段 | 类型 | 说明 | 契约 CUST-1 |
|------|------|------|------------|
| `id` | string | 记录 ID | ✅ |
| `type` | enum | `table/shop/recharge` | ⚠️ 契约有 `type` 但枚举不同 |
| `date` | string | 日期 | ✅ |
| `tableName` | string? | 台桌名 | ❌ 契约有 `table` |
| `startTime` | string? | 开始时间 | ❌ 未定义 |
| `endTime` | string? | 结束时间 | ❌ 未定义 |
| `duration` | string? | 时长 `'3h 20min'` | ⚠️ 契约有 `duration` 但是 number |
| `tableFee` | number? | 台费 | ❌ 未定义 |
| `tableOrigPrice` | number? | 台费原价 | ❌ 未定义 |
| `coaches` | Array<{name,level,levelColor,courseType,hours,perfHours?,fee}> | 助教服务明细 | ❌ 完全未定义 |
| `foodAmount` | number? | 酒水金额 | ❌ 未定义 |
| `foodOrigPrice` | number? | 酒水原价 | ❌ 未定义 |
| `totalAmount` | number? | 总金额 | ⚠️ 契约有 `amount` |
| `totalOrigPrice` | number? | 总原价 | ❌ 未定义 |
| `payMethod` | string? | 支付方式 | ❌ 未定义 |
| `rechargeAmount` | number? | 充值金额 | ❌ 未定义 |
#### 备注 sortedNotes内联 mock3 条)
| 字段 | 类型 | 说明 | 契约 CUST-1 |
|------|------|------|------------|
| `id` | string | 备注 ID | ❌ 契约无备注字段 |
| `tagLabel` | string | 标签 | ❌ |
| `createdAt` | string | 创建时间 | ❌ |
| `content` | string | 内容 | ❌ |
### 页面跳转
| 操作 | 目标 | 参数 |
|------|------|------|
| 查看服务记录 | `/pages/customer-service-records/customer-service-records` | 无参数(⚠️ 未传 customerId |
| 问问助手 | `/pages/chat/chat` | 无参数(⚠️ 未传 customerId |
### spec 未记录的 Gap
- **GAP-23**`balance`(余额)、`consumption60d`近60天消费`idealInterval`(理想到店间隔)、`daysSinceVisit`(距上次到店天数)在契约 CUST-1 中完全未定义。这些是客户详情页 Banner 的核心展示字段。
- **GAP-24**`aiInsight`AI 洞察summary + strategies在契约 CUST-1 中完全未定义。数据来源应为 `biz.ai_cache`,但 `cache_type` 未明确(可能是 `app4_analysis` 或新增类型)。
- **GAP-25**`coachTasks`(关联助教任务列表)在契约 CUST-1 中完全未定义。这是一个复杂的数据结构,需要从 `biz.coach_tasks` + `fdw_etl.v_dwd_assistant_service_log` 聚合。每位助教需返回任务类型、状态、最后服务时间、近60天服务次数/总时长/次均时长。
- **GAP-26**`favoriteCoaches`(最亲密助教)在契约 CUST-1 中完全未定义。需要从 `fdw_etl.v_dws_member_assistant_relation_index` 获取关系指数,并聚合基础课时/激励课时/上课次数/充值金额。
- **GAP-27**:消费记录的 `coaches` 子数组(助教服务明细,含 `perfHours` 折算工时)在契约中完全未定义。这需要从 `fdw_etl.v_dwd_assistant_service_log` 按结算单关联查询。
- **GAP-28**:消费记录的 `tableFee`/`tableOrigPrice`/`foodAmount`/`foodOrigPrice`/`totalOrigPrice`/`payMethod` 等拆分字段在契约中未定义。契约仅有 `amount`(总金额)。
- **GAP-29**:消费记录的 `type` 枚举不一致 — 前端使用 `table/shop/recharge`3 种),契约使用 `type_class`(未明确枚举)。
- **GAP-30**:备注列表在契约 CUST-1 中未定义。前端需要展示客户相关的备注。
- **GAP-31**:跳转 customer-service-records 和 chat 时未传 `customerId` 参数,联调时目标页面无法获取客户 ID。
---
## 场景 7客户服务记录页customer-service-records.ts
### API 调用
- `fetchCustomerRecords({ customerId, year?, month?, table? })``GET /api/xcx/customers/{customerId}/records`
- 参数来源:`options.customerId``options.id`
- 当前实现:首次加载拉取全部记录,月份切换仅本地过滤
### 前端期望字段 — ServiceRecord
| 字段 | 类型 | 说明 | 契约 CUST-2 |
|------|------|------|------------|
| `table` | string | 台桌号 | ✅ |
| `type` | string | 课程类型标签 | ✅ |
| `typeClass` | enum | `basic/vip/tip/recharge` | ✅ `type_class` |
| `recordType` | enum | `course/recharge` | ❌ 未定义 |
| `duration` | number | 折算后小时 | ✅ |
| `durationRaw` | number | 折算前小时 | ✅ `duration_raw` |
| `income` | number | 到手金额 | ✅ |
| `isEstimate` | boolean | 是否预估 | ❌ 未定义 |
| `drinks` | string | 饮品描述 | ✅ |
| `date` | string | 显示日期 | ✅ |
### 页面头部字段
| 字段 | 类型 | 说明 | 契约 CUST-2 |
|------|------|------|------------|
| `customerName` | string | 客户名 | ✅ |
| `customerPhone` | string | 脱敏手机号 | ✅ `customer_phone` |
| `customerPhoneFull` | string | 完整手机号 | ❌ 未定义(需从 CUST-1 获取) |
| `relationIndex` | string | 关系指数 | ✅ |
| `totalServiceCount` | number | 累计服务次数 | ❌ 未定义 |
| `monthCount` | string | 当月次数 | ❌ 需前端计算 |
| `monthHours` | string | 当月工时 | ❌ 需前端计算 |
| `monthRelation` | string | 当月关系指数 | ❌ 未定义 |
### spec 未记录的 Gap
- **GAP-32**`recordType``course/recharge`)和 `isEstimate`(是否预估)在契约 CUST-2 中未定义。
- **GAP-33**`customerPhoneFull`(完整手机号)在 CUST-2 响应中未定义,前端需要点击查看完整号码。
- **GAP-34**`totalServiceCount`(累计服务次数)在 CUST-2 中未定义。
- **GAP-35**月份切换采用本地筛选F10联调后数据量大时需改为按月请求 API。
---
## 场景 8备注列表页notes.ts
### API 调用
- `fetchNotes({ page?, pageSize? })``GET /api/xcx/notes?page=&pageSize=`
- `deleteNote(noteId)``DELETE /api/xcx/notes/{noteId}`
### 前端期望字段 — Note
| 字段 | 类型 | 说明 | 契约 NOTE-1 |
|------|------|------|------------|
| `id` | string | 备注 ID | ✅ |
| `content` | string | 备注内容 | ✅ |
| `tagType` | enum | `customer/coach/system` | ✅ `tag_type` |
| `tagLabel` | string | 标签文案 | ✅ `tag_label` |
| `createdAt` | string | 创建时间 | ✅ `created_at` |
| `score` | number? | 满意度评分 | ✅ |
| `timeLabel` | string | 格式化时间(前端计算) | — |
### 写操作
| 操作 | API | 成功后行为 |
|------|-----|-----------|
| 删除备注 | `DELETE /notes/{noteId}` | 本地 filter 移除 + Toast |
### spec 未记录的 Gap
- **GAP-36**无触底加载逻辑F11API 支持分页但 `onReachBottom()` 未实现。
- **GAP-37**`tagType` 枚举 — mock 数据中有 `'system'` 类型,但契约 NOTE-1 仅定义 `customer/coach/system`。需确认 `system` 类型的备注由谁创建、如何展示。
---
## 场景 9助教详情页coach-detail.ts
### API 调用
- `fetchCoachDetail(coachId)``GET /api/xcx/coaches/{coachId}`
- 参数来源:`options.id`
- 返回类型:`CoachCard`api.ts 定义),但前端实际需要远超 `CoachCard` 的数据
### 前端期望字段 — CoachDetail完整清单
#### 基本信息
| 字段 | 类型 | 说明 | 契约 COACH-1 |
|------|------|------|-------------|
| `id` | string | 助教 ID | ✅ |
| `name` | string | 助教名 | ✅ |
| `avatar` | string | 头像 | ✅ |
| `level` | string | 等级 `'星级'` | ✅ |
| `skills` | string[] | 技能 | ✅ |
| `workYears` | number | 工龄 3 | ❌ 未定义 |
| `customerCount` | number | 客户数 68 | ❌ 未定义 |
| `hireDate` | string | 入职日期 | ❌ 未定义 |
| `store_name` | string | 门店名 | ✅ |
#### 绩效指标 performance6 个指标)
| 字段 | 类型 | 说明 | 契约 COACH-1 |
|------|------|------|-------------|
| `monthlyHours` | number | 本月工时 87.5 | ❌ 未定义 |
| `monthlySalary` | number | 本月工资 6950 | ❌ 未定义 |
| `customerBalance` | number | 客源储值余额 86200 | ❌ 未定义 |
| `tasksCompleted` | number | 任务完成数 38 | ❌ 未定义 |
| `perfCurrent` | number | 当前绩效 80 | ❌ 未定义 |
| `perfTarget` | number | 目标绩效 100 | ❌ 未定义 |
#### 绩效指标卡片 perfCards4 张)
| 卡片 | 需要字段 | 契约 |
|------|---------|------|
| 本月定档业绩 | `monthlyHours` + 折算前工时 | ❌ |
| 本月工资(预估) | `monthlySalary` | ❌ |
| 客源储值余额 | `customerBalance` + `customerCount` | ❌ |
| 本月任务完成 | `tasksCompleted` + 覆盖客户数 | ❌ |
#### 进度条数据
| 字段 | 类型 | 说明 | 契约 |
|------|------|------|------|
| `tierNodes` | number[] | 档位节点 `[0,100,130,160,190,220]` | ❌ 未定义 |
#### 收入明细 income本月/上月各 4 项)
| 项目 | 说明 | 契约 |
|------|------|------|
| 基础课时费 | `¥3,500` | ❌ 未定义 |
| 激励课时费 | `¥1,800` | ❌ 未定义 |
| 充值提成 | `¥1,200` | ❌ 未定义 |
| 酒水提成 | `¥450` | ❌ 未定义 |
#### 任务执行
| 字段 | 类型 | 说明 | 契约 COACH-1 |
|------|------|------|-------------|
| `visibleTasks` | TaskItem[] | 可见任务active | ⚠️ 契约说"同 TASK-1 item 格式"但实际需要更多字段 |
| `hiddenTasks` | TaskItem[] | 隐藏任务inactive | ⚠️ |
| `abandonedTasks` | AbandonedTask[] | 已放弃任务 | ⚠️ |
TaskItem 需要的字段(超出 TASK-1 item
| 字段 | 类型 | 说明 |
|------|------|------|
| `typeLabel` | string | 任务类型标签 |
| `typeClass` | string | 样式类 `high-priority/priority/relationship/callback` |
| `customerName` | string | 客户名 |
| `noteCount` | number | 备注数量 |
| `pinned` | boolean | 是否置顶 |
| `notes` | Array<{pinned?,text,date}> | 备注列表(含置顶标记) |
AbandonedTask 字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `customerName` | string | 客户名 |
| `reason` | string | 放弃原因 |
#### 客户关系 TOP20 — TopCustomer
| 字段 | 类型 | 说明 | 契约 COACH-1 |
|------|------|------|-------------|
| `id` | string | 客户 ID | ✅ |
| `name` | string | 客户名 | ✅ |
| `initial` | string | 姓名首字 | ❌ |
| `avatarGradient` | string | 头像渐变色 | ❌ |
| `heartEmoji` | string | 爱心 emoji `💖/🧡/💛/💙` | ❌ |
| `score` | string | 关系指数 `'9.5'` | ❌ 契约有 `total_spend`/`visit_count` 但无 score |
| `scoreColor` | string | 指数颜色 | ❌ |
| `serviceCount` | number | 服务次数 | ⚠️ 契约有 `visit_count` |
| `balance` | string | 余额 `'¥8,600'` | ❌ 未定义 |
| `consume` | string | 消费 `'¥12,800'` | ⚠️ 契约有 `total_spend` |
#### 近期服务明细 — ServiceRecord
| 字段 | 类型 | 说明 | 契约 COACH-1 |
|------|------|------|-------------|
| `customerId` | string? | 客户 ID | ❌ |
| `customerName` | string | 客户名 | ⚠️ |
| `initial` | string | 姓名首字 | ❌ |
| `avatarGradient` | string | 头像渐变色 | ❌ |
| `type` | string | 课程类型 | ⚠️ |
| `typeClass` | string | 样式类 | ⚠️ |
| `table` | string | 台号 | ⚠️ |
| `duration` | string | 时长 `'2.5h'` | ⚠️ |
| `income` | string | 收入 `'¥200'` | ⚠️ |
| `date` | string | 日期时间 | ⚠️ |
| `perfHours` | string? | 折算工时 `'2h'` | ❌ 未定义 |
#### 历史月份统计 — HistoryMonth
| 字段 | 类型 | 说明 | 契约 COACH-1 |
|------|------|------|-------------|
| `month` | string | 月份标签 `'本月'`/`'上月'`/`'4月'` | ❌ 完全未定义 |
| `estimated` | boolean | 是否预估 | ❌ |
| `customers` | string | 客户数 `'22人'` | ❌ |
| `hours` | string | 工时 `'87.5h'` | ❌ |
| `salary` | string | 工资 `'¥6,950'` | ❌ |
| `callbackDone` | number | 回访完成数 | ❌ |
| `recallDone` | number | 召回完成数 | ❌ |
### 页面跳转
| 操作 | 目标 | 参数 |
|------|------|------|
| 点击任务项 | `/pages/customer-detail/customer-detail` | `?name={customerName}` |
| 点击客户卡片 | `/pages/customer-detail/customer-detail` | `?id={customerId}` |
| 点击服务记录 | `/pages/customer-detail/customer-detail` | `?id={customerId}` |
| 查看更多服务记录 | `/pages/performance-records/performance-records` | `?coachId={coachId}` |
| 问问助手 | `/pages/chat/chat` | `?coachId={coachId}` |
### spec 未记录的 Gap
- **GAP-38**:契约 COACH-1 严重不完整。前端需要 `performance`6 个绩效指标)、`income`(本月/上月各 4 项收入明细)、`tierNodes`(档位节点数组),契约均未定义。
- **GAP-39**`TopCustomer` 需要 `heartEmoji``score`(关系指数)、`scoreColor``balance`(余额)、`consume`(消费),契约仅有 `total_spend`/`visit_count`
- **GAP-40**`ServiceRecord.perfHours`(折算工时)在契约中未定义。
- **GAP-41**`HistoryMonth`(历史月份统计)在契约中完全未定义。需要返回最近 N 个月的汇总数据(客户数、工时、工资、回访/召回完成数)。
- **GAP-42**`TaskItem.notes`(任务关联的备注列表,含置顶标记)在契约中未定义。契约的 `visible_tasks` 说"同 TASK-1 item 格式",但前端需要额外的 `noteCount``pinned``notes[]` 字段。
- **GAP-43**`AbandonedTask.reason`(放弃原因)在契约中未定义。
- **GAP-44**`workYears`(工龄)、`hireDate`(入职日期)在契约中未定义。
---
## 场景 10对话页面chat.ts + chat-history.ts
### chat.ts — API 调用
- `fetchChatMessages(customerId)``GET /api/xcx/chat/{chatId}/messages`
- ⚠️ 注意:前端传入的是 `customerId`(或 `'default'`),但 API 路径参数是 `chatId`。参数语义不匹配。
- `sendChatMessage(chatId, content)``POST /api/xcx/chat/{chatId}/messages`
- 页面参数:`options.customerId`
### chat.ts — 前端期望字段 — ChatMessage
| 字段 | 类型 | 说明 | 契约 CHAT-2 |
|------|------|------|------------|
| `id` | string | 消息 ID | ✅ |
| `role` | enum | `user/assistant` | ✅ |
| `content` | string | 消息内容 | ✅ |
| `timestamp` | string | 时间戳 | ⚠️ 契约用 `created_at` |
| `referenceCard` | object? | 引用卡片 | ❌ 完全未定义 |
| `referenceCard.type` | enum | `customer/record` | ❌ |
| `referenceCard.title` | string | 卡片标题 | ❌ |
| `referenceCard.summary` | string | 卡片摘要 | ❌ |
| `referenceCard.data` | Record<string,string> | 键值对数据 | ❌ |
### chat.ts — SSE 流式回复
- 前端 `simulateStreamOutput()` 模拟流式输出(逐字显示)
- 联调时需替换为真实 SSE 连接(`POST /api/xcx/chat/stream`
- spec R3 已确认保留 SSE 流式端点
### chat.ts — 页面参数
| 来源页面 | 传递参数 | 用途 |
|---------|---------|------|
| task-detail | `?customerId={taskId}` | ⚠️ 实际传的是 taskId |
| customer-detail | 无参数 | ⚠️ 未传 customerId |
| coach-detail | `?coachId={coachId}` | 助教 ID |
| chat-history | `?historyId={id}` | 历史对话 ID |
### chat-history.ts — API 调用
- `fetchChatHistory({ page?, pageSize? })``GET /api/xcx/chat/history`
- 返回:`{ items: ChatHistoryItem[], total, hasMore }`
### chat-history.ts — 前端期望字段 — ChatHistoryItem
| 字段 | 类型 | 说明 | 契约 CHAT-1 |
|------|------|------|------------|
| `id` | string | 对话 ID | ✅ |
| `title` | string | 对话标题 | ❌ 契约无 `title` |
| `lastMessage` | string | 最后消息 | ✅ `last_message` |
| `timestamp` | string | 时间戳 | ⚠️ 契约用 `last_time` |
| `customerName` | string? | 关联客户名 | ✅ |
### chat-history.ts — 页面跳转
| 操作 | 目标 | 参数 |
|------|------|------|
| 点击对话记录 | `/pages/chat/chat` | `?historyId={id}` |
### spec 未记录的 Gap
- **GAP-45**`ChatMessage.referenceCard`(引用卡片)在契约 CHAT-2 中完全未定义。前端需要展示客户概览卡片(含键值对数据),后端需在消息中附带结构化引用数据。
- **GAP-46**`ChatMessage.timestamp` vs 契约 `created_at` — 字段名不一致,前端使用 `timestamp`,契约定义 `created_at`
- **GAP-47**`ChatHistoryItem.title`(对话标题)在契约 CHAT-1 中未定义。契约仅有 `customer_name`/`last_message`/`last_time`/`unread_count`
- **GAP-48**`ChatHistoryItem.timestamp` vs 契约 `last_time` — 字段名不一致。
- **GAP-49**chat 页面接收 `customerId` 参数但 API 路径需要 `chatId`。前端需要一个"根据 customerId 查找或创建对话"的机制,或 API 支持 `customerId` 作为查询参数。
- **GAP-50**chat 页面还接收 `historyId`(从 chat-history 跳转)和 `coachId`(从 coach-detail 跳转),但 `loadMessages()` 仅使用 `customerId`。多种入口参数的路由逻辑未实现。
- **GAP-51**SSE 流式端点 `POST /api/xcx/chat/stream` 在契约中未定义spec R3 已确认需补充)。
---
## 汇总Gap 清单
### 一、架构级 Gap影响多个页面
| # | Gap | 严重度 | 影响页面 | 说明 |
|---|-----|--------|---------|------|
| GAP-01 | globalData.authUser 缺少 role/store_name/coach_level/avatar | 🟠 中 | task-list, performance, performance-records | 多个页面 Banner 需要这些字段,当前硬编码 |
| GAP-04 | pin/unpin API 端点未在契约中定义 | 🔴 高 | task-list | api.ts 无对应函数,前端仅本地更新 |
| GAP-05 | createNote 缺少 score 参数 | 🟠 中 | task-list, task-detail | 前端传 score 但 api.ts 签名无此字段 |
| GAP-09/10 | task-detail 跳转 chat/customer-service-records 时传 taskId 而非 customerId | 🔴 高 | task-detail → chat/customer-service-records | TASK-2 响应需包含 customer_id |
| GAP-31 | customer-detail 跳转时未传 customerId | 🔴 高 | customer-detail → chat/customer-service-records | 联调时目标页面无法获取客户 ID |
| GAP-17 | performance 跳转 task-detail 传 customerName 而非 taskId | 🟠 中 | performance → task-detail | 参数不匹配 |
### 二、TASK-1 扩展 Gap任务列表绩效卡片
| # | Gap | 严重度 | 说明 |
|---|-----|--------|------|
| GAP-02 | performance 字段严重不足(需 15+ 字段,契约仅 4 个) | 🔴 高 | tierNodes、basicHours、bonusHours、currentTier、nextTierHours、tierCompleted、bonusMoney、incomeTrend、incomeTrendDir、prevMonth 等 |
| GAP-03 | enrichTask 需要 lastVisitDays/balance/aiSuggestion | 🟠 中 | 任务卡片扩展字段 |
### 三、PERF-1 Gap绩效概览
| # | Gap | 严重度 | 说明 |
|---|-----|--------|------|
| GAP-12 | this_month_records 需要 DateGroup 分组结构 | 🔴 高 | 契约是扁平数组,前端需按日期分组 + timeRange/courseType/location |
| GAP-13 | 收入档位数据完全未定义 | 🔴 高 | currentTier/nextTier/upgradeHoursNeeded/upgradeBonus |
| GAP-14 | lastMonthIncome 未定义 | 🟠 中 | Banner 需展示上月收入 |
| GAP-15 | incomeItems.desc 未定义 | 🟠 中 | 需费率×工时的拆分描述 |
| GAP-16 | newCustomers/regularCustomers 缺少多个字段 | 🟠 中 | lastService/count/hours/income |
| GAP-18 | 页面无月份切换功能 | 🟡 低 | F8 前端修复项 |
### 四、CUST-1 Gap客户详情 — 最大 Gap 集中区)
| # | Gap | 严重度 | 说明 |
|---|-----|--------|------|
| GAP-23 | balance/consumption60d/idealInterval/daysSinceVisit 未定义 | 🔴 高 | Banner 核心展示字段 |
| GAP-24 | aiInsight (summary + strategies) 未定义 | 🔴 高 | AI 洞察模块 |
| GAP-25 | coachTasks关联助教任务列表未定义 | 🔴 高 | 复杂数据结构,需多表聚合 |
| GAP-26 | favoriteCoaches最亲密助教未定义 | 🔴 高 | 需关系指数 + 服务统计 |
| GAP-27 | 消费记录 coaches 子数组(助教服务明细)未定义 | 🔴 高 | 含 perfHours 折算工时 |
| GAP-28 | 消费记录拆分字段tableFee/foodAmount/totalOrigPrice 等)未定义 | 🟠 中 | 契约仅有 amount |
| GAP-29 | 消费记录 type 枚举不一致 | 🟠 中 | 前端 table/shop/recharge vs 契约未明确 |
| GAP-30 | 备注列表未定义 | 🟠 中 | 客户详情需展示备注 |
### 五、COACH-1 Gap助教详情 — 第二大 Gap 集中区)
| # | Gap | 严重度 | 说明 |
|---|-----|--------|------|
| GAP-38 | performance/income/tierNodes 未定义 | 🔴 高 | 6 个绩效指标 + 本月/上月各 4 项收入 + 档位节点 |
| GAP-39 | TopCustomer 缺少 heartEmoji/score/scoreColor/balance | 🔴 高 | 客户关系 TOP20 核心字段 |
| GAP-40 | ServiceRecord.perfHours 未定义 | 🟠 中 | 折算工时 |
| GAP-41 | HistoryMonth 完全未定义 | 🔴 高 | 历史月份统计5+ 个月) |
| GAP-42 | TaskItem.notes含置顶标记未定义 | 🟠 中 | 任务关联备注 |
| GAP-43 | AbandonedTask.reason 未定义 | 🟡 低 | 放弃原因 |
| GAP-44 | workYears/hireDate 未定义 | 🟡 低 | 助教基本信息 |
### 六、CHAT 模块 Gap
| # | Gap | 严重度 | 说明 |
|---|-----|--------|------|
| GAP-45 | ChatMessage.referenceCard 未定义 | 🔴 高 | 引用卡片(客户概览数据) |
| GAP-46 | timestamp vs created_at 字段名不一致 | 🟠 中 | 前端用 timestamp契约用 created_at |
| GAP-47 | ChatHistoryItem.title 未定义 | 🟠 中 | 对话标题 |
| GAP-48 | ChatHistoryItem.timestamp vs last_time 不一致 | 🟠 中 | 字段名不一致 |
| GAP-49 | customerId → chatId 映射机制缺失 | 🔴 高 | 前端传 customerId 但 API 需要 chatId |
| GAP-50 | 多入口参数路由逻辑未实现 | 🟠 中 | historyId/coachId/customerId 三种入口 |
| GAP-51 | SSE 流式端点未在契约中定义 | 🟠 中 | spec 已确认需补充 |
### 七、其他 Gap
| # | Gap | 严重度 | 说明 |
|---|-----|--------|------|
| GAP-06 | 维客线索 tag 格式不一致(含换行符) | 🟡 低 | 需统一 |
| GAP-07 | 维客线索 source 格式不一致 | 🟡 低 | mock 用 `'By:系统'`,类型定义用 `'manual'` |
| GAP-08 | aiAnalysis/talkingPoints 的 ai_cache cache_type 未明确 | 🟠 中 | 需明确映射 |
| GAP-11 | storageLevel/relationLevel 计算逻辑未明确 | 🟡 低 | 前端本地计算 |
| GAP-19 | avatarChar/avatarColor 是否后端返回 | 🟡 低 | 建议前端自行计算 |
| GAP-20 | courseTypeClass 枚举值前缀不统一 | 🟡 低 | `tag-basic` vs `basic` |
| GAP-21 | 月份切换未重置分页 | 🟡 低 | F9 前端 bug |
| GAP-22 | performance-records Banner 字段来源 | 🟡 低 | 依赖 GAP-01 |
| GAP-32 | recordType/isEstimate 未定义 | 🟡 低 | CUST-2 扩展字段 |
| GAP-33 | customerPhoneFull 未定义 | 🟡 低 | CUST-2 需完整手机号 |
| GAP-34 | totalServiceCount 未定义 | 🟡 低 | CUST-2 累计次数 |
| GAP-35 | 月份切换本地筛选需改 API 请求 | 🟡 低 | F10 前端修复 |
| GAP-36 | notes 页无触底加载 | 🟡 低 | F11 前端修复 |
| GAP-37 | Note.tagType 'system' 类型语义 | 🟡 低 | 需确认 |
---
### 统计
| 严重度 | 数量 | 说明 |
|--------|------|------|
| 🔴 高 | 17 | 阻塞联调,必须在后端开发前解决 |
| 🟠 中 | 19 | 影响功能完整性,需在联调前补充 |
| 🟡 低 | 15 | 可联调后修复或前端自行处理 |
| **合计** | **51** | |
### 最高优先级修复建议
1. **契约大幅扩展 CUST-1**:客户详情是 Gap 最集中的页面GAP-23~30需新增 `balance``consumption60d``idealInterval``daysSinceVisit``aiInsight``coachTasks``favoriteCoaches`、消费记录拆分字段、备注列表。
2. **契约大幅扩展 COACH-1**:助教详情是第二大 Gap 集中区GAP-38~44需新增 `performance`6 指标)、`income`8 项)、`tierNodes``TopCustomer` 扩展字段、`HistoryMonth``ServiceRecord.perfHours`
3. **契约扩展 PERF-1**:绩效概览需要 DateGroup 分组结构GAP-12和收入档位数据GAP-13
4. **契约扩展 TASK-1 performance**:绩效卡片需要 15+ 字段GAP-02
5. **修复 customerId/taskId 混淆**TASK-2 响应需包含 `customer_id`GAP-09/10customer-detail 跳转需传参GAP-31
6. **补充 CHAT 模块**referenceCardGAP-45、customerId→chatId 映射GAP-49、SSE 端点定义GAP-51