# 小程序管理层视角 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 契约一致