Browse Source

股票数据存储到会话;重新渲染图表的方法;情绪大模型取消自动滚动;图表超出容器优化

songjie/feature-20250628160649-上线前优化
宋杰 3 days ago
parent
commit
a5beddb872
  1. 2
      src/store/emotion.ts
  2. 131
      src/utils/chartResize.js
  3. 474
      src/views/AiEmotion.vue
  4. 79
      src/views/components/emoEnergyConverter.vue
  5. 100
      src/views/components/emotionDecod.vue
  6. 56
      src/views/components/emotionalBottomRadar.vue
  7. 67
      src/views/components/marketTemperature.vue

2
src/store/emotion.ts

@ -10,7 +10,7 @@ export const useEmotionStore = defineStore('emotion', {
}), }),
persist: { persist: {
key: 'emotion-store', key: 'emotion-store',
storage: localStorage,
storage: sessionStorage,
paths: ['history', 'stockList', 'activeStockIndex'] paths: ['history', 'stockList', 'activeStockIndex']
}, },
getters: { getters: {

131
src/utils/chartResize.js

@ -0,0 +1,131 @@
/**
* 图表响应式工具函数
* 统一处理ECharts图表的响应式调整
*/
/**
* 防抖函数
* @param {Function} func 要防抖的函数
* @param {number} wait 防抖延迟时间毫秒
* @returns {Function} 防抖后的函数
*/
export function debounce(func, wait = 100) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/**
* 创建图表响应式处理器
* @param {Object} options 配置选项
* @param {Object} options.chart ECharts图表实例
* @param {Object} options.container 图表容器DOM元素
* @param {Object} options.option 图表配置项
* @param {Function} options.beforeResize 在resize前执行的回调函数
* @param {string} options.name 图表名称用于日志
* @returns {Object} 包含清理函数的对象
*/
export function createChartResizeHandler(options) {
const { chart, container, option, beforeResize, name = '图表' } = options;
if (!chart || !container) {
console.warn(`${name}: 图表实例或容器不存在`);
return { cleanup: () => {} };
}
// 图表resize处理函数
const handleResize = debounce(() => {
if (chart && !chart.isDisposed()) {
try {
// 执行resize前的回调
if (typeof beforeResize === 'function') {
beforeResize();
}
// 如果有配置项,重新设置以确保布局更新
if (option) {
chart.setOption(option, true);
}
// 调用图表resize方法
chart.resize();
console.log(`${name}响应式调整完成`);
} catch (error) {
console.error(`${name}响应式调整失败:`, error);
}
}
}, 100);
// 窗口resize监听器
const windowResizeHandler = handleResize;
// 容器resize观察器
let containerObserver = null;
if (window.ResizeObserver) {
containerObserver = new ResizeObserver(handleResize);
containerObserver.observe(container);
}
// 添加窗口resize监听
window.addEventListener('resize', windowResizeHandler);
// 返回清理函数
return {
cleanup: () => {
// 移除窗口resize监听
window.removeEventListener('resize', windowResizeHandler);
// 断开容器观察器
if (containerObserver) {
containerObserver.disconnect();
containerObserver = null;
}
console.log(`${name}响应式监听器已清理`);
},
// 手动触发resize
triggerResize: handleResize
};
}
/**
* 为图表容器添加响应式样式
* @param {HTMLElement} container 图表容器元素
*/
export function applyResponsiveStyles(container) {
if (!container) return;
const styles = {
width: '100%',
boxSizing: 'border-box',
overflow: 'hidden',
margin: '0',
padding: '0'
};
Object.assign(container.style, styles);
}
/**
* 检查图表容器是否具有响应式样式
* @param {HTMLElement} container 图表容器元素
* @returns {boolean} 是否具有响应式样式
*/
export function checkResponsiveStyles(container) {
if (!container) return false;
const computedStyle = window.getComputedStyle(container);
const hasResponsiveWidth = computedStyle.width === '100%' || computedStyle.width.includes('%');
const hasBoxSizing = computedStyle.boxSizing === 'border-box';
const hasOverflowHidden = computedStyle.overflow === 'hidden';
return hasResponsiveWidth && hasBoxSizing && hasOverflowHidden;
}

474
src/views/AiEmotion.vue

@ -53,7 +53,7 @@
<div class="class003"> <div class="class003">
<div class="content1"> <div class="content1">
<img class="img01" src="@/assets/img/AiEmotion/温度计.png" alt="温度计图标"> <img class="img01" src="@/assets/img/AiEmotion/温度计.png" alt="温度计图标">
<span class="title1">温度计</span>
<span class="title1">温度计</span>
</div> </div>
<div class="div00"> <div class="div00">
<div class="div01">股票温度{{ data2 ?? "NA" }}</div> <div class="div01">股票温度{{ data2 ?? "NA" }}</div>
@ -1185,54 +1185,11 @@ function isDataLoaded() {
return true; return true;
} }
//
//
function startAutoScroll() { function startAutoScroll() {
if (isAutoScrolling.value) return;
//
if (!isDataLoaded()) {
console.log('数据尚未加载完成,延迟1秒后重试');
setTimeout(() => {
startAutoScroll();
}, 1000);
return;
}
isAutoScrolling.value = true;
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' // 使autosmooth
});
//
setTimeout(smoothScroll, 50);
} else {
console.log('流畅自动滚动完成');
isAutoScrolling.value = false;
}
}
// 1
setTimeout(smoothScroll, 1000);
//
console.log('自动滚动功能已被禁用');
return;
} }
// Intersection Observer // Intersection Observer
@ -1325,23 +1282,11 @@ function setupIntersectionObserver() {
intersectionObserver.value = observer; intersectionObserver.value = observer;
} }
//
//
function triggerAutoScroll() { function triggerAutoScroll() {
//
if (isAutoScrolling.value) {
console.log('自动滚动正在进行中,请稍候');
return;
}
//
if (!isDataLoaded()) {
console.log('数据尚未准备完成,请等待数据加载后再试');
//
return;
}
console.log('手动触发自动滚动');
startAutoScroll();
//
console.log('自动滚动功能已被禁用');
return;
} }
// //
@ -1349,10 +1294,77 @@ onMounted(async () => {
// //
try { try {
await chatStore.getUserCount(); await chatStore.getUserCount();
console.log('情绪大模型页面:用户次数获取成功');
console.log('情绪大模型页面:用户次数获取成功');
} catch (error) { } catch (error) {
console.error('情绪大模型页面:获取用户次数失败', error); console.error('情绪大模型页面:获取用户次数失败', error);
} }
// resize
const globalResizeHandler = debounce(() => {
console.log('AiEmotion页面:窗口大小变化,触发容器和图表resize');
//
const mainContainer = document.querySelector('.class01');
if (mainContainer) {
//
mainContainer.style.display = 'none';
mainContainer.offsetHeight; //
mainContainer.style.display = '';
}
// resize
const resizeHandlers = [
window.emoEnergyConverterResizeHandler,
window.marketTempResizeHandler,
window.emotionalBottomRadarResizeHandler,
window.emotionDecodResizeHandler
];
resizeHandlers.forEach(handler => {
if (typeof handler === 'function') {
try {
handler();
} catch (error) {
console.error('AiEmotion页面:图表resize失败', error);
}
}
});
// resize
setTimeout(() => {
resizeHandlers.forEach(handler => {
if (typeof handler === 'function') {
try {
handler();
} catch (error) {
console.error('AiEmotion页面:延迟图表resize失败', error);
}
}
});
}, 100);
}, 150); // 150ms
//
if (window.aiEmotionGlobalResizeHandler) {
window.removeEventListener('resize', window.aiEmotionGlobalResizeHandler);
}
//
window.addEventListener('resize', globalResizeHandler);
window.aiEmotionGlobalResizeHandler = globalResizeHandler;
//
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
startImageRotation(); startImageRotation();
@ -1406,6 +1418,12 @@ onUnmounted(() => {
intersectionObserver.value.disconnect(); intersectionObserver.value.disconnect();
intersectionObserver.value = null; intersectionObserver.value = null;
} }
// resize
if (window.aiEmotionGlobalResizeHandler) {
window.removeEventListener('resize', window.aiEmotionGlobalResizeHandler);
window.aiEmotionGlobalResizeHandler = null;
}
}); });
// //
@ -1432,6 +1450,26 @@ defineExpose({
.class003 { .class003 {
padding-top: 8%; padding-top: 8%;
padding-left: 10%; padding-left: 10%;
display: flex;
flex-direction: column;
gap: 1rem;
}
.div00 {
display: flex;
flex-direction: row;
gap: 2%;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
width: 100%;
box-sizing: border-box;
}
.div00::after {
content: "";
display: table;
clear: both;
} }
.class003 .div02 { .class003 .div02 {
@ -1439,16 +1477,15 @@ defineExpose({
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
width: 35%; width: 35%;
min-width: 200px;
min-height: 40px; min-height: 40px;
float: left;
margin-left: 9%;
margin-top: 2%;
text-align: center; text-align: center;
font-size: 24px; font-size: 24px;
color: white; color: white;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-shrink: 0;
} }
.class003 .div01 { .class003 .div01 {
@ -1456,15 +1493,15 @@ defineExpose({
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
width: 35%; width: 35%;
min-width: 200px;
min-height: 40px; min-height: 40px;
float: left;
margin-left: 9%;
text-align: center; text-align: center;
font-size: 24px; font-size: 24px;
color: white; color: white;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-shrink: 0;
} }
.golden-wheel { .golden-wheel {
@ -1516,7 +1553,6 @@ defineExpose({
background: linear-gradient(135deg, rgba(0, 212, 255, 0.15) 0%, rgba(0, 100, 200, 0.15) 100%); background: linear-gradient(135deg, rgba(0, 212, 255, 0.15) 0%, rgba(0, 100, 200, 0.15) 100%);
border: 2px solid rgba(0, 212, 255, 0.4); border: 2px solid rgba(0, 212, 255, 0.4);
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1); box-shadow: 0 8px 25px rgba(0, 212, 255, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1);
backdrop-filter: blur(15px);
.conclusion-item { .conclusion-item {
margin-bottom: 20px; margin-bottom: 20px;
@ -1624,7 +1660,6 @@ defineExpose({
background: linear-gradient(135deg, rgba(0, 212, 255, 0.15) 0%, rgba(0, 100, 200, 0.15) 100%); background: linear-gradient(135deg, rgba(0, 212, 255, 0.15) 0%, rgba(0, 100, 200, 0.15) 100%);
border: 2px solid rgba(0, 212, 255, 0.4); border: 2px solid rgba(0, 212, 255, 0.4);
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1); box-shadow: 0 8px 25px rgba(0, 212, 255, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1);
backdrop-filter: blur(15px);
} }
.text-container p { .text-container p {
@ -1854,13 +1889,19 @@ defineExpose({
/* 确保背景图片完整显示 */ /* 确保背景图片完整显示 */
background-repeat: no-repeat; background-repeat: no-repeat;
/* 防止背景图片重复 */ /* 防止背景图片重复 */
width: 95%;
/* 设置容器宽度 */
width: 100%;
/* 响应式容器宽度 */
max-width: 100%;
/* 确保不超出父容器 */
height: auto; height: auto;
/* 高度根据内容动态变化 */ /* 高度根据内容动态变化 */
min-height: 69rem; min-height: 69rem;
/* 设置最小高度,确保图片显示 */ /* 设置最小高度,确保图片显示 */
margin: 0 auto; margin: 0 auto;
box-sizing: border-box;
/* 包括内边距在宽度计算中 */
transition: all 0.3s ease;
/* 添加平滑过渡效果 */
} }
.class05 { .class05 {
@ -1870,13 +1911,19 @@ defineExpose({
/* 确保背景图片完整显示 */ /* 确保背景图片完整显示 */
background-repeat: no-repeat; background-repeat: no-repeat;
/* 防止背景图片重复 */ /* 防止背景图片重复 */
width: 95%;
/* 设置容器宽度 */
width: 100%;
/* 响应式容器宽度 */
max-width: 100%;
/* 确保不超出父容器 */
height: auto; height: auto;
/* 高度根据内容动态变化 */ /* 高度根据内容动态变化 */
min-height: 90rem; min-height: 90rem;
/* 设置最小高度,确保图片显示 */ /* 设置最小高度,确保图片显示 */
margin: 0 auto; margin: 0 auto;
box-sizing: border-box;
/* 包括内边距在宽度计算中 */
transition: all 0.3s ease;
/* 添加平滑过渡效果 */
} }
.class04 { .class04 {
@ -1886,13 +1933,19 @@ defineExpose({
/* 确保背景图片完整显示 */ /* 确保背景图片完整显示 */
background-repeat: no-repeat; background-repeat: no-repeat;
/* 防止背景图片重复 */ /* 防止背景图片重复 */
width: 95%;
/* 设置容器宽度 */
width: 100%;
/* 响应式容器宽度 */
max-width: 100%;
/* 确保不超出父容器 */
height: auto; height: auto;
/* 高度根据内容动态变化 */ /* 高度根据内容动态变化 */
min-height: 75rem; min-height: 75rem;
/* 设置最小高度,确保图片显示 */ /* 设置最小高度,确保图片显示 */
margin: 0 auto; margin: 0 auto;
box-sizing: border-box;
/* 包括内边距在宽度计算中 */
transition: all 0.3s ease;
/* 添加平滑过渡效果 */
} }
.class03 { .class03 {
@ -1903,17 +1956,18 @@ defineExpose({
background-repeat: no-repeat; background-repeat: no-repeat;
/* 防止背景图片重复 */ /* 防止背景图片重复 */
width: 100%; width: 100%;
/* 设置容器宽度 */
/* 响应式容器宽度 */
max-width: 100%;
/* 确保不超出父容器 */
height: auto; height: auto;
/* 高度根据内容动态变化 */ /* 高度根据内容动态变化 */
min-height: 70rem; min-height: 70rem;
/* 设置最小高度,确保图片显示 */ /* 设置最小高度,确保图片显示 */
margin: 0 auto; margin: 0 auto;
/* display: flex;
flex-direction:row;
align-items: center;
padding: 1rem;
gap: 1rem; */
box-sizing: border-box;
/* 包括内边距在宽度计算中 */
transition: all 0.3s ease;
/* 添加平滑过渡效果 */
} }
.class00 { .class00 {
@ -1921,13 +1975,19 @@ defineExpose({
/* 确保背景图片完整显示 */ /* 确保背景图片完整显示 */
background-repeat: no-repeat; background-repeat: no-repeat;
/* 防止背景图片重复 */ /* 防止背景图片重复 */
width: 95%;
/* 设置容器宽度 */
width: 100%;
/* 响应式容器宽度 */
max-width: 100%;
/* 确保不超出父容器 */
height: auto; height: auto;
/* 高度根据内容动态变化 */ /* 高度根据内容动态变化 */
min-height: 55rem; min-height: 55rem;
/* 设置最小高度,确保图片显示 */ /* 设置最小高度,确保图片显示 */
margin: 0 auto; margin: 0 auto;
box-sizing: border-box;
/* 包括内边距在宽度计算中 */
transition: all 0.3s ease;
/* 添加平滑过渡效果 */
} }
.content1 { .content1 {
@ -1955,7 +2015,7 @@ defineExpose({
display: flex; display: flex;
flex-direction: column; flex-direction: column;
/* 竖向排列元素 */ /* 竖向排列元素 */
margin-left: 37%;
margin-left: 15%;
gap: 1rem; gap: 1rem;
margin-top: -12%; margin-top: -12%;
width: 100%; width: 100%;
@ -1992,18 +2052,25 @@ defineExpose({
} }
.class01 { .class01 {
width: 100%;
/* 固定容器宽度 */
width: 90%;
/* 响应式容器宽度 */
max-width: 1400px;
/* 设置最大宽度,避免在大屏幕上过度拉伸 */
min-width: 320px;
/* 设置最小宽度,确保在小屏幕上可用 */
min-height: 100px; min-height: 100px;
/* 设置最小高度,确保初始显示 */ /* 设置最小高度,确保初始显示 */
height: auto; height: auto;
/* 高度根据内容动态变化 */ /* 高度根据内容动态变化 */
padding: 1rem;
/* 添加内边距,确保内容与边界有间距 */ /* 添加内边距,确保内容与边界有间距 */
box-sizing: border-box; box-sizing: border-box;
/* 包括内边距在宽度和高度计算中 */ /* 包括内边距在宽度和高度计算中 */
background-color: #02107d;
background-color: #2b378d;
margin: 0 auto; margin: 0 auto;
/* 居中容器 */ /* 居中容器 */
transition: width 0.3s ease;
/* 添加平滑过渡效果 */
margin-bottom: 10rem; margin-bottom: 10rem;
} }
@ -2095,8 +2162,115 @@ defineExpose({
background-color: #0056b3; background-color: #0056b3;
} }
/* 响应式布局媒体查询 */
@media only screen and (max-width: 1200px) {
.class01 {
width: 95%;
padding: 0.8rem;
}
.span01 {
width: 40%;
font-size: 1.3rem;
}
.span02 {
font-size: 1.3rem;
}
/* 调整图表容器高度 */
.class00 {
min-height: 45rem;
}
.class03 {
min-height: 60rem;
}
.class04 {
min-height: 65rem;
}
.class05 {
min-height: 75rem;
}
.class06 {
min-height: 58rem;
}
.class08 {
min-height: 42rem;
}
.scaled-img {
height: 350px;
min-height: 30rem;
}
}
@media only screen and (max-width: 992px) {
.class01 {
width: 98%;
padding: 0.6rem;
}
.class003 {
padding-top: 6%;
padding-left: 5%;
}
.div00 {
gap: 1%;
justify-content: center;
}
.class003 .div01,
.class003 .div02 {
width: 45%;
min-width: 180px;
font-size: 20px;
}
/* 调整图表容器高度 */
.class00 {
min-height: 40rem;
}
.class03 {
min-height: 55rem;
}
.class04 {
min-height: 55rem;
}
.class05 {
min-height: 65rem;
}
.class06 {
min-height: 50rem;
}
.class08 {
min-height: 35rem;
}
.scaled-img {
height: 300px;
min-height: 25rem;
}
}
/* 手机端适配样式 */ /* 手机端适配样式 */
@media only screen and (max-width: 768px) { @media only screen and (max-width: 768px) {
.class01 {
width: 100%;
padding: 0.5rem;
margin-bottom: 5rem;
}
.container { .container {
padding-top: 2%; padding-top: 2%;
} }
@ -2232,6 +2406,23 @@ defineExpose({
/* margin-left: -39px; */ /* margin-left: -39px; */
/* min-height: 38rem; */ /* min-height: 38rem; */
} }
/* 调整其他图表容器高度 */
.class00 {
min-height: 35rem;
}
.class03 {
min-height: 45rem;
}
.class05 {
min-height: 48rem;
}
.class06 {
min-height: 35rem;
}
.class02 .container img { .class02 .container img {
width: 68%; width: 68%;
@ -2543,6 +2734,108 @@ defineExpose({
.class0601 { .class0601 {
padding-top: 10%; padding-top: 10%;
} }
.class003 {
padding-top: 4%;
padding-left: 2%;
}
.div00 {
flex-direction: column;
gap: 1rem;
align-items: center;
}
.class003 .div01,
.class003 .div02 {
width: 80%;
min-width: 250px;
font-size: 16px;
min-height: 35px;
}
.span01 {
width: 60%;
font-size: 1.2rem;
padding: 8px;
}
.span02 {
font-size: 1.2rem;
margin-top: -3%;
}
.title1, .title2, .title3, .title4 {
font-size: 18px;
margin-left: 0;
}
}
/* 超小屏幕设备 */
@media only screen and (max-width: 480px) {
.class01 {
width: 100%;
padding: 0.3rem;
margin-bottom: 3rem;
}
.div00 {
flex-direction: column;
gap: 0.8rem;
align-items: center;
}
.class003 .div01,
.class003 .div02 {
width: 90%;
min-width: 200px;
font-size: 14px;
min-height: 30px;
}
.span01 {
width: 70%;
font-size: 1rem;
padding: 6px;
}
.span02 {
font-size: 1rem;
}
.golden-wheel-img {
width: 80%;
}
/* 调整图表容器高度适配超小屏幕 */
.class00 {
min-height: 25rem;
}
.class03 {
min-height: 35rem;
}
.class04 {
min-height: 30rem;
}
.class05 {
min-height: 35rem;
}
.class06 {
min-height: 25rem;
}
.class08 {
min-height: 15rem;
}
.scaled-img {
height: 150px;
min-height: 150px;
}
} }
/* 加载提示样式 */ /* 加载提示样式 */
@ -2560,7 +2853,6 @@ defineExpose({
border: 2px solid rgba(0, 212, 255, 0.4); border: 2px solid rgba(0, 212, 255, 0.4);
border-radius: 20px; border-radius: 20px;
padding: 40px; padding: 40px;
backdrop-filter: blur(15px);
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.3); box-shadow: 0 8px 25px rgba(0, 212, 255, 0.3);
} }

79
src/views/components/emoEnergyConverter.vue

@ -538,33 +538,96 @@ function initQXNLZHEcharts(kline, qxnlzhqData) {
}; };
// //
qxnlzhqEchartsInstance.setOption(option); qxnlzhqEchartsInstance.setOption(option);
// resize
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
// //
window.addEventListener('resize', () => {
qxnlzhqEchartsInstance.resize()
})
const resizeHandler = debounce(() => {
if (qxnlzhqEchartsInstance && !qxnlzhqEchartsInstance.isDisposed()) {
try {
qxnlzhqEchartsInstance.resize();
console.log('情绪能量转化器图表已重新调整大小');
} catch (error) {
console.error('情绪能量转化器图表resize失败:', error);
}
}
}, 100); // 100ms
//
if (window.emoEnergyConverterResizeHandler) {
window.removeEventListener('resize', window.emoEnergyConverterResizeHandler);
}
//
window.addEventListener('resize', resizeHandler);
// resize便
window.emoEnergyConverterResizeHandler = resizeHandler;
//
if (qxnlzhqEchartsRef.value && window.ResizeObserver) {
const containerObserver = new ResizeObserver(debounce(() => {
if (qxnlzhqEchartsInstance && !qxnlzhqEchartsInstance.isDisposed()) {
try {
qxnlzhqEchartsInstance.resize();
console.log('情绪能量转化器容器大小变化,图表已调整');
} catch (error) {
console.error('情绪能量转化器容器resize失败:', error);
}
}
}, 100));
containerObserver.observe(qxnlzhqEchartsRef.value);
window.emoEnergyConverterContainerObserver = containerObserver;
}
} }
onBeforeUnmount(() => { onBeforeUnmount(() => {
// //
if (qxnlzhqEchartsInstance) { if (qxnlzhqEchartsInstance) {
qxnlzhqEchartsInstance.dispose(); qxnlzhqEchartsInstance.dispose();
qxnlzhqEchartsInstance = null;
}
// resize
if (window.emoEnergyConverterResizeHandler) {
window.removeEventListener('resize', window.emoEnergyConverterResizeHandler);
window.emoEnergyConverterResizeHandler = null;
}
//
if (window.emoEnergyConverterContainerObserver) {
window.emoEnergyConverterContainerObserver.disconnect();
window.emoEnergyConverterContainerObserver = null;
} }
}); });
</script> </script>
<style scoped> <style scoped>
#qxnlzhqEcharts { #qxnlzhqEcharts {
min-width: 100%;
width: 100%;
height: 700px; height: 700px;
margin-left: -1rem;
margin: 0;
box-sizing: border-box;
overflow: hidden;
} }
/* 手机端适配样式 */ /* 手机端适配样式 */
@media only screen and (max-width: 768px) { @media only screen and (max-width: 768px) {
#qxnlzhqEcharts { #qxnlzhqEcharts {
min-width: 100%;
width: 100%;
height: 300px; height: 300px;
margin-left: -1rem;
margin-top: -5rem;
margin: 0;
} }
} }

100
src/views/components/emotionDecod.vue

@ -251,7 +251,7 @@ function initQXNLZHEcharts(kline, qxnlzhqData) {
shadowOffsetX: 2, shadowOffsetX: 2,
shadowOffsetY: 2, shadowOffsetY: 2,
}, },
bottom: "5%", //
bottom: "10%", //
}, },
{ {
show: !1, show: !1,
@ -354,23 +354,96 @@ function initQXNLZHEcharts(kline, qxnlzhqData) {
// echarts // echarts
KlineCanvsChart = echarts.init(KlineCanvs.value); KlineCanvsChart = echarts.init(KlineCanvs.value);
KlineCanvsChart.setOption(KlineOption); KlineCanvsChart.setOption(KlineOption);
//
window.addEventListener("resize", () => {
KlineCanvsChart.resize();
});
// resize
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
//
const resizeHandler = debounce(() => {
if (KlineCanvsChart && !KlineCanvsChart.isDisposed()) {
try {
KlineCanvsChart.resize();
console.log('情绪解码器图表已重新调整大小');
} catch (error) {
console.error('情绪解码器图表resize失败:', error);
}
}
}, 100); // 100ms
//
if (window.emotionDecodResizeHandler) {
window.removeEventListener('resize', window.emotionDecodResizeHandler);
}
//
window.addEventListener('resize', resizeHandler);
// resize便
window.emotionDecodResizeHandler = resizeHandler;
//
if (KlineCanvs.value && window.ResizeObserver) {
const containerObserver = new ResizeObserver(debounce(() => {
if (KlineCanvsChart && !KlineCanvsChart.isDisposed()) {
try {
KlineCanvsChart.resize();
console.log('情绪解码器容器大小变化,图表已调整');
} catch (error) {
console.error('情绪解码器容器resize失败:', error);
}
}
}, 100));
containerObserver.observe(KlineCanvs.value);
window.emotionDecodContainerObserver = containerObserver;
}
} }
const windowHeight = ref(window.innerHeight); const windowHeight = ref(window.innerHeight);
const updateHeight = () => { const updateHeight = () => {
windowHeight.value = window.innerHeight; // windowHeight.value = window.innerHeight; //
}; };
//
onMounted(() => { onMounted(() => {
window.addEventListener("resize", updateHeight); //
//
if (!window.emotionDecodHeightHandler) {
window.addEventListener("resize", updateHeight);
window.emotionDecodHeightHandler = updateHeight;
}
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
// //
if (KlineCanvsChart) { if (KlineCanvsChart) {
KlineCanvsChart.dispose(); KlineCanvsChart.dispose();
KlineCanvsChart = null;
}
// resize
if (window.emotionDecodResizeHandler) {
window.removeEventListener('resize', window.emotionDecodResizeHandler);
window.emotionDecodResizeHandler = null;
}
//
if (window.emotionDecodHeightHandler) {
window.removeEventListener('resize', window.emotionDecodHeightHandler);
window.emotionDecodHeightHandler = null;
}
//
if (window.emotionDecodContainerObserver) {
window.emotionDecodContainerObserver.disconnect();
window.emotionDecodContainerObserver = null;
} }
}); });
</script> </script>
@ -381,10 +454,12 @@ onBeforeUnmount(() => {
} }
#qxjmqEcharts { #qxjmqEcharts {
width: 130%;
width: 100%;
height: 800px; height: 800px;
margin-left: -15%;
margin: 0;
top: 5rem; top: 5rem;
box-sizing: border-box;
overflow: hidden;
} }
/* 手机端适配样式 */ /* 手机端适配样式 */
@ -392,15 +467,14 @@ onBeforeUnmount(() => {
#qxjmqEcharts { #qxjmqEcharts {
width: 100%; width: 100%;
height: 400px; height: 400px;
margin-left: -6%;
margin: 0;
top: 5rem; top: 5rem;
} }
.qxjmqbox { .qxjmqbox {
height: auto; height: auto;
width: 130%;
margin-top: -5rem;
margin-left: -1rem;
width: 100%;
margin: 0;
} }
} }

56
src/views/components/emotionalBottomRadar.vue

@ -3,10 +3,12 @@
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'
import { ref, onBeforeUnmount } from 'vue'
import { createChartResizeHandler, applyResponsiveStyles } from '@/utils/chartResize.js'
import * as echarts from 'echarts' import * as echarts from 'echarts'
const bottomRadarRef = ref(null) const bottomRadarRef = ref(null)
let bottomRadarChart = null let bottomRadarChart = null
let resizeHandler = null
function initEmotionalBottomRadar(KlineData, barAndLineData) { function initEmotionalBottomRadar(KlineData, barAndLineData) {
// //
if (bottomRadarChart) { if (bottomRadarChart) {
@ -628,11 +630,30 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
// 使 // 使
bottomRadarChart.setOption(option) bottomRadarChart.setOption(option)
//
window.addEventListener('resize', () => {
adjustGridHeight()
bottomRadarChart.resize()
})
//
if (bottomRadarRef.value) {
applyResponsiveStyles(bottomRadarRef.value);
}
//
if (resizeHandler) {
resizeHandler.cleanup();
}
resizeHandler = createChartResizeHandler({
chart: bottomRadarChart,
container: bottomRadarRef.value,
option: option,
beforeResize: adjustGridHeight,
name: '情绪探底雷达图表'
});
// resize
setTimeout(() => {
if (resizeHandler) {
resizeHandler.triggerResize();
}
}, 100);
function adjustGridHeight() { function adjustGridHeight() {
if (window.innerWidth <= 768) { if (window.innerWidth <= 768) {
option.grid[0].height = '150px' option.grid[0].height = '150px'
@ -660,32 +681,37 @@ defineExpose({
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
//
if (resizeHandler) {
resizeHandler.cleanup();
resizeHandler = null;
}
// //
if (bottomRadarChart) { if (bottomRadarChart) {
bottomRadarChart.dispose()
bottomRadarChart.dispose();
bottomRadarChart = null;
} }
}) })
</script> </script>
<style> <style>
#bottomRadarChart { #bottomRadarChart {
height: auto;
width: 100%; width: 100%;
min-width: 100%;
/* min-height: 100%; */
height: 1040px; height: 1040px;
/* padding-bottom: 3rem; */
box-sizing: border-box;
overflow: hidden;
margin: 0;
padding: 0;
} }
/* 手机端适配样式 */ /* 手机端适配样式 */
@media only screen and (max-width: 768px) { @media only screen and (max-width: 768px) {
#bottomRadarChart { #bottomRadarChart {
height: auto;
width: 100%; width: 100%;
min-width: 100%;
height: 560px; height: 560px;
margin: 0;
padding: 0;
} }
} }
</style> </style>

67
src/views/components/marketTemperature.vue

@ -375,18 +375,61 @@ function initChart(raw, klineDataRawValue, WDRLValue) {
filterMode: 'filter' filterMode: 'filter'
}] }]
}) })
// resize
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
// //
const resizeHandler = () => {
if (chartInstance) {
chartInstance.resize()
const resizeHandler = debounce(() => {
if (chartInstance && !chartInstance.isDisposed()) {
try {
chartInstance.resize();
adjustCellFontSize(); //
console.log('股市温度计图表已重新调整大小');
} catch (error) {
console.error('股市温度计图表resize失败:', error);
}
} }
}, 100); // 100ms
//
if (window.marketTempResizeHandler) {
window.removeEventListener('resize', window.marketTempResizeHandler);
} }
window.addEventListener('resize', resizeHandler)
//
window.addEventListener('resize', resizeHandler);
// resize便 // resize便
if (!window.marketTempResizeHandler) {
window.marketTempResizeHandler = resizeHandler
window.marketTempResizeHandler = resizeHandler;
//
const chartContainer = document.querySelector('.KlineClass');
if (chartContainer && window.ResizeObserver) {
const containerObserver = new ResizeObserver(debounce(() => {
if (chartInstance && !chartInstance.isDisposed()) {
try {
chartInstance.resize();
console.log('股市温度计容器大小变化,图表已调整');
} catch (error) {
console.error('股市温度计容器resize失败:', error);
}
}
}, 100));
containerObserver.observe(chartContainer);
window.marketTempContainerObserver = containerObserver;
} }
// //
adjustCellFontSize() adjustCellFontSize()
} }
@ -420,6 +463,12 @@ onBeforeUnmount(() => {
window.removeEventListener('resize', window.marketTempResizeHandler) window.removeEventListener('resize', window.marketTempResizeHandler)
window.marketTempResizeHandler = null window.marketTempResizeHandler = null
} }
//
if (window.marketTempContainerObserver) {
window.marketTempContainerObserver.disconnect();
window.marketTempContainerObserver = null;
}
}) })
defineExpose({ initChart }) defineExpose({ initChart })
@ -476,9 +525,11 @@ defineExpose({ initChart })
margin-top: 40px; margin-top: 40px;
border-radius: 8px; border-radius: 8px;
padding: 20px; padding: 20px;
margin-left: -2rem;
margin-left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
box-sizing: border-box;
overflow: hidden;
} }
.border4 { .border4 {

Loading…
Cancel
Save