Files
Neo-ZQYY/docs/prd/Neo_Specs/miniprogram-storyboard-walkthrough-gaps.md

814 lines
47 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 走查报告 — API 需求 Gap 分析
> 走查日期2026-03-18
> 走查角色:管理层/店长
> 走查路线3 个看板 → 助教详情 → 客户详情 → 服务记录
> 对比基准:前端内联 mock 数据 vs API 契约 (`API-contract.md`) vs 八¾节 (`NS1-xcx-backend-api.md`)
---
## 场景 1助教看板 → 助教详情 → 客户详情
### 1.1 board-coach`pages/board-coach/board-coach.ts`
#### API 调用
- `fetchBoardCoaches({ skill, sort, time })``CoachItem[]`
- 页面 `onLoad()``loadData()``fetchBoardCoaches()`
- 下拉刷新 `onPullDownRefresh()``loadData()`
- ⚠️ 筛选变更(`onSortChange`/`onSkillChange`/`onTimeChange`)仅更新 data 状态,**不调用 `loadData()`**(八¾节 F1 已记录)
#### 前端期望字段(从内联 MOCK_COACHES 的 CoachItem 接口提取,共 18 个字段)
| 字段 | 类型 | 说明 | 数据源 |
|------|------|------|--------|
| `id` | string | 助教 ID | dim_assistant |
| `name` | string | 助教姓名 | dim_assistant |
| `initial` | string | 姓名首字(头像占位) | 前端可计算 |
| `avatarGradient` | string | 头像渐变色 (blue/green/pink/amber/violet/cyan) | 前端可计算或后端分配 |
| `level` | string | 等级 key: star/senior/middle/junior | dim_assistant |
| `levelClass` | string | 等级样式类 | 前端可映射LEVEL_CLASS 常量) |
| `skills` | `Array<{text: string, cls: string}>` | 技能列表含 emoji 和样式类 | cfg 表 |
| `topCustomers` | `string[]` | Top 客户列表含 emoji 前缀(如 `'💖 王先生'` | dws_member_assistant_relation_index |
| `perfHours` | number | 当期定档工时 | dws_assistant_salary_calc |
| `perfHoursBefore` | number? | 上期定档工时(可选) | dws_assistant_salary_calc (上期) |
| `perfGap` | string? | 距升档差距描述(如 `"距升档 13.8h"`,已达标时不返回) | 后端计算 |
| `perfReached` | boolean | 是否已达标 | 后端计算 |
| `salary` | number | 工资总额(元) | dws_assistant_salary_calc |
| `salaryPerfHours` | number | 定档工时 | 同 perfHours |
| `salaryPerfBefore` | number? | 上期定档工时 | 同 perfHoursBefore |
| `svAmount` | number | 客源储值总额(元) | dws_member_consumption_summary |
| `svCustomerCount` | number | 储值客户数 | dws_member_consumption_summary |
| `svConsume` | number | 储值消耗额(元) | dws_member_consumption_summary |
| `taskRecall` | number | 召回任务完成数 | biz.coach_tasks |
| `taskCallback` | number | 回访任务完成数 | biz.coach_tasks |
#### 筛选参数映射
| 筛选项 | 前端参数 | 后端参数 | 查询影响 |
|--------|---------|---------|---------|
| 排序维度 | `sort`: perf_desc/perf_asc/salary_desc/salary_asc/sv_desc/task_desc | `sort` | 决定排序字段和方向 + 卡片模板(dimType) |
| 技能筛选 | `skill`: all/chinese/snooker/mahjong/karaoke | `skill` | WHERE 过滤助教技能类型 |
| 时间范围 | `time`: month/quarter/last_month/last_3m/last_quarter/last_6m | `time` | 决定统计日期区间 |
交叉约束:`time=last_6m` + `sort=sv_desc` 不兼容TIME_OPTIONS 注释标注)
#### 页面跳转
- 点击助教卡片 `onCoachTap``/pages/coach-detail/coach-detail?id={coachId}`
- Tab 切换 → `board-finance`switchTab/ `board-customer`navigateTo
#### API 契约 vs Mock 数据 vs 八¾节 差异
| 差异项 | API 契约 (BOARD-1) | 前端 Mock (CoachItem) | 八¾节 (B1) | 严重度 |
|--------|--------------------|-----------------------|------------|--------|
| 字段结构 | 扁平简单:`id, name, avatar, level, level_class, skills(string[]), total_hours, total_income, customer_count, satisfaction` | 丰富结构4 维度 20 个字段skills 为对象数组,含 topCustomers | 与 Mock 一致,详细列出 4 维度字段 | 🔴 高 |
| `initial` 字段 | ❌ 无 | ✅ 有 | ✅ 有 | 🟠 中 |
| `avatarGradient` 字段 | ❌ 无(仅 `avatar` URL | ✅ 有 | ✅ 有 | 🟠 中 |
| `skills` 类型 | `string[]` | `Array<{text, cls}>` | `Array<{text, cls}>` | 🔴 高 |
| `topCustomers` 字段 | ❌ 无 | ✅ 有 | ✅ 有 | 🔴 高 |
| 4 维度专属字段 | ❌ 全部缺失(仅 total_hours/total_income/customer_count/satisfaction | ✅ 完整perf/salary/sv/task 各 2-4 个字段) | ✅ 完整 | 🔴 高 |
| `sort` 参数格式 | `sort=field:direction` | `sort=perf_desc` 等枚举 | `sort=perf_desc` 等枚举 | 🟠 中 |
| 分页 | 无分页定义 | 无分页(全量返回) | 无分页 | 🟡 低 |
#### spec 未记录的 Gap
1. 🔴 API 契约 BOARD-1 响应字段与前端实际需求严重不匹配 — 契约仅定义 10 个通用字段,前端需要 20 个含 4 维度专属字段
2. 🔴 `skills` 类型不一致 — 契约为 `string[]`,前端需要 `Array<{text, cls}>`(含 emoji 和样式类)
3. 🔴 `topCustomers` 字段契约完全缺失 — 前端每个助教卡片展示 Top 3 客户
4. 🟠 `sort` 参数格式不一致 — 契约用 `field:direction`,前端用枚举值 `perf_desc`
5. 🟠 `initial`/`avatarGradient` 字段契约缺失 — 前端用于头像渲染,需确认由前端计算还是后端返回
---
### 1.2 coach-detail`pages/coach-detail/coach-detail.ts`
#### API 调用
- `fetchCoachDetail(coachId)``CoachCard | null`api.ts 返回类型过于简单)
- 页面 `onLoad({ id })``loadData(id)``fetchCoachDetail(id)`
- 实际使用内联 mock 数据组装 CoachDetail 对象
#### 前端期望字段(从 mockCoachDetail + 各 mock 数组提取)
**CoachDetail 基础信息:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 助教 ID |
| `name` | string | 助教姓名 |
| `avatar` | string | 头像 URL |
| `level` | string | 等级(中文:星级/高级/中级/初级) |
| `skills` | string[] | 技能列表 |
| `workYears` | number | 工龄 |
| `customerCount` | number | 客户数 |
| `hireDate` | string | 入职日期 |
**performance 绩效指标:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `performance.monthlyHours` | number | 本月定档业绩工时 |
| `performance.monthlySalary` | number | 本月工资(预估) |
| `performance.customerBalance` | number | 客源储值余额 |
| `performance.tasksCompleted` | number | 本月任务完成数 |
| `performance.perfCurrent` | number | 当前绩效值 |
| `performance.perfTarget` | number | 目标绩效值 |
**income 收入明细(本月/上月 Tab 切换):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `income.thisMonth` | `IncomeItem[]` | 本月收入明细(基础课时费/激励课时费/充值提成/酒水提成) |
| `income.lastMonth` | `IncomeItem[]` | 上月收入明细 |
| IncomeItem: `label` | string | 收入项名称 |
| IncomeItem: `amount` | string | 金额(格式化,如 `"¥3,500"` |
| IncomeItem: `color` | string | 颜色标识 |
**任务执行区域(管理层视角核心):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `visibleTasks` | `TaskItem[]` | 可见任务active 状态) |
| `hiddenTasks` | `TaskItem[]` | 隐藏任务inactive 状态,被顶替但未过期) |
| `abandonedTasks` | `AbandonedTask[]` | 已放弃任务 |
| TaskItem: `typeLabel` | string | 任务类型标签(高优先召回/优先召回/关系构建/客户回访) |
| TaskItem: `typeClass` | string | 样式类high-priority/priority/relationship/callback |
| TaskItem: `customerName` | string | 客户姓名 |
| TaskItem: `noteCount` | number | 备注数量 |
| TaskItem: `pinned` | boolean | 是否置顶 |
| TaskItem: `notes` | `Array<{pinned?, text, date}>` | 备注列表(可选) |
| AbandonedTask: `customerName` | string | 客户姓名 |
| AbandonedTask: `reason` | string | 放弃原因 |
**客户关系 TOP20管理层关注指标**
| 字段 | 类型 | 说明 |
|------|------|------|
| TopCustomer: `id` | string | 客户 ID |
| TopCustomer: `name` | string | 客户姓名 |
| TopCustomer: `initial` | string | 姓名首字 |
| TopCustomer: `avatarGradient` | string | 头像渐变色 |
| TopCustomer: `heartEmoji` | string | 爱心 emoji/💛/🤍) |
| TopCustomer: `score` | string | 关系指数 |
| TopCustomer: `scoreColor` | string | 分数颜色success/warning/gray |
| TopCustomer: `serviceCount` | number | 服务次数 |
| TopCustomer: `balance` | string | 余额(格式化) |
| TopCustomer: `consume` | string | 消费额(格式化) |
**近期服务明细:**
| 字段 | 类型 | 说明 |
|------|------|------|
| ServiceRecord: `customerId` | string? | 客户 ID |
| ServiceRecord: `customerName` | string | 客户姓名 |
| ServiceRecord: `initial` | string | 姓名首字 |
| ServiceRecord: `avatarGradient` | string | 头像渐变色 |
| ServiceRecord: `type` | string | 课程类型(基础课/激励课) |
| ServiceRecord: `typeClass` | string | 样式类basic/incentive |
| ServiceRecord: `table` | string | 台桌号 |
| ServiceRecord: `duration` | string | 时长(格式化) |
| ServiceRecord: `income` | string | 收入(格式化) |
| ServiceRecord: `date` | string | 日期时间 |
| ServiceRecord: `perfHours` | string? | 定档工时(可选) |
**历史月份统计(管理层评估助教表现):**
| 字段 | 类型 | 说明 |
|------|------|------|
| HistoryMonth: `month` | string | 月份标签(本月/上月/4月... |
| HistoryMonth: `estimated` | boolean | 是否预估 |
| HistoryMonth: `customers` | string | 客户数(格式化,如 `"22人"` |
| HistoryMonth: `hours` | string | 工时(格式化,如 `"87.5h"` |
| HistoryMonth: `salary` | string | 工资(格式化) |
| HistoryMonth: `callbackDone` | number | 回访完成数 |
| HistoryMonth: `recallDone` | number | 召回完成数 |
**备注列表:**
| 字段 | 类型 | 说明 |
|------|------|------|
| NoteItem: `id` | string | 备注 ID |
| NoteItem: `content` | string | 备注内容 |
| NoteItem: `timestamp` | string | 时间戳 |
| NoteItem: `score` | number | 评分 |
| NoteItem: `customerName` | string | 关联客户/管理员名 |
| NoteItem: `tagLabel` | string | 标签 |
| NoteItem: `createdAt` | string | 创建时间(格式化) |
**绩效进度条数据(前端需要后端提供):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `tierNodes` | number[] | 档位节点数组(如 `[0, 100, 130, 160, 190, 220]` |
| `maxHours` | number | 最大工时(进度条满值) |
#### 筛选参数映射
- 无筛选项,单次加载全部数据
- 收入明细有本月/上月 Tab 切换(纯前端切换,数据一次性返回)
#### 页面跳转
- 点击任务项 `onTaskItemTap``/pages/customer-detail/customer-detail?name={customerName}`(⚠️ 用 name 而非 id
- 点击客户卡片 `onCustomerTap``/pages/customer-detail/customer-detail?id={customerId}`
- 点击服务记录 `onSvcCardTap``/pages/customer-detail/customer-detail?id={customerId}`
- 查看更多服务记录 `onViewMoreRecords``/pages/performance-records/performance-records?coachId={coachId}`
- 问问助手 `onStartChat``/pages/chat/chat?coachId={coachId}`
#### API 契约 vs Mock 数据 vs 八¾节 差异
| 差异项 | API 契约 (COACH-1) | 前端 Mock | 八¾节 | 严重度 |
|--------|--------------------|-----------|----|--------|
| 返回类型 | api.ts 返回 `CoachCard`(仅 id/name/avatar/level/keyMetrics | 实际需要 CoachDetail含 performance/income/tasks/topCustomers/serviceRecords/historyMonths/notes | 仅提到基本信息+任务分组+Top客户+服务记录 | 🔴 高 |
| `income` 本月/上月明细 | ❌ 无 | ✅ 有4 项收入分类 × 2 月) | ❌ 无 | 🔴 高 |
| `topCustomers` TOP20 | 契约仅 `top_customers: Array<{id, name, avatar, total_spend, visit_count}>` | Mock 含 20 条,每条含 heartEmoji/score/scoreColor/serviceCount/balance/consume | ❌ 未详细定义字段 | 🔴 高 |
| `historyMonths` 历史月份 | ❌ 完全缺失 | ✅ 有5 个月,含 estimated/customers/hours/salary/callbackDone/recallDone | ❌ 完全缺失 | 🔴 高 |
| `tierNodes` 档位节点 | ❌ 缺失 | ✅ 有(进度条组件需要) | ❌ 缺失 | 🟠 中 |
| 任务分组 | `visible_tasks`/`hidden_tasks`/`abandoned_tasks` | 同,但 TaskItem 结构含 notes 子数组 | ✅ 已确认 active/inactive/abandoned 映射 | 🟡 低 |
| 备注列表 | ❌ 未在 COACH-1 定义 | ✅ 有(含 score 字段) | ❌ 未提及 | 🟠 中 |
#### spec 未记录的 Gap
1. 🔴 COACH-1 响应缺少 `income` 收入明细(本月/上月 4 项分类)— 管理层评估助教收入结构的核心数据
2. 🔴 COACH-1 响应缺少 `historyMonths` 历史月份统计 — 管理层评估助教长期表现趋势
3. 🔴 `topCustomers` 字段结构不完整 — 契约仅 5 个字段,前端需要 10 个字段(含 heartEmoji/scoreColor/balance/consume
4. 🟠 COACH-1 响应缺少 `tierNodes`/`maxHours` — 绩效进度条组件需要档位节点数据
5. 🟠 COACH-1 响应缺少备注列表 — 管理层需要查看助教相关备注
6. 🟠 `onTaskItemTap``name` 而非 `id` 跳转客户详情 — 前端 Bugname 不唯一
7. 🟡 api.ts 中 `fetchCoachDetail` 返回类型为 `CoachCard`mock-data.ts 中的简单类型),与实际需要的 CoachDetail 不匹配
---
## 场景 2客户看板 → 客户详情 → 客户服务记录
### 2.1 board-customer`pages/board-customer/board-customer.ts`
#### API 调用
- `fetchBoardCustomers({ dimension, project })``CustomerItem[]`
- 页面 `onLoad()``loadData()``fetchBoardCustomers()`
- 下拉刷新 `onPullDownRefresh()``loadData()`
- ⚠️ 筛选变更(`onDimensionChange`/`onProjectChange`)仅更新 data 状态,**不调用 `loadData()`**(八¾节 F2 已记录)
- ⚠️ 缺少分页参数 `page`/`pageSize`(八¾节 F3 已记录)
#### 前端期望字段(从内联 MOCK_CUSTOMERS 的 CustomerItem 接口提取)
**所有维度共享基础字段(每个 item 都返回):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 客户 member_id |
| `name` | string | 客户姓名 |
| `initial` | string | 姓名首字 |
| `avatarCls` | string | 头像样式类avatar--amber/pink/blue 等) |
| `assistants` | `AssistantInfo[]` | 关联助教列表 |
**AssistantInfo 结构:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | string | 助教姓名 |
| `cls` | string | 样式类assistant--assignee/abandoned/normal |
| `heartScore` | number | 爱心分 0-10 |
| `badge` | string? | 标记(跟/弃) |
| `badgeCls` | string? | 标记样式类 |
**8 维度专属字段(按 dimension 参数返回对应字段):**
| 维度 | 专属字段 | 类型 | 说明 |
|------|---------|------|------|
| recall | `idealDays` | number | 理想到店间隔(天) |
| | `elapsedDays` | number | 已过天数 |
| | `overdueDays` | number | 超期天数 |
| | `visits30d` | number | 近30天到店次数 |
| | `balance` | string | 余额(格式化) |
| | `recallIndex` | string | 召回指数 |
| potential | `potentialTags` | `Array<{text, theme}>` | 潜力标签 |
| | `spend30d` | string | 近30天消费 |
| | `avgVisits` | string | 月均到店 |
| | `avgSpend` | string | 次均消费 |
| balance | `balance` | string | 当前余额 |
| | `lastVisit` | string | 最近到店 |
| | `monthlyConsume` | string | 月均消耗 |
| | `availableMonths` | string | 可用月数 |
| recharge | `lastRecharge` | string | 最后充值日期 |
| | `rechargeAmount` | string | 充值金额 |
| | `recharges60d` | string | 近60天充值次数 |
| | `currentBalance` | string | 当前余额 |
| recent | `daysAgo` | number | 距今天数 |
| | `visitFreq` | string | 到店频率 |
| | `idealDays` | number | 理想间隔 |
| | `visits30d` | number | 近30天到店 |
| | `avgSpend` | string | 次均消费 |
| spend60 | `spend60d` | string | 近60天消费总额 |
| | `visits60d` | string | 近60天到店次数 |
| | `highSpendTag` | boolean | 是否高消费标签 |
| | `avgSpend` | string | 次均消费 |
| freq60 | `visits60d` | string | 近60天到店次数 |
| | `avgInterval` | string | 平均到店间隔 |
| | `weeklyVisits` | `Array<{val, pct}>` | 8周到店柱状图 |
| | `spend60d` | string | 近60天消费 |
| loyal | `intimacy` | string | 亲密度指数 |
| | `topCoachName` | string | 最亲密助教姓名 |
| | `topCoachHeart` | number | 最亲密助教爱心分 |
| | `topCoachScore` | string | 最亲密助教关系指数 |
| | `coachName` | string | 主助教姓名 |
| | `coachRatio` | string | 主助教占比 |
| | `coachDetails` | `Array<{name, cls, heartScore, badge?, avgDuration, serviceCount, coachSpend, relationIdx}>` | 助教服务明细表 |
#### 筛选参数映射
| 筛选项 | 前端参数 | 后端参数 | 查询影响 |
|--------|---------|---------|---------|
| 维度切换 | `dimension`: recall/potential/balance/recharge/recent/spend60/freq60/loyal | `dimension` | 决定查询的 FDW 表和排序字段 |
| 项目筛选 | `project`: all/chinese/snooker/mahjong/karaoke | `project` | WHERE 过滤客户偏好项目 |
无交叉约束8×5=40 种有效组合。
#### 页面跳转
- 点击客户卡片 `onCustomerTap``/pages/customer-detail/customer-detail?id={customerId}`
- Tab 切换 → `board-finance`switchTab/ `board-coach`navigateTo
#### API 契约 vs Mock 数据 vs 八¾节 差异
| 差异项 | API 契约 (BOARD-2) | 前端 Mock (CustomerItem) | 八¾节 (B2) | 严重度 |
|--------|--------------------|-----------------------|------------|--------|
| 字段结构 | 扁平简单:`id, name, avatar, tags(string[]), total_spend, visit_count, last_visit, relation_index` | 丰富结构8 维度 40+ 专属字段 + assistants 对象数组 | 与 Mock 一致 | 🔴 高 |
| `assistants` 字段 | ❌ 无 | ✅ 有(含 name/cls/heartScore/badge/badgeCls | ✅ 有 | 🔴 高 |
| `avatarCls` 字段 | ❌ 无(仅 `avatar` URL | ✅ 有 | ✅ 有 | 🟠 中 |
| `initial` 字段 | ❌ 无 | ✅ 有 | ✅ 有 | 🟠 中 |
| 8 维度专属字段 | ❌ 全部缺失 | ✅ 完整 | ✅ 完整 | 🔴 高 |
| `weeklyVisits` 柱状图 | ❌ 无 | ✅ 有freq60 维度8 周数据) | ✅ 有 | 🔴 高 |
| `coachDetails` 明细表 | ❌ 无 | ✅ 有loyal 维度,助教服务明细) | ✅ 有 | 🔴 高 |
| `potentialTags` 标签 | ❌ 无 | ✅ 有potential 维度,含 text+theme | ✅ 有 | 🟠 中 |
| 分页 | ✅ 有page/pageSize | ❌ 无(全量返回 3 条 mock | ✅ 已确认 20 条懒加载 | 🟡 低 |
#### spec 未记录的 Gap
1. 🔴 API 契约 BOARD-2 响应字段与前端实际需求严重不匹配 — 契约仅 8 个通用字段,前端需要 40+ 维度专属字段
2. 🔴 `assistants` 关联助教列表契约完全缺失 — 每个客户卡片展示关联助教及其爱心分/跟弃状态
3. 🔴 `weeklyVisits` 8 周柱状图数据契约缺失 — freq60 维度的核心可视化数据
4. 🔴 `coachDetails` 助教服务明细表契约缺失 — loyal 维度展示每个助教的详细服务数据
5. 🟠 `potentialTags` 标签结构契约缺失 — potential 维度展示客户潜力标签
---
### 2.2 customer-detail`pages/customer-detail/customer-detail.ts`
#### API 调用
- `fetchCustomerDetail(customerId)``MockCustomerDetail | null`
- 页面 `onLoad()``loadDetail()``fetchCustomerDetail(id)`
- ⚠️ `loadDetail()` 中 id 获取方式有 Bug`(this as any).__route__?.split('?')[1]` 无法正确解析 query 参数
#### 前端期望字段(从内联 data 提取,管理层视角)
**客户基础信息:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `detail.id` | string | 客户 ID |
| `detail.name` | string | 客户姓名 |
| `detail.avatarChar` | string | 头像字符 |
| `detail.phone` | string | 完整手机号(前端控制脱敏显示) |
| `detail.balance` | string | 余额(格式化) |
| `detail.consumption60d` | string | 近60天消费格式化 |
| `detail.idealInterval` | string | 理想到店间隔 |
| `detail.daysSinceVisit` | string | 距上次到店天数 |
**AI 洞察(管理层视角特有):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `aiInsight.summary` | string | AI 分析摘要 |
| `aiInsight.strategies` | `Array<{color, text}>` | 策略建议列表 |
**维客线索clues**
| 字段 | 类型 | 说明 |
|------|------|------|
| `clues[].category` | string | 线索大类(含换行符格式化) |
| `clues[].categoryColor` | string | 分类颜色 |
| `clues[].text` | string | 线索文本(含 emoji |
| `clues[].source` | string | 来源(系统/助教名) |
| `clues[].detail` | string? | 详情(可选,展开显示) |
**关联助教 coachTasks管理层关注多助教对同一客户的服务**
| 字段 | 类型 | 说明 |
|------|------|------|
| `coachTasks[].name` | string | 助教姓名 |
| `coachTasks[].level` | string | 等级 |
| `coachTasks[].levelColor` | string | 等级颜色 |
| `coachTasks[].taskType` | string | 任务类型标签 |
| `coachTasks[].taskColor` | string | 任务颜色 |
| `coachTasks[].bgClass` | string | 背景样式类 |
| `coachTasks[].status` | string | 状态normal/pinned/abandoned |
| `coachTasks[].lastService` | string | 最后服务时间 |
| `coachTasks[].metrics` | `Array<{label, value, color?}>` | 指标列表近60天次数/总时长/次均时长) |
**喜好助教 favoriteCoaches**
| 字段 | 类型 | 说明 |
|------|------|------|
| `favoriteCoaches[].emoji` | string | 爱心 emoji |
| `favoriteCoaches[].name` | string | 助教姓名 |
| `favoriteCoaches[].relationIndex` | string | 关系指数 |
| `favoriteCoaches[].indexColor` | string | 指数颜色 |
| `favoriteCoaches[].bgClass` | string | 背景样式类 |
| `favoriteCoaches[].stats` | `Array<{label, value, color?}>` | 统计(基础/激励/上课/充值) |
**消费记录 consumptionRecords3 种类型,管理层关注消费结构):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `ConsumptionRecord.id` | string | 记录 ID |
| `ConsumptionRecord.type` | `"table" \| "shop" \| "recharge"` | 消费类型 |
| `ConsumptionRecord.date` | string | 日期 |
| `ConsumptionRecord.tableName` | string? | 台桌名table 类型) |
| `ConsumptionRecord.startTime` | string? | 开始时间 |
| `ConsumptionRecord.endTime` | string? | 结束时间 |
| `ConsumptionRecord.duration` | string? | 时长 |
| `ConsumptionRecord.tableFee` | number? | 台费(优惠后) |
| `ConsumptionRecord.tableOrigPrice` | number? | 台费原价 |
| `ConsumptionRecord.coaches` | `Array<{name, level, levelColor, courseType, hours, perfHours?, fee}>` | 助教服务明细 |
| `ConsumptionRecord.foodAmount` | number? | 食品酒水金额(优惠后) |
| `ConsumptionRecord.foodOrigPrice` | number? | 食品酒水原价 |
| `ConsumptionRecord.totalAmount` | number? | 总金额 |
| `ConsumptionRecord.totalOrigPrice` | number? | 总原价 |
| `ConsumptionRecord.payMethod` | string? | 支付方式 |
| `ConsumptionRecord.rechargeAmount` | number? | 充值金额recharge 类型) |
**备注列表:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `sortedNotes[].id` | string | 备注 ID |
| `sortedNotes[].tagLabel` | string | 标签(管理员/助教名) |
| `sortedNotes[].createdAt` | string | 创建时间 |
| `sortedNotes[].content` | string | 备注内容 |
#### 页面跳转
- 查看服务记录 `onViewServiceRecords``/pages/customer-service-records/customer-service-records`(⚠️ 未传 customerId 参数!)
- 问问助手 `onStartChat``/pages/chat/chat`(⚠️ 未传 customerId 参数!)
#### API 契约 vs Mock 数据 差异
| 差异项 | API 契约 (CUST-1) | 前端 Mock | 严重度 |
|--------|--------------------|-----------| --------|
| `aiInsight` AI 洞察 | ❌ 完全缺失 | ✅ 有summary + strategies | 🔴 高 |
| `coachTasks` 关联助教任务 | ❌ 完全缺失 | ✅ 有4 个助教,含 metrics | 🔴 高 |
| `favoriteCoaches` 喜好助教 | ❌ 完全缺失 | ✅ 有(含 stats 统计) | 🔴 高 |
| `clues` 维客线索 | 契约有 `retention_clues` 但结构不同 | 前端用 category/categoryColor/text/source/detail | 🟠 中 |
| `consumptionRecords` 结构 | 契约为扁平 `{id, date, type, type_class, amount, table, duration}` | 前端为嵌套结构(含 coaches 子数组、tableFee/foodAmount 分项) | 🔴 高 |
| `balance`/`consumption60d`/`idealInterval`/`daysSinceVisit` | ❌ 缺失 | ✅ 有 | 🟠 中 |
| `avatarChar` | ❌ 无(仅 avatar URL | ✅ 有 | 🟡 低 |
| 备注列表 | ❌ 未在 CUST-1 定义 | ✅ 有 | 🟠 中 |
#### spec 未记录的 Gap
1. 🔴 CUST-1 缺少 `aiInsight` AI 洞察 — 管理层查看客户时的核心决策辅助信息来源biz.ai_cache app4_analysis
2. 🔴 CUST-1 缺少 `coachTasks` 关联助教任务区域 — 管理层关注多助教对同一客户的服务情况
3. 🔴 CUST-1 缺少 `favoriteCoaches` 喜好助教 — 展示客户与各助教的关系指数和服务统计
4. 🔴 CUST-1 消费记录结构严重不匹配 — 契约为扁平结构,前端需要嵌套结构(含助教明细、台费/食品分项、原价/优惠后价格)
5. 🟠 `onViewServiceRecords` 跳转未传 `customerId` — 前端 Bug
6. 🟠 `onStartChat` 跳转未传 `customerId` — 前端 Bug
7. 🟠 `loadDetail()` 中 id 解析方式有 Bug — 应从 `onLoad(options)` 的 options 中获取
---
### 2.3 customer-service-records`pages/customer-service-records/customer-service-records.ts`
#### API 调用
- `fetchCustomerRecords({ customerId })``{ records, hasMore }`
- 页面 `onLoad({ customerId, id })``loadData(id)``fetchCustomerRecords({ customerId: id })`
- ⚠️ 首次加载拉取全部记录,月份切换仅本地过滤(八¾节 F10/L4 已记录)
#### 前端期望字段
**页面头部信息:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `customerName` | string | 客户姓名 |
| `customerPhone` | string | 脱敏手机号 |
| `customerPhoneFull` | string | 完整手机号 |
| `totalServiceCount` | number | 累计服务次数 |
| `relationIndex` | string | 关系指数 |
**ServiceRecord 结构(转换后):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `table` | string | 台桌号 |
| `type` | string | 课程类型标签 |
| `typeClass` | `'basic' \| 'vip' \| 'tip' \| 'recharge'` | 样式类 |
| `recordType` | `'course' \| 'recharge'` | 记录类型 |
| `duration` | number | 折算后小时数 |
| `durationRaw` | number | 折算前小时数 |
| `income` | number | 到手金额 |
| `isEstimate` | boolean | 是否预估 |
| `drinks` | string | 饮品描述 |
| `date` | string | 显示日期+时间段 |
#### 筛选参数映射
| 筛选项 | 前端参数 | 后端参数 | 查询影响 |
|--------|---------|---------|---------|
| 月份切换 | `currentYear`/`currentMonth` | `year`/`month` | 按月筛选记录(当前为本地过滤) |
| 客户 ID | `customerId` | `customerId` | WHERE 过滤 |
#### 页面跳转
- 无跳转(详情页,仅返回上一页)
#### API 契约 vs Mock 数据 差异
| 差异项 | API 契约 (CUST-2) | 前端 Mock | 严重度 |
|--------|--------------------|-----------| --------|
| 源数据结构 | 契约返回 ServiceRecord 格式 | Mock 使用 ConsumptionRecord来自 mock-data.ts前端转换为 ServiceRecord | 🟠 中 |
| `customerPhone`/`customerPhoneFull` | 契约有 `customer_phone` | Mock 硬编码 | 🟡 低 |
| `tables` 台桌列表 | 契约有 `tables: Array<{id, name}>` | Mock 无(前端模拟台号) | 🟡 低 |
| `relationIndex` | 契约有 `relation_index` | Mock 硬编码 `"0.85"` | 🟡 低 |
| 月度统计 | ❌ 契约无 | ✅ 前端本地计算 `monthCount`/`monthHours`/`monthRelation` | 🟠 中 |
#### spec 未记录的 Gap
1. 🟠 CUST-2 响应缺少月度统计汇总 — 前端需要 `monthCount`/`monthHours`,当前本地计算,联调后应由后端返回
2. 🟠 首次加载全量 vs 按月分页 — 当前设计一次拉全部记录本地过滤,数据量大时需改为按月请求
---
## 场景 3财务看板最复杂
### 3.1 board-finance`pages/board-finance/board-finance.ts`
#### API 调用
- `fetchBoardFinance()``BoardFinanceData`(⚠️ 当前签名仅 `{ date?: string }`,缺少 time/area/compare 参数)
- 页面 `onLoad()``fetchBoardFinance()` → 设置 `pageState: 'normal'`
- ⚠️ 筛选变更(`onTimeChange`/`onAreaChange`/`toggleCompare`)仅更新 data 状态,**不调用 API**(八¾节 F4/F5 已记录)
- ⚠️ 所有 6 个板块数据完全内联在 `data` 中,`fetchBoardFinance` 返回的 `_data` 未使用
#### 前端期望字段(从内联 data 提取6 个板块完整结构)
**板块 1经营一览 (overview) — 8 个指标 + 8 个环比值**
| 字段 | 类型 | 说明 |
|------|------|------|
| `overview.occurrence` | string | 发生额/正价(格式化,如 `"¥823,456"` |
| `overview.occurrenceCompare` | string | 环比百分比(如 `"12.5%"` |
| `overview.discount` | string | 总优惠(负值,如 `"-¥113,336"` |
| `overview.discountCompare` | string | 环比 |
| `overview.discountRate` | string | 优惠率(如 `"13.8%"` |
| `overview.discountRateCompare` | string | 环比 |
| `overview.confirmedRevenue` | string | 成交/确认收入 |
| `overview.confirmedCompare` | string | 环比 |
| `overview.cashIn` | string | 实收/现金流入 |
| `overview.cashInCompare` | string | 环比 |
| `overview.cashOut` | string | 现金支出 |
| `overview.cashOutCompare` | string | 环比 |
| `overview.cashBalance` | string | 现金结余 |
| `overview.cashBalanceCompare` | string | 环比 |
| `overview.balanceRate` | string | 结余率 |
| `overview.balanceRateCompare` | string | 环比 |
**板块 2预收资产 (recharge) — 储值卡 + 赠送卡矩阵**
| 字段 | 类型 | 说明 |
|------|------|------|
| `recharge.actualIncome` | string | 储值卡充值实收 |
| `recharge.actualCompare` | string | 环比 |
| `recharge.firstCharge` | string | 首充 |
| `recharge.firstChargeCompare` | string | 环比 |
| `recharge.renewCharge` | string | 续费 |
| `recharge.renewChargeCompare` | string | 环比 |
| `recharge.consumed` | string | 消耗 |
| `recharge.consumedCompare` | string | 环比 |
| `recharge.cardBalance` | string | 储值卡总余额 |
| `recharge.cardBalanceCompare` | string | 环比 |
| `recharge.giftRows` | `Array<{label, total, totalCompare, wine, wineCompare, table, tableCompare, coupon, couponCompare}>` | 赠送卡矩阵3行新增/消费/余额 × 4列合计/酒水卡/台费卡/抵用券) |
| `recharge.allCardBalance` | string | 全类别会员卡余额合计 |
| `recharge.allCardBalanceCompare` | string | 环比 |
赠送卡矩阵结构3×4 = 12 个数据单元 + 12 个环比值 = 24 个字段):
- 行:新增 / 消费 / 余额
- 列:合计(total) / 酒水卡(wine) / 台费卡(table) / 抵用券(coupon)
**板块 3应计收入确认 (revenue) — 4 个子表**
| 字段 | 类型 | 说明 |
|------|------|------|
| `revenue.structureRows` | `Array<{id, name, desc?, amount, discount, booked, bookedCompare, isSub?}>` | 收入结构表9行含子行标记 |
| `revenue.priceItems` | `Array<{name, value, compare}>` | 正价明细4项 |
| `revenue.totalOccurrence` | string | 正价合计 |
| `revenue.totalOccurrenceCompare` | string | 环比 |
| `revenue.discountItems` | `Array<{name, desc?, value, compare}>` | 优惠明细4项 |
| `revenue.confirmedTotal` | string | 确认收入合计 |
| `revenue.confirmedTotalCompare` | string | 环比 |
| `revenue.channelItems` | `Array<{name, desc?, value, compare}>` | 渠道明细3项 |
收入结构表行结构:
- 开台与包厢(含 A区/B区/C区/团建区/麻将区 5 个子行)
- 助教基础课
- 助教激励课
- 食品酒水
**板块 4现金流入 (cashflow)**
| 字段 | 类型 | 说明 |
|------|------|------|
| `cashflow.consumeItems` | `Array<{name, desc, value, compare, isDown}>` | 消费收款3项纸币现金/线上收款/团购平台) |
| `cashflow.rechargeItems` | `Array<{name, desc, value, compare}>` | 充值收款1项会员充值到账 |
| `cashflow.total` | string | 现金流入合计 |
| `cashflow.totalCompare` | string | 环比 |
**板块 5现金流出 (expense) — 4 个子分组**
| 字段 | 类型 | 说明 |
|------|------|------|
| `expense.operationItems` | `Array<{name, value, compare, isDown}>` | 经营支出3项食品饮料/耗材/报销) |
| `expense.fixedItems` | `Array<{name, value, compare, isFlat}>` | 固定支出4项房租/水电/物业/人员工资) |
| `expense.coachItems` | `Array<{name, value, compare, isDown}>` | 助教分成4项基础课/激励课/充值提成/额外奖金) |
| `expense.platformItems` | `Array<{name, value, compare}>` | 平台服务费3项汇来米/美团/抖音) |
| `expense.total` | string | 现金流出合计 |
| `expense.totalCompare` | string | 环比 |
**板块 6助教分析 (coachAnalysis) — 基础课 + 激励课两个子表**
| 字段 | 类型 | 说明 |
|------|------|------|
| `coachAnalysis.basic.totalPay` | string | 基础课总收入 |
| `coachAnalysis.basic.totalPayCompare` | string | 环比 |
| `coachAnalysis.basic.totalShare` | string | 基础课总分成 |
| `coachAnalysis.basic.totalShareCompare` | string | 环比 |
| `coachAnalysis.basic.avgHourly` | string | 平均时薪 |
| `coachAnalysis.basic.avgHourlyCompare` | string | 环比 |
| `coachAnalysis.basic.rows` | `Array<{level, pay, payCompare, share, shareCompare, hourly, hourlyCompare, hourlyFlat?, payDown?, shareDown?}>` | 按等级分行(初级/中级/高级/星级) |
| `coachAnalysis.incentive.*` | 同 basic | 激励课(结构完全相同) |
每行字段:
- `level`: string — 等级名
- `pay`: string — 收入
- `payCompare`: string — 收入环比
- `payDown`: boolean? — 收入是否下降
- `share`: string — 分成
- `shareCompare`: string — 分成环比
- `shareDown`: boolean? — 分成是否下降
- `hourly`: string — 时薪
- `hourlyCompare`: string — 时薪环比
- `hourlyFlat`: boolean? — 时薪是否持平
#### 筛选参数映射
| 筛选项 | 前端参数 | 后端参数 | 查询影响 |
|--------|---------|---------|---------|
| 时间范围 | `selectedTime`: month/lastMonth/week/lastWeek/quarter3/quarter/lastQuarter/half6 | `time` | 决定统计日期区间 |
| 区域筛选 | `selectedArea`: all/hall/hallA/hallB/hallC/mahjong/teamBuilding | `area` | WHERE 过滤区域area≠all 时预收资产板块隐藏 |
| 环比开关 | `compareEnabled`: true/false | `compare`: 0/1 | 控制是否返回环比数据 |
时间范围→日期区间映射(后端需实现):
- `month` → 当月1日 ~ 当月末日
- `lastMonth` → 上月1日 ~ 上月末日
- `week` → 本周一 ~ 本周日
- `lastWeek` → 上周一 ~ 上周日
- `quarter3` → 前3个月不含本月
- `quarter` → 本季度第1天 ~ 本季度末日
- `lastQuarter` → 上季度
- `half6` → 最近6个月不含本月
#### 目录导航 (sectionNav)
- 6 个板块:经营一览/预收资产/应计收入确认/现金流入/现金流出/助教分析
- 每个板块有 emoji + 标题 + sectionId
- 吸顶头显示当前板块 emoji + 标题 + 描述
- 板块描述(`_sectionDescs`6 段固定文案
#### 帮助图标 (helpTip)
- 7 个指标解释occurrence/discount/confirmed/cashIn/cashOut/balance/rechargeActual/firstCharge/renewCharge/consume/cardBalance/allCardBalance
- 每个含 `title` + `content`(多行文本)
#### API 契约 vs Mock 数据 vs 八¾节 差异
| 差异项 | API 契约 (BOARD-3) | 前端 Mock (内联 data) | 八¾节 (B3) | 严重度 |
|--------|--------------------|-----------------------|------------|--------|
| 响应结构 | 扁平 `metrics: Array<{key, label, value, unit, trend, compareValue, sub_items}>` | 6 个板块独立对象,深度嵌套结构 | 仅定义了参数,未定义完整响应结构 | 🔴 高 |
| 板块数量 | 未区分板块(单一 metrics 数组) | 6 个独立板块overview/recharge/revenue/cashflow/expense/coachAnalysis | 提到 6 个板块但未定义结构 | 🔴 高 |
| 环比数据格式 | `trend: 'up'\|'down'\|'flat'` + `compareValue?: string` | 每个值旁有独立的 `xxxCompare` 字段(百分比字符串) + `isDown`/`isFlat` 布尔标记 | 已确认需补充 `compareValue` 字段 | 🔴 高 |
| 赠送卡矩阵 | ❌ 完全缺失 | ✅ 3×4 矩阵24 个字段) | ❌ 未详细定义 | 🔴 高 |
| 收入结构表 | ❌ 缺失 | ✅ 9 行含子行标记 | ❌ 未详细定义 | 🔴 高 |
| 助教分析子表 | ❌ 缺失 | ✅ 基础课+激励课各 4 行(按等级) | ❌ 未详细定义 | 🔴 高 |
| 现金流出 4 子分组 | ❌ 缺失 | ✅ 经营支出/固定支出/助教分成/平台服务费 | ❌ 未详细定义 | 🔴 高 |
| `time`/`area`/`compare` 参数 | 八¾节末尾补充了参数定义 | 前端未传参Bug | ✅ 已定义 | 🟠 中(八¾节已补充) |
| `isDown`/`isFlat` 标记 | ❌ 无 | ✅ 有(控制箭头颜色方向) | ❌ 无 | 🟠 中 |
| 帮助图标内容 | ❌ 完全缺失 | ✅ 12 个指标解释 | ❌ 未提及 | 🟡 低 |
#### spec 未记录的 Gap
1. 🔴 BOARD-3 响应结构与前端实际需求完全不匹配 — 契约为扁平 metrics 数组,前端需要 6 个独立板块的深度嵌套结构
2. 🔴 赠送卡矩阵3×4=12 单元 + 12 环比)完全未定义 — 预收资产板块的核心数据
3. 🔴 收入结构表9 行含子行层级)完全未定义 — 应计收入确认板块的核心数据
4. 🔴 助教分析子表(基础课+激励课各 4 行按等级)完全未定义
5. 🔴 现金流出 4 个子分组(经营/固定/助教分成/平台服务费)完全未定义
6. 🔴 环比数据格式不匹配 — 契约仅 `trend` + `compareValue`,前端需要每个值旁独立的 `xxxCompare` 字段 + `isDown`/`isFlat` 布尔标记
7. 🟠 `isDown`/`isFlat` 布尔标记未定义 — 前端用于控制环比箭头方向和颜色
8. 🟡 帮助图标内容12 个指标解释文案)未定义 — 可硬编码在前端,但后端可提供配置化
---
## 场景 4跨页面数据关联
### 4.1 board-coach → coach-detail → customer-detail → customer-service-records
**参数传递链:**
1. `board-coach` 点击助教卡片 → `coach-detail?id={coachId}`
2. `coach-detail` 点击客户卡片 → `customer-detail?id={customerId}`
3. `coach-detail` 点击任务项 → `customer-detail?name={customerName}`(⚠️ 用 name 而非 id
4. `customer-detail` 查看服务记录 → `customer-service-records`(⚠️ 未传 customerId
5. `coach-detail` 查看更多服务记录 → `performance-records?coachId={coachId}`
6. `coach-detail` 问问助手 → `chat?coachId={coachId}`
**跨页面 Gap**
- 🔴 步骤 3 用 `name` 跳转name 不唯一,应改为 `id`
- 🔴 步骤 4 未传 `customerId``customer-service-records` 无法知道查哪个客户
- 🟠 `customer-detail``onStartChat` 未传 `customerId`chat 页面无法关联客户上下文
### 4.2 board-customer → customer-detail → chat
**参数传递链:**
1. `board-customer` 点击客户卡片 → `customer-detail?id={customerId}`
2. `customer-detail` 问问助手 → `chat`(⚠️ 未传参数)
**跨页面 Gap**
- 🟠 `chat` 页面无法获取客户上下文customerId/customerName
### 4.3 board-finance → coach-detail 入口
**分析结果:**
- board-finance 的助教分析板块coachAnalysis展示按等级汇总的数据**无跳转到 coach-detail 的入口**
- 这是合理的设计 — 财务看板关注的是汇总数据而非个体
---
## 汇总 Gap 清单(按严重度排序)
### 🔴 高严重度(阻塞联调,必须在后端开发前解决)
| # | 类别 | Gap 描述 | 涉及接口 | 涉及页面 |
|---|------|---------|---------|---------|
| G1 | 契约缺陷 | **BOARD-3 响应结构与前端完全不匹配** — 契约为扁平 metrics 数组,前端需要 6 个独立板块的深度嵌套结构overview/recharge/revenue/cashflow/expense/coachAnalysis含 200+ 个字段 | BOARD-3 | board-finance |
| G2 | 契约缺陷 | **BOARD-1 响应字段严重不足** — 契约仅 10 个通用字段,前端需要 20 个含 4 维度专属字段perf/salary/sv/task且 skills 类型不匹配string[] vs Array<{text,cls}> | BOARD-1 | board-coach |
| G3 | 契约缺陷 | **BOARD-2 响应字段严重不足** — 契约仅 8 个通用字段,前端需要 40+ 维度专属字段8 个维度各有独立字段集),且缺少 assistants 关联助教列表 | BOARD-2 | board-customer |
| G4 | 契约缺陷 | **COACH-1 响应缺少多个核心区域** — 缺少 income 收入明细(本月/上月、historyMonths 历史月份统计、tierNodes 档位节点、备注列表topCustomers 字段结构不完整(契约 5 字段 vs 前端 10 字段) | COACH-1 | coach-detail |
| G5 | 契约缺陷 | **CUST-1 响应缺少管理层核心数据** — 缺少 aiInsight AI 洞察、coachTasks 关联助教任务、favoriteCoaches 喜好助教;消费记录结构严重不匹配(契约扁平 vs 前端嵌套含助教明细) | CUST-1 | customer-detail |
| G6 | 契约缺陷 | **BOARD-3 赠送卡矩阵完全未定义** — 预收资产板块的 3×4 矩阵(新增/消费/余额 × 合计/酒水卡/台费卡/抵用券)= 24 个数据字段 + 24 个环比字段 | BOARD-3 | board-finance |
| G7 | 契约缺陷 | **BOARD-3 收入结构表完全未定义** — 9 行含子行层级(开台与包厢含 5 个区域子行 + 助教基础课 + 助教激励课 + 食品酒水),每行含 amount/discount/booked/bookedCompare | BOARD-3 | board-finance |
| G8 | 契约缺陷 | **BOARD-3 助教分析子表完全未定义** — 基础课+激励课各含汇总行 + 4 个等级行(初级/中级/高级/星级),每行含 pay/share/hourly 及各自环比 | BOARD-3 | board-finance |
| G9 | 契约缺陷 | **BOARD-3 现金流出 4 子分组完全未定义** — 经营支出(3项)/固定支出(4项)/助教分成(4项)/平台服务费(3项) | BOARD-3 | board-finance |
| G10 | 契约缺陷 | **环比数据格式不匹配** — 契约仅 `trend` + `compareValue`,前端需要每个值旁独立的 `xxxCompare` 百分比字段 + `isDown`/`isFlat` 布尔标记 | BOARD-3 | board-finance |
| G11 | 前端 Bug | **customer-detail 跳转 customer-service-records 未传 customerId** — 服务记录页无法知道查哪个客户 | CUST-2 | customer-detail → customer-service-records |
| G12 | 前端 Bug | **coach-detail 任务项跳转用 name 而非 id**`onTaskItemTap``name={customerName}`name 不唯一 | — | coach-detail → customer-detail |
| G13 | 类型不匹配 | **api.ts 中 fetchCoachDetail 返回类型为 CoachCard** — 实际需要完整的 CoachDetail含 performance/income/tasks/topCustomers/serviceRecords/historyMonths/notes类型定义严重不足 | COACH-1 | coach-detail |
| G14 | 类型不匹配 | **mock-data.ts 中的类型与页面内联 mock 完全脱节** — BoardFinanceData 仅含 4 个 metrics实际页面需要 6 个板块 200+ 字段CustomerCard/CoachCard 过于简单 | 全部看板 | 全部看板页 |
### 🟠 中严重度(影响功能完整性,联调前需解决)
| # | 类别 | Gap 描述 | 涉及接口 | 涉及页面 |
|---|------|---------|---------|---------|
| G15 | 契约缺陷 | **BOARD-1 sort 参数格式不一致** — 契约用 `field:direction`,前端用枚举值 `perf_desc` | BOARD-1 | board-coach |
| G16 | 契约缺陷 | **BOARD-1/2 缺少 initial/avatarGradient/avatarCls 字段** — 前端用于头像渲染,需确认由前端计算还是后端返回 | BOARD-1/2 | board-coach/board-customer |
| G17 | 契约缺陷 | **CUST-1 缺少 balance/consumption60d/idealInterval/daysSinceVisit** — 客户详情页头部展示的核心指标 | CUST-1 | customer-detail |
| G18 | 契约缺陷 | **CUST-1 维客线索结构不匹配** — 契约用 tag/tag_color/emoji/text/source/desc前端用 category/categoryColor/text/source/detail | CUST-1 | customer-detail |
| G19 | 契约缺陷 | **CUST-1 缺少备注列表** — 客户详情页展示关联备注 | CUST-1 | customer-detail |
| G20 | 契约缺陷 | **COACH-1 缺少备注列表** — 助教详情页展示关联备注 | COACH-1 | coach-detail |
| G21 | 契约缺陷 | **CUST-2 缺少月度统计汇总** — 前端需要 monthCount/monthHours当前本地计算 | CUST-2 | customer-service-records |
| G22 | 契约缺陷 | **BOARD-3 isDown/isFlat 布尔标记未定义** — 前端用于控制环比箭头方向和颜色 | BOARD-3 | board-finance |
| G23 | 前端 Bug | **customer-detail 的 onStartChat 未传 customerId** — chat 页面无法关联客户上下文 | CHAT | customer-detail → chat |
| G24 | 前端 Bug | **customer-detail 的 loadDetail() 中 id 解析方式有 Bug** — 应从 onLoad(options) 获取,而非 `__route__` 解析 | CUST-1 | customer-detail |
| G25 | 设计缺陷 | **BOARD-2 potentialTags 标签结构契约缺失** — potential 维度展示客户潜力标签(含 text+theme | BOARD-2 | board-customer |
| G26 | 设计缺陷 | **COACH-1 tierNodes/maxHours 缺失** — 绩效进度条组件需要档位节点数据,当前硬编码 `[0, 100, 130, 160, 190, 220]` | COACH-1 | coach-detail |
### 🟡 低严重度(不阻塞联调,可后续优化)
| # | 类别 | Gap 描述 | 涉及接口 | 涉及页面 |
|---|------|---------|---------|---------|
| G27 | 设计决策 | **BOARD-1 无分页定义** — 当前全量返回,助教数量少(<50可接受 | BOARD-1 | board-coach |
| G28 | 设计决策 | **BOARD-3 帮助图标内容未定义** — 12 个指标解释文案,可硬编码在前端 | BOARD-3 | board-finance |
| G29 | 设计决策 | **customer-service-records 首次加载全量 vs 按月分页** — 数据量小时可接受,量大时需改为按月请求 | CUST-2 | customer-service-records |
| G30 | 类型不匹配 | **mock-data.ts ConsumptionRecord 结构过于简单** — 仅 6 个字段customer-detail 内联 mock 有 16 个字段(含嵌套 coaches 数组) | CUST-1 | customer-detail |
| G31 | 契约缺陷 | **CUST-2 tables 台桌列表** — 契约定义了但前端未使用(前端模拟台号) | CUST-2 | customer-service-records |
---
## 行动建议
### 优先级 1更新 API 契约(阻塞后端开发)
以下接口的契约需要**完全重写**,以匹配前端实际需求:
1. **BOARD-3 财务看板** — 从扁平 metrics 改为 6 板块嵌套结构,补充赠送卡矩阵、收入结构表、助教分析子表、现金流出子分组的完整字段定义
2. **BOARD-1 助教看板** — 从 10 个通用字段扩展为 20 个含 4 维度专属字段,修正 skills 类型,补充 topCustomers
3. **BOARD-2 客户看板** — 从 8 个通用字段扩展为 40+ 维度专属字段,补充 assistants/weeklyVisits/coachDetails/potentialTags
4. **COACH-1 助教详情** — 补充 income/historyMonths/tierNodes/备注列表,扩展 topCustomers 字段
5. **CUST-1 客户详情** — 补充 aiInsight/coachTasks/favoriteCoaches/备注列表,重写消费记录为嵌套结构
### 优先级 2修复前端 Bug联调前必须完成
1. G11: customer-detail → customer-service-records 传 customerId
2. G12: coach-detail onTaskItemTap 改用 id 而非 name
3. G23: customer-detail → chat 传 customerId
4. G24: customer-detail loadDetail() 修复 id 解析
5. F1-F6: 看板筛选变更触发重新请求(八¾节已记录)
### 优先级 3统一 mock-data.ts 类型定义
当前 `mock-data.ts` 中的类型BoardFinanceData/CustomerCard/CoachCard/CustomerDetail与页面内联 mock 数据严重脱节。建议:
- 将页面内联的完整接口定义CoachItem/CustomerItem/CoachDetail 等)提取到 `mock-data.ts` 或独立的 `types.ts`
- 更新 `api.ts` 中各函数的返回类型
- 确保类型定义与更新后的 API 契约一致