-
![思维矩阵图片]()
+
{{ stockName }}{{ stockName ? '量子四维矩阵图' : '' }}
@@ -206,6 +206,8 @@ const displayedTexts = ref({
disclaimer: ''
});
const typewriterTimers = ref([]);
+// 记录每个股票是否已经显示过打字机效果
+const stockTypewriterShown = ref(new Map());
// 音频播放相关数据
const audioUrl = ref('');
@@ -248,18 +250,45 @@ const parsedConclusion = computed(() => {
watch(currentStock, (newStock) => {
if (newStock && newStock.apiData) {
isPageLoaded.value = true;
+ // 停止当前播放的音频
+ stopAudio();
// 重置触发状态,允许新股票重新触发效果
hasTriggeredAudio.value = false;
hasTriggeredTypewriter.value = false;
- // 清空之前的显示文本
- displayedTexts.value = {
- one1: '',
- one2: '',
- two: '',
- three: '',
- four: '',
- disclaimer: ''
- };
+
+ // 获取股票代码作为唯一标识
+ const stockCode = newStock.stockInfo?.code || newStock.stockInfo?.symbol;
+
+ // 检查该股票是否已经显示过打字机效果
+ if (stockCode && stockTypewriterShown.value.has(stockCode)) {
+ // 如果已经显示过,直接显示完整文本
+ if (newStock.conclusionData) {
+ try {
+ const conclusion = JSON.parse(newStock.conclusionData);
+ displayedTexts.value = {
+ one1: conclusion.one1 || '',
+ one2: conclusion.one2 || '',
+ two: conclusion.two || '',
+ three: conclusion.three || '',
+ four: conclusion.four || '',
+ disclaimer: '该内容由AI内容生成,请注意甄别'
+ };
+ } catch (error) {
+ console.error('解析结论数据失败:', error);
+ }
+ }
+ } else {
+ // 如果没有显示过,清空显示文本,等待打字机效果
+ displayedTexts.value = {
+ one1: '',
+ one2: '',
+ two: '',
+ three: '',
+ four: '',
+ disclaimer: ''
+ };
+ }
+
nextTick(() => {
renderCharts(newStock.apiData);
});
@@ -273,30 +302,30 @@ watch(parsedConclusion, (newConclusion) => {
if (newConclusion) {
console.log('场景应用结论数据:', newConclusion);
// 不再立即开始打字机效果,等待滚动到场景应用部分时触发
-
+
// 尝试多种可能的语音URL字段名
- let voiceUrl = null;
- if (newConclusion.url) {
- // 清理URL字符串,去除空格、反引号等特殊字符
- voiceUrl = newConclusion.url.toString().trim().replace(/[`\s]/g, '');
- } else if (newConclusion.audioUrl) {
- voiceUrl = newConclusion.audioUrl.toString().trim().replace(/[`\s]/g, '');
- } else if (newConclusion.voice_url) {
- voiceUrl = newConclusion.voice_url.toString().trim().replace(/[`\s]/g, '');
- } else if (newConclusion.audio) {
- voiceUrl = newConclusion.audio.toString().trim().replace(/[`\s]/g, '');
- } else if (newConclusion.tts_url) {
- voiceUrl = newConclusion.tts_url.toString().trim().replace(/[`\s]/g, '');
- }
-
- if (voiceUrl && voiceUrl.startsWith('http')) {
- console.log('找到并清理后的语音URL:', voiceUrl);
- audioUrl.value = voiceUrl;
- console.log('音频URL已准备,等待滚动触发播放');
- } else {
- console.log('未找到有效的语音URL,原始URL:', newConclusion.url);
- console.log('结论数据中的所有字段:', Object.keys(newConclusion));
- }
+ let voiceUrl = null;
+ if (newConclusion.url) {
+ // 清理URL字符串,去除空格、反引号等特殊字符
+ voiceUrl = newConclusion.url.toString().trim().replace(/[`\s]/g, '');
+ } else if (newConclusion.audioUrl) {
+ voiceUrl = newConclusion.audioUrl.toString().trim().replace(/[`\s]/g, '');
+ } else if (newConclusion.voice_url) {
+ voiceUrl = newConclusion.voice_url.toString().trim().replace(/[`\s]/g, '');
+ } else if (newConclusion.audio) {
+ voiceUrl = newConclusion.audio.toString().trim().replace(/[`\s]/g, '');
+ } else if (newConclusion.tts_url) {
+ voiceUrl = newConclusion.tts_url.toString().trim().replace(/[`\s]/g, '');
+ }
+
+ if (voiceUrl && voiceUrl.startsWith('http')) {
+ console.log('找到并清理后的语音URL:', voiceUrl);
+ audioUrl.value = voiceUrl;
+ console.log('音频URL已准备,等待滚动触发播放');
+ } else {
+ console.log('未找到有效的语音URL,原始URL:', newConclusion.url);
+ console.log('结论数据中的所有字段:', Object.keys(newConclusion));
+ }
}
}, { immediate: true });
@@ -305,7 +334,7 @@ function startTypewriterEffect(conclusion) {
// 清除之前的定时器
typewriterTimers.value.forEach(timer => clearTimeout(timer));
typewriterTimers.value = [];
-
+
// 清空之前的显示文本
displayedTexts.value = {
one1: '',
@@ -315,41 +344,41 @@ function startTypewriterEffect(conclusion) {
four: '',
disclaimer: ''
};
-
+
// 定义打字速度(毫秒)
- const typeSpeed = 300;
+ const typeSpeed = 250;
let totalDelay = 0;
-
+
// 为每个文本创建打字机效果
const textKeys = ['one1', 'one2', 'two', 'three', 'four'];
-
+
textKeys.forEach((key) => {
if (conclusion[key]) {
const text = conclusion[key];
const startDelay = totalDelay;
-
+
for (let i = 0; i <= text.length; i++) {
const timer = setTimeout(() => {
displayedTexts.value[key] = text.substring(0, i);
}, startDelay + i * typeSpeed);
-
+
typewriterTimers.value.push(timer);
}
-
+
// 更新总延迟,为下一个文本留出时间
totalDelay += text.length * typeSpeed + 300; // 额外300ms间隔
}
});
-
+
// 添加免责声明的打字机效果(在所有内容显示完成后)
const disclaimerText = '该内容由AI内容生成,请注意甄别';
const disclaimerStartDelay = totalDelay + 500; // 额外500ms间隔
-
+
for (let i = 0; i <= disclaimerText.length; i++) {
const timer = setTimeout(() => {
displayedTexts.value.disclaimer = disclaimerText.substring(0, i);
}, disclaimerStartDelay + i * typeSpeed);
-
+
typewriterTimers.value.push(timer);
}
}
@@ -363,7 +392,7 @@ function clearTypewriterTimers() {
// 音频播放函数
function playAudio(url) {
console.log('尝试播放音频:', url);
-
+
if (!url) {
console.warn('音频URL为空,跳过播放');
isAudioPlaying.value = false;
@@ -376,7 +405,7 @@ function playAudio(url) {
console.log('语音功能已关闭,跳过播放');
return;
}
-
+
console.log('开始创建音频实例...');
try {
@@ -411,10 +440,10 @@ function playAudio(url) {
// 保存音频实例到store
audioStore.nowSound = newSound;
audioStore.setAudioInstance(newSound);
-
+
// 播放音频
newSound.play();
-
+
} catch (error) {
console.error('创建音频实例失败:', error);
isAudioPlaying.value = false;
@@ -649,13 +678,13 @@ function isDataLoaded() {
console.log('页面数据尚未加载完成');
return false;
}
-
+
// 检查当前股票数据是否存在
if (!currentStock.value || !currentStock.value.apiData) {
console.log('股票数据尚未加载完成');
return false;
}
-
+
// 检查图表组件是否已渲染
const requiredRefs = [
marketTemperatureRef.value,
@@ -663,13 +692,13 @@ function isDataLoaded() {
emotionalBottomRadarRef.value,
emoEnergyConverterRef.value
];
-
+
const allRefsLoaded = requiredRefs.every(ref => ref !== null);
if (!allRefsLoaded) {
console.log('图表组件尚未完全加载');
return false;
}
-
+
console.log('所有数据和组件已加载完成,可以开始滚动');
return true;
}
@@ -677,7 +706,7 @@ function isDataLoaded() {
// 自动滚动函数
function startAutoScroll() {
if (isAutoScrolling.value) return;
-
+
// 检查数据是否已加载完成
if (!isDataLoaded()) {
console.log('数据尚未加载完成,延迟1秒后重试');
@@ -686,134 +715,153 @@ function startAutoScroll() {
}, 1000);
return;
}
-
+
isAutoScrolling.value = true;
- const sections = document.querySelectorAll('.class02, .class03, .class04, .class05, .class06, .class08, .class09');
-
- let currentIndex = 0;
-
- function scrollToNextSection() {
- if (currentIndex < sections.length) {
- const section = sections[currentIndex];
-
- // 使用更平滑的滚动配置
- section.scrollIntoView({
- behavior: 'smooth',
- block: 'center', // 改为居中显示,视觉效果更好
- inline: 'nearest'
+ console.log('开始流畅自动滚动');
+
+ // 获取页面总高度
+ const documentHeight = document.documentElement.scrollHeight;
+ const windowHeight = window.innerHeight;
+ const maxScrollTop = documentHeight - windowHeight;
+
+ // 滚动参数
+ const scrollDuration = 15000; // 总滚动时间15秒
+ const scrollStep = maxScrollTop / (scrollDuration / 50); // 每50ms滚动的距离
+ let currentScrollTop = 0;
+
+ function smoothScroll() {
+ if (currentScrollTop < maxScrollTop) {
+ currentScrollTop += scrollStep;
+ if (currentScrollTop > maxScrollTop) {
+ currentScrollTop = maxScrollTop;
+ }
+
+ window.scrollTo({
+ top: currentScrollTop,
+ behavior: 'auto' // 使用auto而不是smooth,因为我们自己控制滚动
});
-
- console.log(`滚动到第${currentIndex + 1}个部分`);
- currentSection.value = currentIndex;
- currentIndex++;
-
- // 增加滚动间隔时间,让用户有更多时间观看内容
- setTimeout(scrollToNextSection, 4000); // 从2秒增加到4秒
+
+ // 继续滚动
+ setTimeout(smoothScroll, 50);
} else {
- console.log('自动滚动完成');
+ console.log('流畅自动滚动完成');
isAutoScrolling.value = false;
}
}
-
- // 开始滚动前等待2秒,给用户准备时间
- console.log('自动滚动将在2秒后开始');
- setTimeout(scrollToNextSection, 2000);
+
+ // 延迟1秒开始滚动
+ setTimeout(smoothScroll, 1000);
}
// 设置Intersection Observer监听场景应用部分
- function setupIntersectionObserver() {
- if (!scenarioApplicationRef.value) return;
-
- const observer = new IntersectionObserver(
- (entries) => {
- entries.forEach((entry) => {
- if (entry.isIntersecting && (!hasTriggeredAudio.value || !hasTriggeredTypewriter.value)) {
- console.log('场景应用部分进入视口,开始打字机效果和音频播放');
-
- // 触发打字机效果
- if (!hasTriggeredTypewriter.value && parsedConclusion.value) {
- console.log('开始场景应用打字机效果');
- hasTriggeredTypewriter.value = true;
- startTypewriterEffect(parsedConclusion.value);
- }
-
- // 触发音频播放
- if (!hasTriggeredAudio.value && audioUrl.value && parsedConclusion.value) {
- console.log('自动触发场景应用音频播放');
- hasTriggeredAudio.value = true;
- playAudio(audioUrl.value);
- }
- }
- });
- },
- {
- threshold: 0.3, // 当30%的元素进入视口时触发
- rootMargin: '0px 0px -100px 0px' // 提前100px触发
- }
- );
-
- observer.observe(scenarioApplicationRef.value);
- intersectionObserver.value = observer;
- }
-
- // 手动触发自动滚动
- function triggerAutoScroll() {
- // 检查是否正在滚动
- if (isAutoScrolling.value) {
- console.log('自动滚动正在进行中,请稍候');
- return;
- }
-
- // 检查数据是否已准备好
- if (!isDataLoaded()) {
- console.log('数据尚未准备完成,请等待数据加载后再试');
- // 可以显示提示信息给用户
- return;
- }
-
- console.log('手动触发自动滚动');
- startAutoScroll();
- }
+function setupIntersectionObserver() {
+ if (!scenarioApplicationRef.value) return;
+
+ const observer = new IntersectionObserver(
+ (entries) => {
+ entries.forEach((entry) => {
+ if (entry.isIntersecting && (!hasTriggeredAudio.value || !hasTriggeredTypewriter.value)) {
+ console.log('场景应用部分进入视口,开始打字机效果和音频播放');
+
+ // 获取当前股票代码
+ const stockCode = currentStock.value?.stockInfo?.code || currentStock.value?.stockInfo?.symbol;
+
+ // 触发打字机效果
+ if (!hasTriggeredTypewriter.value && parsedConclusion.value && stockCode) {
+ // 检查该股票是否已经显示过打字机效果
+ if (!stockTypewriterShown.value.has(stockCode)) {
+ console.log('开始场景应用打字机效果');
+ hasTriggeredTypewriter.value = true;
+ startTypewriterEffect(parsedConclusion.value);
+ // 记录该股票已显示过打字机效果
+ stockTypewriterShown.value.set(stockCode, true);
+ } else {
+ console.log('该股票已显示过打字机效果,跳过');
+ hasTriggeredTypewriter.value = true;
+ }
+ }
+
+ // 触发音频播放
+ if (!hasTriggeredAudio.value && audioUrl.value && parsedConclusion.value) {
+ console.log('自动触发场景应用音频播放');
+ hasTriggeredAudio.value = true;
+ playAudio(audioUrl.value);
+ }
+ }
+ });
+ },
+ {
+ threshold: 0.3, // 当30%的元素进入视口时触发
+ rootMargin: '0px 0px -100px 0px' // 提前100px触发
+ }
+ );
+
+ observer.observe(scenarioApplicationRef.value);
+ intersectionObserver.value = observer;
+}
+
+// 手动触发自动滚动
+function triggerAutoScroll() {
+ // 检查是否正在滚动
+ if (isAutoScrolling.value) {
+ console.log('自动滚动正在进行中,请稍候');
+ return;
+ }
+
+ // 检查数据是否已准备好
+ if (!isDataLoaded()) {
+ console.log('数据尚未准备完成,请等待数据加载后再试');
+ // 可以显示提示信息给用户
+ return;
+ }
+
+ console.log('手动触发自动滚动');
+ startAutoScroll();
+}
// 页面挂载完成后触发图片旋转和设置滚动监听
- onMounted(() => {
- startImageRotation();
-
- // 等待DOM完全渲染后设置监听器
- nextTick(() => {
- setupIntersectionObserver();
-
- // 页面加载完成后自动开始滚动
- setTimeout(() => {
- triggerAutoScroll();
- }, 1000); // 延迟1秒开始滚动,确保页面完全渲染
- });
- });
-
- // 组件卸载时清理定时器、音频和observer
- onUnmounted(() => {
- clearTypewriterTimers();
- stopAudio();
-
- // 重置触发状态
- hasTriggeredAudio.value = false;
- hasTriggeredTypewriter.value = false;
-
- // 清理Intersection Observer
- if (intersectionObserver.value) {
- intersectionObserver.value.disconnect();
- intersectionObserver.value = null;
- }
- });
-
- // 导出方法供外部使用
- defineExpose({
- handleSendMessage,
- triggerAutoScroll
- });
+onMounted(() => {
+ startImageRotation();
+
+ // 等待DOM完全渲染后设置监听器
+ nextTick(() => {
+ setupIntersectionObserver();
+
+ // 页面加载完成后自动开始滚动
+ setTimeout(() => {
+ triggerAutoScroll();
+ }, 1000); // 延迟1秒开始滚动,确保页面完全渲染
+ });
+});
+
+// 组件卸载时清理定时器、音频和observer
+onUnmounted(() => {
+ clearTypewriterTimers();
+ stopAudio();
+
+ // 重置触发状态
+ hasTriggeredAudio.value = false;
+ hasTriggeredTypewriter.value = false;
+
+ // 清理Intersection Observer
+ if (intersectionObserver.value) {
+ intersectionObserver.value.disconnect();
+ intersectionObserver.value = null;
+ }
+});
+
+// 导出方法供外部使用
+defineExpose({
+ handleSendMessage,
+ triggerAutoScroll
+});
\ No newline at end of file
diff --git a/src/views/components/emotionalBottomRadar.vue b/src/views/components/emotionalBottomRadar.vue
index 20f0561..83fdd1a 100644
--- a/src/views/components/emotionalBottomRadar.vue
+++ b/src/views/components/emotionalBottomRadar.vue
@@ -185,7 +185,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
axisLine: {
// show: false,
lineStyle: {
- color: '#837b7b', // x轴线颜色
+ color: 'white', // x轴线颜色
}
},
axisTick: {
@@ -212,7 +212,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
// show: false,
lineStyle: {
// color: '#008000'
- color: '#837b7b'
+ color: 'white'
}
},
axisTick: {
@@ -236,7 +236,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
gridIndex: 2,
axisLine: {
lineStyle: {
- color: '#837b7b'
+ color: 'white'
}
},
axisTick: {
@@ -249,7 +249,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
}
},
axisLabel: {
- color: '#000000',
+ color: 'white',
interval: 'auto',
rotate: 45
},
@@ -270,7 +270,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
splitNumber: 4,
axisLine: {
lineStyle: {
- color: '#837b7b' // y轴坐标轴颜色
+ color: 'white' // y轴坐标轴颜色
}
},
axisTick: {
@@ -278,7 +278,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
},
axisLabel: {
width: 50, // 宽度限制
- color: '#000000',
+ color: 'white',
formatter: function (value, index) {
if (index === 0) {
return '0'
@@ -302,7 +302,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
splitNumber: 3,
axisLine: {
lineStyle: {
- color: '#837b7b'
+ color: 'white'
}
},
axisTick: {
@@ -311,7 +311,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
splitNumber: 5, // 刻度数量
axisLabel: {
width: 50, // 宽度限制
- color: '#000000',
+ color: 'white',
formatter: function (value, index) {
// 如果没有刻度数量,其他方法获取不到y轴刻度总长
if (index === 0) {
@@ -336,7 +336,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
splitNumber: 2,
axisLine: {
lineStyle: {
- color: '#837b7b'
+ color: 'white'
}
},
axisTick: {
@@ -345,7 +345,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
splitNumber: 5, // 刻度数量
axisLabel: {
width: 50, // 宽度限制
- color: '#000000',
+ color: 'white',
formatter: function (value, index) {
if (index === 5) {
return ''
diff --git a/src/views/components/marketTemperature.vue b/src/views/components/marketTemperature.vue
index 33680ce..3a3a86e 100644
--- a/src/views/components/marketTemperature.vue
+++ b/src/views/components/marketTemperature.vue
@@ -190,14 +190,29 @@ function initChart(raw, klineDataRawValue, WDRLValue) {
// 创建新的图表实例
chartInstance = echarts.init(KlineCanvs.value)
chartInstance.setOption({
- tooltip: {},
+ tooltip: {
+ formatter: function (params) {
+ if (params.seriesType === 'candlestick') {
+ const date = params.name
+ // 开收低高分别取参数的第2到第5个数
+ const open = params.data[1]
+ const close = params.data[2]
+ const low = params.data[3]
+ const high = params.data[4]
+ return `日期: ${date}
开: ${open}
收: ${close}
低: ${low}
高: ${high}`
+ }
+ return params.value[2]
+ }
+ },
legend: { data: ['K线', '市场温度', '股票温度'], textStyle: { color: 'white' } },
xAxis: {
type: 'category',
data: dateLabels,
- axisLine: { lineStyle: { color: '#8392A5' } }
+ axisLine: { lineStyle: { color: 'white' } }
},
- yAxis: [{}, {
+ yAxis: [{
+ axisLine: { lineStyle: { color: 'white' } }
+ }, {
min: 0,
max: 100,
position: 'right',
@@ -210,7 +225,14 @@ function initChart(raw, klineDataRawValue, WDRLValue) {
name: 'K线',
type: 'candlestick',
data: klineData,
- itemStyle: { color: '#0CF49B', color0: '#FD1050' }
+ itemStyle: {
+ normal: {
+ color: '#FF0000', // 阳线红色
+ color0: '#00FF00', // 阴线绿色
+ borderColor: '#FF0000', // 阳线边框红色
+ borderColor0: '#00FF00' // 阴线边框绿色
+ }
+ }
},
{
name: '市场温度',
@@ -255,8 +277,6 @@ function initChart(raw, klineDataRawValue, WDRLValue) {
adjustCellFontSize()
}
-
-
// 调整单元格字体大小
function adjustCellFontSize() {
const table = document.querySelector('.border4 .el-table')