# P9:小程序前端 — 详情与对话模块 — miniapp-fe-details > 优先级:P9(依赖 P3 + P4 + P5-A) > 预估工作量:大 > P5-B 承接:T1 同时细化 P5 应用 3/6/7 的 Prompt JSON 结构 --- ## 需求(Requirements) ### 用户故事 1. 作为助教,我在客户详情页能看到客户全信息、消费记录(三种样式)、指数总览、备注、AI 分析。 2. 作为助教,我在助教详情页能看到助教信息、客户数、工龄、备注。 3. 作为助教,我在 AI 对话页能与 AI 流式对话,看到来源页面信息。 4. 作为助教,我能查看历史 AI 对话记录。 ### 验收标准 - AC1:消费记录区分三种样式(台桌结账→下沉台费明细、商城订单、充值) - AC2:消费记录默认 10 条,拉到底懒加载(每次 10 条) - AC3:金额为 0 的项不展示;有团购/折扣时展示正价+实付 - AC4:总金额仅在消费条目 >1 时出现 - AC5:AI 对话支持流式展示(逐字输出) - AC6:从其他页面进入 chat.html 时新开对话,第一条消息为页面上下文 - AC7:对话历史列表可查看、可继续对话 --- ## 页面清单 ### customer-detail(客户详情) - 客户信息卡片(昵称、手机、会员卡等级、余额、注册日期) - 指数总览(WBI/NCI/SPI 展示分 + 爱心 icon) - 消费记录列表(三种样式,懒加载) - 台桌结账:下沉到 `dwd_table_fee_log`,每条台费详情,关联总金额汇总 - 商城订单:助教列表(花名+级别+课程类型+服务时长+定档绩效)、支付金额、食品酒水总金额 - 充值:充值金额、支付方式 - 备注列表 - AI 维客线索(应用 8 整合线索 + 人工,读取 `member_retention_clue`;Emoji 作为二级标签、提供者显示规则见下方"维客线索提供者显示规则"章节) - AI 客户分析(应用 7 缓存:运营策略数组 + 总结,结账单出现后自动生成;从 `ai_cache` cache_type=app7_customer_analysis 读取) - "问问助手"入口 → chat.html ### coach-detail(助教详情) - 助教信息卡片(花名、级别、工龄) - 客户数(RS > 2 的客户数量) - 备注按钮(查看此助教为该客户做的备注) ### customer-service-records(客户服务记录) - 服务记录列表(时间 + 持续时长) ### chat(AI 对话) - 来源展示(来源页面 title + 基本信息) - 对话界面(IM 风格) - AI 回复流式展示(SSE) - 消息输入 + 发送 ### chat-history(对话历史) - 历史对话列表(按时间倒序) - 点击进入继续对话 --- ## 后端 API 需求 | API | 说明 | |-----|------| | `GET /api/customers/:id` | 客户详情 | | `GET /api/customers/:id/consumption-records` | 消费记录(分页,懒加载) | | `GET /api/customers/:id/indexes` | 客户指数总览 | | `GET /api/coaches/:id` | 助教详情 | | `GET /api/coaches/:id/customer-count` | 助教客户数(RS>2) | | `GET /api/customers/:id/service-records` | 客户服务记录 | | `POST /api/chat/conversations` | 创建对话 | | `POST /api/chat/conversations/:id/messages` | 发送消息(SSE 流式返回) | | `GET /api/chat/conversations` | 对话历史列表 | | `GET /api/chat/conversations/:id/messages` | 对话消息列表 | ### 消费记录 settle_type 区分 ### settle_type 与消费记录类型映射(已校准,数据源:DWD-DOC 01-业务全景) | settle_type | 含义 | 数量占比 | 消费记录样式 | |:-----------:|------|---------|-------------| | 1 | 台桌结账 | 78.6% | 下沉到 `dwd_table_fee_log` 台费明细 | | 3 | 商城订单 | 21.4% | 助教列表 + 支付金额 + 食品酒水(含 477 笔纯超休/激励课订单) | | 5 | 正常充值 | — | 从 `dwd_recharge_order` 单独查询 | | 7 | 充值退款 | 极少(10 笔) | 不在消费记录中展示 | | 6 | 结算退款 | 极少(1 笔) | 不在消费记录中展示 | ### 金额字段说明(已校准,数据源:DWD-DOC 02-账务全景 + consume 口径文档) ⚠️ 不得直接使用 `consume_money`(三种历史口径混合,不稳定)。 正价金额(消费项目合计,全时期一致): ```sql items_sum = table_charge_money + goods_money + assistant_pd_money + assistant_cx_money + electricity_money ``` 实付金额需按支付渠道拆分展示: | 支付渠道 | 字段 | 说明 | |----------|------|------| | 线上支付 | `pay_amount` | 不含 balance,= `point_amount` + `cash_amount` | | 储值卡 | `balance_amount` | 独立渠道,= `recharge_card_amount` + `gift_card_amount` | | 团购券抵扣 | `coupon_amount` | 门店实际抵扣额 | | 会员折扣 | `member_discount_amount` | 仅 settle_type=1 | | 台费调整 | `adjust_amount` | 手动调价 | | 抹零 | `rounding_amount` | 收支平衡减项 | 团购券三层价格体系(展示时注意区分): - 顾客支付价 → `PCR.sale_price` - 平台结算价 → `SH.pl_coupon_sale_amount`(= SUM(GR.ledger_unit_price)) - 门店抵扣价 → `SH.coupon_amount`(= SUM(GR.ledger_amount)) 已知限制: - `online_pay_channel` 全为 0,无法区分微信/支付宝(聚合支付接入) - `settlement_head_ex` 中 `payment_method`、`is_use_coupon`、`is_activity` 等字段全为 0,不可用 - 团购券与会员折扣不叠加 - 2025-11-09 前台费明细 `is_delete=1`,历史数据不完整 --- ## 维客线索提供者显示规则 ### 后端过滤策略(安全性优先) ⚠️ **重要**:维客线索的过滤必须在后端完成,客户端不进行任何过滤逻辑,以防止数据泄露风险。 **客户详情页后端返回规则**: 后端应返回所有相关的维客线索(包括系统生成、当前用户、他人记录、备注分析),但需要根据用户权限进行脱敏: | 线索类型 | 返回条件 | 说明 | |---------|--------|------| | 系统生成 | 总是返回 | `source = 'ai_consumption'`,完整返回 | | 我的记录 | 总是返回 | `source = 'manual'` 且 `recorded_by_assistant_id = 当前用户ID`,完整返回 | | 他人记录 | 返回完整版本 | `source = 'manual'` 且 `recorded_by_assistant_id ≠ 当前用户ID`,返回 `recorded_by_name` | | 备注分析 | 返回完整版本 | `source = 'ai_note'`,返回原备注的 `recorded_by_name` | ### 前端显示规则 **客户详情页**:前端直接显示后端返回的所有维客线索,显示具体人名: | source 值 | 显示文案 | |----------|--------| | `ai_consumption` | By:系统 | | `manual` 且有 `recordedByAssistantId` | By:我 | | `manual` 或 `ai_note` 且有 `recordedByName` | By:{recordedByName} | 多条线索时,提供者用逗号分隔展示(如"By:系统, 王芳, 李明") **任务详情页**:前端根据后端返回的脱敏数据显示(详见 P6 规范) ### 多人情况处理 当同一客户有多条维客线索时,前端按以下规则展示: 1. **按时间排序**:按 `created_at` 升序排列(最早的在前) 2. **取最先反馈**: - 如果有"By:系统"的线索,优先显示最早的"By:系统" - 如果没有"By:系统",则显示最早的"By:我"或其他人名 3. **单条展示**:维客线索卡片中仅显示一条(最优先的),其他线索可通过"查看全部"或列表展开查看 ### 前端实现示例 ```typescript // 客户详情页:直接显示后端返回的数据 function getClueProvider(clue: RetentionClue): string { if (clue.source === 'ai_consumption') { return 'By:系统' } if (clue.source === 'manual' && clue.recordedByAssistantId) { return 'By:我' } if (clue.recordedByName) { return `By:${clue.recordedByName}` } return 'By:某人' // 备用 } // 从多条线索中选择最优先的 function selectPrimaryClue(clues: RetentionClue[]): RetentionClue { const sorted = clues.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() ) const systemClue = sorted.find(c => c.source === 'ai_consumption') if (systemClue) return systemClue return sorted[0] } ``` --- ## 小程序前端开发强制规范 > 以下规范适用于本 SPEC 中所有小程序页面实现,具有强制约束力。 1. **原型图是唯一视觉真相**:`docs/h5_ui/pages/*.html` 中的结构、层次、元素、配色、间距、交互行为是小程序页面实现的唯一参考标准。任何偏离原型图的实现都需要明确的产品确认。 2. **WXML ≠ HTML**:严禁在小程序中使用 HTML 标签(div/span/p/a/img 等),必须使用小程序原生标签(view/text/image/navigator 等)。 3. **WXSS ≠ CSS**:使用 rpx 单位、仅支持有限选择器、无 DOM/BOM API、样式隔离机制不同。Tailwind CSS 类名必须手动转换为 WXSS。 4. **TDesign 优先**:凡 TDesign 组件库能覆盖的 UI 元素,必须使用 TDesign 组件;自定义实现仅限 TDesign 无法覆盖的场景。 5. **Power 文档优先**:实现前必须加载 `wechat-miniprogram` Power 的相关 steering 文件(`view-layer.md`、`tdesign.md`、`builtin-components.md`),确保语法和组件用法正确。 6. **项目踩坑指南必读**:实现前必须阅读 `docs/prd/MIGRATION-PLAYBOOK.md` 第六章,该文档是基于本项目实际转换经验的避坑手册,涵盖 WXML/WXSS 差异、事件系统、TDesign 用法、rpx 换算规则及新页面开发 Checklist。 --- ## 任务清单 - [ ] T1:实现客户详情 API - T1-a:细化 P5 应用 3(维客线索)Prompt JSON 结构,实现 `consumption_records`、`member_cards` 等字段的拼接函数(对应 P5-T6-完整) - T1-b:细化 P5 应用 6(备注分析)Prompt JSON 结构,实现 `consumption_data` 字段的拼接函数(对应 P5-T9-完整) - T1-c:细化 P5 应用 7(客户分析)Prompt JSON 结构,实现 `objective_data` 字段的拼接函数(对应 P5-T10-完整) - [ ] T2:实现消费记录分页 API(三种样式区分 + 懒加载) - [ ] T3:实现客户指数总览 API - [ ] T4:实现助教详情 API - [ ] T5:实现对话 API(创建/发送/历史/消息列表,SSE 流式) - [ ] T6:实现 customer-detail 小程序页面 - [ ] T7:实现 coach-detail 小程序页面 - [ ] T8:实现 customer-service-records 小程序页面 - [ ] T9:实现 chat 小程序页面(流式展示 + 来源信息) - [ ] T10:实现 chat-history 小程序页面