@@ -271,11 +270,11 @@ function processRefuseMessage(refuseData) {
}
}
-// 组件引用
-const marketTemperatureRef = ref(null); // 引用市场温度计组件
-const emoEnergyConverterRef = ref(null)
-const emotionDecodRef = ref(null)
-const emotionalBottomRadarRef = ref(null)
+// 组件引用 - 修改为数组形式支持多个股票
+const marketTemperatureRef = ref([]); // 引用市场温度计组件数组
+const emoEnergyConverterRef = ref([])
+const emotionDecodRef = ref([])
+const emotionalBottomRadarRef = ref([])
const userInputDisplayRef = ref(null);//消息区域的引用
// 响应式数据
@@ -290,10 +289,53 @@ const loadConversationsFromStore = () => {
}));
};
+// 记录已经添加到对话中的股票,避免重复添加
+const addedStocks = ref(new Set());
+
+// 从stockList生成对话历史
+const loadConversationsFromStockList = () => {
+ // 检查是否有新的股票需要添加到对话中
+ emotionStore.stockList.forEach(stock => {
+ const stockKey = `${stock.stockInfo.code}_${stock.timestamp}`;
+
+ // 如果这个股票还没有添加到对话中
+ if (!addedStocks.value.has(stockKey)) {
+ // 检查messages中是否已经存在相同的用户消息
+ const existingMessage = messages.value.find(msg =>
+ msg.sender === 'user' && msg.text === stock.queryText
+ );
+
+ // 只有当messages中不存在相同消息时才添加
+ if (!existingMessage) {
+ // 只添加用户输入消息,不添加AI回复
+ 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);
+ }
+ }
+
+ // 将这个股票标记为已添加
+ addedStocks.value.add(stockKey);
+ }
+ });
+};
+
// 清空对话记录
const clearConversations = () => {
messages.value = [];
emotionStore.clearConversations();
+ // 清空已添加股票的记录
+ addedStocks.value.clear();
};
// 暴露清空对话记录的方法给父组件
@@ -346,10 +388,10 @@ const moduleVisibility = ref({
// 图表组件显示状态
const chartVisibility = ref({
- marketTemperature: false,
- emotionDecod: false,
- emotionalBottomRadar: false,
- emoEnergyConverter: false
+ marketTemperature: true,
+ emotionDecod: true,
+ emotionalBottomRadar: true,
+ emoEnergyConverter: true
});
const typewriterTimers = ref([]);
// 记录每个股票是否已经显示过打字机效果
@@ -410,6 +452,50 @@ const parsedConclusion = computed(() => {
}
});
+// 辅助函数:获取股票的显示日期
+const getDisplayDate = (stock) => {
+ if (!stock?.apiData) return "";
+ const lastData = stock.apiData.GSWDJ?.at(-1);
+ if (!lastData || !lastData[0]) return "";
+
+ const dateStr = lastData[0];
+ // 假设原格式为 YYYY-MM-DD 或 YYYY/MM/DD
+ const dateMatch = dateStr.match(/(\d{4})[\-\/](\d{1,2})[\-\/](\d{1,2})/);
+ if (dateMatch) {
+ const [, year, month, day] = dateMatch;
+ // 转换为 DD/MM/YYYY 格式
+ return `更新时间:${day.padStart(2, '0')}/${month.padStart(2, '0')}/${year}`;
+ }
+
+ // 如果不匹配预期格式,返回原始值
+ return dateStr;
+};
+
+// 辅助函数:获取股票的市场温度数据
+const getStockData1 = (stock) => {
+ if (!stock?.apiData) return null;
+ const lastData = stock.apiData.GSWDJ?.at(-1);
+ return lastData ? Math.round(lastData[1]) : null;
+};
+
+// 辅助函数:获取股票的股票温度数据
+const getStockData2 = (stock) => {
+ if (!stock?.apiData) return null;
+ const lastData = stock.apiData.GSWDJ?.at(-1);
+ return lastData ? Math.round(lastData[2]) : null;
+};
+
+// 辅助函数:获取股票的结论数据
+const getStockConclusion = (stock) => {
+ if (!stock?.conclusionData) return null;
+ try {
+ return JSON.parse(stock.conclusionData);
+ } catch (error) {
+ console.error('解析股票结论数据失败:', error);
+ return null;
+ }
+};
+
// 监听股票列表变化,当列表为空时隐藏页面数据
@@ -429,6 +515,8 @@ watch(() => emotionStore.stockList, (newStockList) => {
hasTriggeredTypewriter.value = false;
stockTypewriterShown.value.clear();
stockAudioPlayed.value.clear();
+ // 清理已添加股票的记录
+ addedStocks.value.clear();
// 清理显示的文本和标题
displayedTexts.value = {
one1: '',
@@ -460,6 +548,9 @@ watch(() => emotionStore.stockList, (newStockList) => {
emoEnergyConverter: false
};
console.log('股票列表已清空,页面数据已隐藏');
+ } else {
+ // 当stockList有数据时,更新对话记录
+ loadConversationsFromStockList();
}
}, { deep: true });
@@ -1089,11 +1180,20 @@ async function handleSendMessage(input, onComplete) {
const previousMessages = [...messages.value]; // 保存历史消息
messages.value = []; // 清空历史数据
+ // 添加用户消息(只添加一次)
+ const userMessage = reactive({ sender: 'user', text: input });
+ messages.value.push(userMessage);
+
+ // 将用户消息添加到emotion store中
+ emotionStore.addConversation({
+ sender: 'user',
+ text: input,
+ timestamp: new Date().toISOString()
+ });
+
// 检查用户剩余次数
await chatStore.getUserCount(); // 获取最新的用户次数
if (chatStore.UserCount <= 0) {
- const userMessage = reactive({ sender: 'user', text: input });
- messages.value.push(userMessage);
const aiMessage = reactive({ sender: 'ai', text: '您的剩余次数为0,无法使用情绪大模型,请联系客服或购买服务包。' });
messages.value.push(aiMessage);
@@ -1115,39 +1215,6 @@ async function handleSendMessage(input, onComplete) {
return;
}
- // 检查用户是否有使用次数(检查是否有任何权限)
- // const hasPermission = userStore.brainPerssion || userStore.swordPerssion ||
- // userStore.pricePerssion || userStore.timePerssion ||
- // userStore.aibullPerssion || userStore.aiGnbullPerssion ||
- // userStore.airadarPerssion;
-
- // if (!hasPermission) {
- // const userMessage = reactive({ sender: 'user', text: input });
- // messages.value.push(userMessage);
- // const aiMessage = reactive({ sender: 'ai', text: '您当前没有可用权限,请联系客服或购买服务包。' });
- // messages.value.push(aiMessage);
- // // 停止图片旋转,恢复历史数据
- // isRotating.value = false;
- // messages.value = [...previousMessages, ...messages.value];
- // // 调用完成回调,重新启用输入框
- // if (onComplete && typeof onComplete === 'function') {
- // onComplete();
- // // 清除保存的回调函数
- // currentOnCompleteCallback.value = null;
- // }
- // return;
- // }
-
- const userMessage = reactive({ sender: 'user', text: input });
- messages.value.push(userMessage);
-
- // 将用户消息添加到emotion store中
- emotionStore.addConversation({
- sender: 'user',
- text: input,
- timestamp: new Date().toISOString()
- });
-
// 开始思考过程(不带股票名称)
const thinkingMessageRef = await showThinkingProcess();
@@ -1602,36 +1669,36 @@ function hasValidData(obj) {
return false;
}
-// 依次渲染图表的方法
-async function renderChartsSequentially(clonedData) {
- console.log('开始依次渲染图表');
+// 依次渲染图表的方法 - 支持多个股票
+async function renderChartsSequentially(clonedData, stockIndex = 0) {
+ console.log(`开始渲染第${stockIndex}个股票的图表`);
// 定义图表渲染顺序和配置
const chartConfigs = [
{
name: '股市温度计',
- ref: marketTemperatureRef,
+ ref: marketTemperatureRef.value[stockIndex],
visibility: chartVisibility.value.marketTemperature,
method: 'initChart',
params: [clonedData.GSWDJ, clonedData.KLine20, clonedData.WDRL]
},
{
name: '情绪解码器',
- ref: emotionDecodRef,
+ ref: emotionDecodRef.value[stockIndex],
visibility: chartVisibility.value.emotionDecod,
method: 'initQXNLZHEcharts',
params: [clonedData.KLine20, clonedData.QXJMQ]
},
{
name: '情绪探底雷达',
- ref: emotionalBottomRadarRef,
+ ref: emotionalBottomRadarRef.value[stockIndex],
visibility: chartVisibility.value.emotionalBottomRadar,
method: 'initEmotionalBottomRadar',
params: [clonedData.KLine20, clonedData.QXTDLD]
},
{
name: '情绪能量转化器',
- ref: emoEnergyConverterRef,
+ ref: emoEnergyConverterRef.value[stockIndex],
visibility: chartVisibility.value.emoEnergyConverter,
method: 'initQXNLZHEcharts',
params: [clonedData.KLine20, clonedData.QXNLZHQ]
@@ -1640,29 +1707,29 @@ async function renderChartsSequentially(clonedData) {
// 依次渲染每个图表
for (const config of chartConfigs) {
- if (config.ref.value && config.visibility) {
- console.log(`开始渲染${config.name}图表`);
- console.log(`${config.name}Ref方法:`, typeof config.ref.value[config.method]);
+ if (config.ref && config.visibility) {
+ console.log(`开始渲染第${stockIndex}个股票的${config.name}图表`);
+ console.log(`${config.name}Ref方法:`, typeof config.ref[config.method]);
- if (typeof config.ref.value[config.method] === 'function') {
+ if (typeof config.ref[config.method] === 'function') {
try {
- config.ref.value[config.method](...config.params);
- console.log(`${config.name}图表渲染成功`);
+ config.ref[config.method](...config.params);
+ console.log(`第${stockIndex}个股票的${config.name}图表渲染成功`);
// 每个图表渲染完成后等待一段时间再渲染下一个
await new Promise(resolve => setTimeout(resolve, 800));
} catch (error) {
- console.error(`${config.name}图表渲染失败:`, error);
+ console.error(`第${stockIndex}个股票的${config.name}图表渲染失败:`, error);
}
} else {
- console.error(`${config.name}Ref.${config.method} 方法不存在`);
+ console.error(`第${stockIndex}个股票的${config.name}Ref.${config.method} 方法不存在`);
}
} else {
- console.log(`${config.name}图表未渲染,ref存在:`, !!config.ref.value, '数据存在:', config.visibility);
+ console.log(`第${stockIndex}个股票的${config.name}图表未渲染,ref存在:`, !!config.ref, '数据存在:', config.visibility);
}
}
- console.log('所有图表依次渲染完成');
+ console.log(`第${stockIndex}个股票的所有图表依次渲染完成`);
}
// 渲染组件图表的方法
@@ -1746,8 +1813,12 @@ function renderCharts(data) {
}
}, 1000);
- // 开始依次渲染图表
- renderChartsSequentially(clonedData);
+ // 开始依次渲染图表 - 为每个股票渲染
+ emotionStore.stockList.forEach((stock, index) => {
+ if (stock.apiData) {
+ renderChartsSequentially(stock.apiData, index);
+ }
+ });
console.log('图表渲染完成');
} catch (error) {
@@ -1798,20 +1869,29 @@ function isDataLoaded() {
return false;
}
- // 检查图表组件是否已渲染
- const requiredRefs = [
- marketTemperatureRef.value,
- emotionDecodRef.value,
- emotionalBottomRadarRef.value,
- emoEnergyConverterRef.value
- ];
-
- const allRefsLoaded = requiredRefs.every(ref => ref !== null);
- if (!allRefsLoaded) {
- console.log('图表组件尚未完全加载');
+ // 检查图表组件是否已渲染 - 检查所有股票的组件
+ const stockCount = emotionStore.stockList.length;
+ if (stockCount === 0) {
+ console.log('没有股票数据');
return false;
}
+ // 检查每个股票的图表组件是否都已加载
+ for (let i = 0; i < stockCount; i++) {
+ const requiredRefs = [
+ marketTemperatureRef.value[i],
+ emotionDecodRef.value[i],
+ emotionalBottomRadarRef.value[i],
+ emoEnergyConverterRef.value[i]
+ ];
+
+ const allRefsLoaded = requiredRefs.every(ref => ref !== null);
+ if (!allRefsLoaded) {
+ console.log(`第${i}个股票的图表组件尚未完全加载`);
+ return false;
+ }
+ }
+
console.log('所有数据和组件已加载完成');
return true;
}
@@ -1954,6 +2034,8 @@ const handleContainerScroll = () => {
onMounted(async () => {
// 恢复对话记录
loadConversationsFromStore();
+ // 从stockList加载对话记录
+ loadConversationsFromStockList();
// 确保获取用户次数
// try {
diff --git a/src/views/components/emoEnergyConverter.vue b/src/views/components/emoEnergyConverter.vue
index 63feff8..3ea78ff 100644
--- a/src/views/components/emoEnergyConverter.vue
+++ b/src/views/components/emoEnergyConverter.vue
@@ -1,5 +1,5 @@
-
+