Browse Source

Merge branch 'milestone-20250710-上线前优化' of http://39.101.133.168:8807/hongxilin/AIxiaocaishen into dongqian/feature-20250702094358-小财神适配

dongqian/feature-20250702094358-小财神适配
dongqian 1 day ago
parent
commit
62dfe11d06
  1. BIN
      src/assets/img/AIchat/圈1.png
  2. 3
      src/views/AIchat.vue
  3. 262
      src/views/AiEmotion.vue
  4. 12
      src/views/homePage.vue
  5. 4
      vite.config.js

BIN
src/assets/img/AIchat/圈1.png

After

Width: 739  |  Height: 750  |  Size: 154 KiB

3
src/views/AIchat.vue

@ -31,6 +31,7 @@ import title4 from "@/assets/img/AIchat/综合作战.png";
import logo1 from "@/assets/img/AIchat/夺宝奇兵logo.png";
import logo2 from "@/assets/img/AIchat/开启无限财富.png";
import bgc from "@/assets/img/AIchat/圈.png";
import bgc1 from "@/assets/img/AIchat/圈1.png";
const chatStore = useChatStore();
const audioStore = useAudioStore();
const dataStore = useDataStore();
@ -3771,7 +3772,7 @@ onUnmounted(() => {
<div class="chat-container">
<!-- GIF区域 -->
<div class="gif-area">
<img :src="bgc" alt="夺宝奇兵大模型logo" class="bgc" />
<img :src="bgc1" alt="夺宝奇兵大模型logo" class="bgc" />
<img :src="logo1" alt="夺宝奇兵大模型logo" class="logo1" />
<img :src="logo2" alt="夺宝奇兵大模型logo" class="logo2" />
</div>

262
src/views/AiEmotion.vue

@ -45,11 +45,11 @@
</div>
<span class="span02">{{ displayDate }}</span>
</div>
<div class="class0201">
<div class="class0201" v-if="chartVisibility.marketTemperature">
<img src="@/assets/img/AiEmotion/L1.png" alt="情绪监控图标">
</div>
<!-- 温度计图表 -->
<div class="class03">
<div class="class03" v-if="chartVisibility.marketTemperature">
<div class="class003">
<div class="content1">
<img class="img01" src="@/assets/img/AiEmotion/温度计.png" alt="温度计图标">
@ -63,11 +63,11 @@
<marketTemperature ref="marketTemperatureRef" />
</div>
</div>
<div class="class0301">
<div class="class0301" v-if="chartVisibility.emotionDecod">
<img src="@/assets/img/AiEmotion/L2.png" alt="情绪解码图标">
</div>
<!-- 情绪解码器图表 -->
<div class="class04">
<div class="class04" v-if="chartVisibility.emotionDecod">
<div class="class0401">
<img class="img02" src='@/assets/img/AiEmotion/emotionDecod.png' alt="情绪解码器图标">
<span class="title2">情绪解码器</span>
@ -76,11 +76,11 @@
<emotionDecod ref="emotionDecodRef"></emotionDecod>
</div>
</div>
<div class="class0403">
<div class="class0403" v-if="chartVisibility.emotionalBottomRadar">
<img src="@/assets/img/AiEmotion/L3.png" alt="情绪推演图标">
</div>
<!-- 情绪探底雷达图表 -->
<div class="class05">
<div class="class05" v-if="chartVisibility.emotionalBottomRadar">
<div class="class0502">
<img class="img03" src="@/assets/img/AiEmotion/探底雷达.png" alt="探底雷达图表">
<span class="title3">情绪探底雷达</span>
@ -89,11 +89,11 @@
<emotionalBottomRadar ref="emotionalBottomRadarRef"></emotionalBottomRadar>
</div>
</div>
<div class="class0501">
<div class="class0501" v-if="chartVisibility.emoEnergyConverter">
<img src="@/assets/img/AiEmotion/L4.png" alt="情绪套利">
</div>
<!-- 情绪能量转化器图表 -->
<div class="class06">
<div class="class06" v-if="chartVisibility.emoEnergyConverter">
<div class="class0601">
<img class="img04" src="@/assets/img/AiEmotion/能量转化器.png" alt="能量转化器图标">
<span class="title4">情绪能量转化器</span>
@ -277,6 +277,14 @@ const moduleVisibility = ref({
four: false,
disclaimer: false
});
//
const chartVisibility = ref({
marketTemperature: false,
emotionDecod: false,
emotionalBottomRadar: false,
emoEnergyConverter: false
});
const typewriterTimers = ref([]);
//
const stockTypewriterShown = ref(new Map());
@ -372,6 +380,13 @@ watch(() => emotionStore.stockList, (newStockList) => {
four: false,
disclaimer: false
};
//
chartVisibility.value = {
marketTemperature: false,
emotionDecod: false,
emotionalBottomRadar: false,
emoEnergyConverter: false
};
console.log('股票列表已清空,页面数据已隐藏');
}
}, { deep: true });
@ -583,6 +598,13 @@ watch(currentStock, (newStock) => {
}
} else {
console.log('股票数据不存在或API数据未加载');
//
chartVisibility.value = {
marketTemperature: false,
emotionDecod: false,
emotionalBottomRadar: false,
emoEnergyConverter: false
};
}
}, { immediate: true });
@ -625,7 +647,7 @@ watch(parsedConclusion, (newConclusion) => {
}, { immediate: true });
//
function startTypewriterEffect(conclusion) {
function startTypewriterEffect(conclusion, onComplete) {
console.log('开始打字机效果,结论数据:', conclusion);
//
@ -758,10 +780,14 @@ function startTypewriterEffect(conclusion) {
for (let i = 0; i <= disclaimerText.length; i++) {
const timer = setTimeout(() => {
displayedTexts.value.disclaimer = disclaimerText.substring(0, i);
//
//
if (i === disclaimerText.length) {
setTimeout(() => {
scrollToBottom();
//
if (onComplete && typeof onComplete === 'function') {
onComplete();
}
}, 100);
}
}, totalDelay + i * typeSpeed);
@ -877,7 +903,7 @@ function startImageRotation() {
//
async function handleSendMessage(input) {
async function handleSendMessage(input, onComplete) {
console.log("发送内容:", input);
//
isUserInitiated.value = true;
@ -885,6 +911,10 @@ async function handleSendMessage(input) {
//
if (!input || !input.trim()) {
ElMessage.warning("输入内容不能为空");
//
if (onComplete && typeof onComplete === 'function') {
onComplete();
}
return;
}
@ -903,6 +933,10 @@ async function handleSendMessage(input) {
//
isRotating.value = false;
messages.value = [...previousMessages, ...messages.value];
//
if (onComplete && typeof onComplete === 'function') {
onComplete();
}
return;
}
@ -920,6 +954,10 @@ async function handleSendMessage(input) {
//
isRotating.value = false;
messages.value = [...previousMessages, ...messages.value];
//
if (onComplete && typeof onComplete === 'function') {
onComplete();
}
return;
}
@ -947,7 +985,6 @@ async function handleSendMessage(input) {
const result = await getReplyAPI(params);
const response = await result.json();
const parsedData = JSON.parse(response.data);
console.log("第一个接口解析后的数据:", parsedData);
//
if (!parsedData || !parsedData.market || !parsedData.code) {
@ -956,6 +993,10 @@ async function handleSendMessage(input) {
messages.value.push(aiMessage);
isRotating.value = false;
messages.value = [...previousMessages, ...messages.value];
//
if (onComplete && typeof onComplete === 'function') {
onComplete();
}
return;
}
@ -963,7 +1004,6 @@ async function handleSendMessage(input) {
//
isLoading.value = true;
console.log("工作流接口返回股票信息:", parsedData);
isPageLoaded.value = false;
//
@ -985,7 +1025,6 @@ async function handleSendMessage(input) {
//
const conclusionResponse = await conclusionResult.json();
console.log("第二个工作流接口返回数据:", conclusionResponse);
//
if (conclusionResponse && conclusionResponse.data && fetchDataResult) {
@ -1006,26 +1045,28 @@ async function handleSendMessage(input) {
console.error('更新用户次数失败:', error);
}
console.log('所有数据加载完成,开始渲染页面');
//
nextTick(() => {
if (currentStock.value && currentStock.value.apiData) {
renderCharts(currentStock.value.apiData);
console.log('数据加载完成后开始渲染图表');
//
if (isUserInitiated.value && parsedConclusion.value && audioUrl.value) {
const stockCode = currentStock.value.stockInfo?.code || currentStock.value.stockInfo?.symbol;
if (stockCode && !stockTypewriterShown.value.has(stockCode)) {
console.log('用户主动搜索,立即触发音频和打字机效果');
startTypewriterEffect(parsedConclusion.value);
startTypewriterEffect(parsedConclusion.value, onComplete);
if (!stockAudioPlayed.value.has(stockCode)) {
stockAudioPlayed.value.set(stockCode, true);
playAudio(audioUrl.value);
}
stockTypewriterShown.value.set(stockCode, true);
} else {
//
if (onComplete && typeof onComplete === 'function') {
onComplete();
}
}
}
@ -1040,6 +1081,10 @@ async function handleSendMessage(input) {
messages.value.push(aiMessage);
isRotating.value = false;
messages.value = [...previousMessages, ...messages.value];
//
if (onComplete && typeof onComplete === 'function') {
onComplete();
}
return;
}
} catch (error) {
@ -1048,6 +1093,10 @@ async function handleSendMessage(input) {
//
isRotating.value = false;
messages.value = [...previousMessages, ...messages.value];
//
if (onComplete && typeof onComplete === 'function') {
onComplete();
}
return;
} finally {
//
@ -1082,11 +1131,8 @@ async function fetchData(code, market, stockName, queryText) {
);
const stockDataResponse = stockDataResult.data; //
console.log('图表数据接口返回数据:', stockDataResponse.data);
if (stockDataResponse.code === 200 && stockDataResponse.data) {
console.log(stockDataResponse.code)
//
const stockData = {
queryText: queryText,
@ -1108,7 +1154,6 @@ async function fetchData(code, market, stockName, queryText) {
return false; //
}
} catch (error) {
console.error('fetchData error:', error);
const aiMessage = reactive({ sender: 'ai', text: '图表数据请求失败,请检查网络连接' });
messages.value.push(aiMessage);
return false; //
@ -1117,52 +1162,114 @@ async function fetchData(code, market, stockName, queryText) {
//
function renderCharts(data) {
console.log('开始渲染图表,数据:', data);
//
const clonedData = JSON.parse(JSON.stringify(data));
//
chartVisibility.value = {
marketTemperature: !!(clonedData.GSWDJ && clonedData.GSWDJ.length > 0),
emotionDecod: !!(clonedData.QXJMQ && clonedData.QXJMQ.length > 0),
emotionalBottomRadar: !!(clonedData.QXTDLD && clonedData.QXTDLD.length > 0),
emoEnergyConverter: !!(clonedData.QXNLZHQ && clonedData.QXNLZHQ.length > 0)
};
console.log('图表显示状态:', chartVisibility.value);
nextTick(() => {
// DOM
// DOM
setTimeout(() => {
try {
//
const clonedData = JSON.parse(JSON.stringify(data));
console.log('已深拷贝数据,避免污染原始数据');
console.log('所有数据1111111111111:', clonedData)
console.log('图表组件ref状态:', {
marketTemperatureRef: !!marketTemperatureRef.value,
emotionDecodRef: !!emotionDecodRef.value,
emotionalBottomRadarRef: !!emotionalBottomRadarRef.value,
emoEnergyConverterRef: !!emoEnergyConverterRef.value
});
//
if (marketTemperatureRef.value && clonedData.GSWDJ) {
console.log("开始渲染股市温度计图表");
console.log("股市温度计数据", clonedData.GSWDJ);
if (marketTemperatureRef.value && chartVisibility.value.marketTemperature) {
console.log('开始渲染股市温度计图表');
console.log('marketTemperatureRef方法:', typeof marketTemperatureRef.value.initChart);
if (typeof marketTemperatureRef.value.initChart === 'function') {
try {
marketTemperatureRef.value.initChart(clonedData.GSWDJ, clonedData.KLine20, clonedData.WDRL);
console.log("股市温度计图表已渲染");
console.log('股市温度计图表渲染成功');
} catch (error) {
console.error('股市温度计图表渲染失败:', error);
}
} else {
console.error('marketTemperatureRef.initChart 方法不存在');
}
} else {
console.log('股市温度计图表未渲染,ref存在:', !!marketTemperatureRef.value, '数据存在:', chartVisibility.value.marketTemperature);
}
//
if (emotionDecodRef.value && clonedData.QXJMQ) {
console.log("开始渲染情绪解码器图表");
console.log("情绪解码器数据", clonedData.QXJMQ);
if (emotionDecodRef.value && chartVisibility.value.emotionDecod) {
console.log('开始渲染情绪解码器图表');
console.log('emotionDecodRef方法:', typeof emotionDecodRef.value.initQXNLZHEcharts);
if (typeof emotionDecodRef.value.initQXNLZHEcharts === 'function') {
try {
emotionDecodRef.value.initQXNLZHEcharts(clonedData.KLine20, clonedData.QXJMQ);
console.log("情绪解码器图表已渲染");
console.log('情绪解码器图表渲染成功');
} catch (error) {
console.error('情绪解码器图表渲染失败:', error);
}
} else {
console.error('emotionDecodRef.initQXNLZHEcharts 方法不存在');
}
} else {
console.log('情绪解码器图表未渲染,ref存在:', !!emotionDecodRef.value, '数据存在:', chartVisibility.value.emotionDecod);
}
//
if (emotionalBottomRadarRef.value && clonedData.QXTDLD) {
console.log("开始渲染情绪探底雷达图表");
console.log("探底雷达数据", clonedData.QXTDLD);
if (emotionalBottomRadarRef.value && chartVisibility.value.emotionalBottomRadar) {
console.log('开始渲染情绪探底雷达图表');
console.log('emotionalBottomRadarRef方法:', typeof emotionalBottomRadarRef.value.initEmotionalBottomRadar);
if (typeof emotionalBottomRadarRef.value.initEmotionalBottomRadar === 'function') {
try {
emotionalBottomRadarRef.value.initEmotionalBottomRadar(
clonedData.KLine20,
clonedData.QXTDLD
);
console.log("情绪探底雷达图表已渲染");
console.log('情绪探底雷达图表渲染成功');
} catch (error) {
console.error('情绪探底雷达图表渲染失败:', error);
}
} else {
console.error('emotionalBottomRadarRef.initEmotionalBottomRadar 方法不存在');
}
} else {
console.log('情绪探底雷达图表未渲染,ref存在:', !!emotionalBottomRadarRef.value, '数据存在:', chartVisibility.value.emotionalBottomRadar);
}
//
if (emoEnergyConverterRef.value && clonedData.QXNLZHQ) {
console.log("开始渲染情绪能量转化器图表");
console.log("KLine20:", clonedData.KLine20);
console.log("QXNLZHQ:", clonedData.QXNLZHQ);
if (emoEnergyConverterRef.value && chartVisibility.value.emoEnergyConverter) {
console.log('开始渲染情绪能量转化器图表');
console.log('emoEnergyConverterRef方法:', typeof emoEnergyConverterRef.value.initQXNLZHEcharts);
if (typeof emoEnergyConverterRef.value.initQXNLZHEcharts === 'function') {
try {
emoEnergyConverterRef.value.initQXNLZHEcharts(clonedData.KLine20, clonedData.QXNLZHQ);
console.log("情绪能量转化器图表已渲染");
console.log('情绪能量转化器图表渲染成功');
} catch (error) {
console.error('情绪能量转化器图表渲染失败:', error);
}
} else {
console.error('emoEnergyConverterRef.initQXNLZHEcharts 方法不存在');
}
} else {
console.log('情绪能量转化器图表未渲染,ref存在:', !!emoEnergyConverterRef.value, '数据存在:', chartVisibility.value.emoEnergyConverter);
}
console.log('图表渲染完成');
} catch (error) {
console.error('图表渲染过程中发生错误:', error);
console.error('图表渲染错误:', error);
const aiMessage = reactive({ sender: 'ai', text: '图表渲染失败,请重试' });
messages.value.push(aiMessage);
}
}, 100); // 100msDOM
}, 500); // 500msDOM
});
}
@ -1515,10 +1622,10 @@ defineExpose({
</script>
<style scoped>
.disclaimer-item {
p {
.disclaimer-item p {
color: #ffffff !important;
}
font-size: 20px;
font-weight: bold;
}
.container {
@ -1700,8 +1807,6 @@ defineExpose({
padding-left: 15px;
position: relative;
&:last-child {
margin-bottom: 0;
}
@ -2002,6 +2107,7 @@ defineExpose({
transition: all 0.3s ease;
/* 添加平滑过渡效果 */
}
.class04 {
background-image: url('@/assets/img/AiEmotion/bk00000.png');
/* 使用导入的背景图片 */
@ -2058,7 +2164,7 @@ defineExpose({
/* 确保不超出父容器 */
height: auto;
/* 高度根据内容动态变化 */
min-height: 55rem;
/* min-height: 55rem; */
/* 设置最小高度,确保图片显示 */
margin: 0 auto;
box-sizing: border-box;
@ -2245,9 +2351,9 @@ defineExpose({
}
/* 调整图表容器高度 */
.class00 {
/* .class00 {
min-height: 45rem;
}
} */
.class03 {
min-height: 60rem;
@ -2274,9 +2380,9 @@ defineExpose({
}
/* 调整图表容器高度 */
.class00 {
/* .class00 {
min-height: 40rem;
}
} */
.class03 {
min-height: 55rem;
@ -2440,9 +2546,9 @@ defineExpose({
}
/* 调整其他图表容器高度 */
.class00 {
/* .class00 {
min-height: 35rem;
}
} */
.class03 {
min-height: 45rem;
@ -2576,8 +2682,9 @@ defineExpose({
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
&::before {
.conclusion-item::before {
content: '';
position: absolute;
top: 0;
@ -2588,21 +2695,20 @@ defineExpose({
opacity: 0.8;
}
&:last-child {
.conclusion-item:last-child {
margin-bottom: 0;
}
.conclusion-title {
.conclusion-item .conclusion-title {
color: #FFD700;
font-size: 22px;
font-weight: bold;
margin: 0 0 15px 0;
text-align: center;
letter-spacing: 2px;
}
&::after {
.conclusion-item .conclusion-title::after {
content: '';
position: absolute;
bottom: -5px;
@ -2612,9 +2718,8 @@ defineExpose({
height: 2px;
background: linear-gradient(90deg, transparent, #00d4ff, transparent);
}
}
.conclusion-text {
.conclusion-item .conclusion-text {
color: #ffffff;
font-size: 20px;
line-height: 1.8;
@ -2623,8 +2728,9 @@ defineExpose({
word-wrap: break-word;
padding-left: 15px;
position: relative;
}
&::before {
.conclusion-item .conclusion-text::before {
content: '▶';
position: absolute;
left: 0;
@ -2634,12 +2740,10 @@ defineExpose({
opacity: 0.7;
}
&:last-child {
.conclusion-item .conclusion-text:last-child {
margin-bottom: 0;
}
}
}
}
.conclusion-placeholder {
padding: 30px;
@ -2647,31 +2751,29 @@ defineExpose({
border-radius: 12px;
background: rgba(255, 255, 255, 0.05);
border: 1px dashed rgba(153, 153, 153, 0.3);
}
p {
.conclusion-placeholder p {
color: #999999;
font-size: 16px;
margin: 0;
font-style: italic;
}
}
.disclaimer-item {
margin-top: 30px;
/* margin-top: 30px; */
padding: 20px;
border-top: 1px solid rgba(153, 153, 153, 0.2);
text-align: center;
}
p.disclaimer-text {
.disclaimer-item p {
color: #ffffff !important;
font-size: 14px;
font-size: 16px;
margin: 0;
font-style: italic;
opacity: 0.8;
letter-spacing: 1px;
}
}
}
.class05 {
background-size: 100% 100%;
@ -2817,9 +2919,9 @@ defineExpose({
}
/* 调整图表容器高度适配超小屏幕 */
.class00 {
/* .class00 {
min-height: 25rem;
}
} */
.class03 {
min-height: 35rem;

12
src/views/homePage.vue

@ -154,6 +154,8 @@ const messages = ref([]);
const isLoading = computed(() => {
chatStore.isLoading;
});
//
const isInputDisabled = ref(false);
//
const updateMessage = (title) => {
@ -178,8 +180,13 @@ const sendMessage = async () => {
// AiEmotion
if (activeTab.value === "AiEmotion") {
//
isInputDisabled.value = true;
// AiEmotion handleSendMessage
aiEmotionRef.value?.handleSendMessage(message.value);
aiEmotionRef.value?.handleSendMessage(message.value, () => {
//
isInputDisabled.value = false;
});
message.value = ""; //
return;
}
@ -672,7 +679,8 @@ onUnmounted(() => {
:autosize="{ minRows: 1, maxRows: 4 }"
placeholder="请输入股票名称或股票代码..."
class="msg-input"
@keydown.enter.exact.prevent="isLoading ? null : sendMessage()"
@keydown.enter.exact.prevent="(isLoading || isInputDisabled) ? null : sendMessage()"
:disabled="isInputDisabled"
resize="none"
>
</el-input>

4
vite.config.js

@ -38,10 +38,6 @@ export default defineConfig(({ command, mode }) => {
preprocessorOptions: {
scss: {
charset: false, // 避免出现: build时的 @charset 必须在第一行的警告
additionalData: `
@import "@/styles/mixin.scss";
@import "@/styles/variables.scss";
`,
},
},
},

Loading…
Cancel
Save