|
|
@ -183,11 +183,43 @@ import blueBorderImg from '@/assets/img/AiEmotion/blueBorder.png' //导入蓝色 |
|
|
|
import { ElMessage } from 'element-plus'; |
|
|
|
import { useEmotionStore } from '@/store/emotion'; // 导入Pinia store |
|
|
|
import { useAudioStore } from '@/store/audio.js'; // 导入音频store |
|
|
|
import { useChatStore } from '@/store/chat.js'; // 导入聊天store |
|
|
|
import { Howl, Howler } from 'howler'; // 导入音频播放库 |
|
|
|
import { reactive } from 'vue'; |
|
|
|
import { marked } from 'marked'; // 引入marked库 |
|
|
|
// 使用Pinia store |
|
|
|
const emotionStore = useEmotionStore(); |
|
|
|
const audioStore = useAudioStore(); |
|
|
|
const chatStore = useChatStore(); |
|
|
|
|
|
|
|
// 处理refuse数据的函数 |
|
|
|
function processRefuseMessage(refuseData) { |
|
|
|
if (!refuseData) return '未知错误'; |
|
|
|
|
|
|
|
// 如果refuse数据包含Markdown格式,进行转换 |
|
|
|
try { |
|
|
|
// 配置marked选项 |
|
|
|
marked.setOptions({ |
|
|
|
breaks: true, // 支持换行符转换为 <br> |
|
|
|
gfm: true, // 启用 GitHub Flavored Markdown |
|
|
|
sanitize: false, // 不清理 HTML |
|
|
|
smartLists: true, // 智能列表 |
|
|
|
smartypants: true, // 智能标点符号 |
|
|
|
xhtml: false, // 不使用 XHTML 输出 |
|
|
|
}); |
|
|
|
|
|
|
|
// 将Markdown转换为HTML |
|
|
|
const htmlContent = marked(refuseData); |
|
|
|
|
|
|
|
// 移除HTML标签,只保留纯文本用于ElMessage显示 |
|
|
|
const tempDiv = document.createElement('div'); |
|
|
|
tempDiv.innerHTML = htmlContent; |
|
|
|
return tempDiv.textContent || tempDiv.innerText || refuseData; |
|
|
|
} catch (error) { |
|
|
|
console.error('处理refuse消息时出错:', error); |
|
|
|
return refuseData; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 组件引用 |
|
|
|
const marketTemperatureRef = ref(null); // 引用市场温度计组件 |
|
|
@ -357,7 +389,7 @@ watch(currentStock, (newStock) => { |
|
|
|
|
|
|
|
nextTick(() => { |
|
|
|
renderCharts(newStock.apiData); |
|
|
|
console.log('0000000000000000000000000',newStock.apiData) |
|
|
|
console.log('0000000000000000000000000', newStock.apiData) |
|
|
|
// 检查场景应用部分是否已经在视口中,如果是则立即触发效果 |
|
|
|
setTimeout(() => { |
|
|
|
if (scenarioApplicationRef.value && parsedConclusion.value) { |
|
|
@ -663,8 +695,11 @@ function playAudio(url) { |
|
|
|
console.log('开始创建音频实例...'); |
|
|
|
|
|
|
|
try { |
|
|
|
// 设置当前音频URL |
|
|
|
audioStore.setCurrentAudioUrl(url); |
|
|
|
|
|
|
|
// 停止之前的音频 |
|
|
|
if (audioStore.nowSound) { |
|
|
|
if (audioStore.nowSound && audioStore.nowSound.playing()) { |
|
|
|
audioStore.nowSound.stop(); |
|
|
|
} |
|
|
|
|
|
|
@ -675,19 +710,35 @@ function playAudio(url) { |
|
|
|
format: ['mp3', 'wav'], |
|
|
|
onplay: () => { |
|
|
|
isAudioPlaying.value = true; |
|
|
|
audioStore.isPlaying = true; |
|
|
|
console.log('开始播放场景应用语音'); |
|
|
|
}, |
|
|
|
onend: () => { |
|
|
|
isAudioPlaying.value = false; |
|
|
|
audioStore.isPlaying = false; |
|
|
|
audioStore.isPaused = false; |
|
|
|
audioStore.playbackPosition = 0; |
|
|
|
console.log('场景应用语音播放结束'); |
|
|
|
}, |
|
|
|
onstop: () => { |
|
|
|
isAudioPlaying.value = false; |
|
|
|
audioStore.isPlaying = false; |
|
|
|
console.log('场景应用语音播放停止'); |
|
|
|
}, |
|
|
|
onpause: () => { |
|
|
|
isAudioPlaying.value = false; |
|
|
|
audioStore.isPlaying = false; |
|
|
|
console.log('场景应用语音播放暂停'); |
|
|
|
}, |
|
|
|
onerror: (error) => { |
|
|
|
isAudioPlaying.value = false; |
|
|
|
audioStore.isPlaying = false; |
|
|
|
console.error('音频播放错误:', error); |
|
|
|
}, |
|
|
|
onload: () => { |
|
|
|
// 音频加载完成,获取时长 |
|
|
|
audioStore.duration = newSound.duration(); |
|
|
|
console.log('音频加载完成,时长:', audioStore.duration); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
@ -726,14 +777,18 @@ async function handleSendMessage(input) { |
|
|
|
console.log("发送内容:", input); |
|
|
|
|
|
|
|
// 检查用户输入内容是否为空 |
|
|
|
if (!input || !input.trim()) { |
|
|
|
ElMessage.warning("输入内容不能为空"); |
|
|
|
return; |
|
|
|
} |
|
|
|
// 触发图片旋转 |
|
|
|
isRotating.value = true; |
|
|
|
// 设置加载状态,隐藏图表页面 |
|
|
|
isLoading.value = true; |
|
|
|
|
|
|
|
if (input.trim()) { |
|
|
|
const userMessage = reactive({ sender: 'user', text: input }); |
|
|
|
messages.value.push(userMessage); |
|
|
|
// 设置加载状态,隐藏图表页面 |
|
|
|
isLoading.value = true; |
|
|
|
isPageLoaded.value = false; |
|
|
|
// 触发图片旋转 |
|
|
|
isRotating.value = true; |
|
|
|
|
|
|
|
try { |
|
|
|
// 用来调用工作流接口的参数 |
|
|
@ -750,20 +805,21 @@ async function handleSendMessage(input) { |
|
|
|
aibullPrivilegeState: "1", |
|
|
|
aigoldBullPrivilegeS: "1", |
|
|
|
airadarPrivilegeStat: "1", |
|
|
|
marketList: "hk,cn,usa,my,sg,vi,in,gb", |
|
|
|
marketList: "hk,cn,can,usa,my,sg,vi,in,gb", |
|
|
|
}, |
|
|
|
}; |
|
|
|
|
|
|
|
const result = await getReplyAPI(params); |
|
|
|
const response = await result.json(); // 解析返回的 JSON 数据 |
|
|
|
console.log("工作流接口返回数据:", response); |
|
|
|
|
|
|
|
// 解析 data 字段 |
|
|
|
const parsedData = JSON.parse(response.data); // 将字符串形式的 JSON 转换为对象 |
|
|
|
console.log("解析后的数据:", parsedData); |
|
|
|
|
|
|
|
if (parsedData && parsedData.market && parsedData.code) { |
|
|
|
console.log("工作流接口返回股票信息:", parsedData); |
|
|
|
|
|
|
|
isPageLoaded.value = false; |
|
|
|
|
|
|
|
// 调用第二个工作流接口 |
|
|
|
const conclusionParams = { |
|
|
|
content: input.trim(), |
|
|
@ -776,12 +832,6 @@ async function handleSendMessage(input) { |
|
|
|
code: parsedData.code, |
|
|
|
market: parsedData.market, |
|
|
|
}; |
|
|
|
console.log('======================================') |
|
|
|
|
|
|
|
// 取消自动滚动效果 |
|
|
|
// console.log('第二个工作流接口开始调用,立即开始缓慢滚动'); |
|
|
|
// startAutoScroll(); |
|
|
|
|
|
|
|
// 同时调用第二个数据流接口和fetchData方法 |
|
|
|
const [conclusionResult, fetchDataResult] = await Promise.all([ |
|
|
|
getConclusionAPI(conclusionParams), |
|
|
@ -797,22 +847,21 @@ async function handleSendMessage(input) { |
|
|
|
conclusionData.value = conclusionResponse.data; |
|
|
|
// 将结论数据存储到store中的当前激活股票 |
|
|
|
emotionStore.updateActiveStockConclusion(conclusionResponse.data); |
|
|
|
console.log("结论数据已存储到响应式变量和store中:", conclusionData.value); |
|
|
|
} |
|
|
|
|
|
|
|
console.log('------------------------------------') |
|
|
|
|
|
|
|
} else { |
|
|
|
ElMessage.error('工作流接口未返回非股票信息'); |
|
|
|
// 不是股票信息,显示refuse信息,但不隐藏页面数据 |
|
|
|
ElMessage.error(processRefuseMessage(parsedData.refuse)); |
|
|
|
return; // 直接返回,不进行后续处理 |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
ElMessage.error('请求工作流接口失败,请检查网络连接'); |
|
|
|
return; // 请求失败时直接返回 |
|
|
|
} finally { |
|
|
|
// 停止图片旋转 |
|
|
|
isRotating.value = false; |
|
|
|
// 停止图片旋转(只有在设置了旋转状态时才需要停止) |
|
|
|
if (isRotating.value) { |
|
|
|
isRotating.value = false; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
ElMessage.error('消息发送失败,请检查网络连接'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -857,17 +906,13 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
|
conclusionData: conclusionData.value, // 包含结论数据 |
|
|
|
timestamp: new Date().toISOString() |
|
|
|
}; |
|
|
|
|
|
|
|
// 将股票数据添加到store中 |
|
|
|
emotionStore.addStock(stockData); |
|
|
|
|
|
|
|
console.log('股票数据已添加到store'); |
|
|
|
|
|
|
|
} else { |
|
|
|
ElMessage.error('获取接口数据失败'); |
|
|
|
ElMessage.error('请求失败,请检查网络连接'); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
ElMessage.error('获取接口数据失败。。。'); |
|
|
|
ElMessage.error('请求失败,请检查网络连接'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -1115,7 +1160,15 @@ function triggerAutoScroll() { |
|
|
|
} |
|
|
|
|
|
|
|
// 页面挂载完成后触发图片旋转和设置滚动监听 |
|
|
|
onMounted(() => { |
|
|
|
onMounted(async () => { |
|
|
|
// 确保获取用户次数 |
|
|
|
try { |
|
|
|
await chatStore.getUserCount(); |
|
|
|
console.log('情绪大模型页面:用户次数获取成功'); |
|
|
|
} catch (error) { |
|
|
|
console.error('情绪大模型页面:获取用户次数失败', error); |
|
|
|
} |
|
|
|
|
|
|
|
startImageRotation(); |
|
|
|
|
|
|
|
// 等待DOM完全渲染后设置监听器 |
|
|
@ -1141,6 +1194,9 @@ onUnmounted(() => { |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 声明组件可以触发的事件 |
|
|
|
const emit = defineEmits(['updateMessage', 'sendMessage', 'ensureAIchat']); |
|
|
|
|
|
|
|
// 导出方法供外部使用 |
|
|
|
defineExpose({ |
|
|
|
handleSendMessage, |
|
|
@ -1517,21 +1573,21 @@ defineExpose({ |
|
|
|
color: white; |
|
|
|
font-size: 20px; |
|
|
|
font-weight: bold; |
|
|
|
margin-left: 44%; |
|
|
|
margin-left: 45%; |
|
|
|
} |
|
|
|
|
|
|
|
.title3 { |
|
|
|
color: white; |
|
|
|
font-size: 20px; |
|
|
|
font-weight: bold; |
|
|
|
margin-left: 43%; |
|
|
|
margin-left: 44.6%; |
|
|
|
} |
|
|
|
|
|
|
|
.title4 { |
|
|
|
color: white; |
|
|
|
font-size: 20px; |
|
|
|
font-weight: bold; |
|
|
|
margin-left: 41.5%; |
|
|
|
margin-left: 44%; |
|
|
|
} |
|
|
|
|
|
|
|
.class09 { |
|
|
@ -1580,7 +1636,7 @@ defineExpose({ |
|
|
|
/* 设置容器宽度 */ |
|
|
|
height: auto; |
|
|
|
/* 高度根据内容动态变化 */ |
|
|
|
min-height: 66rem; |
|
|
|
min-height: 69rem; |
|
|
|
/* 设置最小高度,确保图片显示 */ |
|
|
|
margin: 0 auto; |
|
|
|
} |
|
|
@ -1596,7 +1652,7 @@ defineExpose({ |
|
|
|
/* 设置容器宽度 */ |
|
|
|
height: auto; |
|
|
|
/* 高度根据内容动态变化 */ |
|
|
|
min-height: 86rem; |
|
|
|
min-height: 90rem; |
|
|
|
/* 设置最小高度,确保图片显示 */ |
|
|
|
margin: 0 auto; |
|
|
|
} |
|
|
|