diff --git a/src/views/AiEmotion.vue b/src/views/AiEmotion.vue index 38f8194..0853e11 100644 --- a/src/views/AiEmotion.vue +++ b/src/views/AiEmotion.vue @@ -624,11 +624,10 @@ const addStock = (stockData) => { // 4. 标记历史记录股票已显示过,避免重复触发 if (stockData.conclusionData) { - const stockCode = - stockData.stockInfo?.code || stockData.stockInfo?.symbol; - if (stockCode) { - stockTypewriterShown.value.set(stockCode, true); - stockAudioPlayed.value.set(stockCode, true); + const stockUniqueId = getStockUniqueId(stockData); + if (stockUniqueId) { + stockTypewriterShown.value.set(stockUniqueId, true); + stockAudioPlayed.value.set(stockUniqueId, true); } console.log("历史记录股票已标记为已显示"); } @@ -688,6 +687,13 @@ const stockTypewriterVisibility = ref(new Map()); const stockAudioPlayed = ref(new Map()); // 跟踪每个股票的音频播放状态 const stockAudioStates = ref(new Map()); + +// 生成股票唯一标识符的辅助函数 +const getStockUniqueId = (stock) => { + const stockCode = stock.stockInfo?.code || stock.stockInfo?.symbol; + const timestamp = stock.timestamp; + return stockCode && timestamp ? `${stockCode}_${timestamp}` : stockCode; +}; // 存储当前的完成回调函数 const currentOnCompleteCallback = ref(null); @@ -697,11 +703,11 @@ const isAudioPlaying = ref(false); // 获取股票的音频播放状态 const getStockAudioState = (stock) => { - const stockCode = stock.stockInfo?.code || stock.stockInfo?.symbol; - if (!stockCode) return { isPlaying: false, isPaused: false }; + const stockUniqueId = getStockUniqueId(stock); + if (!stockUniqueId) return { isPlaying: false, isPaused: false }; return ( - stockAudioStates.value.get(stockCode) || { + stockAudioStates.value.get(stockUniqueId) || { isPlaying: false, isPaused: false, } @@ -710,10 +716,10 @@ const getStockAudioState = (stock) => { // 设置股票的音频播放状态 const setStockAudioState = (stock, state) => { - const stockCode = stock.stockInfo?.code || stock.stockInfo?.symbol; - if (!stockCode) return; + const stockUniqueId = getStockUniqueId(stock); + if (!stockUniqueId) return; - stockAudioStates.value.set(stockCode, { ...state }); + stockAudioStates.value.set(stockUniqueId, { ...state }); }; // 清除所有股票的播放状态(当开始播放新音频时) @@ -735,6 +741,10 @@ const stockCode = computed( currentStock.value?.stockInfo.symbol || "" ); +const currentStockUniqueId = computed(() => { + if (!currentStock.value) return ""; + return getStockUniqueId(currentStock.value); +}); const displayDate = computed(() => { if (!currentStock.value?.apiData) return ""; const lastData = currentStock.value.apiData.GSWDJ?.at(-1); @@ -855,23 +865,23 @@ const getStockConclusion = (stock) => { // 辅助函数:获取股票的打字机文本状态 const getStockTypewriterTexts = (stock) => { - const stockCode = stock.stockInfo?.code || stock.stockInfo?.symbol; - if (!stockCode) return null; - return stockTypewriterTexts.value.get(stockCode) || null; + const stockUniqueId = getStockUniqueId(stock); + if (!stockUniqueId) return null; + return stockTypewriterTexts.value.get(stockUniqueId) || null; }; // 辅助函数:获取股票的打字机可见性状态 const getStockTypewriterVisibility = (stock) => { - const stockCode = stock.stockInfo?.code || stock.stockInfo?.symbol; - if (!stockCode) return null; - return stockTypewriterVisibility.value.get(stockCode) || null; + const stockUniqueId = getStockUniqueId(stock); + if (!stockUniqueId) return null; + return stockTypewriterVisibility.value.get(stockUniqueId) || null; }; // 辅助函数:检查股票是否正在进行打字机效果 const isStockTypewriting = (stock) => { - const stockCode = stock.stockInfo?.code || stock.stockInfo?.symbol; - if (!stockCode) return false; - return stockTypewriterShown.value.has(stockCode) && !stockTypewriterTexts.value.has(stockCode); + const stockUniqueId = getStockUniqueId(stock); + if (!stockUniqueId) return false; + return stockTypewriterShown.value.has(stockUniqueId) && !stockTypewriterTexts.value.has(stockUniqueId); }; // 监听股票列表变化,当列表为空时隐藏页面数据 @@ -929,8 +939,8 @@ watch( hasTriggeredAudio.value = false; hasTriggeredTypewriter.value = false; - // 获取股票代码作为唯一标识 - const stockCode = newStock.stockInfo?.code || newStock.stockInfo?.symbol; + // 获取股票唯一标识 + const stockUniqueId = getStockUniqueId(newStock); // 处理当前股票的音频URL if (newStock.conclusionData) { @@ -942,7 +952,7 @@ watch( : JSON.parse(newStock.conclusionData); // 检查该股票是否已经显示过打字机效果 - if (stockCode && stockTypewriterShown.value.has(stockCode)) { + if (stockUniqueId && stockTypewriterShown.value.has(stockUniqueId)) { // 如果已经显示过,直接显示完整内容,不需要打字机效果 // 提取音频URL但不自动播放,等待用户手动点击 @@ -1037,11 +1047,8 @@ watch( } if (parsedConclusion.value) { - const stockCode = - newStock.stockInfo?.code || newStock.stockInfo?.symbol; - // 如果该股票已经显示过,不需要再处理 - if (stockCode && stockTypewriterShown.value.has(stockCode)) { + if (stockUniqueId && stockTypewriterShown.value.has(stockUniqueId)) { return; } @@ -1052,9 +1059,9 @@ watch( if (isInViewport) { console.log("股票切换后检测到场景应用部分在视口中"); - if (stockCode) { + if (stockUniqueId) { // 检查该股票是否是第一次触发 - if (!stockTypewriterShown.value.has(stockCode)) { + if (!stockTypewriterShown.value.has(stockUniqueId)) { // 如果是用户主动搜索,启动打字机效果和音频播放 if (isUserInitiated.value && audioUrl.value) { console.log( @@ -1063,16 +1070,16 @@ watch( hasTriggeredTypewriter.value = true; hasTriggeredAudio.value = true; - if (!stockAudioPlayed.value.has(stockCode)) { + if (!stockAudioPlayed.value.has(stockUniqueId)) { console.log("开始音频播放和打字机效果"); - stockAudioPlayed.value.set(stockCode, true); + stockAudioPlayed.value.set(stockUniqueId, true); playAudioQueue(parsedConclusion.value, true); } else { // 如果音频已播放过,只启动打字机效果 - startTypewriterEffect(parsedConclusion.value, stockCode); + startTypewriterEffect(parsedConclusion.value, stockUniqueId); } - stockTypewriterShown.value.set(stockCode, true); + stockTypewriterShown.value.set(stockUniqueId, true); } else if (isUserInitiated.value && !audioUrl.value) { console.log( "音频尚未准备好,等待音频加载完成后再触发效果(股票切换后)" @@ -1087,8 +1094,8 @@ watch( const conclusion = parsedConclusion.value; // 结论内容现在直接通过parsedConclusion计算属性显示 - stockTypewriterShown.value.set(stockCode, true); - stockAudioPlayed.value.set(stockCode, true); + stockTypewriterShown.value.set(stockUniqueId, true); + stockAudioPlayed.value.set(stockUniqueId, true); } } else { // 非第一次或已经触发过:直接显示完整内容,不播放音频和打字机效果 @@ -1218,10 +1225,9 @@ watch( // 打字机效果函数 function startTypewriterEffect(conclusion, stockId, onComplete) { - // 如果没有传入stockId,使用当前活跃股票 + // 如果没有传入stockId,使用当前活跃股票的唯一标识符 if (!stockId && emotionStore.activeStock) { - const stock = emotionStore.activeStock; - stockId = stock.stockInfo?.code || stock.stockInfo?.symbol; + stockId = getStockUniqueId(emotionStore.activeStock); } if (!stockId) { @@ -1501,7 +1507,7 @@ const playNextAudio = () => { parsedConclusion.value ) { console.log("🎬 第一个音频开始播放,同时启动打字机效果"); - const stockId = currentStock?.stockInfo?.code || currentStock?.stockInfo?.symbol; + const stockId = currentStock ? getStockUniqueId(currentStock) : null; startTypewriterEffect(parsedConclusion.value, stockId, audioInfo.onComplete); } }, @@ -1766,7 +1772,7 @@ function playAudioQueue( if (shouldStartTypewriter) { console.log("没有音频但需要启动打字机效果"); const currentStock = emotionStore.activeStock; - const stockId = currentStock?.stockInfo?.code || currentStock?.stockInfo?.symbol; + const stockId = currentStock ? getStockUniqueId(currentStock) : null; startTypewriterEffect(conclusion, stockId, onComplete); } } else { @@ -2229,19 +2235,16 @@ async function handleSendMessage(input, onComplete) { parsedConclusion.value && audioUrl.value ) { - const stockCode = - currentStock.value.stockInfo?.code || - currentStock.value.stockInfo?.symbol; - if (stockCode && !stockTypewriterShown.value.has(stockCode)) { - if (!stockAudioPlayed.value.has(stockCode)) { - stockAudioPlayed.value.set(stockCode, true); + const stockUniqueId = getStockUniqueId(currentStock.value); + if (stockUniqueId && !stockTypewriterShown.value.has(stockUniqueId)) { + if (!stockAudioPlayed.value.has(stockUniqueId)) { + stockAudioPlayed.value.set(stockUniqueId, true); playAudioQueue(parsedConclusion.value, true, onComplete); } else { // 如果音频已播放过,只启动打字机效果 - const stockCode = currentStock.value?.stockInfo?.code || currentStock.value?.stockInfo?.symbol; - startTypewriterEffect(parsedConclusion.value, stockCode, onComplete); + startTypewriterEffect(parsedConclusion.value, stockUniqueId, onComplete); } - stockTypewriterShown.value.set(stockCode, true); + stockTypewriterShown.value.set(stockUniqueId, true); } else { // 如果不需要打字机效果,直接调用完成回调 if (onComplete && typeof onComplete === "function") { @@ -2899,14 +2902,12 @@ function setupIntersectionObserver() { if (entry.isIntersecting) { console.log("场景应用部分进入视口"); - // 获取当前股票代码 - const stockCode = - currentStock.value?.stockInfo?.code || - currentStock.value?.stockInfo?.symbol; + // 获取当前股票唯一标识 + const stockUniqueId = currentStock.value ? getStockUniqueId(currentStock.value) : null; - if (parsedConclusion.value && stockCode) { + if (parsedConclusion.value && stockUniqueId) { // 检查该股票是否是第一次触发 - if (!stockTypewriterShown.value.has(stockCode)) { + if (!stockTypewriterShown.value.has(stockUniqueId)) { // 如果是用户主动搜索,启动打字机效果和音频播放 if (isUserInitiated.value && audioUrl.value) { console.log( @@ -2915,10 +2916,10 @@ function setupIntersectionObserver() { // 用户主动搜索时,每次都播放音频和打字机效果 console.log("开始音频播放和打字机效果"); - stockAudioPlayed.value.set(stockCode, true); + stockAudioPlayed.value.set(stockUniqueId, true); playAudioQueue(parsedConclusion.value, true); - stockTypewriterShown.value.set(stockCode, true); + stockTypewriterShown.value.set(stockUniqueId, true); } else { // 非用户主动搜索(如历史记录恢复),直接显示完整内容 console.log( @@ -2928,8 +2929,8 @@ function setupIntersectionObserver() { // 结论内容现在直接通过parsedConclusion计算属性显示 // 记录该股票已显示过 - stockTypewriterShown.value.set(stockCode, true); - stockAudioPlayed.value.set(stockCode, true); + stockTypewriterShown.value.set(stockUniqueId, true); + stockAudioPlayed.value.set(stockUniqueId, true); } } else { // 非第一次或已经触发过:直接显示完整内容,不播放音频和打字机效果 @@ -3257,12 +3258,10 @@ onMounted(async () => { conclusionData.value = currentStockData.conclusionData; // 标记该股票的打字机效果和音频已经显示过,避免后续自动触发 - const stockCode = - currentStockData.stockInfo?.code || - currentStockData.stockInfo?.symbol; - if (stockCode) { - stockTypewriterShown.value.set(stockCode, true); - stockAudioPlayed.value.set(stockCode, true); + const stockUniqueId = getStockUniqueId(currentStockData); + if (stockUniqueId) { + stockTypewriterShown.value.set(stockUniqueId, true); + stockAudioPlayed.value.set(stockUniqueId, true); } } }