fix:暗色模式样式适应
This commit is contained in:
@@ -14,6 +14,7 @@ import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import { generateColorRGBA } from '@/utils/generate-utils';
|
||||
import { LineOutlined } from '@ant-design/icons-vue';
|
||||
import { TableColumnType } from 'ant-design-vue';
|
||||
import { viewTransitionTheme } from 'antdv-pro-layout';
|
||||
const { t, currentLocale } = useI18n();
|
||||
//定义KPI接口
|
||||
interface KPIBase{
|
||||
@@ -69,8 +70,8 @@ const ranges = ref([
|
||||
])
|
||||
//日期范围响应式变量
|
||||
const dateRange = ref<[string, string]>([
|
||||
dayjs().startOf('hour').valueOf().toString(),
|
||||
dayjs().endOf('hour').valueOf().toString(),
|
||||
dayjs().subtract(1, 'hour').startOf('hour').valueOf().toString(), // 上一小时开始
|
||||
dayjs().startOf('hour').add(1, 'hour').valueOf().toString(), // 当前小时结束
|
||||
]);
|
||||
//实时数据状态
|
||||
const isRealtime = ref(false);
|
||||
@@ -265,6 +266,134 @@ const getSeriesConfig = () => ({
|
||||
smooth:0.6,
|
||||
showSymbol: true,
|
||||
});
|
||||
// 添加一个函数来获取当前主题下的网格线颜色
|
||||
const getSplitLineColor = () => {
|
||||
return document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#333333'
|
||||
: '#E8E8E8'; // 亮色模式返回 undefined,使用默认颜色
|
||||
};
|
||||
|
||||
// 添加主题变化的观察器
|
||||
const themeObserver = new MutationObserver(() => {
|
||||
if (chart) {
|
||||
// 获取当前的主题色
|
||||
const splitLineColor = getSplitLineColor();
|
||||
|
||||
// 重新设置完整的图表配置并触发重新渲染
|
||||
requestAnimationFrame(() => {
|
||||
const option = {
|
||||
title: {
|
||||
text: t('views.perfManage.kpiOverView.kpiChartTitle'),
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
// 保持现有的 xAxis 配置
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: chartData.value.map(item =>
|
||||
dayjs(Number(item.date)).format('YYYY-MM-DD HH:mm:ss')
|
||||
),
|
||||
axisLabel: {
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333'
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: splitLineColor
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: '{value}',
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333'
|
||||
},
|
||||
splitNumber: 5,
|
||||
scale: true,
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: splitLineColor
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
selected: Object.fromEntries(
|
||||
selectedKPIs.value.map(kpiId => [
|
||||
kpiColumns.value.find(col => col.kpiId === kpiId)?.title || kpiId,
|
||||
selectedRow.value ? kpiId === selectedRow.value : true
|
||||
])
|
||||
)
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
position: function (point: number[], params: any, dom: HTMLElement, rect: any, size: { viewSize: number[], contentSize: number[] }) {
|
||||
const [x, y] = point;
|
||||
const [viewWidth] = size.viewSize;
|
||||
const [tooltipWidth, tooltipHeight] = size.contentSize;
|
||||
|
||||
// 距离右侧的距离
|
||||
const rightSpace = viewWidth - x;
|
||||
|
||||
// 计算垂直方向的居中位置
|
||||
// 将 tooltip 的中心点对齐到鼠标位置
|
||||
const verticalOffset = -tooltipHeight / 2;
|
||||
|
||||
// 如果右侧空间不足以显示tooltip(假设需要20px的安全距离)
|
||||
if (rightSpace < tooltipWidth + 20) {
|
||||
// 向左显示,垂直居中
|
||||
return [x - tooltipWidth - 10, y + verticalOffset];
|
||||
}
|
||||
|
||||
// 默认向右显示,垂直居中
|
||||
return [x + 10, y + verticalOffset];
|
||||
},
|
||||
backgroundColor: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? 'rgba(48, 48, 48, 0.8)'
|
||||
: 'rgba(255, 255, 255, 0.9)',
|
||||
borderColor: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#555'
|
||||
: '#ddd',
|
||||
textStyle: {
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333'
|
||||
},
|
||||
extraCssText: 'box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);'
|
||||
},
|
||||
// 重新设置系列数据
|
||||
series: selectedKPIs.value.map(kpiId => {
|
||||
const kpi = kpiColumns.value.find(col => col.kpiId === kpiId);
|
||||
if (!kpi) return null;
|
||||
const color = kpiColors.get(kpiId) || generateColorRGBA();
|
||||
return {
|
||||
name: kpi.title,
|
||||
type: 'line',
|
||||
data: chartData.value.map(item => item[kpiId] || 0),
|
||||
itemStyle: { color },
|
||||
...getSeriesConfig(),
|
||||
};
|
||||
}).filter(Boolean)
|
||||
};
|
||||
|
||||
// 使用新的配置更新图表
|
||||
chart!.setOption(option, true);
|
||||
// 强制重新渲染
|
||||
chart!.resize();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const updateChart = () => {
|
||||
if (!chart || !kpiColumns.value.length) return;
|
||||
@@ -299,6 +428,12 @@ const updateChart = () => {
|
||||
title: {
|
||||
text: t('views.perfManage.kpiOverView.kpiChartTitle'),
|
||||
left: 'center',
|
||||
// 添加文字颜色配置,根据主题切换
|
||||
textStyle: {
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
@@ -323,6 +458,18 @@ const updateChart = () => {
|
||||
// 默认向右显示,垂直居中
|
||||
return [x + 10, y + verticalOffset];
|
||||
},
|
||||
backgroundColor: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? 'rgba(48, 48, 48, 0.8)'
|
||||
: 'rgba(255, 255, 255, 0.9)',
|
||||
borderColor: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#555'
|
||||
: '#ddd',
|
||||
textStyle: {
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333'
|
||||
},
|
||||
extraCssText: 'box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);'
|
||||
},
|
||||
legend: {
|
||||
data: selectedKPIs.value.map(kpiId =>
|
||||
@@ -356,11 +503,16 @@ const updateChart = () => {
|
||||
xAxis: {
|
||||
// 指定x轴类型为类目轴,适用于离散的类目数据
|
||||
type: 'category',
|
||||
axisLabel: {
|
||||
formatter: '{value}',
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333'
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
// 使用深浅的间隔色
|
||||
color: '#aaa',
|
||||
color: getSplitLineColor()
|
||||
}
|
||||
},
|
||||
//控制坐标轴两边留白
|
||||
@@ -402,11 +554,20 @@ const updateChart = () => {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: '{value}',
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333'
|
||||
},
|
||||
// 添加自<E58AA0><E887AA><EFBFBD>计算的分割段数
|
||||
splitNumber: 5,
|
||||
// 添加自动计算的最小/最大值范围
|
||||
scale: true,
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: getSplitLineColor()
|
||||
}
|
||||
}
|
||||
},
|
||||
series: series, //配置数据
|
||||
};
|
||||
@@ -435,6 +596,8 @@ const updateChart = () => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//钩子函数
|
||||
onMounted(async () => {
|
||||
try {
|
||||
@@ -457,6 +620,11 @@ onMounted(async () => {
|
||||
} else {
|
||||
console.error('Chart container not found');
|
||||
}
|
||||
// 添加主题观察器
|
||||
themeObserver.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['data-theme']
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize:', error);
|
||||
message.error(t('common.initFail'));
|
||||
@@ -525,6 +693,8 @@ onUnmounted(() => {
|
||||
chart.dispose();
|
||||
chart = null;
|
||||
}
|
||||
// 断开主题观察器
|
||||
themeObserver.disconnect();
|
||||
});
|
||||
|
||||
// 实时数据更新图表数据方法
|
||||
|
||||
Reference in New Issue
Block a user