/** * 💬 会话管理组件 * 展示会话列表、消息详情、删除、导出功能 */ import { ref } from 'vue' import { listConversations, deleteConversation, getConversationMessages, getConversationStats, exportConversation, getRoleList } from '../js/api.js' import { toast, formatDate } from '../js/utils.js' export default { template: `

会话列表

{{ stats.totalConversations || 0 }}
总会话数
{{ stats.totalMessages || 0 }}
总消息数
{{ stats.todayConversations || 0 }}
今日会话
{{ stats.todayMessages || 0 }}
今日消息
会话ID 外部用户ID 角色 消息数 最后消息时间 最后消息预览 操作
暂无会话记录
{{ c.conversationId }} {{ c.accountId || '-' }} {{ c.roleName || '-' }} {{ c.messageCount }} {{ formatDate(c.lastMessageTime) }} {{ c.lastMessagePreview || '-' }}
`, setup() { const conversations = ref([]) const page = ref(1) const pages = ref(1) const total = ref(0) const keyword = ref('') const roleFilter = ref('') const accountFilter = ref('') const roles = ref([]) const stats = ref(null) // 消息详情弹窗 const messageModal = ref({ visible: false, conversationId: '', roleName: '', messages: [] }) async function load(p = 1) { page.value = p try { const json = await listConversations( p, 10, keyword.value || undefined, accountFilter.value || undefined, roleFilter.value || undefined ) if (json.success) { conversations.value = json.data || [] total.value = json.total || 0 pages.value = json.pages || 1 } else { toast(json.message || '查询失败', 'error') } } catch (e) { toast('加载会话失败:' + e.message, 'error') } } async function loadFilters() { try { const roleJson = await getRoleList() if (roleJson.success) roles.value = roleJson.data || [] } catch (e) { console.error('加载筛选项失败', e) } } async function loadStats() { try { const json = await getConversationStats() if (json.success) { stats.value = json.data } } catch (e) { console.error('加载会话统计失败', e) } } async function viewMessages(conversationId) { try { const json = await getConversationMessages(conversationId) if (json.success) { messageModal.value.conversationId = conversationId messageModal.value.messages = json.data || [] const current = conversations.value.find(item => item.conversationId === conversationId) messageModal.value.roleName = current?.roleName || '' messageModal.value.visible = true } else { toast(json.message || '加载消息失败', 'error') } } catch (e) { toast('加载消息失败:' + e.message, 'error') } } function closeMessageModal() { messageModal.value.visible = false messageModal.value.conversationId = '' messageModal.value.roleName = '' messageModal.value.messages = [] } async function remove(conversationId) { if (!confirm('确定删除此会话?该会话下的所有消息将被逻辑删除')) return try { const json = await deleteConversation(conversationId) if (json.success) { toast(`会话删除成功,共删除 ${json.deletedMessages || 0} 条消息`, 'success') load(page.value) loadStats() } else { toast(json.message || '删除失败', 'error') } } catch (e) { toast('删除失败:' + e.message, 'error') } } async function downloadExport(conversationId) { try { const content = await exportConversation(conversationId) const blob = new Blob([content], { type: 'text/plain;charset=utf-8' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `conversation_${conversationId}.txt` document.body.appendChild(a) a.click() document.body.removeChild(a) URL.revokeObjectURL(url) toast('导出成功', 'success') } catch (e) { toast('导出失败:' + e.message, 'error') } } // 初始加载 loadFilters() load() loadStats() return { conversations, page, pages, total, keyword, accountFilter, roleFilter, roles, stats, messageModal, load, loadStats, viewMessages, closeMessageModal, remove, downloadExport, formatDate } } }