# 小程序 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(内联 mock,8 条) | 字段 | 类型 | 说明 | 契约 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(内联 mock,5 条) | 字段 | 类型 | 说明 | 契约 TASK-2 | |------|------|------|------------| | `talkingPoints` | string[] | 话术文本数组 | ✅ | #### 服务记录 serviceRecords(内联 mock,4 条) | 字段 | 类型 | 说明 | 契约 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(内联 mock,5 条) | 字段 | 类型 | 说明 | 契约 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(内联 mock,4 项) | 项目 | 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**:页面无月份切换功能(F8),API 支持 `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(内联 mock,7 条) | 字段 | 类型 | 说明 | 契约 CUST-1 | |------|------|------|------------| | `category` | string | 线索大类(含换行符) | ⚠️ 契约说"同 TASK-2 格式" | | `categoryColor` | string | 颜色 | ⚠️ | | `text` | string | 含 emoji 的摘要 | ⚠️ | | `source` | string | 来源 `'系统'`/`'小燕'` | ⚠️ | | `detail` | string? | 详细描述 | ⚠️ | #### 关联助教 coachTasks(内联 mock,4 位助教) | 字段 | 类型 | 说明 | 契约 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(内联 mock,2 位) | 字段 | 类型 | 说明 | 契约 CUST-1 | |------|------|------|------------| | `emoji` | string | 爱心 emoji | ❌ 完全未定义 | | `name` | string | 助教名 | ❌ | | `relationIndex` | string | 关系指数 `'9.2'` | ❌ | | `indexColor` | string | 指数颜色 | ❌ | | `bgClass` | string | 背景样式类 | ❌ | | `stats` | Array<{label,value,color}> | 统计(基础/激励/上课/充值) | ❌ | #### 消费记录 consumptionRecords(内联 mock,3 条,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(内联 mock,3 条) | 字段 | 类型 | 说明 | 契约 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**:无触底加载逻辑(F11),API 支持分页但 `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 | 门店名 | ✅ | #### 绩效指标 performance(6 个指标) | 字段 | 类型 | 说明 | 契约 COACH-1 | |------|------|------|-------------| | `monthlyHours` | number | 本月工时 87.5 | ❌ 未定义 | | `monthlySalary` | number | 本月工资 6950 | ❌ 未定义 | | `customerBalance` | number | 客源储值余额 86200 | ❌ 未定义 | | `tasksCompleted` | number | 任务完成数 38 | ❌ 未定义 | | `perfCurrent` | number | 当前绩效 80 | ❌ 未定义 | | `perfTarget` | number | 目标绩效 100 | ❌ 未定义 | #### 绩效指标卡片 perfCards(4 张) | 卡片 | 需要字段 | 契约 | |------|---------|------| | 本月定档业绩 | `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 | 键值对数据 | ❌ | ### 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/10),customer-detail 跳转需传参(GAP-31)。 6. **补充 CHAT 模块**:referenceCard(GAP-45)、customerId→chatId 映射(GAP-49)、SSE 端点定义(GAP-51)。