feat: 黄金指标项图表实时5s展示
This commit is contained in:
@@ -719,6 +719,7 @@ export default {
|
|||||||
exportSure:'Confirm whether to export all statistical data',
|
exportSure:'Confirm whether to export all statistical data',
|
||||||
exportEmpty: "Export data is empty",
|
exportEmpty: "Export data is empty",
|
||||||
showChartSelected: "Show All",
|
showChartSelected: "Show All",
|
||||||
|
realTimeData: "Real Time 5s Data",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
traceManage: {
|
traceManage: {
|
||||||
|
|||||||
@@ -719,6 +719,7 @@ export default {
|
|||||||
exportSure:'确认是否导出全部统计数据',
|
exportSure:'确认是否导出全部统计数据',
|
||||||
exportEmpty: "导出数据为空",
|
exportEmpty: "导出数据为空",
|
||||||
showChartSelected: "显示全部",
|
showChartSelected: "显示全部",
|
||||||
|
realTimeData: "实时5s数据",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
traceManage: {
|
traceManage: {
|
||||||
|
|||||||
@@ -14,14 +14,25 @@ import { LineChart, LineSeriesOption } from 'echarts/charts';
|
|||||||
import { UniversalTransition } from 'echarts/features';
|
import { UniversalTransition } from 'echarts/features';
|
||||||
import { CanvasRenderer } from 'echarts/renderers';
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
|
||||||
import { reactive, ref, onMounted, toRaw, markRaw, nextTick } from 'vue';
|
import {
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
toRaw,
|
||||||
|
markRaw,
|
||||||
|
nextTick,
|
||||||
|
onBeforeUnmount,
|
||||||
|
} from 'vue';
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { message, Modal } from 'ant-design-vue/lib';
|
import { message, Modal } from 'ant-design-vue/lib';
|
||||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||||
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import {
|
||||||
|
RESULT_CODE_ERROR,
|
||||||
|
RESULT_CODE_SUCCESS,
|
||||||
|
} from '@/constants/result-constants';
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { getKPITitle, listKPIData } from '@/api/perfManage/goldTarget';
|
import { getKPITitle, listKPIData } from '@/api/perfManage/goldTarget';
|
||||||
@@ -29,8 +40,10 @@ import { parseDateToStr } from '@/utils/date-utils';
|
|||||||
import { writeSheet } from '@/utils/execl-utils';
|
import { writeSheet } from '@/utils/execl-utils';
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
import { generateColorRGBA } from '@/utils/generate-utils';
|
import { generateColorRGBA } from '@/utils/generate-utils';
|
||||||
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
const neInfoStore = useNeInfoStore();
|
const neInfoStore = useNeInfoStore();
|
||||||
const { t, currentLocale } = useI18n();
|
const { t, currentLocale } = useI18n();
|
||||||
|
const ws = new WS();
|
||||||
|
|
||||||
echarts.use([
|
echarts.use([
|
||||||
TooltipComponent,
|
TooltipComponent,
|
||||||
@@ -160,66 +173,17 @@ function fnTableChange(pagination: any, filters: any, sorter: any, extra: any) {
|
|||||||
type StateType = {
|
type StateType = {
|
||||||
/**网元类型 */
|
/**网元类型 */
|
||||||
neType: string[];
|
neType: string[];
|
||||||
|
/**图表实时统计 */
|
||||||
|
chartRealTime: boolean;
|
||||||
/**图表标签选择 */
|
/**图表标签选择 */
|
||||||
chartLegendSelectedFlag: boolean;
|
chartLegendSelectedFlag: boolean;
|
||||||
/**图表标签选择 */
|
|
||||||
chartLegendSelected: Record<string, boolean>;
|
|
||||||
/**图表配置数据 */
|
|
||||||
chartOption: EChartsOption;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**对象信息状态 */
|
/**对象信息状态 */
|
||||||
let state: StateType = reactive({
|
let state: StateType = reactive({
|
||||||
neType: [],
|
neType: [],
|
||||||
|
chartRealTime: false,
|
||||||
chartLegendSelectedFlag: false,
|
chartLegendSelectedFlag: false,
|
||||||
chartLegendSelected: {},
|
|
||||||
chartOption: {
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
position: function (pt: any) {
|
|
||||||
return [pt[0], '10%'];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
data: [],
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
boundaryGap: [0, '100%'],
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
type: 'scroll',
|
|
||||||
orient: 'vertical',
|
|
||||||
top: 40,
|
|
||||||
right: 20,
|
|
||||||
itemWidth: 20,
|
|
||||||
itemGap: 25,
|
|
||||||
textStyle: {
|
|
||||||
color: '#646A73',
|
|
||||||
},
|
|
||||||
icon: 'circle',
|
|
||||||
selected: {},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: '10%',
|
|
||||||
right: '30%',
|
|
||||||
bottom: '20%',
|
|
||||||
},
|
|
||||||
dataZoom: [
|
|
||||||
{
|
|
||||||
type: 'inside',
|
|
||||||
start: 90,
|
|
||||||
end: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: 90,
|
|
||||||
end: 100,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [],
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -373,7 +337,54 @@ function fnRanderChart() {
|
|||||||
if (!container) return;
|
if (!container) return;
|
||||||
kpiChart.value = markRaw(echarts.init(container, 'light'));
|
kpiChart.value = markRaw(echarts.init(container, 'light'));
|
||||||
|
|
||||||
kpiChart.value.setOption(state.chartOption);
|
const option: EChartsOption = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
position: function (pt: any) {
|
||||||
|
return [pt[0], '10%'];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: [], // 数据x轴
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
boundaryGap: [0, '100%'],
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
type: 'scroll',
|
||||||
|
orient: 'vertical',
|
||||||
|
top: 40,
|
||||||
|
right: 20,
|
||||||
|
itemWidth: 20,
|
||||||
|
itemGap: 25,
|
||||||
|
textStyle: {
|
||||||
|
color: '#646A73',
|
||||||
|
},
|
||||||
|
icon: 'circle',
|
||||||
|
selected: {},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '10%',
|
||||||
|
right: '30%',
|
||||||
|
bottom: '20%',
|
||||||
|
},
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
type: 'inside',
|
||||||
|
start: 90,
|
||||||
|
end: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: 90,
|
||||||
|
end: 100,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
series: [], // 数据y轴
|
||||||
|
};
|
||||||
|
kpiChart.value.setOption(option);
|
||||||
|
|
||||||
// 创建 ResizeObserver 实例
|
// 创建 ResizeObserver 实例
|
||||||
var observer = new ResizeObserver(entries => {
|
var observer = new ResizeObserver(entries => {
|
||||||
@@ -385,17 +396,24 @@ function fnRanderChart() {
|
|||||||
observer.observe(container);
|
observer.observe(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**图表标签选择 */
|
||||||
|
let chartLegendSelected: Record<string, boolean> = {};
|
||||||
|
/**图表配置数据x轴 */
|
||||||
|
let chartDataXAxisData: string[] = [];
|
||||||
|
/**图表配置数据y轴 */
|
||||||
|
let chartDataYSeriesData: Record<string, any>[] = [];
|
||||||
|
|
||||||
/**图表数据渲染 */
|
/**图表数据渲染 */
|
||||||
function fnRanderChartData() {
|
function fnRanderChartData() {
|
||||||
if (kpiChart.value == null && tableState.data.length <= 0) {
|
if (kpiChart.value == null && tableState.data.length <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const xDatas: string[] = [];
|
// 重置
|
||||||
const yDatas: Record<string, any>[] = [];
|
chartLegendSelected = {};
|
||||||
|
chartDataXAxisData = [];
|
||||||
|
chartDataYSeriesData = [];
|
||||||
|
|
||||||
const tableColumnsKeyArr: string[] = [];
|
|
||||||
const chartLegendSelected: Record<string, boolean> = {};
|
|
||||||
for (const columns of tableColumns.value) {
|
for (const columns of tableColumns.value) {
|
||||||
if (
|
if (
|
||||||
columns.key === 'neName' ||
|
columns.key === 'neName' ||
|
||||||
@@ -405,8 +423,9 @@ function fnRanderChartData() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const color = generateColorRGBA();
|
const color = generateColorRGBA();
|
||||||
yDatas.push({
|
chartDataYSeriesData.push({
|
||||||
name: `${columns.title}`,
|
name: `${columns.title}`,
|
||||||
|
key: `${columns.key}`,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
symbol: 'none',
|
symbol: 'none',
|
||||||
sampling: 'lttb',
|
sampling: 'lttb',
|
||||||
@@ -427,7 +446,6 @@ function fnRanderChartData() {
|
|||||||
},
|
},
|
||||||
data: [],
|
data: [],
|
||||||
});
|
});
|
||||||
tableColumnsKeyArr.push(`${columns.key}`);
|
|
||||||
chartLegendSelected[`${columns.title}`] = state.chartLegendSelectedFlag;
|
chartLegendSelected[`${columns.title}`] = state.chartLegendSelectedFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,40 +454,38 @@ function fnRanderChartData() {
|
|||||||
if (queryParams.sortOrder === 'desc') {
|
if (queryParams.sortOrder === 'desc') {
|
||||||
orgData = orgData.toReversed();
|
orgData = orgData.toReversed();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const item of orgData) {
|
for (const item of orgData) {
|
||||||
xDatas.push(item['timeGroup']);
|
chartDataXAxisData.push(item['timeGroup']);
|
||||||
const keys = Object.keys(item);
|
const keys = Object.keys(item);
|
||||||
for (let i = 0; i < tableColumnsKeyArr.length; i++) {
|
for (const y of chartDataYSeriesData) {
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
if (tableColumnsKeyArr[i] === key) {
|
if (y.key === key) {
|
||||||
yDatas[i].data.push(+item[key]);
|
y.data.push(+item[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log(queryParams.sortOrder, xDatas, yDatas);
|
// console.log(queryParams.sortOrder, chartLegendSelected);
|
||||||
|
// console.log(chartDataXAxisData, chartDataYSeriesData)
|
||||||
|
|
||||||
// 图标签选择状态标记
|
// 绘制图数据
|
||||||
state.chartLegendSelected = chartLegendSelected;
|
|
||||||
kpiChart.value.setOption({
|
kpiChart.value.setOption({
|
||||||
legend: {
|
legend: {
|
||||||
selected: chartLegendSelected,
|
selected: chartLegendSelected,
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
data: xDatas,
|
data: chartDataXAxisData,
|
||||||
},
|
},
|
||||||
series: yDatas,
|
series: chartDataYSeriesData,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**图表折线显示全部 */
|
/**图表折线显示全部 */
|
||||||
function fnLegendSelected(bool: any) {
|
function fnLegendSelected(bool: any) {
|
||||||
const chartLegendSelected: Record<string, boolean> = {};
|
for (const key of Object.keys(chartLegendSelected)) {
|
||||||
for (const key of Object.keys(state.chartLegendSelected)) {
|
|
||||||
chartLegendSelected[key] = bool;
|
chartLegendSelected[key] = bool;
|
||||||
}
|
}
|
||||||
// 图标签选择状态标记
|
|
||||||
state.chartLegendSelected = chartLegendSelected;
|
|
||||||
kpiChart.value.setOption({
|
kpiChart.value.setOption({
|
||||||
legend: {
|
legend: {
|
||||||
selected: chartLegendSelected,
|
selected: chartLegendSelected,
|
||||||
@@ -477,6 +493,75 @@ function fnLegendSelected(bool: any) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**图表实时统计 */
|
||||||
|
function fnRealTimeSwitch(bool: any) {
|
||||||
|
if (bool) {
|
||||||
|
// 建立链接
|
||||||
|
const options: OptionsType = {
|
||||||
|
url: '/ws',
|
||||||
|
params: {
|
||||||
|
/**订阅通道组
|
||||||
|
*
|
||||||
|
* 指标(GroupID:10)
|
||||||
|
*/
|
||||||
|
subGroupID: '10',
|
||||||
|
},
|
||||||
|
onmessage: wsMessage,
|
||||||
|
onerror: wsError,
|
||||||
|
};
|
||||||
|
ws.connect(options);
|
||||||
|
} else {
|
||||||
|
ws.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**接收数据后回调 */
|
||||||
|
function wsError(ev: any) {
|
||||||
|
// 接收数据后回调
|
||||||
|
console.error(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**接收数据后回调 */
|
||||||
|
function wsMessage(res: Record<string, any>) {
|
||||||
|
const { code, requestId, data } = res;
|
||||||
|
if (code === RESULT_CODE_ERROR) {
|
||||||
|
console.warn(res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订阅组信息
|
||||||
|
if (!data?.groupId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// kpiEvent 黄金指标指标事件
|
||||||
|
if (data.groupId === '10') {
|
||||||
|
const kpiEvent = data.data;
|
||||||
|
for (const key of Object.keys(data.data)) {
|
||||||
|
const v = kpiEvent[key];
|
||||||
|
// x轴
|
||||||
|
if (key === 'timeGroup') {
|
||||||
|
// chartDataXAxisData.shift();
|
||||||
|
chartDataXAxisData.push(v);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// y轴
|
||||||
|
const yItem = chartDataYSeriesData.find(item => item.key === key);
|
||||||
|
if (yItem) {
|
||||||
|
// yItem.data.shift();
|
||||||
|
yItem.data.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制图数据
|
||||||
|
kpiChart.value.setOption({
|
||||||
|
xAxis: {
|
||||||
|
data: chartDataXAxisData,
|
||||||
|
},
|
||||||
|
series: chartDataYSeriesData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 获取网元网元列表
|
// 获取网元网元列表
|
||||||
neInfoStore.fnNelist().then(res => {
|
neInfoStore.fnNelist().then(res => {
|
||||||
@@ -512,8 +597,8 @@ onMounted(() => {
|
|||||||
// 查询当前小时
|
// 查询当前小时
|
||||||
const nowDate: Date = new Date();
|
const nowDate: Date = new Date();
|
||||||
nowDate.setMinutes(0, 0, 0);
|
nowDate.setMinutes(0, 0, 0);
|
||||||
queryRangePicker.value[0] = parseDateToStr(nowDate);
|
// queryRangePicker.value[0] = parseDateToStr(nowDate);
|
||||||
// queryRangePicker.value[0] = '2024-01-30 00:00:00';
|
queryRangePicker.value[0] = '2024-01-30 00:00:00';
|
||||||
nowDate.setMinutes(59, 59, 59);
|
nowDate.setMinutes(59, 59, 59);
|
||||||
queryRangePicker.value[1] = parseDateToStr(nowDate);
|
queryRangePicker.value[1] = parseDateToStr(nowDate);
|
||||||
fnGetListTitle();
|
fnGetListTitle();
|
||||||
@@ -528,6 +613,10 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
ws.close();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -677,20 +766,34 @@ onMounted(() => {
|
|||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
<a-space :size="8" align="center" v-show="!tableState.showTable">
|
<a-form layout="inline" v-show="!tableState.showTable">
|
||||||
<a-tooltip>
|
<a-form-item
|
||||||
<template #title>
|
:label="t('views.perfManage.goldTarget.showChartSelected')"
|
||||||
{{ t('views.perfManage.goldTarget.showChartSelected') }}
|
name="chartLegendSelectedFlag"
|
||||||
</template>
|
>
|
||||||
<a-switch
|
<a-switch
|
||||||
:disabled="tableState.loading"
|
:disabled="tableState.loading"
|
||||||
v-model:checked="state.chartLegendSelectedFlag"
|
v-model:checked="state.chartLegendSelectedFlag"
|
||||||
:checked-children="t('common.switch.open')"
|
:checked-children="t('common.switch.open')"
|
||||||
:un-checked-children="t('common.switch.shut')"
|
:un-checked-children="t('common.switch.shut')"
|
||||||
@change="fnLegendSelected"
|
@change="fnLegendSelected"
|
||||||
|
size="small"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-form-item>
|
||||||
</a-space>
|
<a-form-item
|
||||||
|
:label="t('views.perfManage.goldTarget.realTimeData')"
|
||||||
|
name="chartRealTime"
|
||||||
|
>
|
||||||
|
<a-switch
|
||||||
|
:disabled="tableState.loading"
|
||||||
|
v-model:checked="state.chartRealTime"
|
||||||
|
:checked-children="t('common.switch.open')"
|
||||||
|
:un-checked-children="t('common.switch.shut')"
|
||||||
|
@change="fnRealTimeSwitch"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 表格列表 -->
|
<!-- 表格列表 -->
|
||||||
|
|||||||
Reference in New Issue
Block a user