新增网络监控折线图拆分为单独图表功能

This commit is contained in:
hi2hi 2025-04-10 12:04:31 +08:00
parent 8de81431ca
commit a24401a87c
4 changed files with 192 additions and 125 deletions

View File

@ -33,6 +33,8 @@ window.$$nazhuaConfig = {
// hideTag: false, // 隐藏标签 // hideTag: false, // 隐藏标签
// hideDotBG: true, // 隐藏框框里面的点点背景 // hideDotBG: true, // 隐藏框框里面的点点背景
// monitorRefreshTime: 10, // 监控刷新时间间隔单位s, 0为不刷新为保证不频繁请求源站最低生效值为10s // monitorRefreshTime: 10, // 监控刷新时间间隔单位s, 0为不刷新为保证不频繁请求源站最低生效值为10s
monitorChartType: 'multi', // 监控图表类型 single/multi
monitorChartTypeToggle: true, // 监控图表类型切换
// filterGPUKeywords: ['Virtual Display'], // 如果GPU名称中包含这些关键字则过滤掉 // filterGPUKeywords: ['Virtual Display'], // 如果GPU名称中包含这些关键字则过滤掉
// customCodeMap: {}, // 自定义的地图点信息 // customCodeMap: {}, // 自定义的地图点信息
// nezhaVersion: 'v1', // 哪吒版本 // nezhaVersion: 'v1', // 哪吒版本

View File

@ -3,7 +3,6 @@ import { SVGRenderer } from 'echarts/renderers';
import { LineChart } from 'echarts/charts'; import { LineChart } from 'echarts/charts';
import { import {
TooltipComponent, TooltipComponent,
// LegendComponent,
GridComponent, GridComponent,
DataZoomComponent, DataZoomComponent,
} from 'echarts/components'; } from 'echarts/components';
@ -15,13 +14,11 @@ use([
SVGRenderer, SVGRenderer,
LineChart, LineChart,
TooltipComponent, TooltipComponent,
// LegendComponent,
GridComponent, GridComponent,
DataZoomComponent, DataZoomComponent,
]); ]);
export default ( export default (
cateList,
dateList, dateList,
valueList, valueList,
mode = 'dark', mode = 'dark',
@ -69,23 +66,6 @@ export default (
fontSize: 14, fontSize: 14,
}, },
}, },
// legend: {
// show: false,
// data: cateList.map((i) => ({
// name: i.name,
// itemStyle: {
// color: i.color,
// },
// lineStyle: {
// color: i.color,
// },
// })),
// textStyle: {
// color: mode === 'dark' ? '#ddd' : '#222',
// fontFamily,
// fontSize: 14,
// },
// },
grid: { grid: {
top: 10, top: 10,
left: 5, left: 5,

View File

@ -25,10 +25,6 @@ import VChart from 'vue-echarts';
import lineChart from './line'; import lineChart from './line';
const props = defineProps({ const props = defineProps({
cateList: {
type: Array,
default: () => [],
},
dateList: { dateList: {
type: Array, type: Array,
default: () => [], default: () => [],
@ -45,9 +41,8 @@ const props = defineProps({
const chartRef = ref(); const chartRef = ref();
const option = computed(() => { const option = computed(() => {
if (props.cateList && props.dateList && props.valueList) { if (props.dateList && props.valueList) {
return lineChart( return lineChart(
props.cateList,
props.dateList, props.dateList,
props.valueList, props.valueList,
); );

View File

@ -11,6 +11,22 @@
</span> </span>
</div> </div>
<div class="right-box"> <div class="right-box">
<div
v-if="config.nazhua.monitorChartTypeToggle"
class="chart-type-switch-group"
title="监控折线图是否聚合"
@click="switchChartType"
>
<span class="label-text">聚合</span>
<div
class="switch-box"
:class="{
active: monitorChartType === 'multi',
}"
>
<span class="switch-dot" />
</div>
</div>
<div <div
class="refresh-data-group" class="refresh-data-group"
title="是否自动刷新" title="是否自动刷新"
@ -66,55 +82,104 @@
</div> </div>
</div> </div>
<div class="monitor-cate-group"> <template v-if="monitorChartType === 'single'">
<template <div class="monitor-chart-group">
v-for="cateItem in monitorChartData.cateList" <div
:key="cateItem.id" v-for="(cateItem, index) in monitorChartData.cateList"
> :key="cateItem.id"
<popover :title="cateItem.title"> class="monitor-chart-item"
<template #trigger> >
<div <div class="cate-name-box">
class="monitor-cate-item" <popover :title="cateItem.title">
:class="{ <template #trigger>
disabled: showCates[cateItem.id] === false, <div
}" class="monitor-cate-item"
:style="{ :class="{
'--cate-color': cateItem.color, disabled: showCates[cateItem.id] === false,
}" }"
@click="toggleShowCate(cateItem.id)" :style="{
@touchstart="handleTouchStart(cateItem.id)" '--cate-color': cateItem.color,
@touchend="handleTouchEnd(cateItem.id)" }"
@touchmove="handleTouchMove(cateItem.id)" >
> <span class="cate-legend" />
<span class="cate-legend" /> <span
<span class="cate-name"
class="cate-name" >
{{ cateItem.name }}
</span>
<span
v-if="cateItem.avg !== 0"
class="cate-avg-ms"
>
{{ cateItem.avg }}ms
</span>
<span
v-else
class="cate-avg-ms"
>
-ms
</span>
</div>
</template>
</popover>
</div>
<line-chart
:date-list="monitorChartData.dateList"
:value-list="[monitorChartData.valueList[index]]"
/>
</div>
</div>
</template>
<template v-else>
<div class="monitor-cate-group">
<template
v-for="cateItem in monitorChartData.cateList"
:key="cateItem.id"
>
<popover :title="cateItem.title">
<template #trigger>
<div
class="monitor-cate-item"
:class="{
disabled: showCates[cateItem.id] === false,
}"
:style="{
'--cate-color': cateItem.color,
}"
@click="toggleShowCate(cateItem.id)"
@touchstart="handleTouchStart(cateItem.id)"
@touchend="handleTouchEnd(cateItem.id)"
@touchmove="handleTouchMove(cateItem.id)"
> >
{{ cateItem.name }} <span class="cate-legend" />
</span> <span
<span class="cate-name"
v-if="cateItem.avg !== 0" >
class="cate-avg-ms" {{ cateItem.name }}
> </span>
{{ cateItem.avg }}ms <span
</span> v-if="cateItem.avg !== 0"
<span class="cate-avg-ms"
v-else >
class="cate-avg-ms" {{ cateItem.avg }}ms
> </span>
-ms <span
</span> v-else
</div> class="cate-avg-ms"
</template> >
</popover> -ms
</template> </span>
</div> </div>
</template>
</popover>
</template>
</div>
<line-chart <line-chart
:cate-list="monitorChartData.cateList" :date-list="monitorChartData.dateList"
:date-list="monitorChartData.dateList" :value-list="monitorChartData.valueList"
:value-list="monitorChartData.valueList" />
/> </template>
</dot-dot-box> </dot-dot-box>
</template> </template>
@ -175,6 +240,14 @@ const showCates = ref({});
const monitorData = ref([]); const monitorData = ref([]);
const longPressTimer = ref(null); const longPressTimer = ref(null);
const chartType = ref(config.nazhua.monitorChartType === 'single' ? 'single' : 'multi');
const monitorChartType = computed(() => {
if (config.nazhua.monitorChartTypeToggle) {
return chartType.value;
}
return config.nazhua.monitorChartType;
});
const now = ref(Date.now()); const now = ref(Date.now());
const accpetShowTime = computed(() => now.value - (minute.value * 60 * 1000)); const accpetShowTime = computed(() => now.value - (minute.value * 60 * 1000));
@ -314,6 +387,10 @@ function switchRefresh() {
refreshData.value = !refreshData.value; refreshData.value = !refreshData.value;
} }
function switchChartType() {
chartType.value = chartType.value === 'single' ? 'multi' : 'single';
}
function toggleMinute(value) { function toggleMinute(value) {
now.value = store.state.serverTime || Date.now(); now.value = store.state.serverTime || Date.now();
minute.value = value; minute.value = value;
@ -400,6 +477,51 @@ onUnmounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.server-monitor-group { .server-monitor-group {
--line-chart-size: 300px; --line-chart-size: 300px;
.monitor-cate-item {
--cate-item-height: 28px;
--cate-item-font-size: 14px;
--cate-color: #fff;
display: flex;
align-items: center;
width: var(--cate-item-width);
height: var(--cate-item-height);
gap: 6px;
padding: 0 6px;
font-size: var(--cate-item-font-size);
border-radius: 4px;
cursor: pointer;
@media screen and (max-width: 768px) {
cursor: default;
}
.cate-legend {
width: 0.5em;
height: 0.5em;
background: var(--cate-color);
}
.cate-name {
// flex: 1;
height: var(--cate-item-height);
line-height: calc(var(--cate-item-height) + 2px);
color: #eee;
}
.cate-avg-ms {
height: var(--cate-item-height);
line-height: calc(var(--cate-item-height) + 2px);
text-align: right;
color: #fff;
}
&.disabled {
filter: grayscale(1);
opacity: 0.5;
}
}
} }
.module-head-group { .module-head-group {
@ -425,7 +547,8 @@ onUnmounted(() => {
} }
.peak-shaving-group, .peak-shaving-group,
.refresh-data-group { .refresh-data-group,
.chart-type-switch-group {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
@ -553,63 +676,30 @@ onUnmounted(() => {
margin: 10px 0; margin: 10px 0;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
// justify-content: center;
gap: var(--gap-size); gap: var(--gap-size);
margin-right: calc(var(--gap-size) * -1); margin-right: calc(var(--gap-size) * -1);
}
.monitor-cate-item { .monitor-chart-group {
// --cate-item-width: calc(20% - var(--gap-size)); display: flex;
--cate-item-height: 28px; flex-wrap: wrap;
--cate-item-font-size: 14px; gap: 10px 0;
--cate-color: #fff;
.monitor-chart-item {
width: 50%;
height: calc(var(--line-chart-size) + 28px);
}
@media screen and (max-width: 768px) {
.monitor-chart-item {
width: 100%;
}
}
.cate-name-box {
display: flex; display: flex;
align-items: center; align-items: center;
width: var(--cate-item-width); justify-content: center;
height: var(--cate-item-height);
gap: 6px;
padding: 0 6px;
font-size: var(--cate-item-font-size);
// background: rgba(#fff, 0.2);
border-radius: 4px;
cursor: pointer;
@media screen and (max-width: 768px) {
cursor: default;
}
.cate-legend {
width: 0.5em;
height: 0.5em;
// border-radius: 50%;
// width: 6px;
// height: calc(var(--cate-item-height) - 10px);
// margin-left: -6px;
background: var(--cate-color);
}
.cate-name {
// flex: 1;
height: var(--cate-item-height);
line-height: calc(var(--cate-item-height) + 2px);
// text-overflow: ellipsis;
// white-space: nowrap;
// overflow: hidden;
color: #eee;
}
.cate-avg-ms {
// width: 55px;
height: var(--cate-item-height);
line-height: calc(var(--cate-item-height) + 2px);
text-align: right;
color: #fff;
}
&.disabled {
filter: grayscale(1);
opacity: 0.5;
}
} }
} }
</style> </style>