fix(customer-service): 修复在线客服功能使其可用
- 在微信客服按钮补全必要属性 sessionFrom、onContact、showMessageCard 和 sendMessageTitle - 将按钮样式由 Tailwind 类改为内联样式,避免 border-0 干扰原生按钮渲染 - 添加真机预览测试提示,解决开发者工具无法使用问题 - `ShopChatMessage` 和相关接口新增 conversationId 字段支持消息会话关联 - 消息发送时补全 conversationId 和发送人 ID,保证消息关联准确 - 将会话列表中引用的不存在字段 lastMessage 替换为 content - 移除无用的 useReachBottom,改用 ScrollView 的 onScrollToLower 事件加载历史消息 - 删除未使用的 scrollToBottom ref - 增加条件守卫避免非历史展开时加载更多消息
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<ShopChatConversation | null> => {
|
||||
@@ -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 = () => {
|
||||
<View className="flex flex-col min-h-screen bg-gray-100">
|
||||
<NavBar title="在线客服" />
|
||||
|
||||
<ScrollView scrollY className="flex-1">
|
||||
<ScrollView
|
||||
scrollY
|
||||
className="flex-1"
|
||||
onScrollToLower={handleScrollToLower}
|
||||
lowerThreshold={50}
|
||||
>
|
||||
{/* 客服状态栏 */}
|
||||
<View className="bg-white px-4 py-3 flex items-center justify-between">
|
||||
<View className="flex items-center gap-2">
|
||||
@@ -222,11 +241,25 @@ const CustomerServicePage: React.FC = () => {
|
||||
<View className="px-4 py-3 bg-white border-t border-gray-50">
|
||||
<Button
|
||||
openType="contact"
|
||||
className="w-full h-12 rounded-lg text-white font-medium text-base border-0"
|
||||
style={{ backgroundColor: '#07c160', lineHeight: '48px' }}
|
||||
sessionFrom="customer_service"
|
||||
onContact={handleContact}
|
||||
showMessageCard
|
||||
sendMessageTitle="欢迎咨询"
|
||||
className="w-full rounded-lg text-white font-medium text-base"
|
||||
style={{
|
||||
backgroundColor: '#07c160',
|
||||
lineHeight: '48px',
|
||||
height: '48px',
|
||||
borderRadius: '8px',
|
||||
border: 'none',
|
||||
padding: '0',
|
||||
}}
|
||||
>
|
||||
微信在线客服
|
||||
</Button>
|
||||
<Text className="text-xs text-gray-400 block text-center mt-2">
|
||||
点击进入微信客服对话(开发者工具中不可用,请用真机预览测试)
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* 消息记录入口 */}
|
||||
@@ -276,7 +309,7 @@ const CustomerServicePage: React.FC = () => {
|
||||
>
|
||||
<View className="flex justify-between items-center">
|
||||
<Text className="text-sm text-gray-700" style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{conv.content || conv.lastMessage || '暂无消息'}
|
||||
{conv.content || '暂无消息'}
|
||||
</Text>
|
||||
<Text className="text-xs text-gray-400 ml-2">{formatTime(conv.updateTime)}</Text>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user