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

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

View File

@ -3,7 +3,6 @@ import { SVGRenderer } from 'echarts/renderers';
import { LineChart } from 'echarts/charts';
import {
TooltipComponent,
// LegendComponent,
GridComponent,
DataZoomComponent,
} from 'echarts/components';
@ -15,13 +14,11 @@ use([
SVGRenderer,
LineChart,
TooltipComponent,
// LegendComponent,
GridComponent,
DataZoomComponent,
]);
export default (
cateList,
dateList,
valueList,
mode = 'dark',
@ -69,23 +66,6 @@ export default (
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: {
top: 10,
left: 5,

View File

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

View File

@ -11,6 +11,22 @@
</span>
</div>
<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
class="refresh-data-group"
title="是否自动刷新"
@ -66,55 +82,104 @@
</div>
</div>
<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)"
>
<span class="cate-legend" />
<span
class="cate-name"
<template v-if="monitorChartType === 'single'">
<div class="monitor-chart-group">
<div
v-for="(cateItem, index) in monitorChartData.cateList"
:key="cateItem.id"
class="monitor-chart-item"
>
<div class="cate-name-box">
<popover :title="cateItem.title">
<template #trigger>
<div
class="monitor-cate-item"
:class="{
disabled: showCates[cateItem.id] === false,
}"
:style="{
'--cate-color': cateItem.color,
}"
>
<span class="cate-legend" />
<span
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>
<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>
</template>
</div>
<span class="cate-legend" />
<span
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>
</template>
</div>
<line-chart
:cate-list="monitorChartData.cateList"
:date-list="monitorChartData.dateList"
:value-list="monitorChartData.valueList"
/>
<line-chart
:date-list="monitorChartData.dateList"
:value-list="monitorChartData.valueList"
/>
</template>
</dot-dot-box>
</template>
@ -175,6 +240,14 @@ const showCates = ref({});
const monitorData = ref([]);
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 accpetShowTime = computed(() => now.value - (minute.value * 60 * 1000));
@ -314,6 +387,10 @@ function switchRefresh() {
refreshData.value = !refreshData.value;
}
function switchChartType() {
chartType.value = chartType.value === 'single' ? 'multi' : 'single';
}
function toggleMinute(value) {
now.value = store.state.serverTime || Date.now();
minute.value = value;
@ -400,6 +477,51 @@ onUnmounted(() => {
<style lang="scss" scoped>
.server-monitor-group {
--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 {
@ -425,7 +547,8 @@ onUnmounted(() => {
}
.peak-shaving-group,
.refresh-data-group {
.refresh-data-group,
.chart-type-switch-group {
display: flex;
align-items: center;
gap: 4px;
@ -553,63 +676,30 @@ onUnmounted(() => {
margin: 10px 0;
display: flex;
flex-wrap: wrap;
// justify-content: center;
gap: var(--gap-size);
margin-right: calc(var(--gap-size) * -1);
}
.monitor-cate-item {
// --cate-item-width: calc(20% - var(--gap-size));
--cate-item-height: 28px;
--cate-item-font-size: 14px;
--cate-color: #fff;
.monitor-chart-group {
display: flex;
flex-wrap: wrap;
gap: 10px 0;
.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;
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);
// 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;
}
justify-content: center;
}
}
</style>