/**
* 💬 会话管理组件
* 展示会话列表、消息详情、删除、导出功能
*/
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 || '-' }}
|
|
会话消息详情
会话ID: {{ messageModal.conversationId }}
· 角色:{{ messageModal.roleName }}
· 共 {{ messageModal.messages.length }} 条消息
暂无消息
{{ msg.messageType === 'USER' ? '用户' : msg.messageType === 'ASSISTANT' ? 'AI助手' : '系统' }}
{{ formatDate(msg.createTime) }}
{{ msg.content }}
`,
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
}
}
}