From 889a0f983efe450e4af97e5bbf4b44196bd5aa6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Tue, 14 Jul 2026 20:49:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(customer-service):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=9C=A8=E7=BA=BF=E5=AE=A2=E6=9C=8D=E5=8A=9F=E8=83=BD=E4=BD=BF?= =?UTF-8?q?=E5=85=B6=E5=8F=AF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在微信客服按钮补全必要属性 sessionFrom、onContact、showMessageCard 和 sendMessageTitle - 将按钮样式由 Tailwind 类改为内联样式,避免 border-0 干扰原生按钮渲染 - 添加真机预览测试提示,解决开发者工具无法使用问题 - `ShopChatMessage` 和相关接口新增 conversationId 字段支持消息会话关联 - 消息发送时补全 conversationId 和发送人 ID,保证消息关联准确 - 将会话列表中引用的不存在字段 lastMessage 替换为 content - 移除无用的 useReachBottom,改用 ScrollView 的 onScrollToLower 事件加载历史消息 - 删除未使用的 scrollToBottom ref - 增加条件守卫避免非历史展开时加载更多消息 --- .workbuddy/memory/2026-07-14.md | 31 ++++++++++ src/api/shop/shopChatMessage/model/index.ts | 3 + src/pages/user/customer-service/index.tsx | 65 ++++++++++++++++----- 3 files changed, 83 insertions(+), 16 deletions(-) diff --git a/.workbuddy/memory/2026-07-14.md b/.workbuddy/memory/2026-07-14.md index 381e8a9..805c34b 100644 --- a/.workbuddy/memory/2026-07-14.md +++ b/.workbuddy/memory/2026-07-14.md @@ -244,3 +244,34 @@ adapter `/list` 接口忽略分页,一次返回全部收藏;前端 `listShop 1. 从 `useCartContext` 额外解构 `totalCount`、`refresh` 2. 引入 `useDidShow`,页面显示时(已登录)调 `refresh()` 拉取最新购物车,保证角标准确 3. 购物车图标外包一层 `relative` 容器,`totalCount > 0` 时右上角显示红色圆角角标(>99 显示 `99+`),样式与商城列表页浮动购物车角标一致 + +## 在线客服功能修复(2026-07-14) + +### 问题 +`pages/user/customer-service/index` 在线客服功能使用不了,用户已在微信后台添加客服人员。 + +### 根因(多个问题叠加) +1. **`openType="contact"` 按钮缺少关键属性**:缺少 `sessionFrom`(会话来源标识)、`onContact`(客服回调)、`showMessageCard`/`sendMessageTitle`(客服消息卡片),且按钮被 Tailwind `border-0` 类可能干扰原生渲染 +2. **开发者工具限制**:`open-type="contact"` 在微信开发者工具中不生效,只能在真机上使用,页面缺少提示 +3. **自定义聊天系统消息发送缺失 `conversationId`**:`addShopChatMessage` 调用未传 `conversationId`,消息无法关联到会话;`ShopChatMessage` 模型本身也缺少该字段 +4. **消息发送缺失 `formUserId`**:发送人 ID 未设置 +5. **`conv.lastMessage` 字段不存在**:`ShopChatConversation` 模型只有 `content` 字段,代码引用了不存在的 `lastMessage` +6. **`useReachBottom` 用错场景**:页面使用 `ScrollView` 组件,`useReachBottom` 是页面级滚动钩子,对 ScrollView 无效,应改用 `onScrollToLower` +7. **`scrollToBottom` ref 设了但从未使用**:死代码 + +### 修改 +1. **`src/api/shop/shopChatMessage/model/index.ts`**: + - `ShopChatMessage` 接口新增 `conversationId?: number` + - `ShopChatMessageParam` 接口新增 `conversationId?: number` +2. **`src/pages/user/customer-service/index.tsx`**(全面修复): + - 微信客服按钮补全 `sessionFrom="customer_service"`、`onContact`、`showMessageCard`、`sendMessageTitle` + - 按钮样式从 Tailwind 类改为 inline style(避免 `border-0` 干扰原生按钮),显式设置 `border: 'none'` + - 添加"需真机预览测试"提示文字 + - `addShopChatMessage` 调用补全 `conversationId` 和 `formUserId`(从 `Taro.getStorageSync('UserId')` 获取) + - `conv.lastMessage` 全部改为 `conv.content` + - 会话列表更新 `lastMessage: text` 改为 `content: text` + - 移除 `useReachBottom`,改用 ScrollView `onScrollToLower` + `lowerThreshold={50}` + - 移除未使用的 `scrollToBottom` ref + - `pageShopChatMessage` 参数去掉 `as any` 断言(模型已支持 `conversationId`) + - 新增 `getCurrentUserId()` 辅助函数 + - `handleScrollToLower` 增加 `showHistory` 条件守卫(仅展开历史时才加载更多) diff --git a/src/api/shop/shopChatMessage/model/index.ts b/src/api/shop/shopChatMessage/model/index.ts index 411d45c..39d83fc 100644 --- a/src/api/shop/shopChatMessage/model/index.ts +++ b/src/api/shop/shopChatMessage/model/index.ts @@ -6,6 +6,8 @@ import type { PageParam } from '@/api'; export interface ShopChatMessage { // 自增ID id?: number; + // 会话ID + conversationId?: number; // 发送人ID formUserId?: number; // 发送人名称 @@ -60,4 +62,5 @@ export interface ShopChatMessage { export interface ShopChatMessageParam extends PageParam { id?: number; keywords?: string; + conversationId?: number; } diff --git a/src/pages/user/customer-service/index.tsx b/src/pages/user/customer-service/index.tsx index 48c0285..ace3d96 100644 --- a/src/pages/user/customer-service/index.tsx +++ b/src/pages/user/customer-service/index.tsx @@ -1,13 +1,13 @@ import React, { useEffect, useState, useCallback, useRef } from 'react' import { View, Text, Button, Input, ScrollView } from '@tarojs/components' -import Taro, { useReachBottom } from '@tarojs/taro' +import Taro from '@tarojs/taro' import NavBar from '@/components/NavBar' import LoadMore from '@/components/common/LoadMore' import EmptyState from '@/components/common/EmptyState' import { pageShopChatConversation, addShopChatConversation } from '@/api/shop/shopChatConversation' import { pageShopChatMessage, addShopChatMessage } from '@/api/shop/shopChatMessage' import type { ShopChatConversation, ShopChatConversationParam } from '@/api/shop/shopChatConversation/model' -import type { ShopChatMessage } from '@/api/shop/shopChatMessage/model' +import type { ShopChatMessage, ShopChatMessageParam } from '@/api/shop/shopChatMessage/model' import type { PageResult } from '@/api' definePageConfig({ @@ -29,7 +29,6 @@ const CustomerServicePage: React.FC = () => { const [hasMore, setHasMore] = useState(true) const [msgPage, setMsgPage] = useState(1) const [showHistory, setShowHistory] = useState(false) - const scrollToBottom = useRef(false) const isOnline = () => { const now = new Date() @@ -37,6 +36,12 @@ const CustomerServicePage: React.FC = () => { return h >= 9 && h < 21 } + // 获取当前用户ID + const getCurrentUserId = (): number | undefined => { + const id = Taro.getStorageSync('UserId') + return id || undefined + } + // 加载会话列表 const loadConversations = useCallback(async () => { setLoading(true) @@ -68,19 +73,19 @@ const CustomerServicePage: React.FC = () => { const loadMessages = useCallback(async (conversationId: number, pageNum: number = 1, isLoadMore = false) => { if (isLoadMore) setLoadingMore(true) try { - const result = await pageShopChatMessage({ + const params: ShopChatMessageParam = { conversationId, page: pageNum, limit: 20, order: 'asc', sort: 'createTime', - } as any) + } + const result = await pageShopChatMessage(params) if (result?.list) { if (isLoadMore) { setMessages(prev => [...result.list!, ...prev]) } else { setMessages(result.list) - scrollToBottom.current = true } setHasMore((result.list.length ?? 0) >= 20) setMsgPage(pageNum) @@ -97,11 +102,12 @@ const CustomerServicePage: React.FC = () => { loadConversations() }, [loadConversations]) - useReachBottom(() => { - if (hasMore && currentConversation && !loadingMore) { + // ScrollView 滚动到底部加载更多历史消息 + const handleScrollToLower = () => { + if (hasMore && currentConversation && !loadingMore && showHistory) { loadMessages(currentConversation.id!, msgPage + 1, true) } - }) + } // 创建新会话 const ensureConversation = async (): Promise => { @@ -140,18 +146,21 @@ const CustomerServicePage: React.FC = () => { return } + const userId = getCurrentUserId() await addShopChatMessage({ + conversationId: conv.id, content: text, type: 'text', + formUserId: userId, toUserId: 0, // 发送给客服(服务端路由) - } as any) + }) // 消息发送成功后刷新消息列表 await loadMessages(conv.id, 1, false) - // 同步更新会话列表 lastMessage + // 同步更新会话列表 content 字段 setConversations(prev => prev.map(c => - c.id === conv.id ? { ...c, lastMessage: text, updateTime: new Date().toISOString() } : c + c.id === conv.id ? { ...c, content: text, updateTime: new Date().toISOString() } : c )) } catch (e: any) { console.error('发送消息失败:', e) @@ -162,6 +171,11 @@ const CustomerServicePage: React.FC = () => { } } + // 微信客服回调 - 用户从客服会话返回时触发 + const handleContact = (e: any) => { + console.log('客服会话回调:', e.detail) + } + // 拨打热线 const handleCallHotline = () => { Taro.makePhoneCall({ phoneNumber: SERVICE_HOTLINE }) @@ -205,7 +219,12 @@ const CustomerServicePage: React.FC = () => { - + {/* 客服状态栏 */} @@ -222,11 +241,25 @@ const CustomerServicePage: React.FC = () => { + + 点击进入微信客服对话(开发者工具中不可用,请用真机预览测试) + {/* 消息记录入口 */} @@ -276,7 +309,7 @@ const CustomerServicePage: React.FC = () => { > - {conv.content || conv.lastMessage || '暂无消息'} + {conv.content || '暂无消息'} {formatTime(conv.updateTime)}