From c86e882ab062d7e6a43528052ec46d5852fc7fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E6=9D=B0?= Date: Fri, 22 Aug 2025 14:51:09 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=83=85=E7=BB=AA=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E5=AF=B9=E8=AF=9D=E9=87=8D=E5=A4=8D=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/store/emotion.ts | 66 ++++++++++++++++++++++++++---------- src/views/AiEmotion.vue | 89 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 115 insertions(+), 40 deletions(-) diff --git a/src/store/emotion.ts b/src/store/emotion.ts index 1e4bbaf..7cf7874 100644 --- a/src/store/emotion.ts +++ b/src/store/emotion.ts @@ -38,18 +38,41 @@ export const useEmotionStore = defineStore('emotion', { }, // 添加新股票 addStock(stockData: StockData) { + // 验证必要字段 + if (!stockData.stockInfo?.code || !stockData.stockInfo?.market || !stockData.timestamp) { + console.error('股票数据不完整,无法添加:', stockData); + return false; + } + + // 生成唯一标识 + const uniqueId = this.generateStockUniqueId(stockData); + + // 检查是否已存在相同的股票 + const existingStock = this.stockList.find(stock => { + const existingId = this.generateStockUniqueId(stock); + return existingId === uniqueId; + }); + + if (existingStock) { + console.log('股票已存在,切换到现有股票:', stockData.stockInfo.name); + // 找到现有股票的索引并切换 + const existingIndex = this.stockList.indexOf(existingStock); + this.switchStock(existingIndex); + return false; // 返回false表示没有添加新股票 + } + + // 添加唯一标识到股票数据中 + const stockWithId = { + ...stockData, + uniqueId: uniqueId + }; + // 添加新股票并设为当前激活 - this.stockList.push(stockData); + this.stockList.push(stockWithId); this.activeStockIndex = this.stockList.length - 1; - - // 同时添加到历史记录 - // this.addHistory({ - // queryText: stockData.queryText, - // stockInfo: stockData.stockInfo, - // apiData: stockData.apiData, - // conclusionData: stockData.conclusionData, - // timestamp: stockData.timestamp - // }); + + console.log('成功添加新股票:', stockData.stockInfo.name, 'ID:', uniqueId); + return true; // 返回true表示成功添加新股票 }, // 切换股票 switchStock(index: number) { @@ -141,6 +164,14 @@ export const useEmotionStore = defineStore('emotion', { }; } }, + // 生成股票唯一标识 + generateStockUniqueId(stockData: StockData): string { + if (!stockData.stockInfo?.code || !stockData.stockInfo?.market) { + throw new Error('股票代码和市场信息不能为空'); + } + // 使用 code + market + timestamp 确保唯一性 + return `${stockData.stockInfo.code}_${stockData.stockInfo.market}_${stockData.timestamp}`; + } }, }); @@ -159,15 +190,16 @@ interface HistoryItem { // 定义股票数据的类型 interface StockData { - queryText: string; // 用户输入的查询文本 + queryText: string; stockInfo: { - name: string; // 股票名称 - code: string; // 股票代码 - market: string; // 市场 + name: string; + code: string; + market: string; }; - apiData: any; // API返回的完整数据 - conclusionData?: string; // 第二个工作流接口返回的结论数据 - timestamp: string; // 数据获取时间 + apiData: any; + conclusionData?: string; + timestamp: string; + uniqueId?: string; // 添加唯一标识字段 } // 定义对话消息的类型 diff --git a/src/views/AiEmotion.vue b/src/views/AiEmotion.vue index 7918c12..fd9af0b 100644 --- a/src/views/AiEmotion.vue +++ b/src/views/AiEmotion.vue @@ -538,35 +538,39 @@ const loadConversationsFromStockList = () => { // 检查是否有新的股票需要添加到对话中 emotionStore.stockList.forEach((stock) => { - const stockKey = `${stock.stockInfo.code}_${stock.timestamp}`; + // 验证股票数据完整性 + if (!stock?.stockInfo?.code || !stock?.timestamp || !stock?.queryText) { + console.warn('股票数据不完整,跳过添加:', stock); + return; + } + + // 使用统一的唯一标识生成方法 + const stockKey = getStockUniqueId(stock); + if (!stockKey) { + console.warn('无法生成股票唯一标识,跳过添加:', stock); + return; + } - // 如果这个股票还没有添加到对话中 + // 多重检查避免重复添加 if (!addedStocks.value.has(stockKey)) { - // 检查messages中是否已经存在相同的用户消息 - const existingMessage = messages.value.find( + const existingInMessages = messages.value.find( (msg) => msg.sender === "user" && msg.text === stock.queryText ); + + const storeConversations = emotionStore.getConversations(); + const existingInStore = storeConversations.find( + (conv) => conv.sender === "user" && conv.text === stock.queryText + ); - // 只有当messages中不存在相同消息时才添加 - if (!existingMessage) { - // 只添加用户输入消息,不添加AI回复 + if (!existingInMessages && !existingInStore) { const userMessage = { sender: "user", text: stock.queryText, }; messages.value.push(userMessage); - - // 只将用户消息添加到emotion store中(如果store中也不存在) - const storeConversations = emotionStore.getConversations(); - const existingInStore = storeConversations.find( - (conv) => conv.sender === "user" && conv.text === stock.queryText - ); - if (!existingInStore) { - emotionStore.addConversation(userMessage); - } + emotionStore.addConversation(userMessage); } - // 将这个股票标记为已添加 addedStocks.value.add(stockKey); } }); @@ -584,6 +588,13 @@ const clearConversations = () => { const addStock = (stockData) => { console.log("AiEmotion组件接收到股票数据:", stockData); + // 验证股票数据完整性 + if (!stockData || !stockData.stockInfo || !stockData.stockInfo.code) { + console.error('addStock: 股票数据不完整', stockData); + emit('enableInput'); + return; + } + // 设置为历史记录模式,并重置用户主动搜索标志 isHistoryMode.value = true; isUserInitiated.value = false; @@ -694,6 +705,12 @@ const stockAudioStates = ref(new Map()); // 生成股票唯一标识符的辅助函数 const getStockUniqueId = (stock) => { + // 验证输入参数 + if (!stock || typeof stock !== 'object') { + console.warn('getStockUniqueId: 无效的股票对象'); + return null; + } + // 优先使用预设的uniqueId if (stock.uniqueId) { return stock.uniqueId; @@ -702,7 +719,13 @@ const getStockUniqueId = (stock) => { // 兼容旧的生成方式 const stockCode = stock.stockInfo?.code || stock.stockInfo?.symbol; const timestamp = stock.timestamp; - return stockCode && timestamp ? `${stockCode}_${timestamp}` : null; + + if (!stockCode || !timestamp) { + console.warn('getStockUniqueId: 缺少必要字段', { stockCode, timestamp }); + return null; + } + + return `${stockCode}_${timestamp}`; }; // 存储当前的完成回调函数 const currentOnCompleteCallback = ref(null); @@ -714,7 +737,10 @@ const isAudioPlaying = ref(false); // 获取股票的音频播放状态 const getStockAudioState = (stock) => { const stockUniqueId = getStockUniqueId(stock); - if (!stockUniqueId) return { isPlaying: false, isPaused: false }; + if (!stockUniqueId) { + console.warn('getStockAudioState: 无法获取股票唯一标识'); + return { isPlaying: false, isPaused: false }; + } return ( stockAudioStates.value.get(stockUniqueId) || { @@ -727,7 +753,15 @@ const getStockAudioState = (stock) => { // 设置股票的音频播放状态 const setStockAudioState = (stock, state) => { const stockUniqueId = getStockUniqueId(stock); - if (!stockUniqueId) return; + if (!stockUniqueId) { + console.warn('setStockAudioState: 无法获取股票唯一标识'); + return; + } + + if (!state || typeof state !== 'object') { + console.warn('setStockAudioState: 无效的状态对象'); + return; + } stockAudioStates.value.set(stockUniqueId, { ...state }); }; @@ -876,21 +910,30 @@ const getStockConclusion = (stock) => { // 辅助函数:获取股票的打字机文本状态 const getStockTypewriterTexts = (stock) => { const stockUniqueId = getStockUniqueId(stock); - if (!stockUniqueId) return null; + if (!stockUniqueId) { + console.warn('getStockTypewriterTexts: 无法获取股票唯一标识'); + return null; + } return stockTypewriterTexts.value.get(stockUniqueId) || null; }; // 辅助函数:获取股票的打字机可见性状态 const getStockTypewriterVisibility = (stock) => { const stockUniqueId = getStockUniqueId(stock); - if (!stockUniqueId) return null; + if (!stockUniqueId) { + console.warn('getStockTypewriterVisibility: 无法获取股票唯一标识'); + return null; + } return stockTypewriterVisibility.value.get(stockUniqueId) || null; }; // 辅助函数:检查股票是否正在进行打字机效果 const isStockTypewriting = (stock) => { const stockUniqueId = getStockUniqueId(stock); - if (!stockUniqueId) return false; + if (!stockUniqueId) { + console.warn('isStockTypewriting: 无法获取股票唯一标识'); + return false; + } return stockTypewriterShown.value.has(stockUniqueId) && !stockTypewriterTexts.value.has(stockUniqueId); };