import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { getAgents, getAgentById, createAgent, updateAgent, deleteAgent, bindDevice, unbindDevice, verifyBinding, clearAgentCache } from '../services/agentService.js' // 智能体状态常量 export const AGENT_STATUS = { ACTIVE: 'active', INACTIVE: 'inactive', ARCHIVED: 'archived' } // 智能体角色常量 export const AGENT_ROLES = { ASSISTANT: 'assistant', CONSULTANT: 'consultant', CREATIVE: 'creative', EDUCATOR: 'educator', CUSTOM: 'custom' } // 语音模型常量 export const VOICE_MODELS = { XIAOYI: 'xiaoyi', XIAOMING: 'xiaoming', XIAOLI: 'xiaoli', XIAOWEI: 'xiaowei', CUSTOM: 'custom' } export const useAgentStore = defineStore('agents', () => { // ==================== 状态定义 ==================== // 智能体列表状态 const agents = ref([]) const currentAgent = ref(null) // 列表查询状态 const loading = ref(false) const error = ref(null) const searchQuery = ref('') const statusFilter = ref('') const deviceBoundFilter = ref(null) const sortBy = ref('updatedAt') const sortOrder = ref('desc') // 'asc' | 'desc' // 分页状态 const pagination = ref({ page: 1, pageSize: 12, total: 0, totalPages: 0, hasNext: false, hasPrev: false }) // 设备绑定状态 const bindingStates = ref(new Map()) // agentId -> { loading, error, verifying } // 缓存状态 const lastFetchTime = ref(null) const cacheExpiry = ref(5 * 60 * 1000) // 5分钟 // ==================== 计算属性 ==================== // 过滤后的智能体列表 const filteredAgents = computed(() => { let filtered = [...agents.value] // 搜索过滤 if (searchQuery.value) { const query = searchQuery.value.toLowerCase() filtered = filtered.filter(agent => agent.name.toLowerCase().includes(query) || agent.description.toLowerCase().includes(query) ) } // 状态过滤 if (statusFilter.value) { filtered = filtered.filter(agent => agent.status === statusFilter.value) } // 设备绑定过滤 if (deviceBoundFilter.value !== null) { filtered = filtered.filter(agent => deviceBoundFilter.value ? agent.device.bound : !agent.device.bound ) } // 排序 filtered.sort((a, b) => { let aVal = a[sortBy.value] let bVal = b[sortBy.value] // 处理日期排序 if (sortBy.value === 'created_at' || sortBy.value === 'updatedAt') { aVal = new Date(aVal) bVal = new Date(bVal) } if (sortOrder.value === 'asc') { return aVal < bVal ? -1 : aVal > bVal ? 1 : 0 } else { return aVal > bVal ? -1 : aVal < bVal ? 1 : 0 } }) return filtered }) // 已绑定的智能体数量 const boundAgentsCount = computed(() => { return agents.value.filter(agent => agent.device.bound).length }) // 活跃智能体数量 const activeAgentsCount = computed(() => { return agents.value.filter(agent => agent.status === AGENT_STATUS.ACTIVE).length }) // 缓存是否有效 const isCacheValid = computed(() => { if (!lastFetchTime.value) return false return Date.now() - lastFetchTime.value < cacheExpiry.value }) // 当前页的智能体(考虑分页) const paginatedAgents = computed(() => { const startIndex = (pagination.value.page - 1) * pagination.value.pageSize const endIndex = startIndex + pagination.value.pageSize return filteredAgents.value.slice(startIndex, endIndex) }) // ==================== 基础方法 ==================== /** * 获取智能体列表 * @param {Object} options - 查询选项 */ const fetchAgents = async (options = {}) => { // 检查缓存 if (isCacheValid.value && agents.value.length > 0 && !options.forceRefresh) { return agents.value } loading.value = true error.value = null try { const queryOptions = { page: pagination.value.page, pageSize: pagination.value.pageSize, search: searchQuery.value, status: statusFilter.value, deviceBound: deviceBoundFilter.value, ...options } const result = await getAgents(queryOptions) agents.value = result.agents pagination.value = result.pagination lastFetchTime.value = Date.now() return result.agents } catch (err) { error.value = err.message || '获取智能体列表失败' console.error('Failed to fetch agents:', err) return [] } finally { loading.value = false } } /** * 获取单个智能体详情 * @param {string} id - 智能体ID */ const fetchAgentById = async (id) => { if (!id) return null loading.value = true error.value = null try { const agent = await getAgentById(id) // 更新列表中的智能体(如果存在) const index = agents.value.findIndex(a => a.id === id) if (index !== -1) { agents.value[index] = agent } else { agents.value.push(agent) } currentAgent.value = agent return agent } catch (err) { error.value = err.message || '获取智能体详情失败' console.error('Failed to fetch agent by id:', err) return null } finally { loading.value = false } } /** * 创建智能体 * @param {Object} agentData - 智能体数据 */ const createNewAgent = async (agentData) => { loading.value = true error.value = null try { const newAgent = await createAgent(agentData) // 添加到列表开头 agents.value.unshift(newAgent) pagination.value.total += 1 pagination.value.totalPages = Math.ceil(pagination.value.total / pagination.value.pageSize) // 清除缓存 clearCache() return newAgent } catch (err) { error.value = err.message || '创建智能体失败' console.error('Failed to create agent:', err) throw err } finally { loading.value = false } } /** * 更新智能体 * @param {string} id - 智能体ID * @param {Object} updateData - 更新数据 */ const updateAgentById = async (id, updateData) => { loading.value = true error.value = null try { const updatedAgent = await updateAgent(id, updateData) // 更新列表中的智能体 const index = agents.value.findIndex(a => a.id === id) if (index !== -1) { agents.value[index] = updatedAgent } // 更新当前选中的智能体 if (currentAgent.value && currentAgent.value.id === id) { currentAgent.value = updatedAgent } // 清除缓存 clearCache() return updatedAgent } catch (err) { error.value = err.message || '更新智能体失败' console.error('Failed to update agent:', err) throw err } finally { loading.value = false } } /** * 删除智能体 * @param {string} id - 智能体ID */ const deleteAgentById = async (id) => { loading.value = true error.value = null try { await deleteAgent(id) // 从列表中移除 const index = agents.value.findIndex(a => a.id === id) if (index !== -1) { agents.value.splice(index, 1) pagination.value.total -= 1 pagination.value.totalPages = Math.ceil(pagination.value.total / pagination.value.pageSize) } // 清除当前选中的智能体 if (currentAgent.value && currentAgent.value.id === id) { currentAgent.value = null } // 清除缓存 clearCache() return true } catch (err) { error.value = err.message || '删除智能体失败' console.error('Failed to delete agent:', err) throw err } finally { loading.value = false } } // ==================== 设备绑定相关方法 ==================== /** * 绑定设备 * @param {string} id - 智能体ID * @param {Object} deviceInfo - 设备信息 */ const bindAgentDevice = async (id, deviceInfo) => { const bindingState = bindingStates.value.get(id) || { loading: false, error: null, verifying: false } bindingStates.value.set(id, { ...bindingState, loading: true, error: null }) try { const result = await bindDevice(id, deviceInfo) // 更新智能体设备状态 const agent = agents.value.find(a => a.id === id) if (agent) { agent.device = result.device agent.updatedAt = new Date().toISOString() } if (currentAgent.value && currentAgent.value.id === id) { currentAgent.value.device = result.device currentAgent.value.updatedAt = new Date().toISOString() } return result } catch (err) { const errorMsg = err.message || '设备绑定失败' bindingStates.value.set(id, { ...bindingState, loading: false, error: errorMsg }) console.error('Failed to bind device:', err) throw err } finally { bindingStates.value.set(id, { ...bindingStates.value.get(id), loading: false }) } } /** * 解绑设备 * @param {string} id - 智能体ID */ const unbindAgentDevice = async (id) => { const bindingState = bindingStates.value.get(id) || { loading: false, error: null, verifying: false } bindingStates.value.set(id, { ...bindingState, loading: true, error: null }) try { const result = await unbindDevice(id) // 更新智能体设备状态 const agent = agents.value.find(a => a.id === id) if (agent) { agent.device = { bound: false } agent.updatedAt = new Date().toISOString() } if (currentAgent.value && currentAgent.value.id === id) { currentAgent.value.device = { bound: false } currentAgent.value.updatedAt = new Date().toISOString() } return result } catch (err) { const errorMsg = err.message || '设备解绑失败' bindingStates.value.set(id, { ...bindingState, loading: false, error: errorMsg }) console.error('Failed to unbind device:', err) throw err } finally { bindingStates.value.set(id, { ...bindingStates.value.get(id), loading: false }) } } /** * 验证设备绑定 * @param {string} id - 智能体ID * @param {string} verificationCode - 验证码 */ const verifyAgentBinding = async (id, verificationCode) => { const bindingState = bindingStates.value.get(id) || { loading: false, error: null, verifying: false } bindingStates.value.set(id, { ...bindingState, verifying: true, error: null }) try { const result = await verifyBinding(id, verificationCode) return result } catch (err) { const errorMsg = err.message || '验证失败' bindingStates.value.set(id, { ...bindingState, verifying: false, error: errorMsg }) console.error('Failed to verify binding:', err) throw err } finally { bindingStates.value.set(id, { ...bindingStates.value.get(id), verifying: false }) } } // ==================== 过滤和搜索方法 ==================== /** * 设置搜索查询 * @param {string} query - 搜索关键词 */ const setSearchQuery = (query) => { searchQuery.value = query pagination.value.page = 1 // 重置到第一页 } /** * 设置状态过滤 * @param {string} status - 状态筛选 */ const setStatusFilter = (status) => { statusFilter.value = status pagination.value.page = 1 // 重置到第一页 } /** * 设置设备绑定过滤 * @param {boolean} deviceBound - 设备绑定筛选 */ const setDeviceBoundFilter = (deviceBound) => { deviceBoundFilter.value = deviceBound pagination.value.page = 1 // 重置到第一页 } /** * 设置排序 * @param {string} sortBy - 排序字段 * @param {string} order - 排序方向 */ const setSorting = (sortByField, order = 'desc') => { sortBy.value = sortByField sortOrder.value = order } /** * 设置分页 * @param {number} page - 页码 * @param {number} pageSize - 每页数量 */ const setPagination = (page, pageSize) => { pagination.value.page = page pagination.value.pageSize = pageSize } /** * 清除所有过滤条件 */ const clearFilters = () => { searchQuery.value = '' statusFilter.value = '' deviceBoundFilter.value = null sortBy.value = 'updatedAt' sortOrder.value = 'desc' pagination.value.page = 1 } // ==================== 工具方法 ==================== /** * 获取设备绑定状态 * @param {string} agentId - 智能体ID */ const getBindingState = (agentId) => { return bindingStates.value.get(agentId) || { loading: false, error: null, verifying: false } } /** * 清除错误状态 */ const clearError = () => { error.value = null } /** * 清除设备绑定错误 * @param {string} agentId - 智能体ID */ const clearBindingError = (agentId) => { const state = bindingStates.value.get(agentId) if (state) { bindingStates.value.set(agentId, { ...state, error: null }) } } /** * 清除缓存 */ const clearCache = async () => { try { await clearAgentCache() lastFetchTime.value = null console.log('Agent store cache cleared') } catch (err) { console.error('Failed to clear cache:', err) } } /** * 刷新数据 */ const refresh = async () => { await fetchAgents({ forceRefresh: true }) } /** * 重置状态 */ const reset = () => { agents.value = [] currentAgent.value = null loading.value = false error.value = null searchQuery.value = '' statusFilter.value = '' deviceBoundFilter.value = null sortBy.value = 'updatedAt' sortOrder.value = 'desc' pagination.value = { page: 1, pageSize: 12, total: 0, totalPages: 0, hasNext: false, hasPrev: false } bindingStates.value.clear() lastFetchTime.value = null } return { // 状态 agents, currentAgent, loading, error, searchQuery, statusFilter, deviceBoundFilter, sortBy, sortOrder, pagination, bindingStates, lastFetchTime, cacheExpiry, // 计算属性 filteredAgents, boundAgentsCount, activeAgentsCount, isCacheValid, paginatedAgents, // 基础方法 fetchAgents, fetchAgentById, createNewAgent, updateAgentById, deleteAgentById, // 设备绑定方法 bindAgentDevice, unbindAgentDevice, verifyAgentBinding, // 过滤和搜索方法 setSearchQuery, setStatusFilter, setDeviceBoundFilter, setSorting, setPagination, clearFilters, // 工具方法 getBindingState, clearError, clearBindingError, clearCache, refresh, reset } }, { persist: { key: 'agents', storage: localStorage, paths: ['searchQuery', 'statusFilter', 'deviceBoundFilter', 'sortBy', 'sortOrder', 'pagination.page', 'pagination.pageSize'] } })