feat: 自动提交 - 周一 2025/09/22 15:12:38.91
This commit is contained in:
297
frontend/src/stores/useChatStore.ts
Normal file
297
frontend/src/stores/useChatStore.ts
Normal file
@@ -0,0 +1,297 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { io, type Socket } from 'socket.io-client'
|
||||
|
||||
export interface ChatMessage {
|
||||
id: string
|
||||
role: 'user' | 'assistant' | 'system'
|
||||
content: string
|
||||
timestamp: Date
|
||||
metadata?: {
|
||||
knowledge_used?: string[]
|
||||
confidence_score?: number
|
||||
work_order_id?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface ChatSession {
|
||||
id: string
|
||||
userId: string
|
||||
workOrderId?: string
|
||||
messages: ChatMessage[]
|
||||
status: 'active' | 'ended'
|
||||
createdAt: Date
|
||||
}
|
||||
|
||||
export const useChatStore = defineStore('chat', () => {
|
||||
// 状态
|
||||
const socket = ref<Socket | null>(null)
|
||||
const isConnected = ref(false)
|
||||
const currentSession = ref<ChatSession | null>(null)
|
||||
const messages = ref<ChatMessage[]>([])
|
||||
const isTyping = ref(false)
|
||||
const userId = ref('user_001')
|
||||
const workOrderId = ref<string>('')
|
||||
|
||||
// 计算属性
|
||||
const hasActiveSession = computed(() =>
|
||||
currentSession.value && currentSession.value.status === 'active'
|
||||
)
|
||||
|
||||
const messageCount = computed(() => messages.value.length)
|
||||
|
||||
// 动作
|
||||
const connectWebSocket = () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
try {
|
||||
socket.value = io('ws://localhost:8765', {
|
||||
transports: ['websocket']
|
||||
})
|
||||
|
||||
socket.value.on('connect', () => {
|
||||
isConnected.value = true
|
||||
resolve()
|
||||
})
|
||||
|
||||
socket.value.on('disconnect', () => {
|
||||
isConnected.value = false
|
||||
})
|
||||
|
||||
socket.value.on('error', (error) => {
|
||||
console.error('WebSocket error:', error)
|
||||
reject(error)
|
||||
})
|
||||
|
||||
socket.value.on('message_response', (data) => {
|
||||
handleMessageResponse(data)
|
||||
})
|
||||
|
||||
socket.value.on('typing_start', () => {
|
||||
isTyping.value = true
|
||||
})
|
||||
|
||||
socket.value.on('typing_end', () => {
|
||||
isTyping.value = false
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const disconnectWebSocket = () => {
|
||||
if (socket.value) {
|
||||
socket.value.disconnect()
|
||||
socket.value = null
|
||||
isConnected.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const startChat = async () => {
|
||||
try {
|
||||
if (!socket.value) {
|
||||
await connectWebSocket()
|
||||
}
|
||||
|
||||
const response = await sendSocketMessage({
|
||||
type: 'create_session',
|
||||
user_id: userId.value,
|
||||
work_order_id: workOrderId.value ? parseInt(workOrderId.value) : null
|
||||
})
|
||||
|
||||
if (response.type === 'session_created') {
|
||||
currentSession.value = {
|
||||
id: response.session_id,
|
||||
userId: userId.value,
|
||||
workOrderId: workOrderId.value,
|
||||
messages: [],
|
||||
status: 'active',
|
||||
createdAt: new Date()
|
||||
}
|
||||
|
||||
addMessage('system', '对话已开始,请描述您的问题。')
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
} catch (error) {
|
||||
console.error('启动对话失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const endChat = async () => {
|
||||
try {
|
||||
if (currentSession.value) {
|
||||
await sendSocketMessage({
|
||||
type: 'end_session',
|
||||
session_id: currentSession.value.id
|
||||
})
|
||||
|
||||
currentSession.value.status = 'ended'
|
||||
addMessage('system', '对话已结束。')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('结束对话失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const sendMessage = async (content: string) => {
|
||||
if (!currentSession.value || !content.trim()) {
|
||||
return
|
||||
}
|
||||
|
||||
// 添加用户消息
|
||||
addMessage('user', content)
|
||||
|
||||
try {
|
||||
const response = await sendSocketMessage({
|
||||
type: 'send_message',
|
||||
session_id: currentSession.value.id,
|
||||
message: content
|
||||
})
|
||||
|
||||
if (response.type === 'message_response' && response.result.success) {
|
||||
const result = response.result
|
||||
|
||||
// 添加助手回复
|
||||
addMessage('assistant', result.content, {
|
||||
knowledge_used: result.knowledge_used,
|
||||
confidence_score: result.confidence_score,
|
||||
work_order_id: result.work_order_id
|
||||
})
|
||||
|
||||
// 更新工单ID
|
||||
if (result.work_order_id) {
|
||||
workOrderId.value = result.work_order_id.toString()
|
||||
}
|
||||
} else {
|
||||
addMessage('assistant', '抱歉,我暂时无法处理您的问题。请稍后再试。')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('发送消息失败:', error)
|
||||
addMessage('assistant', '发送消息失败,请检查网络连接。')
|
||||
}
|
||||
}
|
||||
|
||||
const createWorkOrder = async (data: {
|
||||
title: string
|
||||
description: string
|
||||
category: string
|
||||
priority: string
|
||||
}) => {
|
||||
if (!currentSession.value) {
|
||||
throw new Error('没有活跃的会话')
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await sendSocketMessage({
|
||||
type: 'create_work_order',
|
||||
session_id: currentSession.value.id,
|
||||
...data
|
||||
})
|
||||
|
||||
if (response.type === 'work_order_created' && response.result.success) {
|
||||
workOrderId.value = response.result.work_order_id.toString()
|
||||
addMessage('system', `工单创建成功!工单号: ${response.result.order_id}`)
|
||||
return response.result
|
||||
} else {
|
||||
throw new Error(response.result.error || '创建工单失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('创建工单失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const sendSocketMessage = (message: any): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!socket.value) {
|
||||
reject(new Error('WebSocket未连接'))
|
||||
return
|
||||
}
|
||||
|
||||
const messageId = 'msg_' + Date.now()
|
||||
message.messageId = messageId
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
reject(new Error('请求超时'))
|
||||
}, 10000)
|
||||
|
||||
const handleResponse = (data: any) => {
|
||||
if (data.messageId === messageId) {
|
||||
clearTimeout(timeout)
|
||||
socket.value?.off('message_response', handleResponse)
|
||||
resolve(data)
|
||||
}
|
||||
}
|
||||
|
||||
socket.value.on('message_response', handleResponse)
|
||||
socket.value.emit('message', message)
|
||||
})
|
||||
}
|
||||
|
||||
const addMessage = (role: 'user' | 'assistant' | 'system', content: string, metadata?: any) => {
|
||||
const message: ChatMessage = {
|
||||
id: 'msg_' + Date.now() + '_' + Math.random(),
|
||||
role,
|
||||
content,
|
||||
timestamp: new Date(),
|
||||
metadata
|
||||
}
|
||||
|
||||
messages.value.push(message)
|
||||
|
||||
if (currentSession.value) {
|
||||
currentSession.value.messages.push(message)
|
||||
}
|
||||
}
|
||||
|
||||
const clearMessages = () => {
|
||||
messages.value = []
|
||||
if (currentSession.value) {
|
||||
currentSession.value.messages = []
|
||||
}
|
||||
}
|
||||
|
||||
const setUserId = (id: string) => {
|
||||
userId.value = id
|
||||
}
|
||||
|
||||
const setWorkOrderId = (id: string) => {
|
||||
workOrderId.value = id
|
||||
}
|
||||
|
||||
const handleMessageResponse = (data: any) => {
|
||||
// 处理WebSocket消息响应
|
||||
console.log('收到消息响应:', data)
|
||||
}
|
||||
|
||||
return {
|
||||
// 状态
|
||||
socket,
|
||||
isConnected,
|
||||
currentSession,
|
||||
messages,
|
||||
isTyping,
|
||||
userId,
|
||||
workOrderId,
|
||||
|
||||
// 计算属性
|
||||
hasActiveSession,
|
||||
messageCount,
|
||||
|
||||
// 动作
|
||||
connectWebSocket,
|
||||
disconnectWebSocket,
|
||||
startChat,
|
||||
endChat,
|
||||
sendMessage,
|
||||
createWorkOrder,
|
||||
addMessage,
|
||||
clearMessages,
|
||||
setUserId,
|
||||
setWorkOrderId
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user