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

218 lines
9.1 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.
# chat 页面数据来源排查
> 排查日期2026-03-18
> 页面路径pages/chat/chat
## 概览
| 分类 | 数量 | 说明 |
|------|------|------|
| A. Mock 数据 | 4 | 来自 `mock-data.ts` 或页面内联 mock联调时需替换为 API |
| B. 硬编码数据 | 3 | 直接写死在 data 或方法中的值 |
| C. 已对接 API | 0 | 当前页面无任何真实 API 调用 |
| D. 前端计算/派生数据 | 6 | 由工具函数或页面逻辑计算得出 |
| E. 路由参数 | 1 | 从 `onLoad(options)` 获取 |
| F. WXML 硬编码文案 | 8 | 模板中直接写死的中文文案 |
---
## 一、Mock 数据
### A1. `mockChatMessages` — 历史消息列表
| 项目 | 内容 |
|------|------|
| 来源 | `import { mockChatMessages } from '../../utils/mock-data'` |
| 类型 | `ChatMessage[]` |
| 使用位置 | `loadMessages()``enrichMessages(mockChatMessages)``this.setData({ messages })` |
| 涉及字段 | `id`, `role`, `content`, `timestamp`, `referenceCard`(含 `type`, `title`, `summary`, `data` |
| 联调替换 | 需替换为 **AI 对话历史 API**(如 `GET /api/chat/messages?customerId=xxx`),返回分页消息列表 |
| 当前 mock 条数 | 6 条(`msg-001` ~ `msg-006` |
### A2. `mockAIReplies` — AI 回复模板(页面内联 mock
| 项目 | 内容 |
|------|------|
| 来源 | `chat.ts` 顶部常量 `const mockAIReplies = [...]` |
| 类型 | `string[]`3 条固定回复文案) |
| 使用位置 | `triggerAIReply()``mockAIReplies[this._msgCounter % mockAIReplies.length]` |
| 联调替换 | 需替换为 **AI 对话流式接口**(如 `POST /api/chat/send`SSE/WebSocket 流式返回) |
| 当前值 | `['根据数据分析,这位客户近期消费频次有所下降...', '好的,我已经记录了你的需求...', '这位客户偏好中式台球...']` |
### A3. `simulateStreamOutput` — 模拟流式输出
| 项目 | 内容 |
|------|------|
| 来源 | `import { simulateStreamOutput } from '../../utils/chat'` |
| 类型 | 工具函数,逐字 `setTimeout(tick, 50)` 模拟打字效果 |
| 使用位置 | `triggerAIReply()` 中调用,将 mock 回复逐字输出 |
| 联调替换 | 替换为真实 SSE/WebSocket 流式读取逻辑,`callback` 接口可复用 |
### A4. `referenceCard` — 页面顶部引用卡片(条件构造)
| 项目 | 内容 |
|------|------|
| 来源 | `loadMessages()` 中根据 `customerId` 内联构造 |
| 代码 | `{ title: '客户详情', summary: \`正在查看客户 ${customerId} 的相关信息\` }` |
| 联调替换 | 需从 **客户详情 API** 获取客户名称等信息填充,或由跳转页面通过路由参数传入 |
---
## 二、硬编码数据
### B1. `statusBarHeight` 回退值
| 项目 | 内容 |
|------|------|
| 字段 | `statusBarHeight` |
| 位置 | `onLoad()` → `sysInfo.statusBarHeight \|\| 44` |
| 当前值 | `44`(回退默认值) |
| 应获取自 | `wx.getWindowInfo().statusBarHeight`已获取44 仅为兜底) |
| 风险等级 | **低** — 兜底值合理,不同机型差异可忽略 |
### B2. `loadMessages` 延迟时间
| 项目 | 内容 |
|------|------|
| 字段 | `setTimeout(() => { ... }, 500)` |
| 位置 | `loadMessages()` 方法 |
| 当前值 | `500`ms 模拟网络延迟 |
| 联调处理 | 替换为真实 API 调用后移除 `setTimeout`,改用 API 响应回调 |
| 风险等级 | **中** — 联调时必须移除,否则造成不必要的 500ms 延迟 |
### B3. `triggerAIReply` 延迟时间
| 项目 | 内容 |
|------|------|
| 字段 | `setTimeout(() => { this.triggerAIReply() }, 300)` |
| 位置 | `onSendMessage()` 末尾 |
| 当前值 | `300`ms 延迟触发 AI 回复 |
| 联调处理 | 替换为发送消息 API 成功回调后触发流式接收 |
| 风险等级 | **中** — 联调时需重构为 API 驱动的流程 |
---
## 三、已对接 API
**无。** 当前页面 0 个真实 API 调用。
> 注:项目中已存在 `utils/request.ts`(封装了 `wx.request`),联调时可直接使用。
---
## 四、前端计算/派生数据
### D1. `enrichMessages()` 派生字段
对每条消息计算以下展示字段:
| 派生字段 | 计算逻辑 | 来源函数 |
|----------|----------|----------|
| `timeLabel` | 相对时间文案(刚刚/N分钟前/MM-DD | `formatRelativeTime(m.timestamp)` |
| `imTimeLabel` | IM 时间格式HH:mm / MM-DD HH:mm | `formatIMTime(m.timestamp)` |
| `showTimeDivider` | 是否显示时间分割线首条必显示间隔≥5分钟显示 | `shouldShowTimeDivider(prev, curr)` |
| `referenceCard.dataList` | 将 `Record<string,string>` 转为 `{key,value}[]` 供 `wx:for` | `toDataList(m.referenceCard.data)` |
### D2. 用户发送消息时的派生字段
| 派生字段 | 计算逻辑 |
|----------|----------|
| `userMsg.timeLabel` | 固定为 `'刚刚'` |
| `userMsg.imTimeLabel` | `formatIMTime(new Date().toISOString())` |
| `userMsg.showTimeDivider` | `shouldShowTimeDivider(prevTs, now)` |
| `userMsg.id` | `msg-user-${this._msgCounter}`(自增计数器) |
| `userMsg.timestamp` | `new Date().toISOString()`(客户端当前时间) |
### D3. AI 回复消息的派生字段
同 D2 逻辑,`id` 格式为 `msg-ai-${this._msgCounter}`。
### D4. `pageState` 状态机
| 状态值 | 触发条件 |
|--------|----------|
| `'loading'` | `loadMessages()` 开始时 |
| `'empty'` | 消息列表为空且无引用卡片 |
| `'normal'` | 消息加载成功且有内容 |
| `'error'` | `loadMessages()` 捕获异常 |
### D5. `isStreaming` / `streamingContent`
| 字段 | 说明 |
|------|------|
| `isStreaming` | AI 流式回复进行中标志,控制输入框禁用和打字指示器 |
| `streamingContent` | 流式输出的当前内容片段 |
### D6. `scrollToId`
滚动锚点,通过 `scrollToBottom()` 方法设置为 `'scroll-bottom'`,驱动 `scroll-view` 滚动到底部。
---
## 五、路由参数
### E1. `customerId`
| 项目 | 内容 |
|------|------|
| 获取方式 | `onLoad(options)` → `options?.customerId \|\| ''` |
| 用途 | 1. 传入 `loadMessages(customerId)` 加载对应客户的对话2. 决定是否显示页面顶部引用卡片 |
| 当前状态 | 仅用于 mock 逻辑判断,未传入任何 API |
| 联调需求 | 作为 API 请求参数传入消息列表接口 |
---
## 六、WXML 硬编码文案
| 编号 | 文案 | 位置 | 说明 |
|------|------|------|------|
| F1 | `加载中...` | 加载态 `g-toast-loading-text` | 通用加载文案,可保留 |
| F2 | `加载失败,请重试` | 错误态 `error-text` | 通用错误文案,可保留 |
| F3 | `重新加载` | 错误态 `retry-btn-text` | 按钮文案,可保留 |
| F4 | `引用内容` | 引用卡片 `reference-tag` | 标签文案,可保留 |
| F5 | `你好,我是 AI 助手` | 空对话提示 `empty-text` | 欢迎语,建议后续从配置获取 |
| F6 | `有什么可以帮你的?` | 空对话提示 `empty-sub` | 副标题,建议后续从配置获取 |
| F7 | `输入消息...` | 输入框 `placeholder` | 占位文案,可保留 |
| F8 | `AI 助手` | `chat.json` → `navigationBarTitleText` | 导航栏标题,可保留 |
---
## 七、联调 TODO
### 优先级 P0阻塞联调
- [ ] **替换消息列表加载**`loadMessages()` 中 `mockChatMessages` → 调用 `GET /api/chat/messages` 接口
- 入参:`customerId`(可选)、分页参数
- 出参:`ChatMessage[]`
- 移除 `setTimeout(..., 500)` 模拟延迟
- [ ] **替换 AI 回复流程**`triggerAIReply()` 中 `mockAIReplies` + `simulateStreamOutput` → 调用 `POST /api/chat/send` 流式接口
- 入参:`content`(用户消息)、`customerId`、`conversationId`
- 出参SSE/WebSocket 流式文本
- 保留 `isStreaming` 状态控制和逐字渲染逻辑
- [ ] **替换引用卡片数据**`loadMessages()` 中内联构造的 `referenceCard` → 从客户详情 API 或路由参数获取真实客户信息
### 优先级 P1联调后优化
- [ ] **消息发送 API**`onSendMessage()` 中用户消息需先通过 API 持久化,再触发 AI 回复
- [ ] **对话会话管理**:当前无 `conversationId` 概念,需增加会话创建/恢复逻辑
- [ ] **消息 ID 生成**:当前使用前端自增计数器 `_msgCounter`,联调后应使用服务端返回的 ID
### 优先级 P2体验优化
- [ ] **错误重试**`onRetry()` 当前仅重新调用 `loadMessages()`,需增加 toast 提示
- [ ] **空对话欢迎语**F5/F6 硬编码文案考虑从后端配置获取
- [ ] **移除 `simulateStreamOutput`**:联调完成后,`utils/chat.ts` 中的模拟函数可删除(保留 `simulateStreamOutputSync` 用于测试)
- [ ] **移除 `mockAIReplies`**:页面内联 mock 常量清理
- [ ] **移除 `mock-data.ts` 中 `mockChatMessages` 引用**:确认其他页面不再使用后,清理 `ChatMessage` 相关 mock
### 依赖确认
| 依赖项 | 状态 | 说明 |
|--------|------|------|
| `utils/request.ts` | ✅ 已存在 | 封装了 `wx.request`,可直接使用 |
| AI 对话 API后端 | ❌ 待确认 | 需确认接口设计REST vs WebSocket、流式协议 |
| 客户详情 API | ❌ 待确认 | 引用卡片需要客户基本信息 |
| 对话会话 API | ❌ 待确认 | 会话创建、历史会话列表 |