diff --git a/.env.development b/.env.development index 5d11267f..12c39038 100644 --- a/.env.development +++ b/.env.development @@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network EMS" VITE_APP_CODE = "CN EMS" # 应用版本 -VITE_APP_VERSION = "2.240712" +VITE_APP_VERSION = "2.240727" # 接口基础URL地址-不带/后缀 VITE_API_BASE_URL = "/omc-api" diff --git a/.env.production b/.env.production index 9613308b..ebbaf2c6 100644 --- a/.env.production +++ b/.env.production @@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network EMS" VITE_APP_CODE = "CN EMS" # 应用版本 -VITE_APP_VERSION = "2.240712" +VITE_APP_VERSION = "2.240727" # 接口基础URL地址-不带/后缀 VITE_API_BASE_URL = "/omc-api" diff --git a/src/api/ne/neConfigBackup.ts b/src/api/ne/neConfigBackup.ts new file mode 100644 index 00000000..4c96b485 --- /dev/null +++ b/src/api/ne/neConfigBackup.ts @@ -0,0 +1,83 @@ +import { request } from '@/plugins/http-fetch'; + +/** + * 网元配置文件备份记录列表 + * @param query 查询参数 + * @returns object + */ +export function listNeConfigBackup(query: Record) { + return request({ + url: '/ne/config/backup/list', + method: 'get', + params: query, + }); +} + +/** + * 网元配置文件备份记录修改 + * @param data 数据 { id, name, remark } + * @returns object + */ +export function updateNeConfigBackup(data: Record) { + return request({ + url: '/ne/config/backup', + method: 'put', + data: data, + }); +} + +/** + * 网元配置文件备份记录下载 + * @param id 记录ID + * @returns object + */ +export async function downNeConfigBackup(id: string) { + return await request({ + url: '/ne/config/backup/download', + method: 'get', + params: { id }, + responseType: 'blob', + timeout: 180_000, + }); +} + +/** + * 网元配置文件备份记录删除 + * @param id 记录ID + * @returns object + */ +export async function delNeConfigBackup(id: string) { + return request({ + url: '/ne/config/backup', + method: 'delete', + params: { id }, + }); +} + +/** + * 网元配置文件备份导出 + * @param data 数据 { neType, neId } + * @returns object + */ +export function exportNeConfigBackup(data: Record) { + return request({ + url: '/ne/config/backup/export', + method: 'post', + data: data, + responseType: 'blob', + timeout: 180_000, + }); +} + +/** + * 网元配置文件备份导入 + * @param data 数据 { neType, neId, type, path } + * @returns object + */ +export function importNeConfigBackup(data: Record) { + return request({ + url: '/ne/config/backup/import', + method: 'post', + data: data, + }); +} \ No newline at end of file diff --git a/src/api/neData/udm_auth.ts b/src/api/neData/udm_auth.ts index 0af15c84..abc2450d 100644 --- a/src/api/neData/udm_auth.ts +++ b/src/api/neData/udm_auth.ts @@ -113,7 +113,6 @@ export function batchDelUDMAuth(neId: string, imsi: string, num: number) { /** * UDM鉴权用户导入 - * @param neId 网元ID * @param data 表单数据对象 * @returns object */ diff --git a/src/api/neUser/ims.ts b/src/api/neUser/ims.ts index 71c5bf2c..0ead4388 100644 --- a/src/api/neUser/ims.ts +++ b/src/api/neUser/ims.ts @@ -52,9 +52,11 @@ export async function listUENumByIMS(neId: String) { method: 'get', }); if (result.code === RESULT_CODE_SUCCESS) { - return Object.assign(result, { - data: result.data['ueNum'], - }); + let num = result.data['ueNum'] || 0; + if (num === 0) { + num = result.data.data['ueNum'] || 0; + } + return Object.assign(result, { data: num }); } // 模拟数据 diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index b3d0ab90..6c93e187 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -668,9 +668,8 @@ export default { local:'Local File', localUpload:'Local Upload', exportTip:'Confirm that you want to export the network element configuration file?', - exportMsg:'Exported successfully, please download from [Backup Management].', - filePlease: "Please upload a file", - fileNamePlease: 'Please select the server file', + exportMsg:'Exporting Network Element Configuration Information to a File Succeeded', + pathPlease: 'No Backup File Found', }, }, neHost: { @@ -781,6 +780,11 @@ export default { syncNeDone: 'Synchronization to network element terminals complete', saveOk: 'Save Success!', }, + neConfigBackup: { + name: "Name", + downTip: 'Confirmed to download the backup file [{txt}]?', + title: "Modify Backup {txt}", + }, neQuickSetup: { stepPrev: 'Previous', stepPrevTip: 'Confirm that you want to abandon the current change and return to the previous step?', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 3f5c6c67..80742819 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -668,9 +668,8 @@ export default { local:'本地文件', localUpload:'本地上传', exportTip:'确认要导出网元配置信息到文件?', - exportMsg:'导出成功,请到【备份管理】进行下载', - filePlease: "请上传文件", - fileNamePlease: '请选择服务器文件', + exportMsg:'导出网元配置信息到文件成功', + pathPlease: '未发现文件', }, }, neHost: { @@ -781,6 +780,11 @@ export default { syncNeDone: '同步到网元终端完成', saveOk: '保存成功!', }, + neConfigBackup: { + name: "名称", + downTip: '确认要下载备份文件【{txt}】吗?', + title: "修改备份信息 {txt}", + }, neQuickSetup: { stepPrev: '上一步', stepPrevTip: '确认要放弃当前变更返回上一步吗?', diff --git a/src/layouts/BasicLayout.vue b/src/layouts/BasicLayout.vue index f8c8f72a..63d21828 100644 --- a/src/layouts/BasicLayout.vue +++ b/src/layouts/BasicLayout.vue @@ -176,6 +176,7 @@ function fnCheckAppNameOverflow() { if (!text) return; if (text.offsetWidth > container.offsetWidth) { text.classList.add('app-name_scrollable'); + text.setAttribute('data-content', text.innerText); } else { text.classList.remove('app-name_scrollable'); } @@ -342,11 +343,17 @@ onUnmounted(() => { :href="appStore.officialUrl" target="_blank" size="small" + v-perms:has="['system:setting:official']" v-if="appStore.officialUrl !== '#'" > {{ t('loayouts.basic.officialUrl') }} - + {{ t('loayouts.basic.helpDoc') }} @@ -382,20 +389,26 @@ onUnmounted(() => { // text-overflow: ellipsis; white-space: nowrap; width: 148px; - - &_scrollable { - // padding-left: 100%; + > .app-name_scrollable { + padding-right: 12px; display: inline-block; animation: scrollable-animation linear 6s infinite both; - } - - @keyframes scrollable-animation { - 0% { - transform: translate3d(0, 0, 0); + &::after { + content: attr(data-content); + position: absolute; + top: 0; + right: -100%; + transition: right 0.3s ease; } - 100% { - transform: translate3d(-100%, 0, 0); + @keyframes scrollable-animation { + 0% { + transform: translateX(0); + } + + 100% { + transform: translateX(calc(-100% - 12px)); + } } } } diff --git a/src/layouts/components/RightContent.vue b/src/layouts/components/RightContent.vue index 5b1f365d..721e42e4 100644 --- a/src/layouts/components/RightContent.vue +++ b/src/layouts/components/RightContent.vue @@ -91,42 +91,45 @@ function fnChangeLocale(e: any) { - - - - - - - - {{ t('loayouts.rightContent.lockPasswd') }}: - - - - - - + + + + + + + + + {{ t('loayouts.rightContent.lockPasswd') }}: + + + + + + + - + + diff --git a/src/views/dashboard/amfUE/index.vue b/src/views/dashboard/amfUE/index.vue index cefe710e..e9186bc9 100644 --- a/src/views/dashboard/amfUE/index.vue +++ b/src/views/dashboard/amfUE/index.vue @@ -42,7 +42,7 @@ let queryParams = reactive({ /**网元类型 */ neType: 'AMF', neId: '001', - eventType: 'auth-result', + eventType: '', imsi: '', sortField: 'timestamp', sortOrder: 'desc', @@ -58,9 +58,9 @@ let queryParams = reactive({ /**查询参数重置 */ function fnQueryReset() { - eventTypes.value = ['auth-result']; + eventTypes.value = []; queryParams = Object.assign(queryParams, { - eventType: 'auth-result', + eventType: '', imsi: '', startTime: '', endTime: '', @@ -74,7 +74,7 @@ function fnQueryReset() { } /**记录类型 */ -const eventTypes = ref(['auth-result']); +const eventTypes = ref([]); /**查询记录类型变更 */ function fnQueryEventTypeChange(value: any) { @@ -607,10 +607,7 @@ onBeforeUnmount(() => { :value="record.eventJSON.authCode" /> - + {{ t('views.dashboard.ue.resultOk') }} @@ -706,7 +703,7 @@ onBeforeUnmount(() => { /> - {{ t('views.dashboard.ue.resultOK') }} + {{ t('views.dashboard.ue.resultOk') }} (['MOC']); +const recordTypes = ref([]); /**查询记录类型变更 */ function fnQueryRecordTypeChange(value: any) { @@ -639,7 +639,7 @@ onBeforeUnmount(() => { :data-source="tableState.data" :size="tableState.size" :pagination="tablePagination" - :scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }" + :scroll="{ x: tableColumns.length * 150, y: 'calc(100vh - 480px)' }" :row-selection="{ type: 'checkbox', columnWidth: '48px', diff --git a/src/views/dashboard/mmeUE/index.vue b/src/views/dashboard/mmeUE/index.vue index 74a6523d..fb363262 100644 --- a/src/views/dashboard/mmeUE/index.vue +++ b/src/views/dashboard/mmeUE/index.vue @@ -43,7 +43,7 @@ let queryParams = reactive({ /**网元类型 */ neType: 'MME', neId: '001', - eventType: 'auth-result', + eventType: '', imsi: '', sortField: 'timestamp', sortOrder: 'desc', @@ -59,9 +59,9 @@ let queryParams = reactive({ /**查询参数重置 */ function fnQueryReset() { - eventTypes.value = ['auth-result']; + eventTypes.value = []; queryParams = Object.assign(queryParams, { - eventType: 'auth-result', + eventType: '', imsi: '', startTime: '', endTime: '', @@ -75,7 +75,7 @@ function fnQueryReset() { } /**记录类型 */ -const eventTypes = ref(['auth-result']); +const eventTypes = ref([]); /**查询记录类型变更 */ function fnQueryEventTypeChange(value: any) { @@ -670,7 +670,7 @@ onBeforeUnmount(() => { /> - {{ t('views.dashboard.ue.resultOK') }} + {{ t('views.dashboard.ue.resultOk') }} item.id === itemID); - if (!info.neState.online) return; + if (!info || !info.neState.online) return; // if (!info.neState.online) { // info = data.find((item: any) => item.id === itemID); // graphNodeClickID.value = itemID; diff --git a/src/views/dashboard/overview/components/UPFFlow/index.vue b/src/views/dashboard/overview/components/UPFFlow/index.vue index 607c3913..12694af7 100644 --- a/src/views/dashboard/overview/components/UPFFlow/index.vue +++ b/src/views/dashboard/overview/components/UPFFlow/index.vue @@ -203,17 +203,14 @@ function handleRanderChart() { /**查询初始UPF数据 */ function fnGetInitData() { - // 查询10分钟前的 - const nowDate: Date = new Date(); - const tenMinutesAgo = new Date(nowDate.getTime() - 5 * 60 * 1000); + // 查询5分钟前的 + const nowDate = new Date().getTime(); listKPIData({ neType: 'UPF', neId: '001', - startTime: parseDateToStr(tenMinutesAgo), - endTime: parseDateToStr(nowDate), - // startTime: '2024-03-20 19:50:00', - // endTime: '2024-03-20 19:55:00', + startTime: nowDate - 5 * 60 * 1000, + endTime: nowDate, interval: 5, // 5秒 sortField: 'timeGroup', sortOrder: 'asc', diff --git a/src/views/dashboard/overview/css/index.css b/src/views/dashboard/overview/css/index.css index 56a135e4..9b053c7c 100644 --- a/src/views/dashboard/overview/css/index.css +++ b/src/views/dashboard/overview/css/index.css @@ -159,14 +159,14 @@ /* 概览区域 衍生基站信息 */ .skim.base { - height: 20.6%; + height: 12%; } .skim.base .inner .data { display: flex; flex-direction: row; align-items: center; - height: 45%; + height: 75%; } .skim.base .inner .data .item { display: flex; @@ -178,7 +178,7 @@ /* 用户行为 */ .userActivity { /* min-height: 35.8rem; */ - height: 60%; + height: 54.6%; } .userActivity .inner .chart { width: 100%; diff --git a/src/views/dashboard/overview/hooks/useUPFTotalFlow.ts b/src/views/dashboard/overview/hooks/useUPFTotalFlow.ts index 27b19c8a..8a9fdacb 100644 --- a/src/views/dashboard/overview/hooks/useUPFTotalFlow.ts +++ b/src/views/dashboard/overview/hooks/useUPFTotalFlow.ts @@ -1,3 +1,4 @@ +import { parseDateToStr } from '@/utils/date-utils'; import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils'; import { ref } from 'vue'; @@ -22,7 +23,7 @@ export const upfFlowData = ref({ /**UPF-流量数据 数据解析 */ export function upfFlowParse(data: Record) { - upfFlowData.value.lineXTime.push(data['timeGroup']); + upfFlowData.value.lineXTime.push(parseDateToStr(+data['timeGroup'])); const upN3 = parseSizeFromKbs(+data['UPF.03'], 5); upfFlowData.value.lineYUp.push(upN3[0]); const downN6 = parseSizeFromKbs(+data['UPF.06'], 5); @@ -78,7 +79,7 @@ export function upfTFParse(data: Record) { export const upfTFActive = ref(0); /**属性复位 */ -export function upfTotalFlowReset() { +export function upfTotalFlowReset() { upfFlowData.value = { lineXTime: [], lineYUp: [], diff --git a/src/views/dashboard/overview/hooks/useWS.ts b/src/views/dashboard/overview/hooks/useWS.ts index 854a122b..ba193141 100644 --- a/src/views/dashboard/overview/hooks/useWS.ts +++ b/src/views/dashboard/overview/hooks/useWS.ts @@ -94,7 +94,7 @@ export default function useWS() { } switch (data.groupId) { // kpiEvent 指标UPF - case '12': + case '12_001': if (data.data) { upfFlowParse(data.data); } @@ -197,12 +197,12 @@ export default function useWS() { params: { /**订阅通道组 * - * 指标UPF (GroupID:12) + * 指标UPF (GroupID:12_neId) * AMF_UE会话事件(GroupID:1010) * MME_UE会话事件(GroupID:1011) * IMS_CDR会话事件(GroupID:1005) */ - subGroupID: '12,1010,1011,1005', + subGroupID: '12_001,1010,1011,1005', }, onmessage: wsMessage, onerror: wsError, diff --git a/src/views/dashboard/overview/index.vue b/src/views/dashboard/overview/index.vue index 837f7d8f..e8e60d57 100644 --- a/src/views/dashboard/overview/index.vue +++ b/src/views/dashboard/overview/index.vue @@ -272,7 +272,7 @@ onBeforeUnmount(() => {

-    +    5G {{ t('views.dashboard.overview.skim.baseTitle') }}

@@ -304,6 +304,14 @@ onBeforeUnmount(() => { {{ t('views.dashboard.overview.skim.gnbUeNum') }}
+
+ +
+
+

+    4G + {{ t('views.dashboard.overview.skim.baseTitle') }} +

{ function fnChangeLocale(e: any) { changeLocale(e.key); } - -/**系统使用手册跳转 */ -function fnClickHelpDoc(language?: string) { - const routeData = router.resolve({ name: 'HelpDoc' }); - let href = routeData.href; - if (language) { - href = `${routeData.href}?language=${language}`; - } - window.open(href, '_blank'); -}
-
- - - {{ t('loayouts.basic.officialUrl') }} - - - - {{ t('loayouts.basic.helpDoc') }} - - -