From 254c49d894886c84bbd60ab2ece24f5dd810ffdb Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 16 Sep 2025 19:41:57 +0800 Subject: [PATCH] =?UTF-8?q?ref:=20v3=E5=8F=98=E6=9B=B4,=EF=BC=8C=E6=A0=B9?= =?UTF-8?q?=E6=8D=AE=E6=A0=B8=E5=BF=83=E7=BD=91=E8=BF=87=E6=BB=A4=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E7=BD=91=E5=85=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useCoreUid.ts | 6 +- src/layouts/BasicLayout.vue | 11 +- src/router/routers.ts | 2 +- src/store/modules/app.ts | 4 +- src/store/modules/core.ts | 3 +- src/store/modules/ne.ts | 67 +- src/views/account/role/index.vue | 1418 +++++++++++ src/views/account/third-party-login/index.vue | 1122 +++++++++ src/views/account/user/index.vue | 1642 +++++++++++++ .../core-ne/{ne => alarm/active}/index.vue | 0 src/views/core-ne/alarm/event/index.vue | 16 + src/views/core-ne/alarm/forward/index.vue | 16 + src/views/core-ne/alarm/historical/index.vue | 16 + src/views/core-ne/alarm/logs/index.vue | 16 + src/views/core-ne/metrics/kpi/index.vue | 16 + src/views/core-ne/metrics/kpic/index.vue | 16 + .../core-ne/metrics/overview-ims/index.vue | 16 + .../core-ne/monitor/dashboard-kpi/index.vue | 16 + src/views/core-ne/monitor/dashboard/index.vue | 16 + src/views/core-ne/monitor/topology/index.vue | 16 + .../core-ne/monitor/{ => ue-event}/index.vue | 2 +- src/views/core-ne/monitor/vm/index.vue | 16 + .../core-ne/ne-data/cdr/ims-cdr/index.vue | 16 + .../core-ne/ne-data/cdr/sgwc-cdr/index.vue | 16 + .../core-ne/ne-data/cdr/smf-cdr/index.vue | 16 + .../core-ne/ne-data/cdr/smsc-cdr/index.vue | 16 + .../core-ne/ne-data/ims-session/index.vue | 16 + .../core-ne/ne-data/n3iwf-session/index.vue | 16 + src/views/core-ne/ne-data/nssf-amf/index.vue | 16 + .../core-ne/ne-data/nssf-session/index.vue | 16 + .../core-ne/ne-data/radio-state/index.vue | 16 + .../core-ne/ne-data/smf-session/index.vue | 16 + src/views/core-ne/ne-data/ue-event/index.vue | 16 + .../ne/config/hooks/useArrayBatchDel.ts | 85 + .../core-ne/ne/config/hooks/useArrayImport.ts | 207 ++ .../core-ne/ne/config/hooks/useConfigArray.ts | 411 ++++ .../ne/config/hooks/useConfigArrayChild.ts | 352 +++ .../core-ne/ne/config/hooks/useConfigList.ts | 152 ++ .../core-ne/ne/config/hooks/useOptions.ts | 190 ++ src/views/core-ne/ne/config/index.vue | 1082 ++++++++ src/views/core-ne/ne/info/index.vue | 848 +++++++ src/views/core-ne/ne/version/index.vue | 724 ++++++ src/views/core-ne/tool/mml/logs/index.vue | 306 +++ src/views/core-ne/tool/mml/oper-ne/index.vue | 825 +++++++ src/views/core-ne/tool/mml/oper-udm/index.vue | 751 ++++++ .../core-ne/tool/signal/packet/index.vue | 16 + .../core-ne/tool/signal/tcpdump/file.vue | 479 ++++ .../core-ne/tool/signal/tcpdump/index.vue | 811 ++++++ .../core-ne/tool/signal/wireshark/index.vue | 16 + .../tool/terminal/components/hostList.vue | 381 +++ src/views/core-ne/tool/terminal/index.vue | 340 +++ src/views/core-ne/tool/test/iperf/index.vue | 518 ++++ src/views/core-ne/tool/test/net/index.vue | 338 +++ src/views/core-ne/tool/test/ping/index.vue | 408 ++++ src/views/core-ne/tool/test/ps/index.vue | 370 +++ src/views/core-ne/ue/pcf-rule/index.vue | 1219 ++++++++++ src/views/core-ne/ue/udm-auth/index.vue | 1311 ++++++++++ src/views/core-ne/ue/udm-sub/index.vue | 2165 +++++++++++++++++ src/views/core-ne/ue/udm-voip/index.vue | 979 ++++++++ src/views/core-ne/ue/udm-volte/index.vue | 1223 ++++++++++ src/views/index/index.vue | 86 + src/views/index/m/index.vue | 399 +++ src/views/log/login/index.vue | 569 +++++ src/views/log/operation/index.vue | 766 ++++++ src/views/mml/udm/index.vue | 2 +- src/views/ne/info/components/CoreModal.vue | 11 +- src/views/ne/info/index.vue | 2 +- .../components/NeInfoSoftwareLicense.vue | 20 +- .../quick-setup/components/NeInfoConfig.vue | 448 ++++ .../components/NeInfoSoftwareInstall.vue | 433 ++++ .../components/NeInfoSoftwareLicense.vue | 188 ++ .../ne/quick-setup/components/Para5GForm.vue | 564 +++++ src/views/ne/quick-setup/components/Start.vue | 496 ++++ src/views/ne/quick-setup/hooks/usePara5G.ts | 141 ++ src/views/ne/quick-setup/hooks/useStep.ts | 103 + src/views/ne/quick-setup/index.vue | 90 + .../software/components/EditModal.vue | 473 ++++ .../software/components/UploadMoreFile.vue | 506 ++++ src/views/software-version/software/index.vue | 577 +++++ src/views/software-version/version/index.vue | 724 ++++++ src/views/tool/ping/index.vue | 3 +- 81 files changed, 27708 insertions(+), 29 deletions(-) create mode 100644 src/views/account/role/index.vue create mode 100644 src/views/account/third-party-login/index.vue create mode 100644 src/views/account/user/index.vue rename src/views/core-ne/{ne => alarm/active}/index.vue (100%) create mode 100644 src/views/core-ne/alarm/event/index.vue create mode 100644 src/views/core-ne/alarm/forward/index.vue create mode 100644 src/views/core-ne/alarm/historical/index.vue create mode 100644 src/views/core-ne/alarm/logs/index.vue create mode 100644 src/views/core-ne/metrics/kpi/index.vue create mode 100644 src/views/core-ne/metrics/kpic/index.vue create mode 100644 src/views/core-ne/metrics/overview-ims/index.vue create mode 100644 src/views/core-ne/monitor/dashboard-kpi/index.vue create mode 100644 src/views/core-ne/monitor/dashboard/index.vue create mode 100644 src/views/core-ne/monitor/topology/index.vue rename src/views/core-ne/monitor/{ => ue-event}/index.vue (89%) create mode 100644 src/views/core-ne/monitor/vm/index.vue create mode 100644 src/views/core-ne/ne-data/cdr/ims-cdr/index.vue create mode 100644 src/views/core-ne/ne-data/cdr/sgwc-cdr/index.vue create mode 100644 src/views/core-ne/ne-data/cdr/smf-cdr/index.vue create mode 100644 src/views/core-ne/ne-data/cdr/smsc-cdr/index.vue create mode 100644 src/views/core-ne/ne-data/ims-session/index.vue create mode 100644 src/views/core-ne/ne-data/n3iwf-session/index.vue create mode 100644 src/views/core-ne/ne-data/nssf-amf/index.vue create mode 100644 src/views/core-ne/ne-data/nssf-session/index.vue create mode 100644 src/views/core-ne/ne-data/radio-state/index.vue create mode 100644 src/views/core-ne/ne-data/smf-session/index.vue create mode 100644 src/views/core-ne/ne-data/ue-event/index.vue create mode 100644 src/views/core-ne/ne/config/hooks/useArrayBatchDel.ts create mode 100644 src/views/core-ne/ne/config/hooks/useArrayImport.ts create mode 100644 src/views/core-ne/ne/config/hooks/useConfigArray.ts create mode 100644 src/views/core-ne/ne/config/hooks/useConfigArrayChild.ts create mode 100644 src/views/core-ne/ne/config/hooks/useConfigList.ts create mode 100644 src/views/core-ne/ne/config/hooks/useOptions.ts create mode 100644 src/views/core-ne/ne/config/index.vue create mode 100644 src/views/core-ne/ne/info/index.vue create mode 100644 src/views/core-ne/ne/version/index.vue create mode 100644 src/views/core-ne/tool/mml/logs/index.vue create mode 100644 src/views/core-ne/tool/mml/oper-ne/index.vue create mode 100644 src/views/core-ne/tool/mml/oper-udm/index.vue create mode 100644 src/views/core-ne/tool/signal/packet/index.vue create mode 100644 src/views/core-ne/tool/signal/tcpdump/file.vue create mode 100644 src/views/core-ne/tool/signal/tcpdump/index.vue create mode 100644 src/views/core-ne/tool/signal/wireshark/index.vue create mode 100644 src/views/core-ne/tool/terminal/components/hostList.vue create mode 100644 src/views/core-ne/tool/terminal/index.vue create mode 100644 src/views/core-ne/tool/test/iperf/index.vue create mode 100644 src/views/core-ne/tool/test/net/index.vue create mode 100644 src/views/core-ne/tool/test/ping/index.vue create mode 100644 src/views/core-ne/tool/test/ps/index.vue create mode 100644 src/views/core-ne/ue/pcf-rule/index.vue create mode 100644 src/views/core-ne/ue/udm-auth/index.vue create mode 100644 src/views/core-ne/ue/udm-sub/index.vue create mode 100644 src/views/core-ne/ue/udm-voip/index.vue create mode 100644 src/views/core-ne/ue/udm-volte/index.vue create mode 100644 src/views/index/index.vue create mode 100644 src/views/index/m/index.vue create mode 100644 src/views/log/login/index.vue create mode 100644 src/views/log/operation/index.vue create mode 100644 src/views/ne/quick-setup/components/NeInfoConfig.vue create mode 100644 src/views/ne/quick-setup/components/NeInfoSoftwareInstall.vue create mode 100644 src/views/ne/quick-setup/components/NeInfoSoftwareLicense.vue create mode 100644 src/views/ne/quick-setup/components/Para5GForm.vue create mode 100644 src/views/ne/quick-setup/components/Start.vue create mode 100644 src/views/ne/quick-setup/hooks/usePara5G.ts create mode 100644 src/views/ne/quick-setup/hooks/useStep.ts create mode 100644 src/views/ne/quick-setup/index.vue create mode 100644 src/views/software-version/software/components/EditModal.vue create mode 100644 src/views/software-version/software/components/UploadMoreFile.vue create mode 100644 src/views/software-version/software/index.vue create mode 100644 src/views/software-version/version/index.vue diff --git a/src/hooks/useCoreUid.ts b/src/hooks/useCoreUid.ts index e126a35b..4af6efaa 100644 --- a/src/hooks/useCoreUid.ts +++ b/src/hooks/useCoreUid.ts @@ -16,15 +16,15 @@ import { export const CORE_NE_PATH = '/core-ne'; /** - * 获取当前coreUid - * @returns coreUid + * 获取当前coreInfo + * @returns coreInfo */ export function current() { return sessionGetJSON(CACHE_SESSION_CORE) || {}; } /** - * 获取当前coreUid + * 获取当前coreInfo * @returns coreUid */ export function changeCurrent(v: Record) { diff --git a/src/layouts/BasicLayout.vue b/src/layouts/BasicLayout.vue index 78ec26d6..7109af3b 100644 --- a/src/layouts/BasicLayout.vue +++ b/src/layouts/BasicLayout.vue @@ -120,7 +120,16 @@ const menuData = computed(() => { rootRoute.children = rootRouteChildren; } } - const neTypes = neStore.getNeSelectOtions.map(v => v.value); + + // 过滤网元限定菜单 + let neTypes = []; + // 多核心网切换菜单显示 + if (appStore.serverType === APP_SERVER_TYPE_M) { + neTypes = neStore.getCoreDataNeSelectOtions.map(v => v.value); + } else { + neTypes = neStore.getNeSelectOtions.map(v => v.value); + } + let routes = clearMenuItem(router.getRoutes()); routes = routerStore.clearMenuItemByNeList(routes, neTypes); const { menuData } = getMenuData(routes); diff --git a/src/router/routers.ts b/src/router/routers.ts index b685e06e..07c7cc03 100644 --- a/src/router/routers.ts +++ b/src/router/routers.ts @@ -20,7 +20,7 @@ export const constantRoutes: RouteRecordRaw[] = [ path: '/index', name: 'Index', meta: { title: 'router.index', icon: 'icon-pcduan' }, - component: () => import('@/views/index.vue'), + component: () => import('@/views/index/index.vue'), }, { path: '/account', diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts index 17f17c1e..ed2d683c 100644 --- a/src/store/modules/app.ts +++ b/src/store/modules/app.ts @@ -3,7 +3,7 @@ import { CACHE_LOCAL_I18N, CACHE_SESSION_CRYPTO_API, } from '@/constants/cache-keys-constants'; -import { RESULT_CODE_EXCEPTION, RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; import { delAccessToken, delRefreshToken } from '@/plugins/auth-token'; import { parseUrlPath } from '@/plugins/file-static-url'; import { localGet, localSet } from '@/utils/cache-local-utils'; @@ -131,7 +131,7 @@ const useAppStore = defineStore('app', { if (localI18n == null || (!this.i18nOpen && this.i18nDefault)) { localSet(CACHE_LOCAL_I18N, this.i18nDefault); } - }; + } }, }, }); diff --git a/src/store/modules/core.ts b/src/store/modules/core.ts index 189ee4f4..61f7740f 100644 --- a/src/store/modules/core.ts +++ b/src/store/modules/core.ts @@ -55,7 +55,7 @@ const useCoreStore = defineStore('core', { changeCurrent(v); changeCoreUid(v.value); }, - /**刷新核心网列表 */ + /**刷新核心网列表 */ async fnCorelistRefresh() { this.coreList = []; return await this.fnCorelist(); @@ -84,6 +84,7 @@ const useCoreStore = defineStore('core', { }); } // 当前未选择时 + this.coreSelectOtions.unshift(this.globalDefaultSelect); if (!this.currentSelect) { this.setCurrent(this.globalDefaultSelect); } diff --git a/src/store/modules/ne.ts b/src/store/modules/ne.ts index 3e853270..313a767c 100644 --- a/src/store/modules/ne.ts +++ b/src/store/modules/ne.ts @@ -5,6 +5,7 @@ import { } from '@/constants/result-constants'; import { listAllNeInfo } from '@/api/ne/neInfo'; import { parseDataToOptions } from '@/utils/parse-tree-utils'; +import { currentCoreUid } from '@/hooks/useCoreUid'; /**网元信息类型 */ type Ne = { @@ -14,6 +15,10 @@ type Ne = { neCascaderOptions: Record[]; /**选择器单级父类型 */ neSelectOtions: Record[]; + /**Core数据级联options树结构 coreUid */ + coreDataNeCascaderOptions: Map[]>; + /**Core选择器单级父类型 coreUid */ + coreDataNeSelectOtions: Map[]>; }; const useNeStore = defineStore('ne', { @@ -21,6 +26,10 @@ const useNeStore = defineStore('ne', { list: [], neCascaderOptions: [], neSelectOtions: [], + /**Core数据级联options树结构 coreUid */ + coreDataNeCascaderOptions: new Map(), + /**Core选择器单级父类型 coreUid */ + coreDataNeSelectOtions: new Map(), }), getters: { /** @@ -40,13 +49,31 @@ const useNeStore = defineStore('ne', { return state.neCascaderOptions; }, /** - * 选择器单级父类型 + * Core选择器单级父类型 * @param state 内部属性不用传入 * @returns 选择options */ getNeSelectOtions(state) { return state.neSelectOtions; }, + /** + * Core获取级联options树结构 + * @param state 内部属性不用传入 + * @returns 级联options + */ + getCoreDataNeCascaderOptions(state) { + const coreUid = currentCoreUid(); + return state.coreDataNeCascaderOptions.get(coreUid) || []; + }, + /** + * 选择器单级父类型 + * @param state 内部属性不用传入 + * @returns 选择options + */ + getCoreDataNeSelectOtions(state) { + const coreUid = currentCoreUid(); + return state.coreDataNeSelectOtions.get(coreUid) || []; + }, }, actions: { // 刷新网元列表 @@ -70,11 +97,12 @@ const useNeStore = defineStore('ne', { }); if (res.code === RESULT_CODE_SUCCESS) { // 原始列表 - this.list = JSON.parse(JSON.stringify(res.data)); + const originalList = JSON.parse(JSON.stringify(res.data)); + this.list = originalList; // 转级联数据 const options = parseDataToOptions( - res.data, + originalList, 'neType', 'neName', 'neUid' @@ -88,6 +116,39 @@ const useNeStore = defineStore('ne', { value: item.value, }; }); + + // 根据coreUid分组 + let groupCore: Record = {}; + for (const element of originalList) { + if (element.coreId !== 0 && element.coreUid) { + if (groupCore[element.coreUid]) { + groupCore[element.coreUid].push(element); + } else { + groupCore[element.coreUid] = [element]; + } + } + } + // 转Core数据级联options树结构 + for (const coreUid in groupCore) { + const arr = groupCore[coreUid]; + // 转级联数据 + const cascaderOptions = parseDataToOptions( + arr, + 'neType', + 'neName', + 'neUid' + ); + this.coreDataNeCascaderOptions.set(coreUid, cascaderOptions); + + // 转选择器单级父类型 + const selectOtions = cascaderOptions.map(item => { + return { + label: item.label, + value: item.value, + }; + }); + this.coreDataNeSelectOtions.set(coreUid, selectOtions); + } } return res; }, diff --git a/src/views/account/role/index.vue b/src/views/account/role/index.vue new file mode 100644 index 00000000..570405ed --- /dev/null +++ b/src/views/account/role/index.vue @@ -0,0 +1,1418 @@ + + + + + diff --git a/src/views/account/third-party-login/index.vue b/src/views/account/third-party-login/index.vue new file mode 100644 index 00000000..b7400175 --- /dev/null +++ b/src/views/account/third-party-login/index.vue @@ -0,0 +1,1122 @@ + + + + + diff --git a/src/views/account/user/index.vue b/src/views/account/user/index.vue new file mode 100644 index 00000000..1e4dafd0 --- /dev/null +++ b/src/views/account/user/index.vue @@ -0,0 +1,1642 @@ + + + + + diff --git a/src/views/core-ne/ne/index.vue b/src/views/core-ne/alarm/active/index.vue similarity index 100% rename from src/views/core-ne/ne/index.vue rename to src/views/core-ne/alarm/active/index.vue diff --git a/src/views/core-ne/alarm/event/index.vue b/src/views/core-ne/alarm/event/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/alarm/event/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/alarm/forward/index.vue b/src/views/core-ne/alarm/forward/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/alarm/forward/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/alarm/historical/index.vue b/src/views/core-ne/alarm/historical/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/alarm/historical/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/alarm/logs/index.vue b/src/views/core-ne/alarm/logs/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/alarm/logs/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/metrics/kpi/index.vue b/src/views/core-ne/metrics/kpi/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/metrics/kpi/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/metrics/kpic/index.vue b/src/views/core-ne/metrics/kpic/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/metrics/kpic/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/metrics/overview-ims/index.vue b/src/views/core-ne/metrics/overview-ims/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/metrics/overview-ims/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/monitor/dashboard-kpi/index.vue b/src/views/core-ne/monitor/dashboard-kpi/index.vue new file mode 100644 index 00000000..11098799 --- /dev/null +++ b/src/views/core-ne/monitor/dashboard-kpi/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/monitor/dashboard/index.vue b/src/views/core-ne/monitor/dashboard/index.vue new file mode 100644 index 00000000..ae4ce764 --- /dev/null +++ b/src/views/core-ne/monitor/dashboard/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/monitor/topology/index.vue b/src/views/core-ne/monitor/topology/index.vue new file mode 100644 index 00000000..a6798ccf --- /dev/null +++ b/src/views/core-ne/monitor/topology/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/monitor/index.vue b/src/views/core-ne/monitor/ue-event/index.vue similarity index 89% rename from src/views/core-ne/monitor/index.vue rename to src/views/core-ne/monitor/ue-event/index.vue index e2d34afe..2ef60620 100644 --- a/src/views/core-ne/monitor/index.vue +++ b/src/views/core-ne/monitor/ue-event/index.vue @@ -8,7 +8,7 @@ onMounted(() => {}); diff --git a/src/views/core-ne/monitor/vm/index.vue b/src/views/core-ne/monitor/vm/index.vue new file mode 100644 index 00000000..21be8f93 --- /dev/null +++ b/src/views/core-ne/monitor/vm/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/cdr/ims-cdr/index.vue b/src/views/core-ne/ne-data/cdr/ims-cdr/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/cdr/ims-cdr/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/cdr/sgwc-cdr/index.vue b/src/views/core-ne/ne-data/cdr/sgwc-cdr/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/cdr/sgwc-cdr/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/cdr/smf-cdr/index.vue b/src/views/core-ne/ne-data/cdr/smf-cdr/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/cdr/smf-cdr/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/cdr/smsc-cdr/index.vue b/src/views/core-ne/ne-data/cdr/smsc-cdr/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/cdr/smsc-cdr/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/ims-session/index.vue b/src/views/core-ne/ne-data/ims-session/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/ims-session/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/n3iwf-session/index.vue b/src/views/core-ne/ne-data/n3iwf-session/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/n3iwf-session/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/nssf-amf/index.vue b/src/views/core-ne/ne-data/nssf-amf/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/nssf-amf/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/nssf-session/index.vue b/src/views/core-ne/ne-data/nssf-session/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/nssf-session/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/radio-state/index.vue b/src/views/core-ne/ne-data/radio-state/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/radio-state/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/smf-session/index.vue b/src/views/core-ne/ne-data/smf-session/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/smf-session/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne-data/ue-event/index.vue b/src/views/core-ne/ne-data/ue-event/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/ne-data/ue-event/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/ne/config/hooks/useArrayBatchDel.ts b/src/views/core-ne/ne/config/hooks/useArrayBatchDel.ts new file mode 100644 index 00000000..3195d645 --- /dev/null +++ b/src/views/core-ne/ne/config/hooks/useArrayBatchDel.ts @@ -0,0 +1,85 @@ +import { delNeConfigData } from '@/api/ne/neConfig'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { message } from 'ant-design-vue'; +import { reactive } from 'vue'; + +/** + * 批量删除array + * @param param 父级传入 { t, neTypeSelect, fnActiveConfigNode } + * @returns + */ +export default function useArrayBatch({ + t, + neTypeSelect, + fnActiveConfigNode, +}: any) { + /**状态属性 */ + const batchState = reactive({ + open: false, + loading: false, //批量删除 + paramName: '', + startIndex: 1, + num: 1, + }); + + /**对话框表格信息导入弹出窗口 */ + function modalBatchOpen(paramName: string) { + batchState.paramName = paramName; + batchState.open = true; + } + function modalBatchClose() { + if (batchState.loading) { + message.error({ + content: 'Delete is in progress, please wait for it to complete', + duration: 3, + }); + return; + } + batchState.open = false; + batchState.loading = false; + batchState.startIndex = 1; + batchState.num = 1; + fnActiveConfigNode('#'); + } + + async function modalBatchOk() { + let okNum = 0; + let failNum = 0; + const endIndex = batchState.startIndex + batchState.num - 1; + for (let i = endIndex; i >= batchState.startIndex; i--) { + const res = await delNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: batchState.paramName, + loc: `${i}`, + }); + if (res.code === RESULT_CODE_SUCCESS) { + okNum++; + } else { + failNum++; + break; + } + } + + if (okNum > 0) { + message.success({ + content: `Successfully deleted ${okNum} items`, + duration: 3, + }); + } + if (failNum > 0) { + message.error({ + content: `Delete failed, please check the index range`, + duration: 3, + }); + } + modalBatchClose(); + } + + return { + batchState, + modalBatchOpen, + modalBatchClose, + modalBatchOk, + }; +} diff --git a/src/views/core-ne/ne/config/hooks/useArrayImport.ts b/src/views/core-ne/ne/config/hooks/useArrayImport.ts new file mode 100644 index 00000000..b6c8dc1a --- /dev/null +++ b/src/views/core-ne/ne/config/hooks/useArrayImport.ts @@ -0,0 +1,207 @@ +import { addNeConfigData, editNeConfigData } from '@/api/ne/neConfig'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { readSheet } from '@/utils/execl-utils'; +import { message } from 'ant-design-vue'; +import { reactive } from 'vue'; +import saveAs from 'file-saver'; + +/** + * 导入文件加array + * @param param 父级传入 { t, neTypeSelect, arrayState, fnActiveConfigNode } + * @returns + */ +export default function useArrayImport({ + t, + neTypeSelect, + arrayState, + fnActiveConfigNode, +}: any) { + /**网元导入模板解析 */ + const m: Record = { + AMF: { + imeiWhitelist: { + filename: 'import_amf_imeiWhitelist_template', + fileetx: '.xlsx', + itemKey: 'index', + item: (row: Record) => { + const index = row['Index'] || 0; + return { + imeiPrefixValue: `${row['IMEI Prefix']}`, + index: parseInt(index), + }; + }, + }, + whitelist: { + filename: 'import_amf_whitelist_template', + fileetx: '.xlsx', + itemKey: 'index', + item: (row: Record) => { + const index = row['Index'] || 0; + return { + imsiValue: `${row['IMSI Value']}`, + imeiValue: `${row['IMEI Value/Prefix']}`, + index: parseInt(index), + }; + }, + }, + }, + MME: { + white_list: { + filename: 'import_mme_imeiWhitelist_template', + fileetx: '.xlsx', + itemKey: 'index', + item: (row: Record) => { + const index = row['Index'] || 0; + return { + imei: `${row['IMEI']}`, + index: parseInt(index), + }; + }, + }, + }, + }; + + /**状态属性 */ + const importState = reactive({ + open: false, + msgArr: [] as string[], + loading: false, //开始导入 + itemKey: '', // 解析item的key + item: null as any, // 解析item方法 + paramName: '', + filename: '', + fileetx: '', + }); + + /**对话框表格信息导入弹出窗口 */ + function modalImportOpen(neType: string, paramName: string) { + const tmpM = m[neType][paramName]; + importState.itemKey = tmpM.itemKey; + importState.item = tmpM.item; + importState.paramName = paramName; + importState.filename = tmpM.filename; + importState.fileetx = tmpM.fileetx; + importState.open = true; + } + function modalImportClose() { + if (importState.loading) { + message.error({ + content: 'Import is in progress, please wait for it to complete', + duration: 3, + }); + return; + } + importState.open = false; + importState.msgArr = []; + importState.loading = false; + fnActiveConfigNode('#'); + } + + /**对话框表格信息导入上传 */ + async function modalImportUpload(file: File) { + const hide = message.loading(t('common.loading'), 0); + importState.msgArr = []; + + // 获取最大index + let index = 0; + if (arrayState.columnsData.length <= 0) { + index = 0; + } else { + const last = arrayState.columnsData[arrayState.columnsData.length - 1]; + index = last.index.value + 1; + } + + const reader = new FileReader(); + reader.onload = function (e: any) { + const arrayBuffer = e.target.result; + readSheet(arrayBuffer).then(async rows => { + if (rows.length <= 0) { + hide(); + message.error({ + content: t('views.neData.baseStation.importDataEmpty'), + duration: 3, + }); + return; + } + // 开始导入 + importState.loading = true; + for (const row of rows) { + const rowItem = importState.item(row); + const rowKey = rowItem[importState.itemKey] || -1; + let result: any = null; + // 检查index是否定义 + const has = arrayState.columnsData.find( + (item: any) => item[importState.itemKey].value === rowKey + ); + if (has) { + // 已定义则更新 + rowItem.index = has.index.value; + result = await editNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: importState.paramName, + paramData: rowItem, + loc: `${rowItem.index}`, + }); + let msg = `index:${rowItem.index} update fail`; + if (result.code === RESULT_CODE_SUCCESS) { + msg = `index:${rowItem.index} update success`; + } + importState.msgArr.push(msg); + } else { + // 未定义则新增 + result = await addNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: importState.paramName, + paramData: Object.assign(rowItem, { index }), + loc: `${index}`, + }); + let msg = `index:${index} add fail`; + if (result.code === RESULT_CODE_SUCCESS) { + msg = `index:${index} add success`; + index += 1; + } + importState.msgArr.push(msg); + } + } + + hide(); + importState.loading = false; + }); + }; + reader.onerror = function (e) { + hide(); + console.error('reader file error:', e); + }; + reader.readAsArrayBuffer(file); + } + + /**对话框表格信息导入模板 */ + function modalImportTemplate() { + const hide = message.loading(t('common.loading'), 0); + + const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL; + const templateUrl = `${ + baseUrl.length === 1 && baseUrl.indexOf('/') === 0 + ? '' + : baseUrl.indexOf('/') === -1 + ? '/' + baseUrl + : baseUrl + }/neDataImput`; + saveAs( + `${templateUrl}/${importState.filename}${importState.fileetx}`, + `${importState.filename}_${Date.now()}${importState.fileetx}` + ); + + hide(); + } + + return { + importState, + modalImportOpen, + modalImportClose, + modalImportUpload, + modalImportTemplate, + }; +} diff --git a/src/views/core-ne/ne/config/hooks/useConfigArray.ts b/src/views/core-ne/ne/config/hooks/useConfigArray.ts new file mode 100644 index 00000000..3c8d0833 --- /dev/null +++ b/src/views/core-ne/ne/config/hooks/useConfigArray.ts @@ -0,0 +1,411 @@ +import { + addNeConfigData, + delNeConfigData, + editNeConfigData, +} from '@/api/ne/neConfig'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { Modal, message } from 'ant-design-vue/es'; +import { SizeType } from 'ant-design-vue/es/config-provider'; +import { reactive, watch } from 'vue'; + +/** + * 参数配置array类型 + * @param param 父级传入 { t, treeState, neTypeSelect, fnActiveConfigNode, ruleVerification, modalState, fnModalCancel} + * @returns + */ +export default function useConfigArray({ + t, + treeState, + neTypeSelect, + fnActiveConfigNode, + ruleVerification, + modalState, + fnModalCancel, +}: any) { + /**多列列表状态类型 */ + type ArrayStateType = { + /**紧凑型 */ + size: SizeType; + /**多列嵌套记录字段 */ + columns: Record[]; + /**表格字段列排序 */ + columnsDnd: Record[]; + /**多列记录数据 */ + columnsData: Record[]; + /**多列嵌套展开key */ + arrayChildExpandKeys: any[]; + + /**多列记录数据 */ + data: Record[]; + /**多列记录规则 */ + dataRule: Record; + }; + + /**多列列表状态 */ + let arrayState: ArrayStateType = reactive({ + size: 'small', + columns: [], + columnsDnd: [], + columnsData: [], + arrayChildExpandKeys: [], + data: [], + dataRule: {}, + }); + + /**多列表编辑 */ + function arrayEdit(rowIndex: Record) { + const item = arrayState.data.find((s: any) => s.key === rowIndex.value); + if (!item) return; + const from = arrayInitEdit(item, arrayState.dataRule); + // 处理信息 + const row: Record = {}; + for (const v of from.record) { + if (Array.isArray(v.array)) { + continue; + } + row[v.name] = Object.assign({}, v); + } + + // 特殊SMF-upfid选择 + if (neTypeSelect.value[0] === 'SMF' && Reflect.has(row, 'upfId')) { + const v = row.upfId.value; + if (typeof v === 'string') { + if (v === '') { + row.upfId.value = []; + } else if (v.includes(';')) { + row.upfId.value = v.split(';'); + } else if (v.includes(',')) { + row.upfId.value = v.split(','); + } else { + row.upfId.value = [v]; + } + } + } + + modalState.from = row; + modalState.type = 'arrayEdit'; + modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`; + modalState.key = from.key; + modalState.data = from.record.filter((v: any) => !Array.isArray(v.array)); + modalState.open = true; + + // 关闭嵌套 + arrayState.arrayChildExpandKeys = []; + } + + /**多列表编辑关闭 */ + function arrayEditClose() { + arrayState.arrayChildExpandKeys = []; + fnModalCancel(); + } + + /**多列表编辑确认 */ + function arrayEditOk(from: Record) { + const loc = `${from['index']['value']}`; + + // 特殊SMF-upfid选择 + if (neTypeSelect.value[0] === 'SMF' && Reflect.has(from, 'upfId')) { + const v = from.upfId.value; + if (Array.isArray(v)) { + from.upfId.value = v.join(';'); + } + } + + // 遍历提取属性和值 + let data: Record = {}; + for (const key in from) { + // 子嵌套的不插入 + if (from[key]['array']) { + continue; + } + // 检查规则 + const [ok, msg] = ruleVerification(from[key]); + if (!ok) { + message.warning({ + content: `${msg}`, + duration: 3, + }); + return; + } + data[key] = from[key]['value']; + } + + // 发送 + const hide = message.loading(t('common.loading'), 0); + editNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: data, + loc: loc, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.updateItem', { + num: modalState.title, + }), + duration: 3, + }); + fnActiveConfigNode('#'); + } else { + message.warning({ + content: t('views.ne.neConfig.updateItemErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + arrayEditClose(); + }); + } + + /**多列表删除单行 */ + function arrayDelete(rowIndex: Record) { + const loc = `${rowIndex.value}`; + const title = `${treeState.selectNode.paramDisplay} Index-${loc}`; + + Modal.confirm({ + title: t('common.tipTitle'), + content: t('views.ne.neConfig.delItemTip', { + num: title, + }), + onOk() { + delNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + loc: loc, + }).then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.delItemOk', { + num: title, + }), + duration: 2, + }); + arrayEditClose(); + fnActiveConfigNode('#'); + } else { + message.error({ + content: `${res.msg}`, + duration: 2, + }); + } + }); + }, + }); + } + + /**多列表新增单行 */ + function arrayAdd() { + const from = arrayInitAdd(arrayState.data, arrayState.dataRule); + + // 处理信息 + const row: Record = {}; + for (const v of from.record) { + if (Array.isArray(v.array)) { + continue; + } + row[v.name] = Object.assign({}, v); + } + + // 特殊SMF-upfid选择 + if (neTypeSelect.value[0] === 'SMF' && Reflect.has(row, 'upfId')) { + const v = row.upfId.value; + if (typeof v === 'string') { + if (v === '') { + row.upfId.value = []; + } else if (v.includes(';')) { + row.upfId.value = v.split(';'); + } else if (v.includes(',')) { + row.upfId.value = v.split(','); + } else { + row.upfId.value = [v]; + } + } + } + + modalState.from = row; + modalState.type = 'arrayAdd'; + modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`; + modalState.key = from.key; + modalState.data = from.record.filter((v: any) => !Array.isArray(v.array)); + modalState.open = true; + } + + /**多列表新增单行确认 */ + function arrayAddOk(from: Record) { + // 特殊SMF-upfid选择 + if (neTypeSelect.value[0] === 'SMF' && Reflect.has(from, 'upfId')) { + const v = from.upfId.value; + if (Array.isArray(v)) { + from.upfId.value = v.join(';'); + } + } + + // 遍历提取属性和值 + let data: Record = {}; + for (const key in from) { + // 子嵌套的不插入 + if (from[key]['array']) { + continue; + } + // 检查规则 + const [ok, msg] = ruleVerification(from[key]); + if (!ok) { + message.warning({ + content: `${msg}`, + duration: 3, + }); + return; + } + data[key] = from[key]['value']; + } + + // 发送 + const hide = message.loading(t('common.loading'), 0); + addNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: data, + loc: `${from['index']['value']}`, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.addItemOk', { + num: modalState.title, + }), + duration: 3, + }); + fnActiveConfigNode('#'); + } else { + message.warning({ + content: t('views.ne.neConfig.addItemErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + arrayEditClose(); + }); + } + + /**多列表编辑行数据初始化 */ + function arrayInitEdit(data: Record, dataRule: any) { + const dataFrom = data.record; + const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule))); + for (const row of ruleFrom.record) { + // 子嵌套的不初始 + if (row.array) { + row.value = []; + continue; + } + // 查找项的值 + const item = dataFrom.find((s: any) => s.name === row.name); + if (!item) { + continue; + } + // 可选的 + row.optional = 'true'; + // 根据规则类型转值 + if (['enum', 'int'].includes(row.type)) { + row.value = Number(item.value); + } else if ('bool' === row.type) { + row.value = Boolean(item.value); + } else { + row.value = item.value; + } + } + ruleFrom.key = data.key; + ruleFrom.title = data.title; + return ruleFrom; + } + + /**多列表新增行数据初始化 */ + function arrayInitAdd(data: any[], dataRule: any) { + // 有数据时取得最后的index + let dataLastIndex = 0; + if (data.length !== 0) { + const lastFrom = Object.assign( + {}, + JSON.parse(JSON.stringify(data.at(-1))) + ); + if (lastFrom.record.length > 0) { + dataLastIndex = parseInt(lastFrom.key); + dataLastIndex += 1; + } + } + + const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule))); + for (const row of ruleFrom.record) { + // 子嵌套的不初始 + if (row.array) { + row.value = []; + continue; + } + // 可选的 + row.optional = 'true'; + // index值 + if (row.name === 'index') { + let newIndex = + dataLastIndex !== 0 ? dataLastIndex : parseInt(row.value); + if (isNaN(newIndex)) { + newIndex = 0; + } + row.value = newIndex; + ruleFrom.key = newIndex; + ruleFrom.title = `Index-${newIndex}`; + continue; + } + // 根据规则类型转值 + if (['enum', 'int'].includes(row.type)) { + row.value = Number(row.value); + } + if ('bool' === row.type) { + row.value = Boolean(row.value); + } + + // 特殊SMF-upfid选择 + if (neTypeSelect.value[0] === 'SMF' && row.name === 'upfId') { + const v = row.value; + if (typeof v === 'string') { + if (v === '') { + row.value = []; + } else if (v.includes(';')) { + row.value = v.split(';'); + } else if (v.includes(',')) { + row.value = v.split(','); + } else { + row.value = [v]; + } + } + } + } + return ruleFrom; + } + + // 监听表格字段列排序变化关闭展开 + watch( + () => arrayState.columnsDnd, + () => { + arrayEditClose(); + } + ); + + return { + arrayState, + arrayEdit, + arrayEditClose, + arrayEditOk, + arrayDelete, + arrayAdd, + arrayAddOk, + arrayInitEdit, + arrayInitAdd, + }; +} diff --git a/src/views/core-ne/ne/config/hooks/useConfigArrayChild.ts b/src/views/core-ne/ne/config/hooks/useConfigArrayChild.ts new file mode 100644 index 00000000..68f802b7 --- /dev/null +++ b/src/views/core-ne/ne/config/hooks/useConfigArrayChild.ts @@ -0,0 +1,352 @@ +import { + addNeConfigData, + editNeConfigData, + delNeConfigData, +} from '@/api/ne/neConfig'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { Modal, message } from 'ant-design-vue/es'; +import { SizeType } from 'ant-design-vue/es/config-provider'; +import { nextTick, reactive } from 'vue'; + +/** + * 参数配置array类型的嵌套array + * @param param 父级传入 { t, treeState, neTypeSelect, fnActiveConfigNode, ruleVerification, modalState, arrayState, arrayInitEdit, arrayInitAdd, arrayEditClose} + * @returns + */ +export default function useConfigArrayChild({ + t, + treeState, + neTypeSelect, + fnActiveConfigNode, + ruleVerification, + modalState, + arrayState, + arrayInitEdit, + arrayInitAdd, + arrayEditClose, +}: any) { + /**多列嵌套列表状态类型 */ + type ArrayChildStateType = { + /**标题 */ + title: string; + /**层级index */ + loc: string; + /**紧凑型 */ + size: SizeType; + /**多列嵌套记录字段 */ + columns: Record[]; + /**表格字段列排序 */ + columnsDnd: Record[]; + /**多列记录数据 */ + columnsData: Record[]; + + /**多列嵌套记录数据 */ + data: Record[]; + /**多列嵌套记录规则 */ + dataRule: Record; + }; + + /**多列嵌套表格状态 */ + let arrayChildState: ArrayChildStateType = reactive({ + title: '', + loc: '', + size: 'small', + columns: [], + columnsDnd: [], + columnsData: [], + data: [], + dataRule: {}, + }); + + /**多列表展开嵌套行 */ + function arrayChildExpand( + indexRow: Record, + row: Record + ) { + const loc = indexRow.value; + if (arrayChildState.loc === `${loc}/${row.name}`) { + arrayChildState.loc = ''; + arrayState.arrayChildExpandKeys = []; + return; + } + arrayChildState.loc = ''; + arrayState.arrayChildExpandKeys = []; + const from = Object.assign({}, JSON.parse(JSON.stringify(row))); + // 无数据时 + if (!Array.isArray(from.value)) { + from.value = []; + } + const dataArr = Object.freeze(from.value); + const ruleArr = Object.freeze(from.array); + + // 列表项数据 + const dataArray: Record[] = []; + for (const item of dataArr) { + const index = item['index']; + let record: Record[] = []; + for (const key of Object.keys(item)) { + // 规则为准 + for (const rule of ruleArr) { + if (rule['name'] === key) { + const ruleItem = Object.assign({ optional: 'true' }, rule, { + value: item[key], + }); + record.push(ruleItem); + break; + } + } + } + // dataArray.push(record); + dataArray.push({ title: `Index-${index}`, key: index, record }); + } + arrayChildState.data = dataArray; + + // 无数据时,用于新增 + arrayChildState.dataRule = { + title: `Index-0`, + key: 0, + record: ruleArr, + }; + + // 列表数据 + const columnsData: Record[] = []; + for (const v of arrayChildState.data) { + const row: Record = {}; + for (const item of v.record) { + row[item.name] = item; + } + columnsData.push(row); + } + arrayChildState.columnsData = columnsData; + + // 列表字段 + const columns: Record[] = []; + for (const rule of arrayChildState.dataRule.record) { + columns.push({ + title: rule.display, + dataIndex: rule.name, + align: 'left', + resizable: true, + width: 50, + minWidth: 50, + maxWidth: 250, + }); + } + columns.push({ + title: t('common.operate'), + dataIndex: 'index', + key: 'index', + align: 'center', + fixed: 'right', + width: 100, + }); + arrayChildState.columns = columns; + + nextTick(() => { + // 设置展开key + arrayState.arrayChildExpandKeys = [indexRow]; + // 层级标识 + arrayChildState.loc = `${loc}/${from['name']}`; + // 设置展开列表标题 + arrayChildState.title = `${from['display']}`; + }); + } + + /**多列表嵌套行编辑 */ + function arrayChildEdit(rowIndex: Record) { + const item = arrayChildState.data.find( + (s: any) => s.key === rowIndex.value + ); + if (!item) return; + const from = arrayInitEdit(item, arrayChildState.dataRule); + // 处理信息 + const row: Record = {}; + for (const v of from.record) { + if (Array.isArray(v.array)) { + continue; + } + row[v.name] = Object.assign({}, v); + } + + modalState.from = row; + modalState.type = 'arrayChildEdit'; + modalState.title = `${arrayChildState.title} ${from.title}`; + modalState.key = from.key; + modalState.data = from.record.filter((v: any) => !Array.isArray(v.array)); + modalState.open = true; + } + + /**多列表嵌套行编辑确认 */ + function arrayChildEditOk(from: Record) { + const loc = `${arrayChildState.loc}/${from['index']['value']}`; + + let data: Record = {}; + for (const key in from) { + // 子嵌套的不插入 + if (from[key]['array']) { + continue; + } + // 检查规则 + const [ok, msg] = ruleVerification(from[key]); + if (!ok) { + message.warning({ + content: `${msg}`, + duration: 3, + }); + return; + } + data[key] = from[key]['value']; + } + + // 发送 + const hide = message.loading(t('common.loading'), 0); + editNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: data, + loc, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.updateItem', { + num: modalState.title, + }), + duration: 3, + }); + fnActiveConfigNode('#'); + } else { + message.warning({ + content: t('views.ne.neConfig.updateItemErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + arrayEditClose(); + }); + } + + /**多列表嵌套行删除单行 */ + function arrayChildDelete(rowIndex: Record) { + const index = rowIndex.value; + const loc = `${arrayChildState.loc}/${index}`; + const title = `${arrayChildState.title} Index-${index}`; + + Modal.confirm({ + title: t('common.tipTitle'), + content: t('views.ne.neConfig.delItemTip', { + num: title, + }), + onOk() { + delNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + loc, + }).then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.delItemOk', { + num: title, + }), + duration: 2, + }); + arrayEditClose(); + fnActiveConfigNode('#'); + } else { + message.error({ + content: `${res.msg}`, + duration: 2, + }); + } + }); + }, + }); + } + + /**多列表嵌套行新增单行 */ + function arrayChildAdd() { + const from = arrayInitAdd(arrayChildState.data, arrayChildState.dataRule); + // 处理信息 + const row: Record = {}; + for (const v of from.record) { + if (Array.isArray(v.array)) { + continue; + } + row[v.name] = Object.assign({}, v); + } + + modalState.from = row; + modalState.type = 'arrayChildAdd'; + modalState.title = `${arrayChildState.title} ${from.title}`; + modalState.key = from.key; + modalState.data = from.record.filter((v: any) => !Array.isArray(v.array)); + modalState.open = true; + } + + /**多列表新增单行确认 */ + function arrayChildAddOk(from: Record) { + const loc = `${arrayChildState.loc}/${from['index']['value']}`; + + let data: Record = {}; + for (const key in from) { + // 子嵌套的不插入 + if (from[key]['array']) { + continue; + } + // 检查规则 + const [ok, msg] = ruleVerification(from[key]); + if (!ok) { + message.warning({ + content: `${msg}`, + duration: 3, + }); + return; + } + data[key] = from[key]['value']; + } + + // 发送 + const hide = message.loading(t('common.loading'), 0); + addNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: data, + loc, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.addItemOk', { + num: modalState.title, + }), + duration: 3, + }); + fnActiveConfigNode('#'); + } else { + message.warning({ + content: t('views.ne.neConfig.addItemErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + arrayEditClose(); + }); + } + + return { + arrayChildState, + arrayChildExpand, + arrayChildEdit, + arrayChildEditOk, + arrayChildDelete, + arrayChildAdd, + arrayChildAddOk, + }; +} diff --git a/src/views/core-ne/ne/config/hooks/useConfigList.ts b/src/views/core-ne/ne/config/hooks/useConfigList.ts new file mode 100644 index 00000000..0cedcbad --- /dev/null +++ b/src/views/core-ne/ne/config/hooks/useConfigList.ts @@ -0,0 +1,152 @@ +import { editNeConfigData } from '@/api/ne/neConfig'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { SizeType } from 'ant-design-vue/es/config-provider'; +import { message } from 'ant-design-vue/es'; +import { reactive, toRaw } from 'vue'; + +/** + * list类型参数处理 + * @param param 父级传入 {t, treeState, neTypeSelect, ruleVerification} + * @returns + */ +export default function useConfigList({ + t, + treeState, + neTypeSelect, + ruleVerification, +}: any) { + /**单列表状态类型 */ + type ListStateType = { + /**紧凑型 */ + size: SizeType; + /**单列记录字段 */ + columns: Record[]; + /**单列记录数据 */ + data: Record[]; + /**编辑行记录 */ + editRecord: Record; + /**确认提交等待 */ + confirmLoading: boolean; + }; + + /**单列表状态 */ + let listState: ListStateType = reactive({ + size: 'small', + columns: [ + { + title: 'Key', + dataIndex: 'display', + align: 'left', + width: '30%', + }, + { + title: 'Value', + dataIndex: 'value', + align: 'left', + width: '70%', + }, + ], + data: [], + confirmLoading: false, + editRecord: {}, + }); + + /**单列表编辑 */ + function listEdit(row: Record) { + if ( + listState.confirmLoading || + ['read-only', 'read', 'ro'].includes(row.access) + ) { + return; + } + + listState.editRecord = Object.assign({}, row); + } + + /**单列表编辑关闭 */ + function listEditClose() { + listState.confirmLoading = false; + listState.editRecord = {}; + } + + /**单列表编辑确认 */ + function listEditOk() { + if (listState.confirmLoading) return; + const from = toRaw(listState.editRecord); + // 检查规则 + const [ok, msg] = ruleVerification(from); + if (!ok) { + message.warning({ + content: `${msg}`, + duration: 3, + }); + return; + } + + // 发送 + listState.confirmLoading = true; + const hide = message.loading(t('common.loading'), 0); + editNeConfigData({ + neType: neTypeSelect.value[0], + neUid: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: { + [from['name']]: from['value'], + }, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.updateValue', { + num: from['display'], + }), + duration: 3, + }); + // 改变表格数据 + const item = listState.data.find( + (item: Record) => from['name'] === item['name'] + ); + if (item) { + Object.assign(item, listState.editRecord); + } + } else { + message.warning({ + content: t('views.ne.neConfig.updateValueErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + listState.confirmLoading = false; + listState.editRecord = {}; + }); + } + + /**表格分页器参数 */ + let tablePagination = reactive({ + /**当前页数 */ + current: 1, + /**每页条数 */ + pageSize: 10, + /**默认的每页条数 */ + defaultPageSize: 10, + /**指定每页可以显示多少条 */ + pageSizeOptions: ['10', '20', '50', '100'], + /**只有一页时是否隐藏分页器 */ + hideOnSinglePage: true, + /**是否可以快速跳转至某页 */ + 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; + }, + }); + + return { tablePagination, listState, listEdit, listEditClose, listEditOk }; +} diff --git a/src/views/core-ne/ne/config/hooks/useOptions.ts b/src/views/core-ne/ne/config/hooks/useOptions.ts new file mode 100644 index 00000000..d2a02483 --- /dev/null +++ b/src/views/core-ne/ne/config/hooks/useOptions.ts @@ -0,0 +1,190 @@ +import { getNeConfigData } from '@/api/ne/neConfig'; +import { regExpIPv4, regExpIPv6, validURL } from '@/utils/regular-utils'; +import { ref } from 'vue'; + +/** + * 参数公共函数 + * @param param 父级传入 {t} + * @returns + */ +export default function useOptions({ t }: any) { + /**规则校验 */ + function ruleVerification(row: Record): (string | boolean)[] { + let result = [true, '']; + const type = row.type; + const value = row.value; + const filter = row.filter; + const display = row.display; + + // 子嵌套的不检查 + if (row.array) { + return result; + } + + // 可选的同时没有值不检查 + if (row.optional === 'true' && !value) { + return result; + } + switch (type) { + case 'int': + // filter: "0~128" + + if (filter) { + let filterArr = ['0', '1']; + if (filter.indexOf('-') !== -1) { + filterArr = filter.split('-'); + } else if (filter.indexOf('~') !== -1) { + filterArr = filter.split('~'); + } + const minInt = parseInt(filterArr[0]); + const maxInt = parseInt(filterArr[1]); + const valueInt = parseInt(value); + if (valueInt < minInt || valueInt > maxInt) { + return [ + false, + t('views.ne.neConfig.requireInt', { + display, + filter, + }), + ]; + } + } + break; + case 'ipv4': + if (!regExpIPv4.test(value)) { + return [false, t('views.ne.neConfig.requireIpv4', { display })]; + } + break; + case 'ipv6': + if (!regExpIPv6.test(value)) { + return [false, t('views.ne.neConfig.requireIpv6', { display })]; + } + break; + case 'enum': + if (filter && filter.indexOf('{') === 1) { + let filterJson: Record = {}; + try { + filterJson = JSON.parse(filter); //string---json + } catch (error) { + console.error(error); + } + + if (!Object.keys(filterJson).includes(`${value}`)) { + return [false, t('views.ne.neConfig.requireEnum', { display })]; + } + } + break; + case 'bool': + // filter: '{"0":"false", "1":"true"}' + + if (filter && filter.indexOf('{') === 1) { + let filterJson: Record = {}; + try { + filterJson = JSON.parse(filter); //string---json + } catch (error) { + console.error(error); + } + + if (!Object.values(filterJson).includes(`${value}`)) { + return [false, t('views.ne.neConfig.requireBool', { display })]; + } + } + break; + case 'string': + // filter: "0~128" + + // 字符串长度判断 + if (filter) { + try { + let rule: RegExp = new RegExp('^.*$'); + if (filter.indexOf('-') !== -1) { + const filterArr = filter.split('-'); + rule = new RegExp( + '^.{' + filterArr[0] + ',' + filterArr[1] + '}$' + ); + } else if (filter.indexOf('~') !== -1) { + const filterArr = filter.split('~'); + rule = new RegExp( + '^\\S{' + filterArr[0] + ',' + filterArr[1] + '}$' + ); + } + if (!rule.test(value)) { + return [ + false, + t('views.ne.neConfig.requireString', { + display, + }), + ]; + } + } catch (error) { + console.error(error); + } + } + // 字符串http判断 + if (value.startsWith('http')) { + try { + if (!validURL(value)) { + return [ + false, + t('views.ne.neConfig.requireString', { + display, + }), + ]; + } + } catch (error) { + console.error(error); + } + } + + break; + case 'regex': + // filter: "^[0-9]{3}$" + + if (filter) { + try { + let regex = new RegExp(filter); + if (!regex.test(value)) { + return [ + false, + t('views.ne.neConfig.requireString', { + display, + }), + ]; + } + } catch (error) { + console.error(error); + } + } + break; + + default: + return [false, t('views.ne.neConfig.requireUn', { display })]; + } + return result; + } + + /**upfId可选择 */ + const smfByUPFIdOptions = ref<{ value: string; label: string }[]>([]); + /**加载smf配置的upfId */ + function smfByUPFIdLoadData(neUid: string) { + getNeConfigData({ + neType: 'SMF', + neUid: neUid, + paramName: 'upfConfig', + }).then(res => { + smfByUPFIdOptions.value = []; + for (const s of res.data) { + smfByUPFIdOptions.value.push({ + value: s.id, + label: s.id, + }); + } + }); + } + + return { + ruleVerification, + smfByUPFIdLoadData, + smfByUPFIdOptions, + }; +} diff --git a/src/views/core-ne/ne/config/index.vue b/src/views/core-ne/ne/config/index.vue new file mode 100644 index 00000000..f21ec7a8 --- /dev/null +++ b/src/views/core-ne/ne/config/index.vue @@ -0,0 +1,1082 @@ + + + + + diff --git a/src/views/core-ne/ne/info/index.vue b/src/views/core-ne/ne/info/index.vue new file mode 100644 index 00000000..470a13fb --- /dev/null +++ b/src/views/core-ne/ne/info/index.vue @@ -0,0 +1,848 @@ + + + + + diff --git a/src/views/core-ne/ne/version/index.vue b/src/views/core-ne/ne/version/index.vue new file mode 100644 index 00000000..23cd8ba7 --- /dev/null +++ b/src/views/core-ne/ne/version/index.vue @@ -0,0 +1,724 @@ + + + + + diff --git a/src/views/core-ne/tool/mml/logs/index.vue b/src/views/core-ne/tool/mml/logs/index.vue new file mode 100644 index 00000000..42d17d6c --- /dev/null +++ b/src/views/core-ne/tool/mml/logs/index.vue @@ -0,0 +1,306 @@ + + + + + diff --git a/src/views/core-ne/tool/mml/oper-ne/index.vue b/src/views/core-ne/tool/mml/oper-ne/index.vue new file mode 100644 index 00000000..9319f683 --- /dev/null +++ b/src/views/core-ne/tool/mml/oper-ne/index.vue @@ -0,0 +1,825 @@ + + + + + diff --git a/src/views/core-ne/tool/mml/oper-udm/index.vue b/src/views/core-ne/tool/mml/oper-udm/index.vue new file mode 100644 index 00000000..f441da08 --- /dev/null +++ b/src/views/core-ne/tool/mml/oper-udm/index.vue @@ -0,0 +1,751 @@ + + + + + diff --git a/src/views/core-ne/tool/signal/packet/index.vue b/src/views/core-ne/tool/signal/packet/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/tool/signal/packet/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/tool/signal/tcpdump/file.vue b/src/views/core-ne/tool/signal/tcpdump/file.vue new file mode 100644 index 00000000..56a16e91 --- /dev/null +++ b/src/views/core-ne/tool/signal/tcpdump/file.vue @@ -0,0 +1,479 @@ + + + + + diff --git a/src/views/core-ne/tool/signal/tcpdump/index.vue b/src/views/core-ne/tool/signal/tcpdump/index.vue new file mode 100644 index 00000000..1757e90d --- /dev/null +++ b/src/views/core-ne/tool/signal/tcpdump/index.vue @@ -0,0 +1,811 @@ + + + + + diff --git a/src/views/core-ne/tool/signal/wireshark/index.vue b/src/views/core-ne/tool/signal/wireshark/index.vue new file mode 100644 index 00000000..615ad249 --- /dev/null +++ b/src/views/core-ne/tool/signal/wireshark/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/core-ne/tool/terminal/components/hostList.vue b/src/views/core-ne/tool/terminal/components/hostList.vue new file mode 100644 index 00000000..fb438568 --- /dev/null +++ b/src/views/core-ne/tool/terminal/components/hostList.vue @@ -0,0 +1,381 @@ + + + + + diff --git a/src/views/core-ne/tool/terminal/index.vue b/src/views/core-ne/tool/terminal/index.vue new file mode 100644 index 00000000..01dfdb11 --- /dev/null +++ b/src/views/core-ne/tool/terminal/index.vue @@ -0,0 +1,340 @@ + + + + + diff --git a/src/views/core-ne/tool/test/iperf/index.vue b/src/views/core-ne/tool/test/iperf/index.vue new file mode 100644 index 00000000..7a18924d --- /dev/null +++ b/src/views/core-ne/tool/test/iperf/index.vue @@ -0,0 +1,518 @@ + + + + + diff --git a/src/views/core-ne/tool/test/net/index.vue b/src/views/core-ne/tool/test/net/index.vue new file mode 100644 index 00000000..bb96395f --- /dev/null +++ b/src/views/core-ne/tool/test/net/index.vue @@ -0,0 +1,338 @@ + + + + + diff --git a/src/views/core-ne/tool/test/ping/index.vue b/src/views/core-ne/tool/test/ping/index.vue new file mode 100644 index 00000000..ade58349 --- /dev/null +++ b/src/views/core-ne/tool/test/ping/index.vue @@ -0,0 +1,408 @@ + + + + + diff --git a/src/views/core-ne/tool/test/ps/index.vue b/src/views/core-ne/tool/test/ps/index.vue new file mode 100644 index 00000000..3866e8fb --- /dev/null +++ b/src/views/core-ne/tool/test/ps/index.vue @@ -0,0 +1,370 @@ + + + + + diff --git a/src/views/core-ne/ue/pcf-rule/index.vue b/src/views/core-ne/ue/pcf-rule/index.vue new file mode 100644 index 00000000..56c643c2 --- /dev/null +++ b/src/views/core-ne/ue/pcf-rule/index.vue @@ -0,0 +1,1219 @@ + + + + + diff --git a/src/views/core-ne/ue/udm-auth/index.vue b/src/views/core-ne/ue/udm-auth/index.vue new file mode 100644 index 00000000..cf410ac0 --- /dev/null +++ b/src/views/core-ne/ue/udm-auth/index.vue @@ -0,0 +1,1311 @@ + + + + + diff --git a/src/views/core-ne/ue/udm-sub/index.vue b/src/views/core-ne/ue/udm-sub/index.vue new file mode 100644 index 00000000..26df4888 --- /dev/null +++ b/src/views/core-ne/ue/udm-sub/index.vue @@ -0,0 +1,2165 @@ + + + + + diff --git a/src/views/core-ne/ue/udm-voip/index.vue b/src/views/core-ne/ue/udm-voip/index.vue new file mode 100644 index 00000000..e160d8bd --- /dev/null +++ b/src/views/core-ne/ue/udm-voip/index.vue @@ -0,0 +1,979 @@ + + + + + diff --git a/src/views/core-ne/ue/udm-volte/index.vue b/src/views/core-ne/ue/udm-volte/index.vue new file mode 100644 index 00000000..9a126048 --- /dev/null +++ b/src/views/core-ne/ue/udm-volte/index.vue @@ -0,0 +1,1223 @@ + + + + + diff --git a/src/views/index/index.vue b/src/views/index/index.vue new file mode 100644 index 00000000..1aa2a504 --- /dev/null +++ b/src/views/index/index.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/src/views/index/m/index.vue b/src/views/index/m/index.vue new file mode 100644 index 00000000..1dcf38c6 --- /dev/null +++ b/src/views/index/m/index.vue @@ -0,0 +1,399 @@ + + + + + diff --git a/src/views/log/login/index.vue b/src/views/log/login/index.vue new file mode 100644 index 00000000..3526f2e4 --- /dev/null +++ b/src/views/log/login/index.vue @@ -0,0 +1,569 @@ + + + + + diff --git a/src/views/log/operation/index.vue b/src/views/log/operation/index.vue new file mode 100644 index 00000000..e8abc665 --- /dev/null +++ b/src/views/log/operation/index.vue @@ -0,0 +1,766 @@ + + + + + diff --git a/src/views/mml/udm/index.vue b/src/views/mml/udm/index.vue index f04a170a..9eff0cb3 100644 --- a/src/views/mml/udm/index.vue +++ b/src/views/mml/udm/index.vue @@ -508,7 +508,7 @@ function fnAutoCompleteKeydown(evt: any) { onMounted(() => { // 获取网元网元列表 - neStore.neCascaderOptions.forEach(item => { + neStore.getCoreDataNeCascaderOptions.forEach(item => { if (item.value === 'UDM') { neOptions.value = JSON.parse(JSON.stringify(item.children)); } diff --git a/src/views/ne/info/components/CoreModal.vue b/src/views/ne/info/components/CoreModal.vue index c06e5016..1cc2bd28 100644 --- a/src/views/ne/info/components/CoreModal.vue +++ b/src/views/ne/info/components/CoreModal.vue @@ -60,7 +60,7 @@ const modalStateFrom = Form.useForm( coreUid: [ { required: true, - message: t('views.ne.neInfo.oam.kpiTimerPlease'), + message: t('common.selectPlease'), }, ], }) @@ -72,7 +72,12 @@ const modalStateFrom = Form.useForm( function fnModalVisible() { const hide = message.loading(t('common.loading'), 0); modalState.from.neUid = props.neUid; - modalState.from.coreUid = props.coreUid; + if (props.coreUid.length === 8) { + modalState.from.coreUid = props.coreUid; + } else { + modalState.from.coreUid = undefined; + } + modalState.select = 'Associated'; modalState.openByEdit = true; modalState.confirmLoading = false; hide(); @@ -122,6 +127,7 @@ function fnModalOk() { function fnModalCancel() { modalState.openByEdit = false; modalState.confirmLoading = false; + modalState.select = 'Associated'; modalStateFrom.resetFields(); emit('cancel'); emit('update:open', false); @@ -131,7 +137,6 @@ function fnModalCancel() { watch( () => props.open, val => { - console.log('CoreModal open', val, props.neUid, props.coreUid); if (val && props.neUid) { fnModalVisible(); } diff --git a/src/views/ne/info/index.vue b/src/views/ne/info/index.vue index 8247de7b..d2741804 100644 --- a/src/views/ne/info/index.vue +++ b/src/views/ne/info/index.vue @@ -110,7 +110,7 @@ let tableColumns: ColumnsType = [ align: 'left', width: 100, }, - { + { title: t('views.ne.common.coreName'), dataIndex: 'coreName', align: 'left', diff --git a/src/views/ne/neQuickSetup/components/NeInfoSoftwareLicense.vue b/src/views/ne/neQuickSetup/components/NeInfoSoftwareLicense.vue index 6a0fd463..91d2269f 100644 --- a/src/views/ne/neQuickSetup/components/NeInfoSoftwareLicense.vue +++ b/src/views/ne/neQuickSetup/components/NeInfoSoftwareLicense.vue @@ -3,7 +3,7 @@ import { Modal } from 'ant-design-vue/es'; import { defineAsyncComponent, onMounted, onUnmounted, reactive } from 'vue'; import { fnRestStepState, stepState } from '../hooks/useStep'; import useI18n from '@/hooks/useI18n'; -import { codeNeLicense, stateNeLicense } from '@/api/ne/neLicense'; +import { getNeInfo, codeNeLicense } from '@/api/ne/neInfo'; import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; const { t } = useI18n(); const EditModal = defineAsyncComponent( @@ -60,10 +60,10 @@ function fnModalOk(e: any) { return; } if (state.timeCount % 5 === 0) { - stateNeLicense(e.neId).then(res => { + getNeInfo(stepState.neInfo.id).then(res => { if (res.code === RESULT_CODE_SUCCESS && res.data) { - state.from.sn = res.data.sn; - state.from.expire = res.data.expire; + state.from.sn = res.data.serialNum; + state.from.expire = res.data.expiryDate; state.from.ueNumber = res.data.ueNumber; state.from.nbNumber = res.data.ueNumber; @@ -95,15 +95,15 @@ function fnStepEnd() { } onMounted(() => { - const { neUid } = stepState.neInfo; - if (neUid) { + const { id, neUid } = stepState.neInfo; + if (id && neUid) { state.from.neUid = neUid; state.confirmLoading = true; - stateNeLicense(neUid) + getNeInfo(id) .then(res => { if (res.code === RESULT_CODE_SUCCESS && res.data) { - state.from.sn = res.data.sn; - state.from.expire = res.data.expire; + state.from.sn = res.data.serialNum; + state.from.expire = res.data.expiryDate; } else { return codeNeLicense(neUid); } @@ -178,7 +178,7 @@ onUnmounted(() => { +import { Form, Modal, message } from 'ant-design-vue/es'; +import { onMounted, reactive, toRaw } from 'vue'; +import { addNeInfo, getNeInfo } from '@/api/ne/neInfo'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { NE_TYPE_LIST } from '@/constants/ne-constants'; +import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils'; +import { fnRestStepState, fnToStepName, stepState } from '../hooks/useStep'; +import useI18n from '@/hooks/useI18n'; +import useDictStore from '@/store/modules/dict'; +import useNeStore from '@/store/modules/ne'; +const { getDict } = useDictStore(); +const neStore = useNeStore(); +const { t } = useI18n(); + +/**字典数据 */ +let dict: { + /**主机类型 */ + neHostType: DictType[]; + /**分组 */ + neHostGroupId: DictType[]; + /**认证模式 */ + neHostAuthMode: DictType[]; +} = reactive({ + neHostType: [], + neHostGroupId: [], + neHostAuthMode: [], +}); + +/**对话框对象信息状态类型 */ +type ModalStateType = { + /**是否可以下一步 */ + stepNext: boolean; + /**标题 */ + title: string; + /**表单数据 */ + from: Record; + /**确定按钮 loading */ + confirmLoading: boolean; +}; + +/**对话框对象信息状态 */ +let modalState: ModalStateType = reactive({ + stepNext: false, + title: '网元', + from: { + id: undefined, + coreId: undefined, + neUid: '', + neType: '', + neName: '', + ipAddr: '', + port: 33030, + pvFlag: 'PNF', + macAddr: '', + dn: '-', + vendorName: '-', + province: 'Area', + // 主机 + hosts: [ + { + id: undefined, + hostType: 'ssh', + groupId: '1', + title: 'SSH_NE_22', + addr: '', + port: 22, + user: 'omcuser', + authMode: '2', + password: '', + privateKey: '', + passPhrase: '', + remark: '', + }, + { + id: undefined, + hostType: 'telnet', + groupId: '1', + title: 'Telnet_NE_4100', + addr: '', + port: 4100, + user: 'admin', + authMode: '0', + password: 'admin', + remark: '', + }, + ], + }, + confirmLoading: false, +}); + +/**对话框内表单属性和校验规则 */ +const modalStateFrom = Form.useForm( + modalState.from, + reactive({ + neType: [ + { + required: true, + message: t('views.ne.common.neTypePlease'), + }, + ], + neName: [ + { + required: true, + message: t('views.ne.common.neNamePlease'), + }, + ], + ipAddr: [ + { + required: true, + validator: modalStateFromEqualIPV4AndIPV6, + }, + ], + }) +); + +/**表单验证IP地址是否有效 */ +function modalStateFromEqualIPV4AndIPV6( + rule: Record, + value: string, + callback: (error?: string) => void +) { + if (!value) { + return Promise.reject(t('views.ne.common.ipAddrPlease')); + } + + if (value.indexOf('.') === -1 && value.indexOf(':') === -1) { + return Promise.reject(t('valid.ipPlease')); + } + if (value.indexOf('.') !== -1 && !regExpIPv4.test(value)) { + return Promise.reject(t('valid.ipv4Reg')); + } + if (value.indexOf(':') !== -1 && !regExpIPv6.test(value)) { + return Promise.reject(t('valid.ipv6Reg')); + } + return Promise.resolve(); +} + +/** + * 对话框弹出确认执行函数 + * 进行表达规则校验 + */ +function fnModalOk() { + const from = toRaw(modalState.from); + modalStateFrom + .validate() + .then(() => { + // 清除更新必要信息 + from.id = undefined; + from.hostIds = ''; + for (let index = 0; index < from.hosts.length; index++) { + from.hosts[index].id = undefined; + } + const hide = message.loading(t('common.loading'), 0); + addNeInfo(from) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: `${t('common.operateOk')}`, + duration: 3, + }); + return res.data; + } + message.error({ + content: res.msg, + duration: 3, + }); + return 0; + }) + .then(neId => { + if (neId === 0) { + return; + } + neStore.fnNelistRefresh(); // 刷新缓存的网元信息 + getNeInfo(neId).then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + stepState.neInfo = res.data; // 保存网元信息 + modalState.stepNext = true; // 开启下一步 + } else { + message.error({ + content: res.msg, + duration: 3, + }); + } + }); + }) + .finally(() => { + hide(); + modalState.confirmLoading = false; + }); + }) + .catch(e => { + message.error(t('common.errorFields', { num: e.errorFields.length }), 3); + }) + .finally(() => { + modalState.confirmLoading = false; + }); +} + +/** + * 表单修改网元类型 + */ +function fnNeTypeChange(v: any) { + // 网元默认只含22和4100 + if (modalState.from.hosts.length === 3) { + modalState.from.hosts.pop(); + } + const hostsLen = modalState.from.hosts.length; + // UPF标准版本可支持5002 + if (hostsLen === 2 && v === 'UPF') { + modalState.from.hosts.push({ + id: undefined, + hostType: 'telnet', + groupId: '1', + title: 'Telnet_NE_5002', + addr: modalState.from.ip, + port: 5002, + user: 'admin', + authMode: '0', + password: 'admin', + remark: '', + }); + } + // UDM可支持6379 + if (hostsLen === 2 && v === 'UDM') { + modalState.from.hosts.push({ + id: undefined, + hostType: 'redis', + groupId: '1', + title: 'REDIS_NE_6379', + addr: modalState.from.ip, + port: 6379, + user: 'udmdb', + authMode: '0', + password: 'helloearth', + dbName: '0', + remark: '', + }); + } +} + +/** + * 表单修改网元IP + */ +function fnNeIPChange(e: any) { + const v = e.target.value; + if (v.length < 7) return; + for (const host of modalState.from.hosts) { + host.addr = v; + } +} + +/**返回上一步 */ +function fnStepPrev() { + Modal.confirm({ + title: t('common.tipTitle'), + content: t('views.ne.neQuickSetup.stepPrevTip'), + onOk() { + fnRestStepState(t); + fnToStepName('Start'); + }, + }); +} + +/**下一步操作 */ +function fnStepNext() { + if (!modalState.stepNext) return; + Modal.confirm({ + title: t('common.tipTitle'), + content: t('views.ne.neQuickSetup.configStepNext'), + onOk() { + fnToStepName('NeInfoSoftwareInstall'); + }, + }); +} + +onMounted(() => { + // 初始字典数据 + Promise.allSettled([ + getDict('ne_host_type'), + getDict('ne_host_groupId'), + getDict('ne_host_authMode'), + ]) + .then(resArr => { + if (resArr[0].status === 'fulfilled') { + dict.neHostType = resArr[0].value; + } + if (resArr[1].status === 'fulfilled') { + dict.neHostGroupId = resArr[1].value; + } + if (resArr[2].status === 'fulfilled') { + dict.neHostAuthMode = resArr[2].value; + } + }) + .finally(() => { + if (stepState.neInfo.id) { + Object.assign(modalState.from, stepState.neInfo); + } else { + modalState.from.ipAddr = stepState.neHost.addr; + Object.assign(modalState.from.hosts[0], stepState.neHost); + Object.assign(modalState.from.hosts[1], { + addr: modalState.from.ipAddr, + user: 'admin', + password: 'admin', + }); + } + }); +}); + + + + + diff --git a/src/views/ne/quick-setup/components/NeInfoSoftwareInstall.vue b/src/views/ne/quick-setup/components/NeInfoSoftwareInstall.vue new file mode 100644 index 00000000..ac3f1f0d --- /dev/null +++ b/src/views/ne/quick-setup/components/NeInfoSoftwareInstall.vue @@ -0,0 +1,433 @@ + + + + + diff --git a/src/views/ne/quick-setup/components/NeInfoSoftwareLicense.vue b/src/views/ne/quick-setup/components/NeInfoSoftwareLicense.vue new file mode 100644 index 00000000..91d2269f --- /dev/null +++ b/src/views/ne/quick-setup/components/NeInfoSoftwareLicense.vue @@ -0,0 +1,188 @@ + + + + + diff --git a/src/views/ne/quick-setup/components/Para5GForm.vue b/src/views/ne/quick-setup/components/Para5GForm.vue new file mode 100644 index 00000000..d6e004ff --- /dev/null +++ b/src/views/ne/quick-setup/components/Para5GForm.vue @@ -0,0 +1,564 @@ + + + + + diff --git a/src/views/ne/quick-setup/components/Start.vue b/src/views/ne/quick-setup/components/Start.vue new file mode 100644 index 00000000..a623b061 --- /dev/null +++ b/src/views/ne/quick-setup/components/Start.vue @@ -0,0 +1,496 @@ + + + + + diff --git a/src/views/ne/quick-setup/hooks/usePara5G.ts b/src/views/ne/quick-setup/hooks/usePara5G.ts new file mode 100644 index 00000000..0aef57e7 --- /dev/null +++ b/src/views/ne/quick-setup/hooks/usePara5G.ts @@ -0,0 +1,141 @@ +import { reactive, toRaw } from 'vue'; +import { updateNeInfo } from '@/api/ne/neInfo'; +import useNeStore from '@/store/modules/ne'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { getPara5GFilee, savePara5GFile } from '@/api/ne/neAction'; +const neStore = useNeStore(); + +/**对象信息信息状态类型 */ +type StateType = { + /**表单数据 */ + from: Record; + /**OMC信息,需修改当前的IP */ + omcInfo: Record; + /**根据网元显示配置项 */ + hasNE: { + amf: boolean; + upf: boolean; + ims: boolean; + mme: boolean; + }; + /**确定按钮 loading */ + confirmLoading: boolean; +}; + +export function usePara5G() { + /**对象信息状态 */ + let state: StateType = reactive({ + from: {}, + omcInfo: {}, + hasNE: { + amf: false, + upf: false, + ims: false, + mme: false, + }, + confirmLoading: false, + }); + + /**载入数据*/ + function fnReloadData() { + state.confirmLoading = true; + Promise.all([getPara5GFilee(), neStore.fnNelistRefresh()]).then(resArr => { + // 已保存的配置 + if (resArr[0].code === RESULT_CODE_SUCCESS) { + Object.assign(state.from, resArr[0].data); + } + // 填充固定网元类型的ip + if ( + resArr[1].code === RESULT_CODE_SUCCESS && + Array.isArray(resArr[1].data) + ) { + for (const item of resArr[1].data) { + const ipAddr = item.ipAddr; + // 公共配置文件sbi的各网元IP + switch (item.neType) { + case 'OMC': + state.from.sbi.omc_ip = ipAddr; + Object.assign(state.omcInfo, item); // 主动改OMC_IP + break; + case 'IMS': + state.from.sbi.ims_ip = ipAddr; + state.hasNE.ims = true; + break; + case 'AMF': + state.from.sbi.amf_ip = ipAddr; + state.hasNE.amf = true; + break; + case 'AUSF': + state.from.sbi.ausf_ip = ipAddr; + break; + case 'UDM': + state.from.sbi.udm_ip = ipAddr; + state.from.sbi.db_ip = '0.0.0.0'; + break; + case 'SMF': + state.from.sbi.smf_ip = ipAddr; + break; + case 'PCF': + state.from.sbi.pcf_ip = ipAddr; + break; + case 'NSSF': + state.from.sbi.nssf_ip = ipAddr; + break; + case 'NRF': + state.from.sbi.nrf_ip = ipAddr; + break; + case 'UPF': + state.from.sbi.upf_ip = ipAddr; + state.hasNE.upf = true; + break; + case 'LMF': + state.from.sbi.lmf_ip = ipAddr; + break; + case 'NEF': + state.from.sbi.nef_ip = ipAddr; + break; + case 'MME': + state.from.sbi.mme_ip = ipAddr; + if (ipAddr.includes('.')) { + state.from.external.mmes11_ip = ipAddr + '/24'; + } + state.hasNE.mme = true; + break; + case 'N3IWF': + state.from.sbi.n3iwf_ip = ipAddr; + break; + case 'SMSC': + state.from.sbi.smsc_ip = ipAddr; + break; + } + } + } + state.confirmLoading = false; + }); + } + + /**保存数据 */ + async function fnSaveData() { + if (state.confirmLoading) return; + state.confirmLoading = true; + const res = await savePara5GFile({ + content: toRaw(state.from), + syncNe: [], + }); + if (res.code === RESULT_CODE_SUCCESS) { + // 更新omc_ip + if (state.omcInfo.id) { + state.omcInfo.ip = state.from.sbi.omc_ip; + await updateNeInfo(toRaw(state.omcInfo)); + } + } + state.confirmLoading = false; + return res; + } + + return { + state, + fnReloadData, + fnSaveData, + }; +} diff --git a/src/views/ne/quick-setup/hooks/useStep.ts b/src/views/ne/quick-setup/hooks/useStep.ts new file mode 100644 index 00000000..5c301309 --- /dev/null +++ b/src/views/ne/quick-setup/hooks/useStep.ts @@ -0,0 +1,103 @@ +import { defineAsyncComponent, reactive, shallowRef, watch } from 'vue'; + +/**步骤信息状态类型 */ +type StepStateType = { + /**步骤名称 */ + stepName: string; + /**安装网元步骤信息 */ + steps: any[]; + /**安装网元步骤当前选中 */ + current: number; + /**连接主机 */ + neHost: Record; + /**网元信息 */ + neInfo: Record; +}; + +/**步骤信息状态 */ +export const stepState: StepStateType = reactive({ + stepName: 'Para5G', + steps: [ + { + title: '服务器环境', + description: '服务端与网元服务', + }, + { + title: '配置网元信息', + description: '网元信息设置', + }, + { + title: '网元软件安装', + description: '软件安装到服务端', + }, + { + title: '网元授权激活', + description: '网元服务授权激活', + }, + ], + current: -1, + neHost: {}, + neInfo: {}, +}); + +/**步骤信息状态复位 */ +export function fnRestStepState(t?: any) { + stepState.stepName = 'Para5G'; + stepState.current = -1; + stepState.neHost = {}; + stepState.neInfo = {}; + + // 多语言翻译 + if (t) { + stepState.steps = [ + { + title: t('views.ne.neQuickSetup.startTitle'), + description: t('views.ne.neQuickSetup.startDesc'), + }, + { + title: t('views.ne.neQuickSetup.configTitle'), + description: t('views.ne.neQuickSetup.configDesc'), + }, + { + title: t('views.ne.neQuickSetup.installTitle'), + description: t('views.ne.neQuickSetup.installDesc'), + }, + { + title: t('views.ne.neQuickSetup.licenseTitle'), + description: t('views.ne.neQuickSetup.licenseDesc'), + }, + ]; + } +} + +/**跳转步骤组件 */ +export function fnToStepName(stepName: string) { + stepState.current = [ + 'Start', + 'NeInfoConfig', + 'NeInfoSoftwareInstall', + 'NeInfoSoftwareLicense', + ].indexOf(stepName); + + stepState.stepName = stepName; +} + +export function useStep({ t }: any) { + // 异步加载组件 + const Start = defineAsyncComponent(() => import('../components/Start.vue')); + + // 当前组件 + const currentComponent = shallowRef(Start); + + watch( + () => stepState.stepName, + v => { + const loadComponent = defineAsyncComponent( + () => import(`../components/${v}.vue`) + ); + currentComponent.value = loadComponent; + } + ); + + return { currentComponent }; +} diff --git a/src/views/ne/quick-setup/index.vue b/src/views/ne/quick-setup/index.vue new file mode 100644 index 00000000..894c9201 --- /dev/null +++ b/src/views/ne/quick-setup/index.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/views/software-version/software/components/EditModal.vue b/src/views/software-version/software/components/EditModal.vue new file mode 100644 index 00000000..dbabc2d6 --- /dev/null +++ b/src/views/software-version/software/components/EditModal.vue @@ -0,0 +1,473 @@ + + + + + diff --git a/src/views/software-version/software/components/UploadMoreFile.vue b/src/views/software-version/software/components/UploadMoreFile.vue new file mode 100644 index 00000000..b020ada5 --- /dev/null +++ b/src/views/software-version/software/components/UploadMoreFile.vue @@ -0,0 +1,506 @@ + + + + + diff --git a/src/views/software-version/software/index.vue b/src/views/software-version/software/index.vue new file mode 100644 index 00000000..2cb6e101 --- /dev/null +++ b/src/views/software-version/software/index.vue @@ -0,0 +1,577 @@ + + + + + diff --git a/src/views/software-version/version/index.vue b/src/views/software-version/version/index.vue new file mode 100644 index 00000000..23cd8ba7 --- /dev/null +++ b/src/views/software-version/version/index.vue @@ -0,0 +1,724 @@ + + + + + diff --git a/src/views/tool/ping/index.vue b/src/views/tool/ping/index.vue index ac51e910..ade58349 100644 --- a/src/views/tool/ping/index.vue +++ b/src/views/tool/ping/index.vue @@ -393,8 +393,7 @@ onBeforeUnmount(() => {}); prefix="ping" url="/tool/ping/run" :ne-type="state.params.neType" - :ne-uid="state.params.neUid" - :core-uid="state.params.coreUid" + :ne-uid="state.params.neUid" :rows="state.params.rows" :cols="state.params.cols" :process-messages="fnProcessMessage"