diff --git a/src/api/perfManage/customData.ts b/src/api/perfManage/customData.ts new file mode 100644 index 00000000..237b0a65 --- /dev/null +++ b/src/api/perfManage/customData.ts @@ -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) { + // 发起请求 + const result = await request({ + url: `/pm/kpiC/report`, + method: 'get', + params: query, + }); + return result; +} diff --git a/src/api/perfManage/customTarget.ts b/src/api/perfManage/customTarget.ts index 4134a0fd..ac3b9ab6 100644 --- a/src/api/perfManage/customTarget.ts +++ b/src/api/perfManage/customTarget.ts @@ -8,57 +8,72 @@ import { parseDateToStr } from '@/utils/date-utils'; * @param query 查询参数 * @returns object */ -export async function listCustom(query: Record) { - let totalSQL = 'select count(*) as total from pm_custom_title where 1=1 '; - let rowsSQL = 'select * from pm_custom_title where 1=1 '; +// export async function listCustom(query: Record) { +// let totalSQL = 'select count(*) as total from pm_custom_title where 1=1 '; +// let rowsSQL = 'select * from pm_custom_title where 1=1 '; - // 查询 - let querySQL = ''; - if (query.neType) { - querySQL += ` and ne_type like '%${query.neType}%' `; - } +// // 查询 +// let querySQL = ''; +// if (query.neType) { +// querySQL += ` and ne_type like '%${query.neType}%' `; +// } - // 排序 - let sortSql = ' order by update_time '; - if (query.sortOrder === 'asc') { - sortSql += ' asc '; - } else { - sortSql += ' desc '; - } - // 分页 - const pageNum = (query.pageNum - 1) * query.pageSize; - const limtSql = ` limit ${pageNum},${query.pageSize} `; +// // 排序 +// let sortSql = ' order by update_time '; +// if (query.sortOrder === 'asc') { +// sortSql += ' asc '; +// } else { +// sortSql += ' desc '; +// } +// // 分页 +// const pageNum = (query.pageNum - 1) * query.pageSize; +// const limtSql = ` limit ${pageNum},${query.pageSize} `; +// // 发起请求 +// const result = await request({ +// url: `/api/rest/databaseManagement/v1/select/omc_db/pm_custom_title`, +// method: 'get', +// params: { +// totalSQL: totalSQL + querySQL, +// rowsSQL: rowsSQL + querySQL + sortSql + limtSql, +// }, +// }); + +// // 解析数据 +// if (result.code === RESULT_CODE_SUCCESS) { +// const data: DataList = { +// total: 0, +// rows: [], +// code: result.code, +// msg: result.msg, +// }; +// result.data.data.forEach((item: any) => { +// const itemData = item['pm_custom_title']; +// if (Array.isArray(itemData)) { +// if (itemData.length === 1 && itemData[0]['total'] >= 0) { +// data.total = itemData[0]['total']; +// } else { +// data.rows = itemData.map(v => parseObjLineToHump(v)); +// } +// } +// }); +// return data; +// } +// return result; +// } + +/** + * 新 查询自定义指标 + * @param query 查询参数 + * @returns object + */ +export async function listCustom(query?: Record) { // 发起请求 const result = await request({ - url: `/api/rest/databaseManagement/v1/select/omc_db/pm_custom_title`, + url: `/pm/kpiC/title/totalList`, method: 'get', - params: { - totalSQL: totalSQL + querySQL, - rowsSQL: rowsSQL + querySQL + sortSql + limtSql, - }, + params: query, }); - - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS) { - const data: DataList = { - total: 0, - rows: [], - code: result.code, - msg: result.msg, - }; - result.data.data.forEach((item: any) => { - const itemData = item['pm_custom_title']; - if (Array.isArray(itemData)) { - if (itemData.length === 1 && itemData[0]['total'] >= 0) { - data.total = itemData[0]['total']; - } else { - data.rows = itemData.map(v => parseObjLineToHump(v)); - } - } - }); - return data; - } return result; } @@ -68,22 +83,10 @@ export async function listCustom(query: Record) { * @returns object */ export async function getCustom(id: string | number) { - // 发起请求 - const result = await request({ - url: `/api/rest/databaseManagement/v1/select/omc_db/pm_custom_title`, + return request({ + url: `/pm/kpiC/title/${id}`, method: 'get', - params: { - SQL: `select * from pm_custom_title where id = ${id}`, - }, }); - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { - let data = result.data.data[0]; - return Object.assign(result, { - data: parseObjLineToHump(data['pm_custom_title'][0]), - }); - } - return result; } /** @@ -92,21 +95,10 @@ export async function getCustom(id: string | number) { * @returns object */ export function addCustom(data: Record) { - let obj: any = { - title: data.title, - ne_type: data.neType, - kpi_id: data.kpiId, - object_type: data.objectType, - expression: data.expression, - period: data.period, - description: data.description, - kpi_set: data.kpiSet, - }; - return request({ - url: `/api/rest/databaseManagement/v1/omc_db/pm_custom_title`, + url: `/pm/kpiC/title`, method: 'post', - data: { 'data': [obj] }, + data: data, }); } @@ -116,20 +108,10 @@ export function addCustom(data: Record) { * @returns object */ export function updateCustom(data: Record) { - let obj: any = { - title: data.title, - ne_type: data.neType, - kpi_id: data.kpiId, - object_type: data.objectType, - expression: data.expression, - period: data.period, - description: data.description, - kpi_set: data.kpiSet, - }; return request({ - url: `/api/rest/databaseManagement/v1/omc_db/pm_custom_title?WHERE=id=${data.id}`, + url: `/pm/kpiC/title/${data.id}`, method: 'put', - data: { data: obj }, + data: data, }); } @@ -139,8 +121,7 @@ export function updateCustom(data: Record) { */ export async function delCustom(data: Record) { return request({ - url: `/api/rest/databaseManagement/v1/omc_db/pm_custom_title?WHERE=id=${data.id}`, + url: `/pm/kpiC/title/${data.id}`, method: 'delete', }); } - diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index 9d40bcd2..c1737b86 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -1051,6 +1051,7 @@ export default { }, customTarget:{ kpiId:' Custom Indicator', + kpiIdTip:'This Ne has no custom indicators', period:' Granularity', title:' Custom Indicator Title', objectType:' Object type', @@ -1067,6 +1068,8 @@ export default { inactive:'Inactive', symbol:'Symbol', element:'Element', + granularity:'Granularity', + unit:'Unit', } }, traceManage: { @@ -1284,7 +1287,7 @@ export default { tailLines: 'End Lines', }, exportFile:{ - fileName:'File Name', + fileName:'File Source', downTip: "Confirm the download file name is [{fileName}] File?", downTipErr: "Failed to get file", deleteTip: "Confirm the delete file name is [{fileName}] File?", diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 7062158a..b235130f 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -1,3 +1,5 @@ +import { title } from "process"; + export default { // 语言 i18n: '中文', @@ -1051,6 +1053,7 @@ export default { }, customTarget:{ kpiId:'自定义指标项', + kpiIdTip:'该网元没有自定义指标', period:'颗粒度', title:'自定义指标项标题', objectType:'对象类型', @@ -1067,6 +1070,8 @@ export default { inactive:'停用', symbol:"符号", element:'元素', + granularity:'颗粒度', + unit:'单位', } }, traceManage: { @@ -1284,7 +1289,7 @@ export default { tailLines: '末尾行数', }, exportFile:{ - fileName:'文件名', + fileName:'文件来源', downTip: "确认下载文件名为 【{fileName}】 文件?", downTipErr: "文件获取失败", deleteTip: "确认删除文件名为 【{fileName}】 文件?", diff --git a/src/views/logManage/exportFile/index.vue b/src/views/logManage/exportFile/index.vue index ca97ce8d..9e9db183 100644 --- a/src/views/logManage/exportFile/index.vue +++ b/src/views/logManage/exportFile/index.vue @@ -139,7 +139,9 @@ function fnDownloadFile(row: Record) { if (downLoading.value) return; Modal.confirm({ title: t('common.tipTitle'), - content: t('views.logManage.exportFile.downTip', { fileName: row.fileName }), + content: t('views.logManage.exportFile.downTip', { + fileName: row.fileName, + }), onOk() { downLoading.value = true; const hide = message.loading(t('common.loading'), 0); @@ -175,7 +177,9 @@ function fnRecordDelete(row: Record) { if (delLoading.value) return; Modal.confirm({ title: t('common.tipTitle'), - content: t('views.logManage.exportFile.deleteTip', { fileName: row.fileName }), + content: t('views.logManage.exportFile.deleteTip', { + fileName: row.fileName, + }), onOk() { const key = 'delFile'; delLoading.value = true; @@ -288,6 +292,19 @@ onMounted(() => { /> + + + + + {{ queryParams.path }} + + + + diff --git a/src/views/perfManage/customTarget/index.vue b/src/views/perfManage/customTarget/index.vue index 2c5b78f3..b7e44405 100644 --- a/src/views/perfManage/customTarget/index.vue +++ b/src/views/perfManage/customTarget/index.vue @@ -7,8 +7,8 @@ import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'; import { ColumnsType } from 'ant-design-vue/lib/table'; import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; import useI18n from '@/hooks/useI18n'; -import useDictStore from '@/store/modules/dict'; import useNeInfoStore from '@/store/modules/neinfo'; +import { parseObjLineToHump } from '@/utils/parse-utils'; import { addCustom, delCustom, @@ -16,15 +16,17 @@ import { listCustom, updateCustom, } from '@/api/perfManage/customTarget'; -const { getDict } = useDictStore(); +import { getKPITitle } from '@/api/perfManage/goldTarget'; +import useDictStore from '@/store/modules/dict'; const { t, currentLocale } = useI18n(); +const { getDict } = useDictStore(); /**字典数据 */ let dict: { - /**原始严重程度 */ - activeAlarmSeverity: DictType[]; + /**状态 */ + sysNormalDisable: DictType[]; } = reactive({ - activeAlarmSeverity: [], + sysNormalDisable: [], }); /**查询参数 */ @@ -85,15 +87,22 @@ let tableColumns: ColumnsType = [ align: 'center', }, { - title: t('views.perfManage.customTarget.kpiSet'), - dataIndex: 'kpiSet', + title: t('views.perfManage.customTarget.title'), + dataIndex: 'title', align: 'center', }, { - title: t('views.perfManage.customTarget.period'), - dataIndex: 'threshold', + title: t('views.perfManage.customTarget.description'), + dataIndex: 'description', align: 'center', }, + { + title: t('views.perfManage.customTarget.status'), + dataIndex: 'status', + key: 'status', + align: 'left', + width: 100, + }, { title: t('common.operate'), key: 'id', @@ -175,13 +184,14 @@ function fnGetList(pageNum?: number) { queryParams.pageNum = pageNum; } listCustom(toRaw(queryParams)).then(res => { - if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) { + if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { // 取消勾选 if (tableState.selectedRowKeys.length > 0) { tableState.selectedRowKeys = []; } tablePagination.total = res.total; - tableState.data = res.rows; + tableState.data = res.data; + if ( tablePagination.total <= (queryParams.pageNum - 1) * tablePagination.pageSize && @@ -207,8 +217,6 @@ type ModalStateType = { neType: string[]; /**网元类型性能测量集 */ neTypPerformance: Record[]; - /**网元类型对象类型集 */ - objectTypeArr: Record[]; /**已选择性能测量项 */ selectedPre: string[]; /**表单数据 */ @@ -224,21 +232,32 @@ let modalState: ModalStateType = reactive({ title: '', neType: [], neTypPerformance: [], - objectTypeArr: [], selectedPre: [], from: { - id: '', - neType: '', - objectType: '', - expression: '', - kpiSet: '', - title: '', + id: undefined, + neType: 'UDM', kpiId: '', - period: 900, + title: '', + expression: '', + status: 'Active', + unit: '', + description: '', }, confirmLoading: false, }); +/**表单中多选的OPTION */ +const modalStateFromOption = reactive({ + symbolJson: [ + { label: '(', value: '(' }, + { label: ')', value: ')' }, + { label: '+', value: '+' }, + { label: '-', value: '-' }, + { label: '*', value: '*' }, + { label: '/', value: '/' }, + ], +}); + /**对话框内表单属性和校验规则 */ const modalStateFrom = Form.useForm( modalState.from, @@ -249,14 +268,6 @@ const modalStateFrom = Form.useForm( message: t('views.traceManage.task.neTypePlease'), }, ], - objectType: [ - { - required: true, - message: - t('views.perfManage.customTarget.objectType') + - t('common.unableNull'), - }, - ], expression: [ { required: true, @@ -279,60 +290,45 @@ const modalStateFrom = Form.useForm( t('views.perfManage.customTarget.title') + t('common.unableNull'), }, ], - period: [ + unit: [ { required: true, message: - t('views.perfManage.customTarget.period') + t('common.unableNull'), + t('views.perfManage.customTarget.unit') + t('common.unableNull'), }, ], }) ); -/**性能测量数据集选择初始 */ +/**性能测量数据集选择初始 value:neType*/ function fnSelectPerformanceInit(value: any) { - const performance = useNeInfoStore().perMeasurementList.filter( - i => i.neType === value - ); - if (modalState.from.objectType) modalState.from.objectType = ''; - if (modalState.selectedPre.length > 0) modalState.selectedPre = []; - modalState.from.expression = ''; - const arrSet = new Set(); - performance.forEach((data: any) => { - arrSet.add(data.objectType); - }); - // 组装对象类型options - modalState.objectTypeArr = Array.from(arrSet).map((value: any) => ({ - label: value, - value: value, - })); - - //进行分组选择 - const groupedData = performance.reduce((groups: any, item: any) => { - const { kpiCode, ...rest } = item; - if (!groups[kpiCode]) { - groups[kpiCode] = []; + modalState.neTypPerformance = [ + { + value: 'granularity', + label: t('views.perfManage.customTarget.granularity'), + }, + ]; + // 当前语言 + var language = currentLocale.value.split('_')[0]; + if (language === 'zh') language = 'cn'; + // 获取表头文字 + getKPITitle(value).then(res => { + if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { + for (const item of res.data) { + const kpiDisplay = item[`${language}Title`]; + const kpiValue = item[`kpiId`]; + modalState.neTypPerformance.push({ + value: kpiValue, + label: kpiDisplay, + }); + } + } else { + message.warning({ + content: t('common.getInfoFail'), + duration: 2, + }); } - groups[kpiCode].push(rest); - return groups; - }, {}); - - //渲染出性能测量集的选择项 - modalState.neTypPerformance = Object.keys(groupedData).map(kpiCode => { - return { - label: kpiCode, - options: groupedData[kpiCode].map((item: any) => { - return { - value: item.kpiId, - label: - currentLocale.value === 'zh_CN' - ? JSON.parse(item.titleJson).cn - : JSON.parse(item.titleJson).en, - kpiCode: kpiCode, - }; - }), - }; }); } @@ -340,30 +336,17 @@ function fnSelectPerformanceInit(value: any) { * 对话框弹出显示为 新增或者修改 * @param noticeId 网元id, 不传为新增 */ -function fnModalVisibleByEdit(id?: string) { +function fnModalVisibleByEdit(row?: any, id?: any) { if (!id) { modalStateFrom.resetFields(); modalState.title = t('views.perfManage.customTarget.addCustom'); modalState.visibleByEdit = true; + fnSelectPerformanceInit(modalState.from.neType); } else { - if (modalState.confirmLoading) return; - const hide = message.loading(t('common.loading'), 0); - modalState.confirmLoading = true; - getCustom(id).then(res => { - modalState.confirmLoading = false; - hide(); - if (res.code === RESULT_CODE_SUCCESS && res.data) { - fnSelectPerformanceInit(res.data.neType); - modalState.selectedPre = res.data.kpiSet - ? res.data.kpiSet.split(',') - : []; - modalState.from = Object.assign(modalState.from, res.data); - modalState.title = t('views.perfManage.customTarget.editCustom'); - modalState.visibleByEdit = true; - } else { - message.error(t('views.perfManage.customTarget.errorCustomInfo'), 3); - } - }); + fnSelectPerformanceInit(row.neType); + modalState.from = Object.assign(modalState.from, row); + modalState.title = t('views.perfManage.customTarget.editCustom'); + modalState.visibleByEdit = true; } } @@ -375,13 +358,6 @@ function fnModalOk() { modalStateFrom .validate() .then(e => { - // if (modalState.selectedPre.length === 0) { - // message.error({ - // content: `${res.msg}`, - // duration: 3, - // }); - // } - modalState.from.kpiSet = modalState.selectedPre.join(','); const from = toRaw(modalState.from); //return false; modalState.confirmLoading = true; @@ -424,46 +400,57 @@ function fnModalCancel() { modalStateFrom.resetFields(); modalState.neType = []; modalState.neTypPerformance = []; - modalState.selectedPre = []; } /** * 选择性能指标,填充进当前计算公式的值 */ function fnSelectPer(s: any, option: any) { + modalState.from.expression += `'${s}'`; +} + +function fnSelectSymbol(s: any) { modalState.from.expression += s; } - -/** - * 多选框取消性能指标 表达式的变化 - */ -function fnDelPer(s: any, option: any) { - modalState.from.expression = modalState.from.expression.replace(s, ''); -} - -// function checkText(e:any){ -// console.log(e); -// const reg = /^[*+-/]*$/; - -// } - +/**网元参数 */ +let neCascaderOptions = ref[]>([]); onMounted(() => { - // 初始字典数据 - Promise.allSettled([getDict('active_alarm_severity')]).then(resArr => { - if (resArr[0].status === 'fulfilled') { - dict.activeAlarmSeverity = resArr[0].value; - } - }); - Promise.allSettled([ // 获取网元网元列表 + getDict('sys_normal_disable'), useNeInfoStore().fnNelist(), - // 获取性能测量集列表 - useNeInfoStore().fnNeTaskPerformance(), - ]).finally(() => { - // 获取列表数据 - fnGetList(); - }); + ]) + .then(resArr => { + if (resArr[0].status === 'fulfilled') { + dict.sysNormalDisable = resArr[0].value; + } + + if ( + resArr[1].status === 'fulfilled' && + Array.isArray(resArr[1].value.data) + ) { + if (resArr[1].value.data.length > 0) { + // 过滤不可用的网元 + neCascaderOptions.value = + useNeInfoStore().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; + } + } + } + }) + .finally(() => { + // 获取列表数据 + fnGetList(); + }); }); @@ -484,7 +471,7 @@ onMounted(() => { > @@ -580,7 +567,7 @@ onMounted(() => { @@ -593,6 +580,24 @@ onMounted(() => { + + @@ -610,7 +615,12 @@ onMounted(() => { @ok="fnModalOk" @cancel="fnModalCancel" > - + { > { - - - - - - + + + + + + { - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + @@ -714,6 +750,7 @@ onMounted(() => { +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(undefined); + +/**图实例对象 */ +const kpiChart = ref(null); + +/**网元参数 */ +let neCascaderOptions = ref[]>([]); + +/**记录开始结束时间 */ +let queryRangePicker = ref<[string, string]>(['', '']); + +/**表格字段列 */ +let tableColumns = ref([]); + +/**表格字段列排序 */ +let tableColumnsDnd = ref([]); + +/**表格分页器参数 */ +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[]; + /**显示表格 */ + 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 = {}; + 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[`unit`]? item[`title`]+ `(${item['unit']})`:item[`title`]; + 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 = {}; +/**图表配置数据x轴 */ +let chartDataXAxisData: string[] = []; +/**图表配置数据y轴 */ +let chartDataYSeriesData: Record[] = []; + +/**图表数据渲染 */ +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) { + 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(); +}); + + + + +