聊天判断修正

This commit is contained in:
2025-12-28 16:47:38 +08:00
parent 8448a801ce
commit 579e63efb0
6 changed files with 246 additions and 159 deletions

View File

@@ -15,160 +15,172 @@
<div class="filter-right">
<el-select v-model="statusFilter" placeholder="对话状态" clearable style="width: 120px;">
<el-option label="进行中" value="ongoing" />
<el-option label="已结束" value="ended" />
<el-option label="已转工单" value="converted" />
<el-option label="进行中" value="active" />
<el-option label="已结束" value="closed" />
</el-select>
<el-select v-model="satisfactionFilter" placeholder="满意度" clearable style="width: 120px;">
<el-option label="满意" value="satisfied" />
<el-option label="一般" value="normal" />
<el-option label="不满意" value="unsatisfied" />
</el-select>
<el-input v-model="searchKeyword" placeholder="搜索客户/内容" style="width: 200px;" :prefix-icon="Search" clearable />
<el-input v-model="searchKeyword" placeholder="搜索客户/聊天室" style="width: 200px;" :prefix-icon="Search" clearable @keyup.enter="loadChatRooms" />
<el-button type="primary" @click="loadChatRooms">搜索</el-button>
</div>
</div>
</el-card>
<!-- 对话列表 -->
<el-card>
<el-table :data="filteredChats" style="width: 100%">
<el-table-column prop="chatId" label="对话ID" width="140">
<el-card v-loading="loading">
<el-table :data="chatRooms" style="width: 100%">
<el-table-column prop="roomId" label="聊天室ID" width="180">
<template #default="{ row }">
<span style="color: #409eff; font-weight: 500;">{{ row.chatId }}</span>
<span style="color: #409eff; font-weight: 500;">{{ row.roomId?.substring(0, 8) }}...</span>
</template>
</el-table-column>
<el-table-column prop="customerName" label="客户信息" width="150">
<el-table-column prop="roomName" label="聊天室名称" width="180" />
<el-table-column prop="guestName" label="客户" width="120" />
<el-table-column prop="workcaseId" label="关联工单" width="140">
<template #default="{ row }">
<div class="customer-info">
<span class="name">{{ row.customerName }}</span>
<span class="phone">{{ row.customerPhone }}</span>
</div>
<span v-if="row.workcaseId" style="color: #67c23a;">{{ row.workcaseId }}</span>
<span v-else style="color: #909399;">-</span>
</template>
</el-table-column>
<el-table-column prop="agentName" label="客服人员" width="100" />
<el-table-column prop="messageCount" label="消息数" width="80" align="center" />
<el-table-column prop="duration" label="对话时长" width="100" />
<el-table-column prop="status" label="状态" width="100">
<template #default="{ row }">
<el-tag :type="getStatusType(row.status)" size="small">
{{ row.statusName }}
{{ getStatusName(row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="satisfaction" label="满意度" width="100">
<template #default="{ row }">
<el-rate v-model="row.satisfaction" disabled allow-half />
</template>
</el-table-column>
<el-table-column prop="startTime" label="开始时间" width="160" />
<el-table-column label="操作" width="200" fixed="right">
<el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-button type="primary" link size="small" @click="viewChat(row)">查看</el-button>
<el-button type="success" link size="small" @click="downloadChat(row)">下载</el-button>
<el-button v-if="row.status === 'ongoing'" type="warning" link size="small" @click="endChat(row)">结束</el-button>
<el-button v-if="row.status === 'active'" type="warning" link size="small" @click="closeChat(row)">关闭</el-button>
</template>
</el-table-column>
</el-table>
<div class="table-pagination">
<el-pagination v-model:current-page="currentPage" :page-size="10" :total="chats.length" layout="total, prev, pager, next" />
<el-pagination
v-model:current-page="currentPage"
:page-size="pageSize"
:total="total"
layout="total, prev, pager, next"
@current-change="loadChatRooms"
/>
</div>
</el-card>
</div>
<!-- 查看对话详情弹窗 -->
<el-dialog v-model="showChatDialog" title="对话详情" width="700px">
<div class="chat-messages">
<div v-for="(msg, idx) in currentChatMessages" :key="idx" class="message-item" :class="msg.type">
<div class="message-header">
<span class="sender">{{ msg.sender }}</span>
<span class="time">{{ msg.time }}</span>
</div>
<div class="message-content">{{ msg.content }}</div>
</div>
</div>
<!-- 查看对话详情弹窗 - 复用 ChatMessage 组件 -->
<el-dialog v-model="showChatDialog" title="对话详情" width="800px" class="chat-dialog">
<ChatMessage v-if="showChatDialog && currentRoomId" :room-id="currentRoomId" :chat-room="currentChatRoom" />
</el-dialog>
</AdminLayout>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { ref, onMounted } from 'vue'
import AdminLayout from '@/views/admin/AdminLayout.vue'
import { ChatMessage } from '@/views/public/ChatRoom/'
import { Download, Search } from 'lucide-vue-next'
import { ElMessage } from 'element-plus'
import { workcaseChatAPI } from '@/api/workcase/workcaseChat'
import type { ChatRoomVO } from '@/types/workcase/chatRoom'
const dateRange = ref<[Date, Date] | null>(null)
const statusFilter = ref('')
const satisfactionFilter = ref('')
const searchKeyword = ref('')
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
const loading = ref(false)
const showChatDialog = ref(false)
const currentChatMessages = ref<any[]>([])
const currentRoomId = ref('')
const currentChatRoom = ref<ChatRoomVO | undefined>(undefined)
const chats = ref([
{ chatId: 'CH001', customerName: '张三', customerPhone: '13800138000', agentName: '王五', messageCount: 24, duration: '15分钟', status: 'ended', statusName: '已结束', satisfaction: 4, startTime: '2024-12-13 10:30' },
{ chatId: 'CH002', customerName: '李四', customerPhone: '13800138001', agentName: '赵六', messageCount: 18, duration: '12分钟', status: 'ended', statusName: '已结束', satisfaction: 5, startTime: '2024-12-13 09:15' },
{ chatId: 'CH003', customerName: '王五', customerPhone: '13800138002', agentName: '孙七', messageCount: 32, duration: '22分钟', status: 'converted', statusName: '已转工单', satisfaction: 3, startTime: '2024-12-12 14:20' },
{ chatId: 'CH004', customerName: '赵六', customerPhone: '13800138003', agentName: '李四', messageCount: 15, duration: '10分钟', status: 'ongoing', statusName: '进行中', satisfaction: 0, startTime: '2024-12-13 11:00' },
{ chatId: 'CH005', customerName: '孙七', customerPhone: '13800138004', agentName: '王五', messageCount: 28, duration: '18分钟', status: 'ended', statusName: '已结束', satisfaction: 4.5, startTime: '2024-12-13 08:45' }
])
// 聊天室列表
const chatRooms = ref<ChatRoomVO[]>([])
const filteredChats = computed(() => {
let result = chats.value
if (statusFilter.value) {
result = result.filter(c => c.status === statusFilter.value)
}
if (satisfactionFilter.value) {
const satisfaction = satisfactionFilter.value === 'satisfied' ? 4 : satisfactionFilter.value === 'normal' ? 2.5 : 1
result = result.filter(c => {
if (satisfactionFilter.value === 'satisfied') return c.satisfaction >= 4
if (satisfactionFilter.value === 'normal') return c.satisfaction >= 2 && c.satisfaction < 4
if (satisfactionFilter.value === 'unsatisfied') return c.satisfaction < 2
return true
// 加载聊天室列表
const loadChatRooms = async () => {
loading.value = true
try {
const filter: any = {}
if (statusFilter.value) {
filter.status = statusFilter.value
}
if (searchKeyword.value) {
filter.roomName = searchKeyword.value
}
const res = await workcaseChatAPI.getChatRoomPage({
filter,
pageParam: {
page: currentPage.value,
pageSize: pageSize.value
}
})
if (res.success) {
chatRooms.value = res.dataList || []
total.value = res.total || 0
} else {
ElMessage.error(res.message || '加载聊天室列表失败')
}
} catch (error) {
console.error('加载聊天室列表失败:', error)
ElMessage.error('加载聊天室列表失败')
} finally {
loading.value = false
}
if (searchKeyword.value) {
const keyword = searchKeyword.value.toLowerCase()
result = result.filter(c =>
c.customerName.toLowerCase().includes(keyword) ||
c.customerPhone.includes(keyword)
)
}
return result.slice((currentPage.value - 1) * 10, currentPage.value * 10)
})
}
const getStatusType = (status: string) => {
const map: Record<string, string> = {
ongoing: 'success',
ended: 'info',
converted: 'warning'
active: 'success',
closed: 'info'
}
return map[status] || 'info'
}
const viewChat = (row: any) => {
currentChatMessages.value = [
{ type: 'customer', sender: row.customerName, time: '10:30:15', content: '你好,我的设备出现了故障' },
{ type: 'agent', sender: row.agentName, time: '10:30:45', content: '您好,感谢您的咨询。请问是什么故障呢?' },
{ type: 'customer', sender: row.customerName, time: '10:31:20', content: '显示屏不亮了,但是有声音' },
{ type: 'agent', sender: row.agentName, time: '10:31:50', content: '好的,这可能是显示屏的问题。请问您的设备型号是什么?' },
{ type: 'customer', sender: row.customerName, time: '10:32:30', content: 'TH-500GF' },
{ type: 'agent', sender: row.agentName, time: '10:33:00', content: '好的,我为您创建了一个工单,技术人员会尽快联系您' }
]
const getStatusName = (status: string) => {
const map: Record<string, string> = {
active: '进行中',
closed: '已结束'
}
return map[status] || status
}
const viewChat = (row: ChatRoomVO) => {
currentRoomId.value = row.roomId || ''
currentChatRoom.value = row
showChatDialog.value = true
}
const downloadChat = (row: any) => {
ElMessage.success(`下载对话: ${row.chatId}`)
}
const endChat = (row: any) => {
ElMessage.info(`结束对话: ${row.chatId}`)
const closeChat = async (row: ChatRoomVO) => {
if (!row.roomId) return
try {
const loginDomain = JSON.parse(localStorage.getItem('loginDomain') || '{}')
const userId = loginDomain?.userInfo?.userId || ''
const res = await workcaseChatAPI.closeChatRoom(row.roomId, userId)
if (res.success) {
ElMessage.success('聊天室已关闭')
await loadChatRooms()
} else {
ElMessage.error(res.message || '关闭失败')
}
} catch (error) {
console.error('关闭聊天室失败:', error)
ElMessage.error('关闭聊天室失败')
}
}
const exportData = () => {
ElMessage.success('数据导出功')
ElMessage.success('数据导出功能开发中')
}
onMounted(() => {
loadChatRooms()
})
</script>
<style lang="scss" scoped>
@@ -196,50 +208,11 @@ const exportData = () => {
color: #909399;
}
.chat-messages {
display: flex;
flex-direction: column;
gap: 12px;
max-height: 400px;
overflow-y: auto;
}
.message-item {
padding: 10px 12px;
border-radius: 8px;
background: #f5f7fa;
}
.message-item.customer {
background: #e6f7ff;
margin-left: 20px;
}
.message-item.agent {
background: #f0f9ff;
margin-right: 20px;
}
.message-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 6px;
font-size: 12px;
}
.message-header .sender {
font-weight: 500;
color: #303133;
}
.message-header .time {
color: #909399;
}
.message-content {
color: #303133;
line-height: 1.5;
word-break: break-word;
.chat-dialog {
:deep(.el-dialog__body) {
padding: 0;
max-height: 600px;
overflow: hidden;
}
}
</style>