# 小程序管理层视角 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` 跳转客户详情 — 前端 Bug，name 不唯一
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?}>` | 统计（基础/激励/上课/充值） |

**消费记录 consumptionRecords（3 种类型，管理层关注消费结构）：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `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 契约一致
