Files
Neo-ZQYY/docs/miniprogram-dev/api-audit/customer-detail.md

222 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# customer-detail 页面数据来源排查
> 排查日期2026-03-18
> 页面路径pages/customer-detail/customer-detail
## 概览
| 分类 | 数量 | 说明 |
|------|------|------|
| A. Mock 数据 | 1 处 import + 1 处页面内联 | `mockCustomerDetail` 已 import 但未使用;`mockRecords` 内联定义 |
| B. 硬编码数据 | 7 个数据块 | `detail``aiInsight``clues``coachTasks``favoriteCoaches``sortedNotes``consumptionRecords` |
| C. 已对接 API | 0 | 页面无任何 `request()` 调用 |
| D. 前端计算/派生 | 3 处 | `aiColor` 随机、`phoneVisible` 切换、`pageState` 状态机 |
| E. 路由参数 | 0 | `onLoad(options)` 未读取任何参数 |
| F. WXML 硬编码文案 | 14 处 | 标题、标签、按钮文字等 |
---
## 一、Mock 数据
### 1.1 `mockCustomerDetail`(已 import 未使用)
| 项目 | 说明 |
|------|------|
| 来源 | `import { mockCustomerDetail } from "../../utils/mock-data"` |
| 状态 | **已 import 但页面内未引用**,属于死代码 |
| mock-data.ts 中的字段 | `id`, `name`, `avatar`, `tags`, `heartScore`, `phone`, `spiIndex`, `consumptionRecords[]` |
| 联调动作 | 删除此 import页面 `detail` 对象改为从 API 获取 |
### 1.2 `mockRecords`(页面内联 mock
| 项目 | 说明 |
|------|------|
| 来源 | 页面顶部 `const mockRecords: ConsumptionRecord[]` 硬编码 3 条记录 |
| 赋值位置 | `data.consumptionRecords: mockRecords` |
| 字段清单 | 每条记录含:`id`, `type`, `date`, `tableName`, `startTime`, `endTime`, `duration`, `tableFee`, `tableOrigPrice`, `coaches[]``name`, `level`, `levelColor`, `courseType`, `hours`, `perfHours`, `fee`, `foodAmount`, `foodOrigPrice`, `totalAmount`, `totalOrigPrice`, `payMethod`, `rechargeAmount` |
| 联调 API | `GET /api/xcx/customer/{member_id}/consumption-records`(待开发) |
| 风险 | 🔴 高 — 金额字段涉及 `tableFee`/`totalAmount` 等财务数据,需严格对齐 DWD-DOC 口径 |
---
## 二、硬编码数据
### 2.1 `detail` 对象(客户基础信息)
| 字段 | 硬编码值 | 应对接来源 | 风险 |
|------|----------|-----------|------|
| `id` | `"cust_001"` | API 返回 `member_id` | 🔴 高 |
| `name` | `"王先生"` | API `dim_member.nickname` | 🔴 高 |
| `avatarChar` | `"王"` | 前端从 `name` 截取首字 | 🟡 中 |
| `phone` | `"13812345678"` | API `dim_member.mobile`(注意 DQ-6需通过 `member_id` JOIN `dim_member` | 🔴 高 |
| `balance` | `"8,600"` | API 储值余额(`balance_pay` | 🔴 高 |
| `consumption60d` | `"2,800"` | API 近60天消费汇总 | 🔴 高 |
| `idealInterval` | `"7天"` | API / AI 计算 | 🟡 中 |
| `daysSinceVisit` | `"12天"` | API 最后到店距今天数 | 🔴 高 |
**联调 API**`GET /api/xcx/customer/{member_id}/profile`(待开发)
### 2.2 `aiInsight` 对象AI 智能洞察)
| 字段 | 硬编码值 | 应对接来源 | 风险 |
|------|----------|-----------|------|
| `summary` | 长文本("高价值 VIP 客户…" | AI 缓存 API `GET /api/xcx/ai-cache?cache_type=customer_insight&target_id={member_id}` | 🔴 高 |
| `strategies[]` | 3 条策略,含 `color` + `text` | 同上AI 缓存返回 | 🔴 高 |
**联调 API**`GET /api/xcx/ai-cache`(已有路由 `xcx_ai_cache.py`,需确认 `cache_type` 枚举是否包含 `customer_insight`
### 2.3 `clues` 数组(维客线索)
共 7 条硬编码线索:
| 索引 | category | text 摘要 | source | 应对接来源 | 风险 |
|------|----------|----------|--------|-----------|------|
| 0 | 客户基础 | 🎂 生日 3月15日 · VIP会员 · 注册2年 | 系统 | API 维客线索 | 🔴 高 |
| 1 | 消费习惯 | 🌙 常来夜场 · 月均4-5次 | 系统 | API 维客线索 | 🔴 高 |
| 2 | 消费习惯 | 💰 高客单价(含 detail | 系统 | API 维客线索 | 🔴 高 |
| 3 | 玩法偏好 | 🎱 偏爱中式 · 斯诺克进阶中 | 系统 | API 维客线索 | 🔴 高 |
| 4 | 促销接受 | 🍷 爱点酒水套餐(含 detail | 系统 | API 维客线索 | 🔴 高 |
| 5 | 社交关系 | 👥 常带朋友(含 detail | 系统 | API 维客线索 | 🔴 高 |
| 6 | 重要反馈 | ⚠️ 想练斯诺克走位… | 小燕 | API 维客线索 | 🔴 高 |
**联调 API**`GET /api/retention-clue/{member_id}?site_id=X`(已有路由 `member_retention_clue.py`
### 2.4 `coachTasks` 数组(助教任务分配)
共 4 条硬编码任务卡片:
| 索引 | name | taskType | 字段清单 | 风险 |
|------|------|----------|---------|------|
| 0 | 小燕 | 高优先召回 | `level`, `levelColor`, `taskColor`, `bgClass`, `status`, `lastService`, `metrics[]`近60天次数/总时长/次均时长) | 🔴 高 |
| 1 | 泡芙 | 优先召回 | 同上 + `status: "pinned"` | 🔴 高 |
| 2 | Amy | 关系构建 | 同上 | 🔴 高 |
| 3 | Lucy | 客户回访 | 同上 + `status: "abandoned"` | 🔴 高 |
**联调 API**`GET /api/xcx/customer/{member_id}/coach-tasks`(待开发;后端 `biz.coach_tasks` 表已存在)
### 2.5 `favoriteCoaches` 数组(最喜欢的助教)
共 2 条硬编码:
| 索引 | name | 字段清单 | 风险 |
|------|------|---------|------|
| 0 | 小燕 | `emoji`, `relationIndex: "9.2"`, `indexColor`, `bgClass`, `stats[]`(基础/激励/上课/充值) | 🔴 高 |
| 1 | 泡芙 | 同上,`relationIndex: "7.8"` | 🔴 高 |
**联调 API**`GET /api/xcx/customer/{member_id}/favorite-coaches`(待开发;需 DWS 层助教-客户关系聚合)
### 2.6 `sortedNotes` 数组(备注记录)
共 3 条硬编码备注:
| 索引 | tagLabel | createdAt | content 摘要 | 风险 |
|------|----------|-----------|-------------|------|
| 0 | 管理员 | 2026-03-05 14:30 | 对斯诺克课程感兴趣… | 🔴 高 |
| 1 | 小燕 | 2026-02-20 16:45 | 客户反馈服务态度很好… | 🔴 高 |
| 2 | 管理员 | 2026-02-10 10:00 | 储值活动当天即充值… | 🔴 高 |
**联调 API**`GET /api/xcx/notes?target_type=member&target_id={member_id}`(已有路由 `xcx_notes.py`
### 2.7 其他硬编码值
| 位置 | 字段 | 硬编码值 | 说明 | 风险 |
|------|------|----------|------|------|
| `data` | `pageState` | `"loading"` | 初始状态,正常 | 🟢 低 |
| `data` | `phoneVisible` | `false` | UI 状态,正常 | 🟢 低 |
| `data` | `loadingMore` | `false` | UI 状态,正常 | 🟢 低 |
| `data` | `noteModalVisible` | `false` | UI 状态,正常 | 🟢 低 |
| `loadDetail()` | `pageState` | 直接设为 `"normal"` | ⚠️ 无 API 调用,直接跳过 loading | 🔴 高 |
| WXML | 手机号掩码 | `'138****5678'` | 硬编码掩码,应从 `detail.phone` 动态生成 | 🟡 中 |
---
## 三、已对接 API
| API | 状态 |
|-----|------|
| (无) | 页面当前 **零 API 调用**`loadDetail()` 为空壳 |
---
## 四、前端计算/派生数据
| 字段 | 计算逻辑 | 说明 |
|------|----------|------|
| `aiColor` | `onLoad` 中随机从 6 色数组取值 | 用于 AI 洞察卡片配色,纯 UI 装饰 |
| `phoneVisible` | `onTogglePhone()` 切换布尔值 | 控制手机号显示/隐藏 |
| `pageState` | `loadDetail()` 中设为 `"normal"` | 应改为loading → API 成功 normal / 失败 error / 空 empty |
---
## 五、路由参数
| 参数 | 状态 | 说明 |
|------|------|------|
| `options.id` / `options.memberId` | ❌ 未读取 | `onLoad(options)` 接收了 `options` 但未使用任何参数 |
**联调时必须**:从 `options` 中读取 `memberId`(或 `id`),作为所有 API 请求的入参。
---
## 六、WXML 中的硬编码文案
| 位置 | 文案 | 是否需要动态化 | 说明 |
|------|------|---------------|------|
| 导航栏 | `"客户详情"` | ❌ 保持 | JSON 配置 `navigationBarTitleText` |
| loading 态 | `"加载中..."` | ❌ 保持 | 通用文案 |
| empty 态 | `"未找到客户信息"` | ❌ 保持 | 通用文案 |
| error 态 | `"加载失败"` | ❌ 保持 | 通用文案 |
| error 按钮 | `"点击重试"` | ❌ 保持 | 通用文案 |
| banner 统计标签 | `"储值余额"` / `"60天消费"` / `"理想间隔"` / `"距今到店"` | ❌ 保持 | 固定标签 |
| AI 卡片标题 | `"AI 智能洞察"` | ❌ 保持 | 固定标题 |
| 策略标题 | `"当前推荐策略"` | ❌ 保持 | 固定标题 |
| 维客线索标题 | `"维客线索"` | ❌ 保持 | 固定标题 |
| 助教任务标题 | `"助教任务分配"` / `"当前进行中"` | ❌ 保持 | 固定标题 |
| 最喜欢助教标题 | `"最喜欢的助教"` / `"近60天"` | ❌ 保持 | 固定标题 |
| 消费记录 | `"消费记录"` / `"商城订单"` / `"总金额"` / `"🍷 食品酒水"` | ❌ 保持 | 固定标签 |
| 底部按钮 | `"问问助手"` / `"备注"` | ❌ 保持 | 固定文案 |
| 空态提示 | `"暂无消费记录"` / `"暂无备注"` | ❌ 保持 | 通用文案 |
---
## 七、联调 TODO
### 优先级 P0页面核心数据阻塞上线
| # | 数据块 | 当前状态 | 需要的 API | 后端现状 |
|---|--------|---------|-----------|---------|
| 1 | 客户基础信息 `detail` | 全部硬编码 | `GET /api/xcx/customer/{member_id}/profile` | ❌ 待开发 |
| 2 | 消费记录 `consumptionRecords` | 内联 mock | `GET /api/xcx/customer/{member_id}/consumption-records` | ❌ 待开发 |
| 3 | 路由参数 `memberId` | 未读取 | 从 `onLoad(options)` 读取 | — |
| 4 | `loadDetail()` 空壳 | 直接设 normal | 改为真实 API 调用 + 状态管理 | — |
### 优先级 P1重要业务数据
| # | 数据块 | 当前状态 | 需要的 API | 后端现状 |
|---|--------|---------|-----------|---------|
| 5 | 维客线索 `clues` | 全部硬编码 | `GET /api/retention-clue/{member_id}` | ✅ 已有路由 |
| 6 | 备注记录 `sortedNotes` | 全部硬编码 | `GET /api/xcx/notes?target_type=member&target_id={member_id}` | ✅ 已有路由 |
| 7 | AI 智能洞察 `aiInsight` | 全部硬编码 | `GET /api/xcx/ai-cache?cache_type=customer_insight&target_id={member_id}` | ⚠️ 路由已有,需确认 cache_type |
### 优先级 P2增强功能
| # | 数据块 | 当前状态 | 需要的 API | 后端现状 |
|---|--------|---------|-----------|---------|
| 8 | 助教任务 `coachTasks` | 全部硬编码 | `GET /api/xcx/customer/{member_id}/coach-tasks` | ❌ 待开发(`biz.coach_tasks` 表已有) |
| 9 | 最喜欢助教 `favoriteCoaches` | 全部硬编码 | `GET /api/xcx/customer/{member_id}/favorite-coaches` | ❌ 待开发(需 DWS 聚合) |
### 前端清理项
| # | 项目 | 说明 |
|---|------|------|
| 10 | 删除 `import { mockCustomerDetail }` | 死代码import 后未使用 |
| 11 | 删除 `const mockRecords` 内联 mock | 替换为 API 数据 |
| 12 | 手机号掩码硬编码 `'138****5678'` | 改为从 `detail.phone` 动态生成掩码 |
| 13 | `ConsumptionRecord` interface | 页面内重复定义,应移至 `utils/types.ts` 或复用 `mock-data.ts` 中的类型 |
### 注意事项
- **DQ-6 会员手机号断档**`settlement_head.member_phone` 自 2025-12 起全为 NULL后端 API 必须通过 `member_id` JOIN `dim_member.mobile` 获取
- **金额口径**:消费记录中的金额字段需严格对齐 DWD-DOC 标杆文档,禁止直接使用 `consume_money`
- **助教费用拆分**:消费记录中的 `coaches[].fee` 需区分陪打(`assistant_pd_money`)和超休(`assistant_cx_money`