diff --git a/package.json b/package.json index 1f88a6d5..38387fa8 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "crypto-js": "4.2.0", "dayjs": "1.11.13", "echarts": "5.6.0", + "echarts-liquidfill": "^3.1.0", "file-saver": "2.0.5", "grid-layout-plus": "1.0.6", "intl-tel-input": "25.2.0", diff --git a/src/api/faultManage/actAlarm.ts b/src/api/faultManage/actAlarm.ts index 4d8f2dcc..5c2413a1 100644 --- a/src/api/faultManage/actAlarm.ts +++ b/src/api/faultManage/actAlarm.ts @@ -373,3 +373,137 @@ export async function top3Sel(filterFlag?: string) { } return result; } + + +export async function alarmDashGetAct() { + let totalSQL = `select count(*) as total from alarm where alarm_status='1' `; + let rowsSQL = `select ne_type,alarm_id,alarm_title,orig_severity,event_time from alarm WHERE alarm_status='1' and orig_severity!='Event' order by event_time desc limit 0,10 `; + // 查询 + + + // 发起请求 + const result = await request({ + url: `/api/rest/databaseManagement/v1/select/omc_db/alarm`, + method: 'get', + params: { + SQL: totalSQL, + rowsSQL: rowsSQL, + }, + }); + + // 解析数据 + 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['alarm']; + 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; +} + +export async function alarmDashGetHis() { + let totalSQL = `select count(*) as total from alarm where alarm_status='0' `; + let rowsSQL = `select ne_type,alarm_id,alarm_title,orig_severity,event_time from alarm WHERE alarm_status='0' and orig_severity!='Event' order by event_time desc limit 0,10 `; + // 查询 + + + // 发起请求 + const result = await request({ + url: `/api/rest/databaseManagement/v1/select/omc_db/alarm`, + method: 'get', + params: { + SQL: totalSQL, + rowsSQL: rowsSQL, + }, + }); + + // 解析数据 + 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['alarm']; + 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; +} +export async function getAlarmTrend(params: any) { + const days = Number(params.days || 1); + let groupFormat = days === 1 ? '%H:00' : '%Y-%m-%d'; + let timeCondition = days === 1 + ? `event_time >= DATE_SUB(NOW(), INTERVAL 1 DAY)` + : `event_time >= DATE_SUB(CURDATE(), INTERVAL ${days} DAY)`; + let totalSQL = `select count(*) as total from alarm where alarm_status='0' `; + + let rowsSQL = ` SELECT + DATE_FORMAT(event_time, '${groupFormat}') AS time, + SUM(CASE WHEN orig_severity='Critical' THEN 1 ELSE 0 END) AS Critical, + SUM(CASE WHEN orig_severity='Major' THEN 1 ELSE 0 END) AS Major, + SUM(CASE WHEN orig_severity='Minor' THEN 1 ELSE 0 END) AS Minor, + SUM(CASE WHEN orig_severity='Warning' THEN 1 ELSE 0 END) AS Warning + FROM alarm + WHERE alarm_status='0' + AND ${timeCondition} + GROUP BY time + ORDER BY time ASC `; + // 查询 + + + // 发起请求 + const result = await request({ + url: `/api/rest/databaseManagement/v1/select/omc_db/alarm`, + method: 'get', + params: { + SQL: totalSQL, + rowsSQL: rowsSQL, + }, + }); + + // 解析数据 + 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['alarm']; + 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; +} + diff --git a/src/hooks/useRangePicker.ts b/src/hooks/useRangePicker.ts new file mode 100644 index 00000000..61190722 --- /dev/null +++ b/src/hooks/useRangePicker.ts @@ -0,0 +1,47 @@ +import dayjs from 'dayjs'; + +/**日期快捷选择 */ +export function dayjsRanges() { + return [ + { + label: 'Today', + value: [dayjs().startOf('day'), dayjs()], + }, + { + label: 'Last 1 hour', + value: [ + dayjs().subtract(1, 'hour').startOf('hour'), + dayjs().subtract(1, 'hour').endOf('hour'), + ], + }, + // { + // label: 'Last 3 hour', + // value: [dayjs().subtract(3, 'hours'), dayjs()], + // }, + // { + // label: 'Last 6 hour', + // value: [dayjs().subtract(6, 'hours'), dayjs()], + // }, + { + label: 'Last 1 day', + value: [ + dayjs().subtract(1, 'day').startOf('day'), + dayjs().subtract(1, 'day').endOf('day'), + ], + }, + { + label: 'Last 7 day', + value: [ + dayjs().subtract(7, 'day').startOf('day'), + dayjs().subtract(1, 'day').endOf('day'), + ], + }, + { + label: 'Last 15 day', + value: [ + dayjs().subtract(15, 'day').startOf('day'), + dayjs().subtract(1, 'day').endOf('day'), + ], + }, + ]; +} diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index 2f639a10..9decde19 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -361,10 +361,13 @@ export default { imsUeNum: "VoNR/VoLTE", smfUeNum: "Data Sessions", gnbBase: "Online gNodeB", + gnbSumBase: "Total gNodeB", enbBase: "Online eNodeB", + enbSumBase: "Total eNodeB", gnbUeNum:'5G Active Users', enbUeNum:'4G Active Users', baseTitle:'Online Information', + nodeBInfo: 'NodeB Information', }, upfFlow:{ title: "UPF Throughput", @@ -394,6 +397,7 @@ export default { }, userActivity: { title: "User Activity", + imsTitle: "IMS Activity", type: "Type", duration: "Duration", caller: "Caller", @@ -668,7 +672,7 @@ export default { toIpPleace: "Please input the remote backup server IP address", toPort: "Service Port", username: "UserName", - usernamePleace: 'Please enter the service login username', + usernamePleace: 'Please enter the service login username', password: "Password", dir: "Save Dir", dirPleace: 'Please enter the service address target file directory', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 73214c60..3eb6e173 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -361,10 +361,13 @@ export default { imsUeNum: "IMS 会话数", smfUeNum: "Data 会话数", gnbBase: "5G 基站数", + gnbSumBase: "5G 基站总数", gnbUeNum:'5G 用户数', enbBase: "4G 基站数", + enbSumBase: "4G 基站总数", enbUeNum:'4G 用户数', baseTitle:'在线信息', + nodeBInfo: '基站信息', }, upfFlow:{ title: "用户面吞吐量", @@ -394,6 +397,7 @@ export default { }, userActivity: { title: "用户活动", + imsTitle: "IMS 活动", type: "类型", duration: "时长", caller: "主叫", @@ -668,7 +672,7 @@ export default { toIpPleace: "请输入远程备份服务器 IP 地址", toPort: "服务端口", username: "登录用户名", - usernamePleace: '请输入服务登录用户名', + usernamePleace: '请输入服务登录用户名', password: "登录密码", dir: "保存目录", dirPleace: '请输入服务地址目标文件目录', diff --git a/src/views/dashboard/imsCDR/index.vue b/src/views/dashboard/imsCDR/index.vue index 12230357..6b7b9a0c 100644 --- a/src/views/dashboard/imsCDR/index.vue +++ b/src/views/dashboard/imsCDR/index.vue @@ -24,6 +24,7 @@ import PQueue from 'p-queue'; import { listTenant } from '@/api/system/tenant'; import { useClipboard } from '@vueuse/core'; import dayjs, { type Dayjs } from 'dayjs'; +import { dayjsRanges } from '@/hooks/useRangePicker'; const { copy } = useClipboard({ legacy: true }); const { t } = useI18n(); const { getDict } = useDictStore(); @@ -52,21 +53,6 @@ let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>([ dayjs().startOf('hour'), dayjs().endOf('hour'), ]); -/**时间范围 */ -let rangePickerPresets = ref([ - { - label: 'Now hour', - value: [dayjs().startOf('hour'), dayjs().endOf('hour')], - }, - { label: 'Today', value: [dayjs().startOf('day'), dayjs().endOf('day')] }, - { - label: 'Yesterday', - value: [ - dayjs().subtract(1, 'day').startOf('day'), - dayjs().subtract(1, 'day').endOf('day'), - ], - }, -]); /**查询参数 */ let queryParams = reactive({ @@ -648,7 +634,7 @@ onBeforeUnmount(() => { > item.name), //label数组 - textStyle: { - color: '#A7D6F4', // 设置图例文字颜色 - }, + show: false }, - grid: [ + xAxis: [ { - top: '60%', - left: '15%', - right: '25%', - bottom: '10%', + type: 'value', + gridIndex: 0, + show: false, }, + { + type: 'value', + gridIndex: 1, + show: false, + } + ], + yAxis: [ + { + type: 'category', + gridIndex: 0, + data: alarmTypeType.value.map((item: any) => item.name), + axisLabel: { color: '#fff', fontSize: 14,fontWeight: 'bold' }, + axisLine: { show: false }, + axisTick: { show: false }, + inverse: true + }, + { + type: 'category', + gridIndex: 1, + data: alarmTypeTypeTop.value.map((item: any) => item.name), + axisLabel: { color: '#fff', fontSize: 14,fontWeight: 'bold' }, + axisLine: { show: false }, + axisTick: { show: false }, + inverse: true + } ], series: [ - //饼图: + // 四类型告警横向柱状图 { - type: 'pie', - radius: '35%', - color: ['#f5222d', '#fa8c16', '#fadb14', '#1677ff', '#13c2c2'], + type: 'bar', + xAxisIndex: 0, + yAxisIndex: 0, + barWidth: 18, + itemStyle: { + borderRadius: [0, 8, 8, 0], + color: function (params: any) { + // 渐变色 + const colorArr = [ + new echarts.graphic.LinearGradient(0, 0, 1, 0, [ + { offset: 0, color: '#f5222d' }, + { offset: 1, color: '#fa8c16' } + ]), + new echarts.graphic.LinearGradient(0, 0, 1, 0, [ + { offset: 0, color: '#fa8c16' }, + { offset: 1, color: '#fadb14' } + ]), + new echarts.graphic.LinearGradient(0, 0, 1, 0, [ + { offset: 0, color: '#fadb14' }, + { offset: 1, color: '#1677ff' } + ]), + new echarts.graphic.LinearGradient(0, 0, 1, 0, [ + { offset: 0, color: '#1677ff' }, + { offset: 1, color: '#00fcff' } + ]) + ]; + return colorArr[params.dataIndex] || colorArr[3]; + } + }, label: { show: true, - position: 'inner', + position: 'right', + color: '#fff', //淡蓝色 + fontWeight: 'bold', + fontSize: 16, formatter: (params: any) => { if (!params.value) return ''; return `${params.value}`; }, }, - labelLine: { - show: false, - }, - center: ['35%', '25%'], - data: alarmTypeType.value, - zlevel: 2, // 设置zlevel为1,使得柱状图在下层显示 - itemStyle: { - shadowBlur: 10, - shadowOffsetX: 0, - shadowColor: 'rgba(0, 0, 0, 0.5)', - }, + data: alarmTypeType.value.map((item: any) => item.value), + zlevel: 2 }, - //柱状 + // Top3横向柱状图 { + name: 'Top3', type: 'bar', - barWidth: 12, // 柱子宽度 - barCategoryGap: '30%', // 控制同一系列的柱间距离 - label: { - show: true, - position: 'right', // 位置 - color: '#A7D6F4', //淡蓝色 - fontSize: 14, - distance: 14, // label与柱子距离 - formatter: '{c}', - }, + xAxisIndex: 1, + yAxisIndex: 1, + barWidth: 18, itemStyle: { borderRadius: [0, 20, 20, 0], // 圆角(左上、右上、右下、左下) color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ @@ -210,42 +254,19 @@ function initPicture() { { offset: 1, color: '#2f54eb' }, ]), // 渐变 }, - data: alarmTypeTypeTop.value, - }, - ], - // 柱状图设置 - xAxis: [ - { - splitLine: { - show: false, + label: { + show: true, + position: 'right', + color: '#fff', //淡蓝色 + fontWeight: 'bold', + fontSize: 16, + formatter: '{c}' }, - type: 'value', - show: false, - }, - ], - yAxis: [ - { - splitLine: { - show: false, - }, - axisLine: { - //y轴 - show: false, - }, - type: 'category', - axisTick: { - show: false, - }, - inverse: true, - data: alarmTypeTypeTop.value.map((item: any) => item.name), - axisLabel: { - color: '#A7D6F4', - fontSize: 14, - }, - }, - ], + data: alarmTypeTypeTop.value.map((item: any) => item.value), + zlevel: 1 + } + ] }; - fnDesign(alarmTypeBar.value, optionData); }); } diff --git a/src/views/dashboard/overview/components/IMSActivity/index.vue b/src/views/dashboard/overview/components/IMSActivity/index.vue new file mode 100644 index 00000000..ca2aa043 --- /dev/null +++ b/src/views/dashboard/overview/components/IMSActivity/index.vue @@ -0,0 +1,268 @@ + + + + + diff --git a/src/views/dashboard/overview/components/NeResources/index.vue b/src/views/dashboard/overview/components/NeResources/index.vue index fb32626f..669214c8 100644 --- a/src/views/dashboard/overview/components/NeResources/index.vue +++ b/src/views/dashboard/overview/components/NeResources/index.vue @@ -1,24 +1,19 @@ diff --git a/src/views/dashboard/overview/components/Topology/index.vue b/src/views/dashboard/overview/components/Topology/index.vue index 51e55688..1b9e04c8 100644 --- a/src/views/dashboard/overview/components/Topology/index.vue +++ b/src/views/dashboard/overview/components/Topology/index.vue @@ -188,7 +188,7 @@ function handleRanderGraph( } graphG6.value.changeSize( entry.contentRect.width, - entry.contentRect.height - 30 + entry.contentRect.height - 20 ); graphG6.value.fitCenter(); }); diff --git a/src/views/dashboard/overview/components/UserActivity/index.vue b/src/views/dashboard/overview/components/UserActivity/index.vue index 7bd187c1..614b19a2 100644 --- a/src/views/dashboard/overview/components/UserActivity/index.vue +++ b/src/views/dashboard/overview/components/UserActivity/index.vue @@ -65,73 +65,6 @@ onMounted(() => { + +