|
@ -168,11 +168,12 @@ |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 返回顶部按钮 --> |
|
|
<!-- 返回顶部按钮 --> |
|
|
<div class="back-to-top" @click="scrollToTop" v-show="isPageLoaded"> |
|
|
<div class="back-to-top" @click="scrollToTop" v-show="isPageLoaded"> |
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
|
|
<path d="M12 4L12 20M12 4L6 10M12 4L18 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
|
|
|
|
|
|
|
|
<path d="M12 4L12 20M12 4L6 10M12 4L18 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" |
|
|
|
|
|
stroke-linejoin="round" /> |
|
|
</svg> |
|
|
</svg> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
@ -797,18 +798,6 @@ function startTypewriterEffect(conclusion, onComplete) { |
|
|
for (let i = 0; i <= disclaimerText.length; i++) { |
|
|
for (let i = 0; i <= disclaimerText.length; i++) { |
|
|
const timer = setTimeout(() => { |
|
|
const timer = setTimeout(() => { |
|
|
displayedTexts.value.disclaimer = disclaimerText.substring(0, i); |
|
|
displayedTexts.value.disclaimer = disclaimerText.substring(0, i); |
|
|
// 在打字机效果的最后一个字符显示完成后,滚动到底部并调用完成回调 |
|
|
|
|
|
if (i === disclaimerText.length) { |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
scrollToBottom(); |
|
|
|
|
|
// 调用完成回调,重新启用输入框 |
|
|
|
|
|
if (onComplete && typeof onComplete === 'function') { |
|
|
|
|
|
onComplete(); |
|
|
|
|
|
// 清除保存的回调函数 |
|
|
|
|
|
currentOnCompleteCallback.value = null; |
|
|
|
|
|
} |
|
|
|
|
|
}, 100); |
|
|
|
|
|
} |
|
|
|
|
|
}, totalDelay + i * typeSpeed); |
|
|
}, totalDelay + i * typeSpeed); |
|
|
typewriterTimers.value.push(timer); |
|
|
typewriterTimers.value.push(timer); |
|
|
} |
|
|
} |
|
@ -858,9 +847,9 @@ function playAudio(url) { |
|
|
emotionAudioStore.isPlaying = true; |
|
|
emotionAudioStore.isPlaying = true; |
|
|
console.log('开始播放场景应用语音'); |
|
|
console.log('开始播放场景应用语音'); |
|
|
// 音频开始播放时,滚动到底部 |
|
|
// 音频开始播放时,滚动到底部 |
|
|
setTimeout(() => { |
|
|
|
|
|
scrollToBottom(); |
|
|
|
|
|
}, 100); |
|
|
|
|
|
|
|
|
// setTimeout(() => { |
|
|
|
|
|
// scrollToBottom(); |
|
|
|
|
|
// }, 100); |
|
|
}, |
|
|
}, |
|
|
onend: () => { |
|
|
onend: () => { |
|
|
isAudioPlaying.value = false; |
|
|
isAudioPlaying.value = false; |
|
@ -964,27 +953,27 @@ async function handleSendMessage(input, onComplete) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 检查用户是否有使用次数(检查是否有任何权限) |
|
|
// 检查用户是否有使用次数(检查是否有任何权限) |
|
|
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 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 }); |
|
|
const userMessage = reactive({ sender: 'user', text: input }); |
|
|
messages.value.push(userMessage); |
|
|
messages.value.push(userMessage); |
|
@ -996,14 +985,22 @@ async function handleSendMessage(input, onComplete) { |
|
|
userData: { |
|
|
userData: { |
|
|
token: localStorage.getItem('localToken'), |
|
|
token: localStorage.getItem('localToken'), |
|
|
language: "cn", |
|
|
language: "cn", |
|
|
brainPrivilegeState: userStore.brainPerssion, |
|
|
|
|
|
swordPrivilegeState: userStore.swordPerssion, |
|
|
|
|
|
stockForecastPrivilegeState: userStore.pricePerssion, |
|
|
|
|
|
spaceForecastPrivilegeState: userStore.timePerssion, |
|
|
|
|
|
aibullPrivilegeState: userStore.aibullPerssion, |
|
|
|
|
|
aigoldBullPrivilegeState: userStore.aiGnbullPerssion, |
|
|
|
|
|
airadarPrivilegeState: userStore.airadarPerssion, |
|
|
|
|
|
marketList: userStore.aiGoldMarketList, |
|
|
|
|
|
|
|
|
// brainPrivilegeState: userStore.brainPerssion, |
|
|
|
|
|
// swordPrivilegeState: userStore.swordPerssion, |
|
|
|
|
|
// stockForecastPrivilegeState: userStore.pricePerssion, |
|
|
|
|
|
// spaceForecastPrivilegeState: userStore.timePerssion, |
|
|
|
|
|
// aibullPrivilegeState: userStore.aibullPerssion, |
|
|
|
|
|
// aigoldBullPrivilegeState: userStore.aiGnbullPerssion, |
|
|
|
|
|
// airadarPrivilegeState: userStore.airadarPerssion, |
|
|
|
|
|
// marketList: userStore.aiGoldMarketList, |
|
|
|
|
|
brainPrivilegeState: '1', |
|
|
|
|
|
swordPrivilegeState: '1', |
|
|
|
|
|
stockForecastPrivilegeState: '1', |
|
|
|
|
|
spaceForecastPrivilegeState: '1', |
|
|
|
|
|
aibullPrivilegeState: '1', |
|
|
|
|
|
aigoldBullPrivilegeState: '1', |
|
|
|
|
|
airadarPrivilegeState: '1', |
|
|
|
|
|
marketList: "hk,cn,usa,my,sg,vi,in,gb", |
|
|
}, |
|
|
}, |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -1116,7 +1113,7 @@ async function handleSendMessage(input, onComplete) { |
|
|
} |
|
|
} |
|
|
isRotating.value = false; |
|
|
isRotating.value = false; |
|
|
messages.value = [...previousMessages, ...messages.value]; |
|
|
messages.value = [...previousMessages, ...messages.value]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有之前的股票数据且页面已加载,重新渲染图表 |
|
|
// 如果有之前的股票数据且页面已加载,重新渲染图表 |
|
|
if (isPageLoaded.value && emotionStore.activeStock && emotionStore.activeStock.apiData) { |
|
|
if (isPageLoaded.value && emotionStore.activeStock && emotionStore.activeStock.apiData) { |
|
|
nextTick(() => { |
|
|
nextTick(() => { |
|
@ -1124,7 +1121,7 @@ async function handleSendMessage(input, onComplete) { |
|
|
console.log('搜索失败,恢复显示之前股票的图表:', emotionStore.activeStock.stockInfo.name); |
|
|
console.log('搜索失败,恢复显示之前股票的图表:', emotionStore.activeStock.stockInfo.name); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 调用完成回调,重新启用输入框 |
|
|
// 调用完成回调,重新启用输入框 |
|
|
if (onComplete && typeof onComplete === 'function') { |
|
|
if (onComplete && typeof onComplete === 'function') { |
|
|
onComplete(); |
|
|
onComplete(); |
|
@ -1136,7 +1133,7 @@ async function handleSendMessage(input, onComplete) { |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
// 请求失败时关闭加载状态 |
|
|
// 请求失败时关闭加载状态 |
|
|
isLoading.value = false; |
|
|
isLoading.value = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有之前的股票数据,恢复显示状态;否则设置为false |
|
|
// 如果有之前的股票数据,恢复显示状态;否则设置为false |
|
|
if (emotionStore.stockList.length > 0 && emotionStore.activeStock) { |
|
|
if (emotionStore.stockList.length > 0 && emotionStore.activeStock) { |
|
|
isPageLoaded.value = true; |
|
|
isPageLoaded.value = true; |
|
@ -1149,13 +1146,13 @@ async function handleSendMessage(input, onComplete) { |
|
|
} else { |
|
|
} else { |
|
|
isPageLoaded.value = false; |
|
|
isPageLoaded.value = false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const aiMessage = reactive({ sender: 'ai', text: '请求工作流接口失败,请检查网络连接' }); |
|
|
const aiMessage = reactive({ sender: 'ai', text: '请求工作流接口失败,请检查网络连接' }); |
|
|
messages.value.push(aiMessage); |
|
|
messages.value.push(aiMessage); |
|
|
// 请求失败时停止图片旋转,恢复历史数据 |
|
|
// 请求失败时停止图片旋转,恢复历史数据 |
|
|
isRotating.value = false; |
|
|
isRotating.value = false; |
|
|
messages.value = [...previousMessages, ...messages.value]; |
|
|
messages.value = [...previousMessages, ...messages.value]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有之前的股票数据且页面已加载,重新渲染图表 |
|
|
// 如果有之前的股票数据且页面已加载,重新渲染图表 |
|
|
if (isPageLoaded.value && emotionStore.activeStock && emotionStore.activeStock.apiData) { |
|
|
if (isPageLoaded.value && emotionStore.activeStock && emotionStore.activeStock.apiData) { |
|
|
nextTick(() => { |
|
|
nextTick(() => { |
|
@ -1163,7 +1160,7 @@ async function handleSendMessage(input, onComplete) { |
|
|
console.log('请求失败,恢复显示之前股票的图表:', emotionStore.activeStock.stockInfo.name); |
|
|
console.log('请求失败,恢复显示之前股票的图表:', emotionStore.activeStock.stockInfo.name); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 调用完成回调,重新启用输入框 |
|
|
// 调用完成回调,重新启用输入框 |
|
|
if (onComplete && typeof onComplete === 'function') { |
|
|
if (onComplete && typeof onComplete === 'function') { |
|
|
onComplete(); |
|
|
onComplete(); |
|
@ -1208,13 +1205,13 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
if (stockDataResponse.code === 200 && stockDataResponse.data) { |
|
|
if (stockDataResponse.code === 200 && stockDataResponse.data) { |
|
|
// 检查关键数据字段是否完整 |
|
|
// 检查关键数据字段是否完整 |
|
|
const validation = validateRequiredFields(stockDataResponse.data); |
|
|
const validation = validateRequiredFields(stockDataResponse.data); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有关键数据缺失,返回失败,不添加到StockTabs |
|
|
// 如果有关键数据缺失,返回失败,不添加到StockTabs |
|
|
if (!validation.isValid) { |
|
|
if (!validation.isValid) { |
|
|
console.log('API返回数据不完整,缺失字段:', validation.missingFields); |
|
|
console.log('API返回数据不完整,缺失字段:', validation.missingFields); |
|
|
// 关闭加载状态 |
|
|
// 关闭加载状态 |
|
|
isLoading.value = false; |
|
|
isLoading.value = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有之前的股票数据,恢复显示状态;否则设置为false |
|
|
// 如果有之前的股票数据,恢复显示状态;否则设置为false |
|
|
if (emotionStore.stockList.length > 0 && emotionStore.activeStock) { |
|
|
if (emotionStore.stockList.length > 0 && emotionStore.activeStock) { |
|
|
isPageLoaded.value = true; |
|
|
isPageLoaded.value = true; |
|
@ -1227,15 +1224,15 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
} else { |
|
|
} else { |
|
|
isPageLoaded.value = false; |
|
|
isPageLoaded.value = false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const aiMessage = reactive({ |
|
|
|
|
|
sender: 'ai', |
|
|
|
|
|
text: `数据丢失了,请稍后重试。` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const aiMessage = reactive({ |
|
|
|
|
|
sender: 'ai', |
|
|
|
|
|
text: `数据丢失了,请稍后重试。` |
|
|
}); |
|
|
}); |
|
|
messages.value.push(aiMessage); |
|
|
messages.value.push(aiMessage); |
|
|
return false; // 返回失败标识,不添加股票到标签 |
|
|
return false; // 返回失败标识,不添加股票到标签 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 只有数据完整时才创建股票数据对象并添加到store |
|
|
// 只有数据完整时才创建股票数据对象并添加到store |
|
|
const stockData = { |
|
|
const stockData = { |
|
|
queryText: queryText, |
|
|
queryText: queryText, |
|
@ -1254,7 +1251,7 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
} else { |
|
|
} else { |
|
|
// 关闭加载状态 |
|
|
// 关闭加载状态 |
|
|
isLoading.value = false; |
|
|
isLoading.value = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有之前的股票数据,恢复显示状态;否则设置为false |
|
|
// 如果有之前的股票数据,恢复显示状态;否则设置为false |
|
|
if (emotionStore.stockList.length > 0 && emotionStore.activeStock) { |
|
|
if (emotionStore.stockList.length > 0 && emotionStore.activeStock) { |
|
|
isPageLoaded.value = true; |
|
|
isPageLoaded.value = true; |
|
@ -1267,7 +1264,7 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
} else { |
|
|
} else { |
|
|
isPageLoaded.value = false; |
|
|
isPageLoaded.value = false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const aiMessage = reactive({ sender: 'ai', text: '图表数据请求失败,请检查网络连接' }); |
|
|
const aiMessage = reactive({ sender: 'ai', text: '图表数据请求失败,请检查网络连接' }); |
|
|
messages.value.push(aiMessage); |
|
|
messages.value.push(aiMessage); |
|
|
return false; // 返回失败标识 |
|
|
return false; // 返回失败标识 |
|
@ -1275,7 +1272,7 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
// 关闭加载状态 |
|
|
// 关闭加载状态 |
|
|
isLoading.value = false; |
|
|
isLoading.value = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有之前的股票数据,恢复显示状态;否则设置为false |
|
|
// 如果有之前的股票数据,恢复显示状态;否则设置为false |
|
|
if (emotionStore.stockList.length > 0 && emotionStore.activeStock) { |
|
|
if (emotionStore.stockList.length > 0 && emotionStore.activeStock) { |
|
|
isPageLoaded.value = true; |
|
|
isPageLoaded.value = true; |
|
@ -1288,7 +1285,7 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
} else { |
|
|
} else { |
|
|
isPageLoaded.value = false; |
|
|
isPageLoaded.value = false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const aiMessage = reactive({ sender: 'ai', text: '图表数据请求失败,请检查网络连接' }); |
|
|
const aiMessage = reactive({ sender: 'ai', text: '图表数据请求失败,请检查网络连接' }); |
|
|
messages.value.push(aiMessage); |
|
|
messages.value.push(aiMessage); |
|
|
return false; // 返回失败标识 |
|
|
return false; // 返回失败标识 |
|
@ -1299,15 +1296,15 @@ async function fetchData(code, market, stockName, queryText) { |
|
|
function validateRequiredFields(data) { |
|
|
function validateRequiredFields(data) { |
|
|
const requiredFields = ['GSWDJ', 'KLine20', 'QXJMQ', 'QXTDLD', 'WDRL']; |
|
|
const requiredFields = ['GSWDJ', 'KLine20', 'QXJMQ', 'QXTDLD', 'WDRL']; |
|
|
const missingFields = []; |
|
|
const missingFields = []; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const field of requiredFields) { |
|
|
for (const field of requiredFields) { |
|
|
if (!data[field] || |
|
|
|
|
|
(Array.isArray(data[field]) && data[field].length === 0) || |
|
|
|
|
|
(typeof data[field] === 'object' && !hasValidData(data[field]))) { |
|
|
|
|
|
|
|
|
if (!data[field] || |
|
|
|
|
|
(Array.isArray(data[field]) && data[field].length === 0) || |
|
|
|
|
|
(typeof data[field] === 'object' && !hasValidData(data[field]))) { |
|
|
missingFields.push(field); |
|
|
missingFields.push(field); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
return { |
|
|
isValid: missingFields.length === 0, |
|
|
isValid: missingFields.length === 0, |
|
|
missingFields: missingFields |
|
|
missingFields: missingFields |
|
@ -1319,15 +1316,15 @@ function hasValidData(obj) { |
|
|
if (!obj || typeof obj !== 'object') { |
|
|
if (!obj || typeof obj !== 'object') { |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义可以为空的数组字段 |
|
|
// 定义可以为空的数组字段 |
|
|
const allowedEmptyArrays = ['lowxh', 'qixh', 'topxh']; |
|
|
const allowedEmptyArrays = ['lowxh', 'qixh', 'topxh']; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查对象的所有属性值 |
|
|
// 检查对象的所有属性值 |
|
|
for (const key in obj) { |
|
|
for (const key in obj) { |
|
|
if (obj.hasOwnProperty(key)) { |
|
|
if (obj.hasOwnProperty(key)) { |
|
|
const value = obj[key]; |
|
|
const value = obj[key]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果是字符串字段 |
|
|
// 如果是字符串字段 |
|
|
if (typeof value === 'string') { |
|
|
if (typeof value === 'string') { |
|
|
// 字符串字段必须有内容,为空则表示异常 |
|
|
// 字符串字段必须有内容,为空则表示异常 |
|
@ -1358,36 +1355,36 @@ function hasValidData(obj) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 渲染组件图表的方法 |
|
|
// 渲染组件图表的方法 |
|
|
function renderCharts(data) { |
|
|
function renderCharts(data) { |
|
|
console.log('开始渲染图表,数据:', data); |
|
|
console.log('开始渲染图表,数据:', data); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 深拷贝数据避免污染原始数据 |
|
|
// 深拷贝数据避免污染原始数据 |
|
|
const clonedData = JSON.parse(JSON.stringify(data)); |
|
|
const clonedData = JSON.parse(JSON.stringify(data)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查关键数据字段是否完整 |
|
|
// 检查关键数据字段是否完整 |
|
|
const validation = validateRequiredFields(clonedData); |
|
|
const validation = validateRequiredFields(clonedData); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有任何关键数据缺失,不渲染页面并返回提示 |
|
|
// 如果有任何关键数据缺失,不渲染页面并返回提示 |
|
|
if (!validation.isValid) { |
|
|
if (!validation.isValid) { |
|
|
console.log('关键数据缺失:', validation.missingFields); |
|
|
console.log('关键数据缺失:', validation.missingFields); |
|
|
const aiMessage = reactive({ |
|
|
|
|
|
sender: 'ai', |
|
|
|
|
|
text: `数据不完整,缺少以下关键数据:${validation.missingFields.join('、')}。请稍后重试或联系客服。` |
|
|
|
|
|
|
|
|
const aiMessage = reactive({ |
|
|
|
|
|
sender: 'ai', |
|
|
|
|
|
text: `数据不完整,缺少以下关键数据:${validation.missingFields.join('、')}。请稍后重试或联系客服。` |
|
|
}); |
|
|
}); |
|
|
messages.value.push(aiMessage); |
|
|
messages.value.push(aiMessage); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 隐藏页面内容 |
|
|
// 隐藏页面内容 |
|
|
isPageLoaded.value = false; |
|
|
isPageLoaded.value = false; |
|
|
isLoading.value = false; |
|
|
isLoading.value = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return; // 直接返回,不进行后续渲染 |
|
|
return; // 直接返回,不进行后续渲染 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 先设置图表组件显示状态 |
|
|
// 先设置图表组件显示状态 |
|
|
chartVisibility.value = { |
|
|
chartVisibility.value = { |
|
|
marketTemperature: !!(clonedData.GSWDJ && clonedData.GSWDJ.length > 0), |
|
|
marketTemperature: !!(clonedData.GSWDJ && clonedData.GSWDJ.length > 0), |
|
@ -1395,7 +1392,7 @@ function renderCharts(data) { |
|
|
emotionalBottomRadar: !!(clonedData.QXTDLD && clonedData.QXTDLD.length > 0), |
|
|
emotionalBottomRadar: !!(clonedData.QXTDLD && clonedData.QXTDLD.length > 0), |
|
|
emoEnergyConverter: !!(clonedData.QXNLZHQ && (Array.isArray(clonedData.QXNLZHQ) ? clonedData.QXNLZHQ.length > 0 : hasValidData(clonedData.QXNLZHQ))) |
|
|
emoEnergyConverter: !!(clonedData.QXNLZHQ && (Array.isArray(clonedData.QXNLZHQ) ? clonedData.QXNLZHQ.length > 0 : hasValidData(clonedData.QXNLZHQ))) |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('图表显示状态:', chartVisibility.value); |
|
|
console.log('图表显示状态:', chartVisibility.value); |
|
|
console.log('数据检查:', { |
|
|
console.log('数据检查:', { |
|
|
GSWDJ: !!(clonedData.GSWDJ && clonedData.GSWDJ.length > 0), |
|
|
GSWDJ: !!(clonedData.GSWDJ && clonedData.GSWDJ.length > 0), |
|
@ -1404,7 +1401,7 @@ function renderCharts(data) { |
|
|
QXNLZHQ: !!(clonedData.QXNLZHQ && (Array.isArray(clonedData.QXNLZHQ) ? clonedData.QXNLZHQ.length > 0 : hasValidData(clonedData.QXNLZHQ))) |
|
|
QXNLZHQ: !!(clonedData.QXNLZHQ && (Array.isArray(clonedData.QXNLZHQ) ? clonedData.QXNLZHQ.length > 0 : hasValidData(clonedData.QXNLZHQ))) |
|
|
}); |
|
|
}); |
|
|
console.log('QXNLZHQ数据详情:', clonedData.QXNLZHQ); |
|
|
console.log('QXNLZHQ数据详情:', clonedData.QXNLZHQ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nextTick(() => { |
|
|
nextTick(() => { |
|
|
// 增加延迟确保DOM完全更新和组件完全挂载 |
|
|
// 增加延迟确保DOM完全更新和组件完全挂载 |
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
@ -1415,7 +1412,7 @@ function renderCharts(data) { |
|
|
emotionalBottomRadarRef: !!emotionalBottomRadarRef.value, |
|
|
emotionalBottomRadarRef: !!emotionalBottomRadarRef.value, |
|
|
emoEnergyConverterRef: !!emoEnergyConverterRef.value |
|
|
emoEnergyConverterRef: !!emoEnergyConverterRef.value |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查DOM元素是否存在 |
|
|
// 检查DOM元素是否存在 |
|
|
console.log('DOM元素检查:', { |
|
|
console.log('DOM元素检查:', { |
|
|
marketTemperatureDOM: !!document.querySelector('.class03'), |
|
|
marketTemperatureDOM: !!document.querySelector('.class03'), |
|
@ -1423,11 +1420,11 @@ function renderCharts(data) { |
|
|
emotionalBottomRadarDOM: !!document.querySelector('.class05'), |
|
|
emotionalBottomRadarDOM: !!document.querySelector('.class05'), |
|
|
emoEnergyConverterDOM: !!document.querySelector('.class06') |
|
|
emoEnergyConverterDOM: !!document.querySelector('.class06') |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查具体的组件元素 |
|
|
// 检查具体的组件元素 |
|
|
const emoEnergyElement = document.querySelector('emo-energy-converter'); |
|
|
const emoEnergyElement = document.querySelector('emo-energy-converter'); |
|
|
console.log('emoEnergyConverter元素:', emoEnergyElement); |
|
|
console.log('emoEnergyConverter元素:', emoEnergyElement); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 等待更长时间再次检查ref |
|
|
// 等待更长时间再次检查ref |
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
console.log('延迟检查emoEnergyConverterRef:', !!emoEnergyConverterRef.value); |
|
|
console.log('延迟检查emoEnergyConverterRef:', !!emoEnergyConverterRef.value); |
|
@ -1435,7 +1432,7 @@ function renderCharts(data) { |
|
|
console.log('emoEnergyConverter方法:', typeof emoEnergyConverterRef.value.initQXNLZHEcharts); |
|
|
console.log('emoEnergyConverter方法:', typeof emoEnergyConverterRef.value.initQXNLZHEcharts); |
|
|
} |
|
|
} |
|
|
}, 1000); |
|
|
}, 1000); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染股市温度计图表 |
|
|
// 渲染股市温度计图表 |
|
|
if (marketTemperatureRef.value && chartVisibility.value.marketTemperature) { |
|
|
if (marketTemperatureRef.value && chartVisibility.value.marketTemperature) { |
|
|
console.log('开始渲染股市温度计图表'); |
|
|
console.log('开始渲染股市温度计图表'); |
|
@ -1453,7 +1450,7 @@ function renderCharts(data) { |
|
|
} else { |
|
|
} else { |
|
|
console.log('股市温度计图表未渲染,ref存在:', !!marketTemperatureRef.value, '数据存在:', chartVisibility.value.marketTemperature); |
|
|
console.log('股市温度计图表未渲染,ref存在:', !!marketTemperatureRef.value, '数据存在:', chartVisibility.value.marketTemperature); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染情绪解码器图表 |
|
|
// 渲染情绪解码器图表 |
|
|
if (emotionDecodRef.value && chartVisibility.value.emotionDecod) { |
|
|
if (emotionDecodRef.value && chartVisibility.value.emotionDecod) { |
|
|
console.log('开始渲染情绪解码器图表'); |
|
|
console.log('开始渲染情绪解码器图表'); |
|
@ -1471,7 +1468,7 @@ function renderCharts(data) { |
|
|
} else { |
|
|
} else { |
|
|
console.log('情绪解码器图表未渲染,ref存在:', !!emotionDecodRef.value, '数据存在:', chartVisibility.value.emotionDecod); |
|
|
console.log('情绪解码器图表未渲染,ref存在:', !!emotionDecodRef.value, '数据存在:', chartVisibility.value.emotionDecod); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染情绪探底雷达图表 |
|
|
// 渲染情绪探底雷达图表 |
|
|
if (emotionalBottomRadarRef.value && chartVisibility.value.emotionalBottomRadar) { |
|
|
if (emotionalBottomRadarRef.value && chartVisibility.value.emotionalBottomRadar) { |
|
|
console.log('开始渲染情绪探底雷达图表'); |
|
|
console.log('开始渲染情绪探底雷达图表'); |
|
@ -1492,7 +1489,7 @@ function renderCharts(data) { |
|
|
} else { |
|
|
} else { |
|
|
console.log('情绪探底雷达图表未渲染,ref存在:', !!emotionalBottomRadarRef.value, '数据存在:', chartVisibility.value.emotionalBottomRadar); |
|
|
console.log('情绪探底雷达图表未渲染,ref存在:', !!emotionalBottomRadarRef.value, '数据存在:', chartVisibility.value.emotionalBottomRadar); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染情绪能量转化器图表 |
|
|
// 渲染情绪能量转化器图表 |
|
|
if (emoEnergyConverterRef.value && chartVisibility.value.emoEnergyConverter) { |
|
|
if (emoEnergyConverterRef.value && chartVisibility.value.emoEnergyConverter) { |
|
|
console.log('开始渲染情绪能量转化器图表'); |
|
|
console.log('开始渲染情绪能量转化器图表'); |
|
@ -1510,7 +1507,7 @@ function renderCharts(data) { |
|
|
} else { |
|
|
} else { |
|
|
console.log('情绪能量转化器图表未渲染,ref存在:', !!emoEnergyConverterRef.value, '数据存在:', chartVisibility.value.emoEnergyConverter); |
|
|
console.log('情绪能量转化器图表未渲染,ref存在:', !!emoEnergyConverterRef.value, '数据存在:', chartVisibility.value.emoEnergyConverter); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('图表渲染完成'); |
|
|
console.log('图表渲染完成'); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error('图表渲染错误:', error); |
|
|
console.error('图表渲染错误:', error); |
|
@ -1521,21 +1518,21 @@ function renderCharts(data) { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const scrollToBottom = async () => { |
|
|
|
|
|
// 如果用户正在手动滚动,则不执行自动滚动 |
|
|
|
|
|
if (isUserScrolling.value) { |
|
|
|
|
|
console.log('用户正在手动滚动,跳过自动滚动'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// const scrollToBottom = async () => { |
|
|
|
|
|
// // 如果用户正在手动滚动,则不执行自动滚动 |
|
|
|
|
|
// if (isUserScrolling.value) { |
|
|
|
|
|
// console.log('用户正在手动滚动,跳过自动滚动'); |
|
|
|
|
|
// return; |
|
|
|
|
|
// } |
|
|
|
|
|
|
|
|
const container = userInputDisplayRef.value; |
|
|
|
|
|
if (!container) return; |
|
|
|
|
|
await nextTick(); |
|
|
|
|
|
console.log(container.scrollHeight, "container.scrollHeight"); |
|
|
|
|
|
console.log(container.scrollTop, "container.scrollTop"); |
|
|
|
|
|
console.log(container.offsetHeight, "container.offsetHeight"); |
|
|
|
|
|
container.scrollTop = container.scrollHeight - container.offsetHeight; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// const container = userInputDisplayRef.value; |
|
|
|
|
|
// if (!container) return; |
|
|
|
|
|
// await nextTick(); |
|
|
|
|
|
// console.log(container.scrollHeight, "container.scrollHeight"); |
|
|
|
|
|
// console.log(container.scrollTop, "container.scrollTop"); |
|
|
|
|
|
// console.log(container.offsetHeight, "container.offsetHeight"); |
|
|
|
|
|
// container.scrollTop = container.scrollHeight - container.offsetHeight; |
|
|
|
|
|
// }; |
|
|
|
|
|
|
|
|
// 处理用户滚动事件 |
|
|
// 处理用户滚动事件 |
|
|
const handleUserScroll = () => { |
|
|
const handleUserScroll = () => { |
|
@ -1704,7 +1701,7 @@ function triggerAutoScroll() { |
|
|
const scrollToTop = () => { |
|
|
const scrollToTop = () => { |
|
|
const topAnchor = document.getElementById('top-anchor'); |
|
|
const topAnchor = document.getElementById('top-anchor'); |
|
|
if (topAnchor) { |
|
|
if (topAnchor) { |
|
|
topAnchor.scrollIntoView({ |
|
|
|
|
|
|
|
|
topAnchor.scrollIntoView({ |
|
|
behavior: 'smooth', |
|
|
behavior: 'smooth', |
|
|
block: 'start', |
|
|
block: 'start', |
|
|
inline: 'nearest' |
|
|
inline: 'nearest' |
|
@ -1712,7 +1709,7 @@ const scrollToTop = () => { |
|
|
} else { |
|
|
} else { |
|
|
window.scrollTo({ top: 0, behavior: 'smooth' }); |
|
|
window.scrollTo({ top: 0, behavior: 'smooth' }); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 备用方案:直接滚动到页面顶部 |
|
|
// 备用方案:直接滚动到页面顶部 |
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
const currentScrollTop = window.pageYOffset || document.documentElement.scrollTop; |
|
|
const currentScrollTop = window.pageYOffset || document.documentElement.scrollTop; |
|
@ -1816,7 +1813,7 @@ onMounted(async () => { |
|
|
|
|
|
|
|
|
// 添加页面滚动监听器,控制返回顶部按钮显示 |
|
|
// 添加页面滚动监听器,控制返回顶部按钮显示 |
|
|
window.addEventListener('scroll', handlePageScroll, { passive: true }); |
|
|
window.addEventListener('scroll', handlePageScroll, { passive: true }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加document滚动监听器(备用方案) |
|
|
// 添加document滚动监听器(备用方案) |
|
|
document.addEventListener('scroll', handlePageScroll, { passive: true }); |
|
|
document.addEventListener('scroll', handlePageScroll, { passive: true }); |
|
|
|
|
|
|
|
@ -1876,13 +1873,13 @@ onMounted(async () => { |
|
|
// 组件卸载时清理定时器、音频和observer |
|
|
// 组件卸载时清理定时器、音频和observer |
|
|
onUnmounted(() => { |
|
|
onUnmounted(() => { |
|
|
clearTypewriterTimers(); |
|
|
clearTypewriterTimers(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有未完成的回调函数,调用它来重新启用输入框 |
|
|
// 如果有未完成的回调函数,调用它来重新启用输入框 |
|
|
if (currentOnCompleteCallback.value && typeof currentOnCompleteCallback.value === 'function') { |
|
|
if (currentOnCompleteCallback.value && typeof currentOnCompleteCallback.value === 'function') { |
|
|
currentOnCompleteCallback.value(); |
|
|
currentOnCompleteCallback.value(); |
|
|
currentOnCompleteCallback.value = null; |
|
|
currentOnCompleteCallback.value = null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stopAudio(); |
|
|
stopAudio(); |
|
|
|
|
|
|
|
|
// 重置触发状态 |
|
|
// 重置触发状态 |
|
@ -3362,7 +3359,7 @@ defineExpose({ |
|
|
width: 40px !important; |
|
|
width: 40px !important; |
|
|
height: 40px !important; |
|
|
height: 40px !important; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.back-to-top svg { |
|
|
.back-to-top svg { |
|
|
width: 20px; |
|
|
width: 20px; |
|
|
height: 20px; |
|
|
height: 20px; |
|
|