feat: 黄金指标项图表实时5s展示
This commit is contained in:
@@ -14,14 +14,25 @@ import { LineChart, LineSeriesOption } from 'echarts/charts';
|
||||
import { UniversalTransition } from 'echarts/features';
|
||||
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 { message, Modal } from 'ant-design-vue/lib';
|
||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
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 useI18n from '@/hooks/useI18n';
|
||||
import { getKPITitle, listKPIData } from '@/api/perfManage/goldTarget';
|
||||
@@ -29,8 +40,10 @@ import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { writeSheet } from '@/utils/execl-utils';
|
||||
import saveAs from 'file-saver';
|
||||
import { generateColorRGBA } from '@/utils/generate-utils';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t, currentLocale } = useI18n();
|
||||
const ws = new WS();
|
||||
|
||||
echarts.use([
|
||||
TooltipComponent,
|
||||
@@ -160,66 +173,17 @@ function fnTableChange(pagination: any, filters: any, sorter: any, extra: any) {
|
||||
type StateType = {
|
||||
/**网元类型 */
|
||||
neType: string[];
|
||||
/**图表实时统计 */
|
||||
chartRealTime: boolean;
|
||||
/**图表标签选择 */
|
||||
chartLegendSelectedFlag: boolean;
|
||||
/**图表标签选择 */
|
||||
chartLegendSelected: Record<string, boolean>;
|
||||
/**图表配置数据 */
|
||||
chartOption: EChartsOption;
|
||||
};
|
||||
|
||||
/**对象信息状态 */
|
||||
let state: StateType = reactive({
|
||||
neType: [],
|
||||
chartRealTime: 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;
|
||||
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 实例
|
||||
var observer = new ResizeObserver(entries => {
|
||||
@@ -385,17 +396,24 @@ function fnRanderChart() {
|
||||
observer.observe(container);
|
||||
}
|
||||
|
||||
/**图表标签选择 */
|
||||
let chartLegendSelected: Record<string, boolean> = {};
|
||||
/**图表配置数据x轴 */
|
||||
let chartDataXAxisData: string[] = [];
|
||||
/**图表配置数据y轴 */
|
||||
let chartDataYSeriesData: Record<string, any>[] = [];
|
||||
|
||||
/**图表数据渲染 */
|
||||
function fnRanderChartData() {
|
||||
if (kpiChart.value == null && tableState.data.length <= 0) {
|
||||
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) {
|
||||
if (
|
||||
columns.key === 'neName' ||
|
||||
@@ -405,8 +423,9 @@ function fnRanderChartData() {
|
||||
continue;
|
||||
}
|
||||
const color = generateColorRGBA();
|
||||
yDatas.push({
|
||||
chartDataYSeriesData.push({
|
||||
name: `${columns.title}`,
|
||||
key: `${columns.key}`,
|
||||
type: 'line',
|
||||
symbol: 'none',
|
||||
sampling: 'lttb',
|
||||
@@ -427,7 +446,6 @@ function fnRanderChartData() {
|
||||
},
|
||||
data: [],
|
||||
});
|
||||
tableColumnsKeyArr.push(`${columns.key}`);
|
||||
chartLegendSelected[`${columns.title}`] = state.chartLegendSelectedFlag;
|
||||
}
|
||||
|
||||
@@ -436,40 +454,38 @@ function fnRanderChartData() {
|
||||
if (queryParams.sortOrder === 'desc') {
|
||||
orgData = orgData.toReversed();
|
||||
}
|
||||
|
||||
for (const item of orgData) {
|
||||
xDatas.push(item['timeGroup']);
|
||||
chartDataXAxisData.push(item['timeGroup']);
|
||||
const keys = Object.keys(item);
|
||||
for (let i = 0; i < tableColumnsKeyArr.length; i++) {
|
||||
for (const y of chartDataYSeriesData) {
|
||||
for (const key of keys) {
|
||||
if (tableColumnsKeyArr[i] === key) {
|
||||
yDatas[i].data.push(+item[key]);
|
||||
if (y.key === 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({
|
||||
legend: {
|
||||
selected: chartLegendSelected,
|
||||
},
|
||||
xAxis: {
|
||||
data: xDatas,
|
||||
data: chartDataXAxisData,
|
||||
},
|
||||
series: yDatas,
|
||||
series: chartDataYSeriesData,
|
||||
});
|
||||
}
|
||||
|
||||
/**图表折线显示全部 */
|
||||
function fnLegendSelected(bool: any) {
|
||||
const chartLegendSelected: Record<string, boolean> = {};
|
||||
for (const key of Object.keys(state.chartLegendSelected)) {
|
||||
for (const key of Object.keys(chartLegendSelected)) {
|
||||
chartLegendSelected[key] = bool;
|
||||
}
|
||||
// 图标签选择状态标记
|
||||
state.chartLegendSelected = chartLegendSelected;
|
||||
kpiChart.value.setOption({
|
||||
legend: {
|
||||
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(() => {
|
||||
// 获取网元网元列表
|
||||
neInfoStore.fnNelist().then(res => {
|
||||
@@ -512,8 +597,8 @@ onMounted(() => {
|
||||
// 查询当前小时
|
||||
const nowDate: Date = new Date();
|
||||
nowDate.setMinutes(0, 0, 0);
|
||||
queryRangePicker.value[0] = parseDateToStr(nowDate);
|
||||
// queryRangePicker.value[0] = '2024-01-30 00:00:00';
|
||||
// queryRangePicker.value[0] = parseDateToStr(nowDate);
|
||||
queryRangePicker.value[0] = '2024-01-30 00:00:00';
|
||||
nowDate.setMinutes(59, 59, 59);
|
||||
queryRangePicker.value[1] = parseDateToStr(nowDate);
|
||||
fnGetListTitle();
|
||||
@@ -528,6 +613,10 @@ onMounted(() => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
ws.close();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -677,20 +766,34 @@ onMounted(() => {
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
<a-space :size="8" align="center" v-show="!tableState.showTable">
|
||||
<a-tooltip>
|
||||
<template #title>
|
||||
{{ t('views.perfManage.goldTarget.showChartSelected') }}
|
||||
</template>
|
||||
<a-form layout="inline" v-show="!tableState.showTable">
|
||||
<a-form-item
|
||||
:label="t('views.perfManage.goldTarget.showChartSelected')"
|
||||
name="chartLegendSelectedFlag"
|
||||
>
|
||||
<a-switch
|
||||
:disabled="tableState.loading"
|
||||
v-model:checked="state.chartLegendSelectedFlag"
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
@change="fnLegendSelected"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
<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>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
|
||||
Reference in New Issue
Block a user