自定义指标
This commit is contained in:
19
src/api/perfManage/customData.ts
Normal file
19
src/api/perfManage/customData.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
|
||||
/**
|
||||
* 新 查询自定义指标数据
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export async function listCustomData(query: Record<string, any>) {
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/pm/kpiC/report`,
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
834
src/views/perfManage/kpiCReport/index.vue
Normal file
834
src/views/perfManage/kpiCReport/index.vue
Normal file
@@ -0,0 +1,834 @@
|
||||
<script setup lang="ts">
|
||||
import * as echarts from 'echarts/core';
|
||||
import {
|
||||
TooltipComponent,
|
||||
TooltipComponentOption,
|
||||
GridComponent,
|
||||
GridComponentOption,
|
||||
LegendComponent,
|
||||
LegendComponentOption,
|
||||
DataZoomComponent,
|
||||
DataZoomComponentOption,
|
||||
} from 'echarts/components';
|
||||
import { LineChart, LineSeriesOption } from 'echarts/charts';
|
||||
import { UniversalTransition } from 'echarts/features';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
|
||||
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_ERROR,
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { listCustom } from '@/api/perfManage/customTarget';
|
||||
import { listCustomData } from '@/api/perfManage/customData';
|
||||
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';
|
||||
import { useRoute } from 'vue-router';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const route = useRoute();
|
||||
const { t, currentLocale } = useI18n();
|
||||
const ws = new WS();
|
||||
|
||||
echarts.use([
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
LegendComponent,
|
||||
DataZoomComponent,
|
||||
LineChart,
|
||||
CanvasRenderer,
|
||||
UniversalTransition,
|
||||
]);
|
||||
|
||||
type EChartsOption = echarts.ComposeOption<
|
||||
| TooltipComponentOption
|
||||
| GridComponentOption
|
||||
| LegendComponentOption
|
||||
| DataZoomComponentOption
|
||||
| LineSeriesOption
|
||||
>;
|
||||
|
||||
/**图DOM节点实例对象 */
|
||||
const kpiChartDom = ref<HTMLElement | undefined>(undefined);
|
||||
|
||||
/**图实例对象 */
|
||||
const kpiChart = ref<any>(null);
|
||||
|
||||
/**网元参数 */
|
||||
let neCascaderOptions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**记录开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<ColumnsType>([]);
|
||||
|
||||
/**表格字段列排序 */
|
||||
let tableColumnsDnd = ref<ColumnsType>([]);
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
current: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
/**默认的每页条数 */
|
||||
defaultPageSize: 20,
|
||||
/**指定每页可以显示多少条 */
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
/**只有一页时是否隐藏分页器 */
|
||||
hideOnSinglePage: false,
|
||||
/**是否可以快速跳转至某页 */
|
||||
showQuickJumper: true,
|
||||
/**是否可以改变 pageSize */
|
||||
showSizeChanger: true,
|
||||
/**数据总数 */
|
||||
total: 0,
|
||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
||||
onChange: (page: number, pageSize: number) => {
|
||||
tablePagination.current = page;
|
||||
tablePagination.pageSize = pageSize;
|
||||
},
|
||||
});
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: Record<string, any>[];
|
||||
/**显示表格 */
|
||||
showTable: boolean;
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
tableColumns: [],
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: true,
|
||||
data: [],
|
||||
showTable: false,
|
||||
});
|
||||
|
||||
/**表格紧凑型变更操作 */
|
||||
function fnTableSize({ key }: MenuInfo) {
|
||||
tableState.size = key as SizeType;
|
||||
}
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams: any = reactive({
|
||||
/**网元类型 */
|
||||
neType: '',
|
||||
/**网元标识 */
|
||||
neId: '',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**排序字段 */
|
||||
sortField: 'created_at',
|
||||
/**排序方式 */
|
||||
sortOrder: 'desc',
|
||||
});
|
||||
|
||||
/**表格分页、排序、筛选变化时触发操作, 排序方式,取值为 ascend descend */
|
||||
function fnTableChange(pagination: any, filters: any, sorter: any, extra: any) {
|
||||
const { columnKey, order } = sorter;
|
||||
if (!order) return;
|
||||
if (order.startsWith(queryParams.sortOrder)) return;
|
||||
|
||||
if (order) {
|
||||
queryParams.sortField = columnKey;
|
||||
queryParams.sortOrder = order.replace('end', '');
|
||||
} else {
|
||||
queryParams.sortOrder = 'asc';
|
||||
}
|
||||
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**对象信息状态类型 */
|
||||
type StateType = {
|
||||
/**网元类型 */
|
||||
neType: string[];
|
||||
/**图表实时统计 */
|
||||
chartRealTime: boolean;
|
||||
/**图表标签选择 */
|
||||
chartLegendSelectedFlag: boolean;
|
||||
};
|
||||
|
||||
/**对象信息状态 */
|
||||
let state: StateType = reactive({
|
||||
neType: [],
|
||||
chartRealTime: false,
|
||||
chartLegendSelectedFlag: false,
|
||||
});
|
||||
|
||||
/**
|
||||
* 数据列表导出
|
||||
*/
|
||||
function fnRecordExport() {
|
||||
Modal.confirm({
|
||||
title: 'Tip',
|
||||
content: t('views.perfManage.goldTarget.exportSure'),
|
||||
onOk() {
|
||||
const key = 'exportKPI';
|
||||
message.loading({ content: t('common.loading'), key });
|
||||
|
||||
if (tableState.data.length <= 0) {
|
||||
message.error({
|
||||
content: t('views.perfManage.goldTarget.exportEmpty'),
|
||||
key,
|
||||
duration: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const tableColumnsTitleArr: string[] = [];
|
||||
const tableColumnsKeyArr: string[] = [];
|
||||
for (const columns of tableColumnsDnd.value) {
|
||||
tableColumnsTitleArr.push(`${columns.title}`);
|
||||
tableColumnsKeyArr.push(`${columns.key}`);
|
||||
}
|
||||
|
||||
const kpiDataArr = [];
|
||||
for (const item of tableState.data) {
|
||||
const kpiData: Record<string, any> = {};
|
||||
const keys = Object.keys(item);
|
||||
for (let i = 0; i <= tableColumnsKeyArr.length; i++) {
|
||||
for (const key of keys) {
|
||||
if (tableColumnsKeyArr[i] === key) {
|
||||
const title = tableColumnsTitleArr[i];
|
||||
kpiData[title] = item[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
kpiDataArr.push(kpiData);
|
||||
}
|
||||
|
||||
writeSheet(kpiDataArr, 'KPI', { header: tableColumnsTitleArr })
|
||||
.then(fileBlob => saveAs(fileBlob, `kpi_data_${Date.now()}.xlsx`))
|
||||
.finally(() => {
|
||||
message.success({
|
||||
content: t('common.msgSuccess', { msg: t('common.export') }),
|
||||
key,
|
||||
duration: 2,
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**查询数据列表表头 */
|
||||
function fnGetListTitle() {
|
||||
// 当前语言
|
||||
var language = currentLocale.value.split('_')[0];
|
||||
if (language === 'zh') language = 'cn';
|
||||
|
||||
// 获取表头文字
|
||||
listCustom({ neType: state.neType[0], status: 'Active' })
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
if (res.data.length === 0) {
|
||||
message.error({
|
||||
content: t('views.perfManage.customTarget.kpiIdTip'),
|
||||
duration: 2,
|
||||
});
|
||||
tableState.data = [];
|
||||
tableColumns.value = [];
|
||||
tableColumnsDnd.value = [];
|
||||
fnRanderChartData();
|
||||
return false;
|
||||
}
|
||||
tableColumns.value = [];
|
||||
const columns: ColumnsType = [];
|
||||
for (const item of res.data) {
|
||||
const kpiDisplay = item[`title`] + `(${item['unit']})`;
|
||||
const kpiValue = item[`kpiId`];
|
||||
columns.push({
|
||||
title: kpiDisplay,
|
||||
dataIndex: kpiValue,
|
||||
align: 'left',
|
||||
key: kpiValue,
|
||||
resizable: true,
|
||||
width: 100,
|
||||
minWidth: 150,
|
||||
maxWidth: 300,
|
||||
});
|
||||
}
|
||||
columns.push({
|
||||
title: t('views.perfManage.perfData.neName'),
|
||||
dataIndex: 'neName',
|
||||
key: 'neName',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
});
|
||||
columns.push({
|
||||
title: t('views.perfManage.goldTarget.time'),
|
||||
dataIndex: 'timeGroup',
|
||||
align: 'left',
|
||||
fixed: 'right',
|
||||
key: 'timeGroup',
|
||||
sorter: true,
|
||||
width: 100,
|
||||
});
|
||||
|
||||
nextTick(() => {
|
||||
tableColumns.value = columns;
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.getInfoFail'),
|
||||
duration: 2,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.then(result => {
|
||||
result && fnGetList();
|
||||
});
|
||||
}
|
||||
|
||||
/**查询数据列表 */
|
||||
function fnGetList() {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
queryParams.neType = state.neType[0];
|
||||
queryParams.neId = state.neType[1];
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listCustomData(toRaw(queryParams))
|
||||
.then(res => {
|
||||
tableState.loading = false;
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
tablePagination.total = res.data.length;
|
||||
tableState.data = res.data;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.then(result => {
|
||||
if (result) {
|
||||
fnRanderChartData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**切换显示类型 图或表格 */
|
||||
function fnChangShowType() {
|
||||
tableState.showTable = !tableState.showTable;
|
||||
}
|
||||
|
||||
/**绘制图表 */
|
||||
function fnRanderChart() {
|
||||
const container: HTMLElement | undefined = kpiChartDom.value;
|
||||
if (!container) return;
|
||||
kpiChart.value = markRaw(echarts.init(container, 'light'));
|
||||
|
||||
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 => {
|
||||
if (kpiChart.value) {
|
||||
kpiChart.value.resize();
|
||||
}
|
||||
});
|
||||
// 监听元素大小变化
|
||||
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;
|
||||
}
|
||||
|
||||
// 重置
|
||||
chartLegendSelected = {};
|
||||
chartDataXAxisData = [];
|
||||
chartDataYSeriesData = [];
|
||||
|
||||
for (var columns of tableColumns.value) {
|
||||
if (
|
||||
columns.key === 'neName' ||
|
||||
columns.key === 'startIndex' ||
|
||||
columns.key === 'timeGroup'
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const color = generateColorRGBA();
|
||||
chartDataYSeriesData.push({
|
||||
name: `${columns.title}`,
|
||||
key: `${columns.key}`,
|
||||
type: 'line',
|
||||
symbol: 'none',
|
||||
sampling: 'lttb',
|
||||
itemStyle: {
|
||||
color: color,
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: color.replace(')', ',0.8)'),
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: color.replace(')', ',0.3)'),
|
||||
},
|
||||
]),
|
||||
},
|
||||
data: [],
|
||||
});
|
||||
chartLegendSelected[`${columns.title}`] = state.chartLegendSelectedFlag;
|
||||
}
|
||||
|
||||
// 用降序就反转
|
||||
let orgData = tableState.data;
|
||||
if (queryParams.sortOrder === 'desc') {
|
||||
orgData = orgData.toReversed();
|
||||
}
|
||||
|
||||
for (const item of orgData) {
|
||||
chartDataXAxisData.push(item['timeGroup']);
|
||||
const keys = Object.keys(item);
|
||||
for (const y of chartDataYSeriesData) {
|
||||
for (const key of keys) {
|
||||
if (y.key === key) {
|
||||
y.data.push(+item[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// console.log(queryParams.sortOrder, chartLegendSelected);
|
||||
// console.log(chartDataXAxisData, chartDataYSeriesData);
|
||||
|
||||
// 绘制图数据
|
||||
kpiChart.value.setOption(
|
||||
{
|
||||
legend: {
|
||||
selected: chartLegendSelected,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: chartDataXAxisData,
|
||||
},
|
||||
series: chartDataYSeriesData,
|
||||
},
|
||||
{
|
||||
replaceMerge: ['xAxis', 'series'],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**图表折线显示全部 */
|
||||
function fnLegendSelected(bool: any) {
|
||||
for (const key of Object.keys(chartLegendSelected)) {
|
||||
chartLegendSelected[key] = bool;
|
||||
}
|
||||
kpiChart.value.setOption({
|
||||
legend: {
|
||||
selected: chartLegendSelected,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**图表实时统计 */
|
||||
function fnRealTimeSwitch(bool: any) {
|
||||
if (bool) {
|
||||
tableState.seached = false;
|
||||
// 建立链接
|
||||
const options: OptionsType = {
|
||||
url: '/ws',
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* 指标(GroupID:10_neType_neId)
|
||||
*/
|
||||
subGroupID: `20_${queryParams.neType}_${queryParams.neId}`,
|
||||
},
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
};
|
||||
ws.connect(options);
|
||||
} else {
|
||||
tableState.seached = true;
|
||||
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 黄金指标指标事件
|
||||
const kpiEvent = data.data;
|
||||
tableState.data.unshift(kpiEvent);
|
||||
tablePagination.total++;
|
||||
|
||||
// 非对应网元类型
|
||||
if (kpiEvent.neType !== queryParams.neType) return;
|
||||
|
||||
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(() => {
|
||||
// 目前支持的 AMF AUSF MME MOCNGW NSSF SMF UDM UPF PCF
|
||||
// 获取网元网元列表
|
||||
neInfoStore.fnNelist().then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
if (res.data.length > 0) {
|
||||
// 过滤不可用的网元
|
||||
neCascaderOptions.value = neInfoStore.getNeCascaderOptions.filter(
|
||||
(item: any) => {
|
||||
return !['OMC', 'NSSF', 'NEF', 'NRF', 'LMF', 'N3IWF'].includes(
|
||||
item.value
|
||||
);
|
||||
}
|
||||
);
|
||||
if (neCascaderOptions.value.length === 0) {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 无查询参数neType时 默认选择UPF
|
||||
const queryNeType = (route.query.neType as string) || 'UPF';
|
||||
const item = neCascaderOptions.value.find(s => s.value === queryNeType);
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
state.neType = [info.neType, info.neId];
|
||||
queryParams.neType = info.neType;
|
||||
queryParams.neId = info.neId;
|
||||
} else {
|
||||
const info = neCascaderOptions.value[0].children[0];
|
||||
state.neType = [info.neType, info.neId];
|
||||
queryParams.neType = info.neType;
|
||||
queryParams.neId = info.neId;
|
||||
}
|
||||
|
||||
// 查询当前小时
|
||||
|
||||
const now = new Date();
|
||||
now.setMinutes(0, 0, 0);
|
||||
queryRangePicker.value[0] = parseDateToStr(now.getTime());
|
||||
now.setMinutes(59, 59, 59);
|
||||
queryRangePicker.value[1] = parseDateToStr(now.getTime());
|
||||
fnGetListTitle();
|
||||
// 绘图
|
||||
fnRanderChart();
|
||||
}
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
ws.close();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParamsFrom" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
name="neType"
|
||||
:label="t('views.traceManage.task.neType')"
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="state.neType"
|
||||
:options="neCascaderOptions"
|
||||
:allow-clear="false"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="10" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.perfManage.goldTarget.timeFrame')"
|
||||
name="timeFrame"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
bordered
|
||||
:allow-clear="false"
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :lg="2" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="tableState.loading"
|
||||
@click.prevent="fnGetListTitle()"
|
||||
>
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="tableState.loading"
|
||||
@click.prevent="fnChangShowType()"
|
||||
>
|
||||
<template #icon> <AreaChartOutlined /> </template>
|
||||
{{
|
||||
tableState.showTable
|
||||
? t('views.perfManage.goldTarget.kpiChartTitle')
|
||||
: t('views.perfManage.goldTarget.kpiTableTitle')
|
||||
}}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="dashed"
|
||||
:loading="tableState.loading"
|
||||
@click.prevent="fnRecordExport()"
|
||||
v-show="tableState.showTable"
|
||||
>
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
</template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center" v-show="tableState.showTable">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<TableColumnsDnd
|
||||
v-if="tableColumns.length > 0"
|
||||
:cache-id="`kpiTarget_${state.neType[0]}`"
|
||||
:columns="tableColumns"
|
||||
v-model:columns-dnd="tableColumnsDnd"
|
||||
></TableColumnsDnd>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
<a-button type="text">
|
||||
<template #icon><ColumnHeightOutlined /></template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="middle">
|
||||
{{ t('common.size.middle') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="small">
|
||||
{{ t('common.size.small') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
<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-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>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
v-show="tableState.showTable"
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumnsDnd"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumnsDnd.length * 200, y: 'calc(100vh - 480px)' }"
|
||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||
:show-expand-column="false"
|
||||
@change="fnTableChange"
|
||||
>
|
||||
</a-table>
|
||||
|
||||
<!-- 图表 -->
|
||||
<div style="padding: 24px" v-show="!tableState.showTable">
|
||||
<div ref="kpiChartDom" style="height: 450px; width: 100%"></div>
|
||||
</div>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
Reference in New Issue
Block a user