Compare commits
128 Commits
r2.2405.4-
...
2.2408.1-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1187383b6 | ||
|
|
8d8605e0cd | ||
|
|
8af48936e5 | ||
|
|
e21a8dc898 | ||
|
|
3c1ee63359 | ||
|
|
bc3940016a | ||
|
|
6ab4fbea6f | ||
|
|
c73fcbd91c | ||
|
|
023e317b0d | ||
|
|
543a2b7434 | ||
|
|
4ae9051411 | ||
|
|
532546c3f5 | ||
|
|
ab0d26513c | ||
|
|
8e9498ec83 | ||
|
|
ca048f223c | ||
|
|
e9ff6493dd | ||
|
|
396fb0b124 | ||
|
|
3a854be8fe | ||
|
|
c1f34f56ac | ||
|
|
b80bae0126 | ||
|
|
6c383b58c8 | ||
|
|
06db1344c3 | ||
|
|
fac47279b5 | ||
|
|
a36a12f783 | ||
|
|
acd19ebdbd | ||
|
|
d53c4c34f0 | ||
|
|
2d9011cf6b | ||
|
|
fcf53d0995 | ||
|
|
a2d93ddafe | ||
|
|
79920542c1 | ||
|
|
6efd9cb61a | ||
|
|
4dc6699974 | ||
|
|
3bdae264e1 | ||
|
|
9e0a99d160 | ||
|
|
5ac0ca41eb | ||
|
|
a7de701d4d | ||
|
|
f0561242ca | ||
|
|
6102972373 | ||
|
|
d095531952 | ||
|
|
d49dc9ebfd | ||
|
|
43a99e9328 | ||
|
|
d333221620 | ||
|
|
481734cfe1 | ||
|
|
1fa8601675 | ||
|
|
c1aabdbe42 | ||
|
|
953a36f142 | ||
|
|
c5f62e8d76 | ||
|
|
946139facb | ||
|
|
95931b2b6e | ||
|
|
e31c85835d | ||
|
|
847bae4c77 | ||
|
|
e69f43a0c2 | ||
|
|
d96e1ad259 | ||
|
|
3829d339e7 | ||
|
|
cd4073bec3 | ||
|
|
e67126c57a | ||
|
|
2f651b5d1f | ||
|
|
525854604f | ||
|
|
d42a8701da | ||
|
|
2b680d6d20 | ||
|
|
de79760a0e | ||
|
|
a5b5269b91 | ||
|
|
8a2d0ccfa1 | ||
|
|
650b02dc30 | ||
|
|
b42d8cb370 | ||
|
|
a213be0d64 | ||
|
|
2a2b441e09 | ||
|
|
84bdb44286 | ||
|
|
06b6175a76 | ||
|
|
11b790e140 | ||
|
|
296a9ba02b | ||
|
|
1801a46396 | ||
|
|
f6644a0d97 | ||
|
|
57f575aa84 | ||
|
|
68cbbe7133 | ||
|
|
c11d814312 | ||
|
|
e1548d2c98 | ||
|
|
1ec374eb26 | ||
|
|
0955a79965 | ||
|
|
374a9bde7e | ||
|
|
639a4f0b1f | ||
|
|
d1b9d7b9ba | ||
|
|
3298203f60 | ||
|
|
8f3cce52c0 | ||
|
|
ce06a88e89 | ||
|
|
749a04972d | ||
|
|
a311f0a09b | ||
|
|
c74d311537 | ||
|
|
1492f18791 | ||
|
|
cbc81643a5 | ||
|
|
c18b557c97 | ||
|
|
b6bd9bc3d5 | ||
|
|
199607e322 | ||
|
|
ee10119d77 | ||
|
|
1b1a56e49b | ||
|
|
afdc188e17 | ||
|
|
5de7d0a73f | ||
|
|
8f73d80a42 | ||
|
|
5a85f245b0 | ||
|
|
ff600c49f6 | ||
|
|
4c7e99fdd7 | ||
|
|
a6037a9737 | ||
|
|
1d55c092b1 | ||
|
|
8bdfd7ea28 | ||
|
|
39ad75fbd3 | ||
|
|
7ef775209d | ||
|
|
a8e0f36562 | ||
|
|
be50fc9c5c | ||
|
|
375f236e32 | ||
|
|
c9eb0240d8 | ||
|
|
b67d591d0a | ||
|
|
7275a87fba | ||
|
|
c103222b65 | ||
|
|
5133d09ec2 | ||
|
|
d88cec34df | ||
|
|
eadd4709ee | ||
|
|
04cbdc6b11 | ||
|
|
233496e184 | ||
|
|
919f8ef2a5 | ||
|
|
8f8d056f45 | ||
|
|
8fcd7974e4 | ||
|
|
cb7fc418a5 | ||
|
|
e6d4a898a8 | ||
|
|
be4fc896d7 | ||
|
|
e5a5ef6f96 | ||
|
|
530662bf5d | ||
|
|
2e7514d3ca | ||
|
|
1db61a5d4e |
@@ -5,13 +5,13 @@ VITE_HISTORY_HASH = false
|
||||
VITE_HISTORY_BASE_URL = "/"
|
||||
|
||||
# 应用名称
|
||||
VITE_APP_NAME = "Core Network EMS"
|
||||
VITE_APP_NAME = "Core Network OMC"
|
||||
|
||||
# 应用标识
|
||||
VITE_APP_CODE = "CN EMS"
|
||||
VITE_APP_CODE = "OMC"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.240530.1"
|
||||
VITE_APP_VERSION = "2.240801"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
@@ -5,13 +5,13 @@ VITE_HISTORY_HASH = true
|
||||
VITE_HISTORY_BASE_URL = "/"
|
||||
|
||||
# 应用名称
|
||||
VITE_APP_NAME = "Core Network EMS"
|
||||
VITE_APP_NAME = "Core Network OMC"
|
||||
|
||||
# 应用标识
|
||||
VITE_APP_CODE = "CN EMS"
|
||||
VITE_APP_CODE = "OMC"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.240530.1"
|
||||
VITE_APP_VERSION = "2.240801"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
10
README.md
10
README.md
@@ -2,7 +2,6 @@
|
||||
|
||||
## 简介
|
||||
|
||||
- 系统布局使用 [@ant-design-vue/pro-layout](https://github.com/vueComponent/pro-components)
|
||||
- 图标来源 [@ant-design/icons-vue](https://ant.design/components/icon)
|
||||
- 菜单图标使用自定义 iconfont `font_8d5l8fzk5b87iudi.js`图标文件
|
||||
|
||||
@@ -11,7 +10,7 @@
|
||||
```text
|
||||
Jenkins: http://192.168.2.166:3185/
|
||||
Nginx: http://192.168.2.166:3188/#/index
|
||||
后端暴露端口: http://192.168.2.166:3186 \ http://192.168.2.166:3187
|
||||
后端暴露端口: http://192.168.2.166:33030
|
||||
|
||||
|
||||
新网管:192.168.5.13
|
||||
@@ -73,10 +72,3 @@ https://192.168.5.27:31325/#/workloads?namespace=default
|
||||
```text
|
||||
eyJhbGciOiJSUzI1NiIsImtpZCI6ImZFVUhIb1puLW04M1dfSUYyRU8zWlZueXBpNUh4T0hTRVlzU19jNlVGQ0kifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLW44ZzRtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI2M2NmYjAyNS01ZmQ0LTQ0ZTgtOTdiNC0yYWRiYWIxNzc5M2MiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.R3GRygFOjngTj-mEMBAHDeBxm3lpsXZYvC6cdTxByONtLrcMXDebwNVeKtAZ1V9qh2OrjD8n9CIygjULGPdfV6S520vjMh7Oa2q68nOyW49DNWQyYD8xLo-dQ6sX07fI7X_I3H35YUWW80jJAXjJawqIGXBSMG5intlo4tLTUSXmjCfhoQvFsgeRWu0j76pDvhMAvLPcgEXfTCi9tyL3yqJBIKONcKwmMlJeaKSR3pQk3KiibqrBO0MZclRozpke6J0ulfzTemwDDyCqBZmLsRPZ2yDd5hVBIJ9bHEcK0a25NmSFFzmd8XWQPZwg3Y4IbbY-8UhByGq0p9xS-7pGCQ
|
||||
```
|
||||
|
||||
```ssh
|
||||
# https://blog.csdn.net/m0_54706625/article/details/129721121
|
||||
sudo chmod 700 -/.ssh/
|
||||
sudo chmod 700 /home/mask/.ssh #这个尤其容易忽视掉,我就是从这个坑里爬出来。有木有很高兴呀!
|
||||
sudo chmod 600 ~/.ssh/authorized_keys
|
||||
```
|
||||
|
||||
25
package.json
25
package.json
@@ -14,30 +14,31 @@
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@antv/g6": "~4.8.24",
|
||||
"@codemirror/lang-javascript": "^6.2.1",
|
||||
"@codemirror/lang-javascript": "^6.2.2",
|
||||
"@codemirror/lang-yaml": "^6.1.1",
|
||||
"@codemirror/merge": "^6.6.1",
|
||||
"@codemirror/merge": "^6.6.3",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@tato30/vue-pdf": "^1.9.6",
|
||||
"@vueuse/core": "~10.9.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"@tato30/vue-pdf": "~1.9.7",
|
||||
"@vueuse/core": "~10.10.1",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"ant-design-vue": "^3.2.20",
|
||||
"antdv-pro-layout": "^3.2.6",
|
||||
"antdv-pro-layout": "~3.3.5",
|
||||
"antdv-pro-modal": "^3.1.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"dayjs": "^1.11.11",
|
||||
"echarts": "~5.5.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"intl-tel-input": "~22.0.2",
|
||||
"intl-tel-input": "~23.0.12",
|
||||
"js-base64": "^3.7.7",
|
||||
"js-cookie": "^3.0.5",
|
||||
"localforage": "^1.10.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"p-queue": "^8.0.1",
|
||||
"p-queue": "~8.0.1",
|
||||
"pinia": "^2.1.7",
|
||||
"vue": "~3.3.13",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-router": "^4.3.2",
|
||||
"vue-router": "^4.4.0",
|
||||
"vue3-smooth-dnd": "^0.0.6",
|
||||
"xlsx": "~0.18.5"
|
||||
},
|
||||
@@ -46,12 +47,12 @@
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"less": "^4.2.0",
|
||||
"typescript": "~5.4.5",
|
||||
"unplugin-vue-components": "~0.26.0",
|
||||
"vite": "~5.2.10",
|
||||
"vite": "~5.3.1",
|
||||
"vite-plugin-compression": "~0.5.1",
|
||||
"vue-tsc": "~1.8.27"
|
||||
"vue-tsc": "~2.0.22"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
*/
|
||||
(function () {
|
||||
// host = ip:port
|
||||
const host = '192.168.8.100:33030';
|
||||
|
||||
// const host = '192.168.8.100:33030';
|
||||
const host = `${window.location.hostname}:33030`;
|
||||
|
||||
// Service Address
|
||||
sessionStorage.setItem('baseUrl', `http://${host}`);
|
||||
// websocket Address
|
||||
|
||||
11
src/App.vue
11
src/App.vue
@@ -11,8 +11,8 @@ import useAppStore from '@/store/modules/app';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { t, currentLocale } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
dayjs.extend(advancedFormat)
|
||||
|
||||
dayjs.extend(advancedFormat);
|
||||
dayjs.locale('zh-cn'); // 默认中文
|
||||
usePrimaryColor(); // 载入用户自定义主题色
|
||||
|
||||
@@ -52,10 +52,11 @@ console.info(
|
||||
</ConfigProvider>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
<style lang="css">
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body .ant-pro-basicLayout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -63,10 +64,6 @@ body .ant-pro-basicLayout {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.ant-pro-sider {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.slide-left-enter-active,
|
||||
.slide-left-leave-active,
|
||||
.slide-right-enter-active,
|
||||
|
||||
@@ -18,7 +18,7 @@ export async function getParamConfigTopTab(neType: string) {
|
||||
url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/param_config`,
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: `SELECT top_display,top_tag,method FROM param_config WHERE ne_type = '${neType}'`,
|
||||
SQL: `SELECT id,top_display,top_tag,method FROM param_config WHERE ne_type = '${neType}' ORDER BY id ASC`,
|
||||
},
|
||||
});
|
||||
// 解析数据
|
||||
|
||||
83
src/api/ne/neConfigBackup.ts
Normal file
83
src/api/ne/neConfigBackup.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 网元配置文件备份记录列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listNeConfigBackup(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/config/backup/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元配置文件备份记录修改
|
||||
* @param data 数据 { id, name, remark }
|
||||
* @returns object
|
||||
*/
|
||||
export function updateNeConfigBackup(data: Record<string, any>) {
|
||||
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<string, any>) {
|
||||
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<string, any>) {
|
||||
return request({
|
||||
url: '/ne/config/backup/import',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
@@ -134,6 +134,7 @@ export function saveOAMFile(data: Record<string, any>) {
|
||||
url: `/ne/info/oamFile`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,5 +174,6 @@ export function serviceNeAction(data: Record<string, any>) {
|
||||
url: `/ne/action/service`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,10 +19,24 @@ export function listAMFDataUE(query: Record<string, any>) {
|
||||
* @returns object
|
||||
*/
|
||||
export function delAMFDataUE(ueIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/amf/ue/${ueIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
return request({
|
||||
url: `/neData/amf/ue/${ueIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* AMF-UE会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportAMFDataUE(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/amf/ue/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,10 +19,24 @@ export function listIMSDataCDR(query: Record<string, any>) {
|
||||
* @returns object
|
||||
*/
|
||||
export function delIMSDataCDR(cdrIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/ims/cdr/${cdrIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
return request({
|
||||
url: `/neData/ims/cdr/${cdrIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* IMS-CDR会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportIMSDataCDR(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/ims/cdr/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
42
src/api/neData/mme.ts
Normal file
42
src/api/neData/mme.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询MME-UE会话事件列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listMMEDataUE(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/mme/ue/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* MME-UE会话删除
|
||||
* @param id 信息ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delMMEDataUE(ueIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/mme/ue/${ueIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* MME-UE会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportMMEDataUE(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/mme/ue/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
42
src/api/neData/smf.ts
Normal file
42
src/api/neData/smf.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询SMF-CDR会话事件
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listSMFDataCDR(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/smf/cdr/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SMF-CDR会话删除
|
||||
* @param id 信息ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delSMFDataCDR(cdrIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/smf/cdr/${cdrIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SMF-CDR会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportSMFDataCDR(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/smf/cdr/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
141
src/api/neData/udm_auth.ts
Normal file
141
src/api/neData/udm_auth.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* UDM鉴权用户重载数据
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function resetUDMAuth(neId: string) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listUDMAuth(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/udm/auth/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户信息
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @returns object
|
||||
*/
|
||||
export function getUDMAuth(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${neId}/${imsi}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户新增
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${data.neId}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户批量新增
|
||||
* @param data 鉴权对象
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchAddUDMAuth(data: Record<string, any>, num: number) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${data.neId}/${num}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户修改
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${data.neId}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户删除
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @returns object
|
||||
*/
|
||||
export function delUDMAuth(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${neId}/${imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户批量删除
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchDelUDMAuth(neId: string, imsi: string, num: number) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${neId}/${imsi}/${num}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户导入
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户导出
|
||||
* @param data 数据参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/udm/auth/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
140
src/api/neData/udm_sub.ts
Normal file
140
src/api/neData/udm_sub.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* UDM签约用户重载数据
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function resetUDMSub(neId: string) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listUDMSub(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/udm/sub/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户信息
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @returns object
|
||||
*/
|
||||
export function getUDMSub(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${neId}/${imsi}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户新增
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addUDMSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${data.neId}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户批量新增
|
||||
* @param data 签约对象
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchAddUDMSub(data: Record<string, any>, num: number) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${data.neId}/${num}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户修改
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateUDMSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${data.neId}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户删除
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function delUDMSub(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${neId}/${imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户批量删除
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchDelUDMSub(neId: string, imsi: string, num: number) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${neId}/${imsi}/${num}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户导出
|
||||
* @param data 数据参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportUDMSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/udm/sub/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户导入
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importUDMSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 签约鉴权导出
|
||||
* @param query 查询参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportAuth(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/udm/auth/export',
|
||||
method: 'post',
|
||||
data: query,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入鉴权数据
|
||||
* @param neId 网元ID
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importAuthData(data: FormData) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询鉴权列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listAuth(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/udm/auth/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询重新更新加载全部
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function loadAuth(neId: string) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询鉴权详细
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function getAuth(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${neId}/${imsi}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${data.neId}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${data.neId}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function batchAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${data.neID}/${data.num}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function delAuth(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${neId}/${imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function batchDelAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${data.neID}/${data.imsi}/${data.num}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -25,8 +25,10 @@ export async function listBase5G(query: Record<string, any>) {
|
||||
data.total = rows.length;
|
||||
data.rows = rows;
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
// data.rows =[{"address":"192.168.1.137:38412","id":"217","name":"attach-enb-100000-20","ueNum":0}]
|
||||
// data.rows = [{"address":"192.168.1.137:38412","id":"217","name":"attach-enb-100000-20","ueNum":0}]
|
||||
// data.rows = [{address: "192.168.8.223", id: 257, name: "SmallCell", ueNum: 0}]
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
@@ -21,46 +20,70 @@ export async function listUEInfoBySMF(query: Record<string, any>) {
|
||||
msg: result.msg,
|
||||
};
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
||||
const rows = parseObjLineToHump(result.data.data);
|
||||
data.total = rows.length;
|
||||
data.rows = rows;
|
||||
if (result.code === RESULT_CODE_SUCCESS && result.data) {
|
||||
if (Array.isArray(result.data.data)) {
|
||||
const rows = result.data.data;
|
||||
data.total = rows.length;
|
||||
data.rows = rows;
|
||||
} else {
|
||||
Object.assign(data, result.data);
|
||||
}
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
// data.code = RESULT_CODE_SUCCESS;
|
||||
// data.total = 2;
|
||||
// data.rows = [
|
||||
// {
|
||||
// imsi: 'imsi-460002082101038',
|
||||
// msisdn: 'msisdn-12307550000',
|
||||
// imsi: 'imsi-460000100000090',
|
||||
// msisdn: 'msisdn-12307550090',
|
||||
// pduSessionInfo: [
|
||||
// {
|
||||
// activeTime: '2024-05-08 11:08:22',
|
||||
// activeTime: '2024-06-19 14:35:26',
|
||||
// dnn: 'ims',
|
||||
// ipv4: '10.10.86.2',
|
||||
// ipv6: '',
|
||||
// pduSessionID: 5,
|
||||
// ranN3IP: '192.168.5.100',
|
||||
// sstSD: '1-000001',
|
||||
// tai: '46000-001124',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.14.201',
|
||||
// },
|
||||
// {
|
||||
// activeTime: '2024-05-08 11:08:23',
|
||||
// dnn: 'cmnet',
|
||||
// ipv4: '10.10.86.201',
|
||||
// ipv4: '10.10.48.8',
|
||||
// ipv6: '',
|
||||
// pduSessionID: 6,
|
||||
// ranN3IP: '192.168.5.100',
|
||||
// ranN3IP: '192.168.1.137',
|
||||
// sstSD: '1-000001',
|
||||
// tai: '46000-001124',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.14.201',
|
||||
// upfN3IP: '192.168.1.161',
|
||||
// },
|
||||
// {
|
||||
// activeTime: '2024-06-19 14:35:26',
|
||||
// dnn: 'cmnet',
|
||||
// ipv4: '10.10.48.9',
|
||||
// ipv6: '2001:4860:4860::/64',
|
||||
// pduSessionID: 7,
|
||||
// ranN3IP: '192.168.1.137',
|
||||
// sstSD: '1-000001',
|
||||
// tai: '46000-001124',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.1.161',
|
||||
// },
|
||||
// ],
|
||||
// ratType: 'NR',
|
||||
// },
|
||||
// {
|
||||
// imsi: 'imsi-460602072701180',
|
||||
// msisdn: 'msisdn-123460600080',
|
||||
// pduSessionInfo: [
|
||||
// {
|
||||
// activeTime: '2024-06-19 14:31:09',
|
||||
// dnn: 'cmnet',
|
||||
// ipv4: '10.10.48.4',
|
||||
// ipv6: '',
|
||||
// pduSessionID: 5,
|
||||
// ranN3IP: '192.168.8.223',
|
||||
// sstSD: '1-000001',
|
||||
// tai: '46060-0001',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.1.161',
|
||||
// },
|
||||
// ],
|
||||
// ratType: 'EUTRAN',
|
||||
// },
|
||||
// ];
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 签约列表导出
|
||||
* @param query 查询参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportSub(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/udm/sub/export',
|
||||
method: 'post',
|
||||
data: query,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入签约数据
|
||||
* @param neId 网元ID
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importSubData(data: FormData) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询重新更新加载全部
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function loadSub(neId: string) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询签约列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listSub(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/udm/sub/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询签约详细
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function getSub(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${neId}/${imsi}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改签约
|
||||
* @param data 签约对象
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function updateSub(neId: string, data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${neId}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增签约
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addSub(neID: string, data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${neID}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增新增签约
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function batchAddSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${data.neID}/${data.num}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除签约
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function delSub(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${neId}/${imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除签约
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function batchDelSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${data.neID}/${data.imsi}/${data.num}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { request } from '@/plugins/http-fetch';
|
||||
// 网元抓包PACP 开始
|
||||
export function dumpStart(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tcpdump/start',
|
||||
url: '/trace/tcpdump/start',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
@@ -12,7 +12,7 @@ export function dumpStart(data: Record<string, string>) {
|
||||
// 网元抓包PACP 结束
|
||||
export function dumpStop(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tcpdump/stop',
|
||||
url: '/trace/tcpdump/stop',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
@@ -21,7 +21,7 @@ export function dumpStop(data: Record<string, string>) {
|
||||
// UPF标准版内部抓包
|
||||
export function traceUPF(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tcpdump/traceUPF',
|
||||
url: '/trace/tcpdump/traceUPF',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<template>
|
||||
<a-modal
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:title="t('components.CronModal.title')"
|
||||
:visible="props.visible"
|
||||
:body-style="{ padding: '0 24px' }"
|
||||
:destroy-on-close="true"
|
||||
@cancel="fnCronModal(false)"
|
||||
@ok="fnCronModal(true)"
|
||||
>
|
||||
@@ -31,7 +32,7 @@
|
||||
v-model:value="cronStr"
|
||||
disabled
|
||||
/>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import CronSecond from './components/Second.vue';
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, PropType } from 'vue';
|
||||
const props = defineProps({
|
||||
/**数据 */
|
||||
options: {
|
||||
type: Array,
|
||||
type: Array as PropType<DictType[]>,
|
||||
},
|
||||
/**当前的值对应数据中的项字段 */
|
||||
valueField: {
|
||||
type: String,
|
||||
type: String as PropType<keyof DictType>,
|
||||
default: 'value',
|
||||
},
|
||||
/**当前的值 */
|
||||
@@ -16,7 +16,7 @@ const props = defineProps({
|
||||
default: '',
|
||||
},
|
||||
/**数据默认值,当前值不存在时 */
|
||||
valueOption: {
|
||||
valueDefault: {
|
||||
type: [Number, String],
|
||||
},
|
||||
});
|
||||
@@ -24,13 +24,13 @@ const props = defineProps({
|
||||
/**遍历找到对应值数据项 */
|
||||
const item = computed(() => {
|
||||
if (Array.isArray(props.options) && props.options.length > 0) {
|
||||
let option = (props.options as any[]).find(
|
||||
let option = props.options.find(
|
||||
item => `${item[props.valueField]}` === `${props.value}`
|
||||
);
|
||||
// 数据默认值
|
||||
if (props.valueOption != undefined && !option) {
|
||||
option = (props.options as any[]).find(
|
||||
item => `${item[props.valueField]}` === `${props.valueOption }`
|
||||
if (!option && props.valueDefault != undefined) {
|
||||
option = props.options.find(
|
||||
item => `${item[props.valueField]}` === `${props.valueDefault}`
|
||||
);
|
||||
}
|
||||
return option;
|
||||
@@ -41,14 +41,10 @@ const item = computed(() => {
|
||||
|
||||
<template>
|
||||
<template v-if="item">
|
||||
<a-tag
|
||||
v-if="item.elTagType"
|
||||
:class="item.elTagClass"
|
||||
:color="item.elTagType"
|
||||
>
|
||||
<a-tag v-if="item.tagType" :class="item.tagClass" :color="item.tagType">
|
||||
{{ item.label }}
|
||||
</a-tag>
|
||||
<span v-else :class="item.elTagClass">
|
||||
<span v-else :class="item.tagClass">
|
||||
{{ item.label }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, watchEffect, CSSProperties, computed } from 'vue';
|
||||
import { useDraggable } from '@vueuse/core';
|
||||
const emit = defineEmits(['update:visible', 'ok', 'cancel']);
|
||||
/**于a-modal保持一致 */
|
||||
const props = defineProps({
|
||||
/**是否弹出显示,必传 */
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
/**窗口标题 */
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**窗口宽度 */
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: '520px',
|
||||
},
|
||||
bodyStyle: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
keyboard: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
mask: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
maskClosable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
maskStyle: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
destroyOnClose: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
confirmLoading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
footer: {
|
||||
type: Object as any,
|
||||
},
|
||||
});
|
||||
|
||||
// 对标题进行监听
|
||||
const modalTitleRef = ref<HTMLElement | null>(null);
|
||||
const { x, y, isDragging } = useDraggable(modalTitleRef);
|
||||
|
||||
const startX = ref<number>(0);
|
||||
const startY = ref<number>(0);
|
||||
const startedDrag = ref(false);
|
||||
const transformX = ref(0);
|
||||
const transformY = ref(0);
|
||||
const preTransformX = ref(0);
|
||||
const preTransformY = ref(0);
|
||||
const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 });
|
||||
|
||||
watch([x, y], () => {
|
||||
if (!startedDrag.value) {
|
||||
startX.value = x.value;
|
||||
startY.value = y.value;
|
||||
const bodyRect = document.body.getBoundingClientRect();
|
||||
const titleRectEl = modalTitleRef.value;
|
||||
if (titleRectEl) {
|
||||
const titleRect = titleRectEl.getBoundingClientRect();
|
||||
dragRect.value.right = bodyRect.width - (titleRect.width + 24);
|
||||
dragRect.value.bottom = bodyRect.height - (titleRect.height + 16);
|
||||
}
|
||||
preTransformX.value = transformX.value;
|
||||
preTransformY.value = transformY.value;
|
||||
}
|
||||
startedDrag.value = true;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (!isDragging.value) {
|
||||
startedDrag.value = false;
|
||||
}
|
||||
if (startedDrag.value) {
|
||||
const dragRectX = Math.min(
|
||||
Math.max(dragRect.value.left + 24, x.value),
|
||||
dragRect.value.right
|
||||
);
|
||||
transformX.value = preTransformX.value + dragRectX - startX.value;
|
||||
|
||||
const dragRectY = Math.min(
|
||||
Math.max(dragRect.value.top + 16, y.value),
|
||||
dragRect.value.bottom
|
||||
);
|
||||
transformY.value = preTransformY.value + dragRectY - startY.value;
|
||||
}
|
||||
});
|
||||
|
||||
// 位移
|
||||
const transformStyle = computed<CSSProperties>(() => {
|
||||
return {
|
||||
transform: `translate(${transformX.value}px, ${transformY.value}px)`,
|
||||
};
|
||||
});
|
||||
|
||||
/**监听是否显示,位置还原 */
|
||||
watch(
|
||||
() => props.visible,
|
||||
val => {
|
||||
if (val) {
|
||||
transformX.value = 0;
|
||||
transformY.value = 0;
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
wrapClassName="draggable-modal"
|
||||
:width="props.width"
|
||||
:keyboard="props.keyboard"
|
||||
:mask="props.mask"
|
||||
:mask-closable="props.maskClosable"
|
||||
:visible="props.visible"
|
||||
:confirm-loading="props.confirmLoading"
|
||||
:body-style="props.bodyStyle"
|
||||
:mask-style="props.maskStyle"
|
||||
:destroy-on-close="props.destroyOnClose"
|
||||
:footer="props.footer"
|
||||
@ok="(e:any) => emit('ok', e)"
|
||||
@cancel="(e:any) => emit('cancel', e)"
|
||||
>
|
||||
<template #title>
|
||||
<div
|
||||
ref="modalTitleRef"
|
||||
class="draggable-modal-title"
|
||||
v-text="title"
|
||||
></div>
|
||||
</template>
|
||||
<template #modalRender="{ originVNode }">
|
||||
<div :style="transformStyle">
|
||||
<component :is="originVNode" />
|
||||
</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.draggable-modal {
|
||||
// 穿透选择文字
|
||||
// 给a-modal设置 get-container=".ant-pro-page-container"
|
||||
// 防止跳转显示
|
||||
// &.ant-modal-wrap {
|
||||
// pointer-events: none;
|
||||
// }
|
||||
&-title {
|
||||
width: 100%;
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
141
src/components/GlobalMask/index.vue
Normal file
141
src/components/GlobalMask/index.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, computed } from 'vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useThrottleFn } from '@vueuse/core';
|
||||
import { getConfigKey } from '@/api/system/config';
|
||||
const maskStore = useMaskStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**显示遮罩 */
|
||||
const isVisible = computed(() => !['none', 'lock'].includes(maskStore.type));
|
||||
|
||||
// 用户无操作一段时间后进行锁屏
|
||||
function idleTimeout(time: number, callback: Function) {
|
||||
if (time === 0) return;
|
||||
let timeoutId: any;
|
||||
let idleTime = 0;
|
||||
function resetIdleTime() {
|
||||
idleTime = 0;
|
||||
}
|
||||
// 监听用户活动事件
|
||||
document.addEventListener('mousemove', useThrottleFn(resetIdleTime, 1000));
|
||||
document.addEventListener('keydown', useThrottleFn(resetIdleTime, 1000));
|
||||
document.addEventListener('click', useThrottleFn(resetIdleTime, 1000));
|
||||
// 定时检查用户是否长时间无操作
|
||||
timeoutId = setInterval(() => {
|
||||
idleTime += 1000;
|
||||
if (idleTime >= time) {
|
||||
clearTimeout(timeoutId);
|
||||
callback();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/**组件实例挂载之后调用 */
|
||||
onMounted(() => {
|
||||
// 本地锁定类型设置;
|
||||
maskStore.handleMaskType(maskStore.type);
|
||||
getConfigKey('sys.lockTime')
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
maskStore.lockTimeout = +res.data;
|
||||
}
|
||||
maskStore.handleMaskType(maskStore.type);
|
||||
// 是锁屏的调整到页面
|
||||
if (maskStore.type === 'lock') {
|
||||
maskStore.handleMaskType('lock');
|
||||
router.push({ name: 'LockScreen', query: { redirect: route.path } });
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// 无操作x秒后跳转锁屏
|
||||
idleTimeout(maskStore.lockTimeout * 1000, () => {
|
||||
if (route.name === 'LockScreen') return;
|
||||
maskStore.handleMaskType('lock');
|
||||
router.push({ name: 'LockScreen', query: { redirect: route.path } });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**组件实例被卸载之后调用 */
|
||||
onUnmounted(() => {});
|
||||
</script>
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="isVisible"
|
||||
get-container="#app"
|
||||
:footer="null"
|
||||
:zIndex="1008"
|
||||
:closable="false"
|
||||
:keyboard="false"
|
||||
:centered="true"
|
||||
:maskClosable="false"
|
||||
:maskStyle="{
|
||||
backdropFilter: 'blur(10px)',
|
||||
WebkitBackdropFilter: 'blur(10px)',
|
||||
}"
|
||||
wrapClassName="lock-screen"
|
||||
:wrap-style="{
|
||||
background: 'rgba(0, 0, 0, 0.85)',
|
||||
}"
|
||||
>
|
||||
<!-- 锁屏-OMC重启升级 -->
|
||||
<div class="lock-screen_reload" v-if="maskStore.type === 'reload'">
|
||||
<LoadingOutlined style="font-size: 56px" />
|
||||
<div class="text">
|
||||
{{ t('components.LockScreen.backReload') }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{ t('components.LockScreen.backReload2') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 锁屏-OMC系统重置 -->
|
||||
<div class="lock-screen_reload" v-if="maskStore.type === 'reset'">
|
||||
<LoadingOutlined style="font-size: 56px" />
|
||||
<div class="text">
|
||||
{{ t('components.LockScreen.systemReset') }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{ t('components.LockScreen.systemReset2') }}
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.lock-screen_reload {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
|
||||
color: #fff;
|
||||
|
||||
& .text {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
& .desc {
|
||||
margin-top: 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.lock-screen {
|
||||
.ant-modal-content {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,230 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, toRaw, onMounted, onUnmounted } from 'vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { message } from 'ant-design-vue/lib';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
import { getConfigKey } from '@/api/system/config';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { computed } from 'vue';
|
||||
const lockedStore = useLockedStore();
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
|
||||
const password = ref('');
|
||||
/**设置定时器ID */
|
||||
let timeoutDuration = 10 * 60 * 1000; // 设置超时时间为10分钟,单位为毫秒
|
||||
let timeoutId: any = null;
|
||||
|
||||
// 超时锁屏
|
||||
function resetTimeout() {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
timeoutId = setTimeout(() => {
|
||||
lockedStore.fnLock('lock');
|
||||
}, timeoutDuration);
|
||||
}
|
||||
|
||||
/**解锁 */
|
||||
function handleUnlock() {
|
||||
let lockFrom: any = {};
|
||||
lockFrom.username = userStore.userName;
|
||||
lockFrom.password = password.value;
|
||||
userStore.fnLogin(toRaw(lockFrom)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('components.LockScreen.validSucc'), 3);
|
||||
password.value = '';
|
||||
lockedStore.fnLock('none');
|
||||
} else {
|
||||
message.error(t('components.LockScreen.validError'), 3);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**返回登录界面 */
|
||||
function backLogin() {
|
||||
lockedStore.fnLock('none');
|
||||
userStore.fnLogOut().finally(() => router.push({ name: 'Login' }));
|
||||
}
|
||||
|
||||
const isLocked = computed(() => lockedStore.type !== 'none');
|
||||
|
||||
onMounted(() => {
|
||||
// 本地锁定类型设置;
|
||||
lockedStore.fnLock(lockedStore.type);
|
||||
// getConfigKey('sys.lockTime')
|
||||
// .then(res => {
|
||||
// if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
// lockedStore.lockTimeout = res.data;
|
||||
// timeoutDuration = res.data * 1000;
|
||||
// }
|
||||
// // 本地锁定类型设置
|
||||
// lockedStore.fnLock(lockedStore.type);
|
||||
// })
|
||||
// .finally(() => {
|
||||
// if (timeoutDuration !== 0) {
|
||||
// resetTimeout();
|
||||
// // 监听用户的操作,重置超时时间
|
||||
// window.addEventListener('mousemove', resetTimeout);
|
||||
// window.addEventListener('keydown', resetTimeout);
|
||||
// }
|
||||
// });
|
||||
});
|
||||
|
||||
/**组件实例被卸载之后调用 */
|
||||
onUnmounted(() => {
|
||||
// if (timeoutId) {
|
||||
// clearTimeout(timeoutId);
|
||||
// }
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="isLocked"
|
||||
get-container="#app"
|
||||
:footer="null"
|
||||
:zIndex="1008"
|
||||
:closable="false"
|
||||
:keyboard="false"
|
||||
:centered="true"
|
||||
:maskClosable="false"
|
||||
:maskStyle="{
|
||||
backdropFilter: 'blur(10px)',
|
||||
WebkitBackdropFilter: 'blur(10px)',
|
||||
}"
|
||||
wrapClassName="lock-screen"
|
||||
:wrap-style="{
|
||||
background: 'rgba(0, 0, 0, 0.85)',
|
||||
}"
|
||||
>
|
||||
<!-- 锁屏-登录 -->
|
||||
<div class="lock-screen_login" v-if="lockedStore.type === 'lock'">
|
||||
<div class="lock-screen_login-user">
|
||||
<a-avatar
|
||||
shape="circle"
|
||||
:size="100"
|
||||
:src="userStore.getAvatar"
|
||||
:alt="userStore.userName"
|
||||
></a-avatar>
|
||||
<span class="nick">
|
||||
{{ userStore.nickName }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="lock-screen_login-from">
|
||||
<a-input-group compact>
|
||||
<a-input
|
||||
type="password"
|
||||
v-model:value="password"
|
||||
:placeholder="t('components.LockScreen.inputPlacePwd')"
|
||||
:maxlength="32"
|
||||
style="width: calc(100% - 50px)"
|
||||
@keyup.enter="handleUnlock"
|
||||
/>
|
||||
<a-button type="primary" @click="handleUnlock">
|
||||
<LoginOutlined />
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
<a-button type="text" class="logout" @click="backLogin">
|
||||
{{ t('components.LockScreen.backLogin') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 锁屏-OMC重启升级 -->
|
||||
<div class="lock-screen_reload" v-if="lockedStore.type === 'reload'">
|
||||
<LoadingOutlined style="font-size: 56px" />
|
||||
<div class="text">
|
||||
{{ t('components.LockScreen.backReload') }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{ t('components.LockScreen.backReload2') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 锁屏-OMC系统重置 -->
|
||||
<div class="lock-screen_reload" v-if="lockedStore.type === 'reset'">
|
||||
<LoadingOutlined style="font-size: 56px" />
|
||||
<div class="text">
|
||||
{{ t('components.LockScreen.systemReset') }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{ t('components.LockScreen.systemReset2') }}
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.lock-screen_login {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
|
||||
&-user {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.nick {
|
||||
font-size: 28px;
|
||||
max-width: 164px;
|
||||
white-space: nowrap;
|
||||
text-align: start;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&-from {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
width: 256px;
|
||||
margin-top: 30px;
|
||||
|
||||
.logout {
|
||||
margin-top: 8px;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
|
||||
&:hover {
|
||||
color: var(--ant-primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lock-screen_reload {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
|
||||
color: #fff;
|
||||
|
||||
& .text {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
& .desc {
|
||||
margin-top: 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.lock-screen {
|
||||
.ant-modal-content {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -22,7 +22,7 @@ const props = defineProps({
|
||||
/**窗口单行字符数 */
|
||||
cols: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
default: 120,
|
||||
},
|
||||
/**窗口行数 */
|
||||
rows: {
|
||||
|
||||
@@ -35,19 +35,22 @@ const props = defineProps({
|
||||
|
||||
/**弹框关闭事件 */
|
||||
function fnModalClose() {
|
||||
if(props.loading) return
|
||||
if (props.loading) return;
|
||||
emit('close');
|
||||
}
|
||||
|
||||
/**上传前检查或转换压缩 */
|
||||
function fnBeforeUpload(file: FileType) {
|
||||
if (props.loading) return false;
|
||||
// 检查文件大小
|
||||
if (props.size > 0) {
|
||||
// 检查文件大小
|
||||
if (props.size > 0) {
|
||||
const fileSize = file.size;
|
||||
const isLtM = fileSize / 1024 / 1024 < props.size;
|
||||
if (!isLtM) {
|
||||
message.error(`${t('components.UploadModal.allowFilter')} ${props.size}MB`, 3);
|
||||
message.error(
|
||||
`${t('components.UploadModal.allowFilter')} ${props.size}MB`,
|
||||
3
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -56,7 +59,10 @@ function fnBeforeUpload(file: FileType) {
|
||||
const fileName = file.name;
|
||||
const isAllowType = props.ext.some(v => fileName.endsWith(v));
|
||||
if (!isAllowType) {
|
||||
message.error(`${t('components.UploadModal.onlyAllow')} ${props.ext.join('、')}`, 3);
|
||||
message.error(
|
||||
`${t('components.UploadModal.onlyAllow')} ${props.ext.join('、')}`,
|
||||
3
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -65,19 +71,20 @@ function fnBeforeUpload(file: FileType) {
|
||||
|
||||
/**上传请求发出 */
|
||||
function fnUpload(up: UploadRequestOption) {
|
||||
emit('upload', up.file)
|
||||
emit('upload', up.file);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="500px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:confirm-loading="props.loading"
|
||||
:footer="null"
|
||||
:footer="false"
|
||||
@cancel="fnModalClose"
|
||||
>
|
||||
<a-space :size="8" direction="vertical" style="width: 100%">
|
||||
@@ -93,20 +100,26 @@ function fnUpload(up: UploadRequestOption) {
|
||||
<p class="ant-upload-drag-icon">
|
||||
<inbox-outlined></inbox-outlined>
|
||||
</p>
|
||||
<p class="ant-upload-text">{{t('components.UploadModal.uploadTip')}}</p>
|
||||
<p class="ant-upload-text">
|
||||
{{ t('components.UploadModal.uploadTip') }}
|
||||
</p>
|
||||
<p class="ant-upload-hint">
|
||||
<div v-if="props.size > 0">
|
||||
{{t('components.UploadModal.allowSize')}} {{ props.size }} MB
|
||||
</div>
|
||||
<div v-if="props.ext.length > 0">
|
||||
{{t('components.UploadModal.allowFormat')}} {{ props.ext.join('、') }}
|
||||
|
||||
</div>
|
||||
<template v-if="props.size > 0">
|
||||
<div>
|
||||
{{ t('components.UploadModal.allowSize') }} {{ props.size }} MB
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="props.ext.length > 0">
|
||||
<div>
|
||||
{{ t('components.UploadModal.allowFormat') }}
|
||||
{{ props.ext.join('、') }}
|
||||
</div>
|
||||
</template>
|
||||
</p>
|
||||
</a-upload-dragger>
|
||||
<slot></slot>
|
||||
</a-space>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**管理员-系统指定角色KEY */
|
||||
export const ADMIN_ROLE_KEY = 'admin';
|
||||
/**系统管理员-系统指定角色KEY */
|
||||
export const ADMIN_ROLE_KEY = 'system';
|
||||
|
||||
/**管理员-系统指定权限 */
|
||||
/**系统管理员-系统指定权限 */
|
||||
export const ADMIN_PERMISSION = '*:*:*';
|
||||
|
||||
@@ -10,8 +10,11 @@ export const CACHE_LOCAL_PRIMARY_COLOR = 'cache:local:primaryColor';
|
||||
/**本地缓存-多语言 */
|
||||
export const CACHE_LOCAL_I18N = 'cache:local:i18n';
|
||||
|
||||
/**本地缓存-锁屏设置 */
|
||||
export const CACHE_LOCAL_LOCK = 'cache:local:Lock';
|
||||
/**本地缓存-遮罩设置 */
|
||||
export const CACHE_LOCAL_MASK = 'cache:local:mask';
|
||||
|
||||
/**本地缓存-锁屏密码 */
|
||||
export const CACHE_LOCAL_LOCK_PASSWD = 'cache:local:lock:passwd';
|
||||
|
||||
/**数据缓存表-表格排序 */
|
||||
export const CACHE_DB_TABLE_DND = 'tbl_dnd';
|
||||
|
||||
@@ -20,7 +20,7 @@ export const NE_TYPE_LIST = [
|
||||
|
||||
/**
|
||||
* 网元拓展包列表,默认顺序
|
||||
* IMS-adb/rtproxy/mf
|
||||
* UDM-adb
|
||||
* IMS-adb/kvdb/rtproxy/mf
|
||||
* UDM-adb/kvdb
|
||||
*/
|
||||
export const NE_EXPAND_LIST = ['ADB', 'RTPROXY', 'MF'];
|
||||
export const NE_EXPAND_LIST = ['ADB', 'KVDB', 'RTPROXY', 'MF'];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { onBeforeMount } from 'vue';
|
||||
import { ConfigProvider } from 'ant-design-vue/lib';
|
||||
import { ConfigProvider, message } from 'ant-design-vue/lib';
|
||||
import { CACHE_LOCAL_PRIMARY_COLOR } from '@/constants/cache-keys-constants';
|
||||
import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||
|
||||
@@ -8,6 +8,7 @@ import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||
*/
|
||||
export const usePrimaryColor = () => {
|
||||
onBeforeMount(() => {
|
||||
message.config({ top: '100px' }); // 全局配置消息距离顶部的位置
|
||||
changePrimaryColor(getLocalColor());
|
||||
});
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ export default {
|
||||
updateTime: 'Update Time',
|
||||
remark: 'Remark',
|
||||
description: 'Description',
|
||||
operate: 'Operation',
|
||||
operate: 'More Action',
|
||||
operateOk: 'Operation Successful!',
|
||||
operateErr: 'Operation Failed!',
|
||||
copyText: "Copy",
|
||||
@@ -130,7 +130,7 @@ export default {
|
||||
onlyAllow:'Only supports upload file formats',
|
||||
},
|
||||
LockScreen: {
|
||||
inputPlacePwd:'Please enter login password',
|
||||
inputPlacePwd:'Lock Screen Password',
|
||||
validSucc:'Validation Passed',
|
||||
validError:'Validation Failure',
|
||||
backLogin:'Logout to Relogin',
|
||||
@@ -149,6 +149,7 @@ export default {
|
||||
page403: 'No Access',
|
||||
page404: 'Match Page Not Found',
|
||||
helpDoc: 'System User Documentation',
|
||||
lockScreen: 'Lock Screen',
|
||||
account: {
|
||||
index: "Personal Center",
|
||||
profile: "Personal Info",
|
||||
@@ -185,7 +186,9 @@ export default {
|
||||
},
|
||||
rightContent: {
|
||||
lock: "Lock Screen",
|
||||
lockTip: "Confirmed to perform a lock screen?",
|
||||
lockTip: "Confirmation of the lock screen?",
|
||||
lockPasswd: "Unlock Password",
|
||||
lockPasswdTip: "No password can be set",
|
||||
helpDoc: "System User Documentation",
|
||||
fullscreen: "Full Screen",
|
||||
logout: "Logout",
|
||||
@@ -559,8 +562,6 @@ export default {
|
||||
realTimeDataStart: "Turn on real-time data",
|
||||
realTimeDataStop: "Turn off real-time data",
|
||||
cdrInfo: "CDR Info",
|
||||
neName: "NE name",
|
||||
rmUID: "UID",
|
||||
time: "Time",
|
||||
rowInfo: "Info",
|
||||
type: "Type",
|
||||
@@ -569,19 +570,27 @@ export default {
|
||||
called: "Called",
|
||||
result: "Result",
|
||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||
exportTip: "Do you confirm to export the current query conditions of the CDR data? (Maximum 10,000 items can be exported.)",
|
||||
smfChargingID: 'Charging ID',
|
||||
smfSubscriptionIDData: 'Subscription ID Data',
|
||||
smfSubscriptionIDType: 'Subscription ID Type',
|
||||
smfDataVolumeUplink: 'Data Volume Uplink',
|
||||
smfDataVolumeDownlink: 'Data Volume Downlink',
|
||||
smfDataTotalVolume: 'Data Total Volume',
|
||||
smfDuration: 'Duration',
|
||||
smfInvocationTime: 'Invocation Time',
|
||||
},
|
||||
ue: {
|
||||
eventType: "Event Type",
|
||||
realTimeDataStart: "Turn on real-time data",
|
||||
realTimeDataStop: "Turn off real-time data",
|
||||
ueInfo: "UE Info",
|
||||
neName: "NE name",
|
||||
rmUID: "UID",
|
||||
time: "Time",
|
||||
rowInfo: "Info",
|
||||
result: "Result",
|
||||
resultOk: "Successes",
|
||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||
exportTip: "Do you confirm to export the event data of the current query condition? (Maximum 10,000 items can be exported.)",
|
||||
},
|
||||
},
|
||||
ne: {
|
||||
@@ -659,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: {
|
||||
@@ -704,7 +712,7 @@ export default {
|
||||
uploadTitle: "Update Software",
|
||||
upload: "Upload",
|
||||
uploadNotFile: "No software files uploaded",
|
||||
uploadBatch: "Update Softwares",
|
||||
uploadBatch: "Batch Upload",
|
||||
uploadBatchMax: "Multiple packages can be uploaded, with up to {txt} selected at the same time.",
|
||||
uploadFileName: "Parses file names in the format of: amf-r2.240x.xx-xxx",
|
||||
name: "File Name",
|
||||
@@ -739,8 +747,9 @@ export default {
|
||||
upgradeBatch: "Batch Upgrade",
|
||||
upgradeBatchTip: "Do you perform new version upgrades on checked records?",
|
||||
upgradeNotNewVer: 'No new version found',
|
||||
upgradeOMCVer: 'Rejection of batch operation upgrades OMC',
|
||||
upgradeDone: 'Update complete, service being reloaded',
|
||||
upgradeFail: 'The update failed, check if the service terminal environment is available!',
|
||||
upgradeFail: 'The update fails, please check whether the software file exists and whether the service terminal environment is available!',
|
||||
upgradeModal: 'Network Element Version Updates',
|
||||
},
|
||||
neLicense: {
|
||||
@@ -756,19 +765,17 @@ export default {
|
||||
licensePath: "License File",
|
||||
licensePathTip: "Please upload license file",
|
||||
upload: 'Upload',
|
||||
uploadBatch: "Upload License",
|
||||
uploadFile: "Upload License",
|
||||
uploadChangeOk: 'Network Element renewed license successfully and is being calibrated in the background!',
|
||||
uploadChangeFail: "Some network elements failed to update the license, please check whether the service terminal environment is available!",
|
||||
},
|
||||
neConfPara5G: {
|
||||
save: 'Save',
|
||||
reload: 'Reload',
|
||||
title: 'Save Info',
|
||||
sync: 'Sync to NE',
|
||||
syncNe: 'Select NE',
|
||||
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: {
|
||||
reloadPara5G: 'Reload',
|
||||
stepPrev: 'Previous',
|
||||
stepPrevTip: 'Confirm that you want to abandon the current change and return to the previous step?',
|
||||
stepNext: 'Next',
|
||||
@@ -861,8 +868,8 @@ export default {
|
||||
checkDel: 'Check Delete',
|
||||
batchAddText: 'Batch Add',
|
||||
batchDelText: 'Batch Delete',
|
||||
enable:'Enable',
|
||||
disable:'Disable',
|
||||
enable:'Enabled',
|
||||
disable:'Disabled',
|
||||
startIMSI: 'Start IMSI',
|
||||
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
||||
imsiTip1: 'MCC=Mobile Country Code, consisting of three digits.',
|
||||
@@ -875,7 +882,8 @@ export default {
|
||||
micoTip: 'Signed MICO business flag bits',
|
||||
rfspTip:'RFSP index, in NG-RAN, the index of a specific RRM configuration, parameter between 0 and 127',
|
||||
ueTypeTip: 'Operator-defined subscriber UE Usage Type, integer, parameter between 0 and 127',
|
||||
epsFlagTip: 'Enable or disable 4G EPS service',
|
||||
cnFlag: 'Whether to enable 5G Core Network service',
|
||||
epsFlagTip: 'Whether to enable 4G EPS service',
|
||||
contextIdTip: 'To sign up for an APN Context ID, you must select it from the APN Context list.',
|
||||
apnContextTip: 'The list of APNs available to the phone, up to six, is defined in the HSS.',
|
||||
staticIpTip: 'Specify the static IP address to be used by the cell phone user to access the Internet, and "-" means dynamic IP address is used.',
|
||||
@@ -1357,7 +1365,7 @@ export default {
|
||||
status0: "Failures",
|
||||
status1: "Active",
|
||||
createTime: "Time",
|
||||
costTime: "Time Consumption",
|
||||
costTime: "Time Lap",
|
||||
viewLog: "Scheduling log Info",
|
||||
delTip: "Are you sure you want to delete the scheduling log entry with the number [{num}]?",
|
||||
delOk: "Deleted Successfully",
|
||||
@@ -1598,7 +1606,7 @@ export default {
|
||||
loginIp: 'Login Address',
|
||||
loginTime: 'Login Time',
|
||||
status: 'Status',
|
||||
userNameTip:'The account cannot start with a number and can contain uppercase and lowercase letters, numbers, and no less than 5 digits',
|
||||
userNameTip:'The account number can only contain strings of uppercase letters, lowercase letters and numbers with a minimum length of 6 digits',
|
||||
passwdTip:'The password should contain at least uppercase and lowercase letters, numbers, special symbols, and no less than 6 digits',
|
||||
nickNameTip:'Nicknames no less than 2 digits',
|
||||
emailTip:'Please enter the correct email address',
|
||||
@@ -1762,7 +1770,7 @@ export default {
|
||||
className:'Department Name',
|
||||
classId:'Department Number',
|
||||
classSort:'Department Sorting',
|
||||
status:'Position Status',
|
||||
status:'Department Status',
|
||||
createTime:'Creation Time',
|
||||
highClass:'Higher Office',
|
||||
emailTip:'Please input the correct email address',
|
||||
@@ -1793,13 +1801,13 @@ export default {
|
||||
operate:{
|
||||
operId:'Log ID',
|
||||
moduleName:'Module Name',
|
||||
workType:'Business Type',
|
||||
workType:'Operation',
|
||||
operUser:'Operator',
|
||||
requestMe:'Request Method',
|
||||
host:'Request Host',
|
||||
operStatus:'Status',
|
||||
operDate:'Time',
|
||||
useTime:'Time Consumption',
|
||||
useTime:'Time Lap',
|
||||
logInfo:'Operation Log Information',
|
||||
delSure:'Are you sure to delete the data item with access number [{ids}]?',
|
||||
delAllSure:'Confirm to clear all login log data items?',
|
||||
@@ -1934,6 +1942,7 @@ export default {
|
||||
stepNeInfoStepNext: 'Confirm that you want to proceed to the next step to configure the parameters of the network element?',
|
||||
stepPara5GTitle: "Configuration Parameter",
|
||||
stepPara5GDesc: "Setting network element global parameter information",
|
||||
savePara5GOk: 'Save Success!',
|
||||
stepPara5GStepPrev: 'Confirm that you want to abandon the current change and return to the previous step?',
|
||||
stepPara5GStepNext: 'Confirm that you want to proceed to the next step for the network element service installation?',
|
||||
stepInstallTitle: "Service Install",
|
||||
|
||||
@@ -57,7 +57,7 @@ export default {
|
||||
updateTime: '更新时间',
|
||||
remark: '备注',
|
||||
description: '说明',
|
||||
operate: '操作',
|
||||
operate: '更多操作',
|
||||
operateOk: '操作成功!',
|
||||
operateErr: '操作失败!',
|
||||
copyText: "复制",
|
||||
@@ -130,7 +130,7 @@ export default {
|
||||
onlyAllow:'只支持上传文件格式',
|
||||
},
|
||||
LockScreen: {
|
||||
inputPlacePwd:'请输入登录密码',
|
||||
inputPlacePwd:'请输入锁屏密码',
|
||||
validSucc:'校验通过',
|
||||
validError:'校验失败',
|
||||
backLogin:'退出并重新登录',
|
||||
@@ -149,6 +149,7 @@ export default {
|
||||
page403: '没有访问权限',
|
||||
page404: '找不到匹配页面',
|
||||
helpDoc: '系统使用文档',
|
||||
lockScreen: '锁屏',
|
||||
account: {
|
||||
index: "个人中心",
|
||||
profile: "个人信息",
|
||||
@@ -186,6 +187,8 @@ export default {
|
||||
rightContent: {
|
||||
lock: "锁屏",
|
||||
lockTip: "确认要进行锁屏吗?",
|
||||
lockPasswd: "解锁密码",
|
||||
lockPasswdTip: "可不设置密码",
|
||||
helpDoc: "系统使用文档",
|
||||
fullscreen: "全屏显示",
|
||||
logout: "退出登录",
|
||||
@@ -559,8 +562,6 @@ export default {
|
||||
realTimeDataStart: "开启实时数据",
|
||||
realTimeDataStop: "关闭实时数据",
|
||||
cdrInfo: "CDR信息",
|
||||
neName: "网元名称",
|
||||
rmUID: "资源标识",
|
||||
time: "记录时间",
|
||||
rowInfo: "记录信息",
|
||||
type: "记录类型",
|
||||
@@ -569,19 +570,27 @@ export default {
|
||||
called: "被叫",
|
||||
result: "结果",
|
||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||
exportTip: "确认导出当前查询条件的话单数据吗?(导出最大支持一万条)",
|
||||
smfChargingID: '计费ID',
|
||||
smfSubscriptionIDData: '订阅 ID 数据',
|
||||
smfSubscriptionIDType: '订阅 ID 类型',
|
||||
smfDataVolumeUplink: '数据量上行链路',
|
||||
smfDataVolumeDownlink: '数据量下行链路',
|
||||
smfDataTotalVolume: '数据总量',
|
||||
smfDuration: '持续时间',
|
||||
smfInvocationTime: '调用时间',
|
||||
},
|
||||
ue: {
|
||||
eventType: "事件类型",
|
||||
realTimeDataStart: "开启实时数据",
|
||||
realTimeDataStop: "关闭实时数据",
|
||||
ueInfo: "UE信息",
|
||||
neName: "网元名称",
|
||||
rmUID: "资源标识",
|
||||
rowInfo: "记录信息",
|
||||
time: "记录时间",
|
||||
result: "结果",
|
||||
resultOk: "成功",
|
||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||
exportTip: "确认导出当前查询条件的事件数据吗?(导出最大支持一万条)",
|
||||
},
|
||||
},
|
||||
ne: {
|
||||
@@ -659,9 +668,8 @@ export default {
|
||||
local:'本地文件',
|
||||
localUpload:'本地上传',
|
||||
exportTip:'确认要导出网元配置信息到文件?',
|
||||
exportMsg:'导出成功,请到【备份管理】进行下载',
|
||||
filePlease: "请上传文件",
|
||||
fileNamePlease: '请选择服务器文件',
|
||||
exportMsg:'导出网元配置信息到文件成功',
|
||||
pathPlease: '未发现文件',
|
||||
},
|
||||
},
|
||||
neHost: {
|
||||
@@ -704,7 +712,7 @@ export default {
|
||||
uploadTitle: "上传软件",
|
||||
upload: "上传",
|
||||
uploadNotFile: "未上传软件文件",
|
||||
uploadBatch: "上传软件包",
|
||||
uploadBatch: "批量上传",
|
||||
uploadBatchMax: "可上传多个软件包,最多同时选择{txt}个。",
|
||||
uploadFileName: "解析文件名称格式如: amf-r2.240x.xx-xxx",
|
||||
name: "文件名",
|
||||
@@ -739,8 +747,9 @@ export default {
|
||||
upgradeBatch: "批量更新",
|
||||
upgradeBatchTip: "对勾选的记录进行新版本升级吗?",
|
||||
upgradeNotNewVer: '没有发现新版本',
|
||||
upgradeOMCVer: '拒绝批量操作升级OMC',
|
||||
upgradeDone: '更新完成,服务正在重载',
|
||||
upgradeFail: '更新失败,请检查服务终端环境是否可用!',
|
||||
upgradeFail: '更新失败,请检查软件文件是否存在且服务终端环境是否可用!',
|
||||
upgradeModal: '网元版本更新',
|
||||
},
|
||||
neLicense: {
|
||||
@@ -756,19 +765,17 @@ export default {
|
||||
licensePath: "许可证文件",
|
||||
licensePathTip: "请上传许可证文件",
|
||||
upload: '上传',
|
||||
uploadBatch: "上传许可证",
|
||||
uploadFile: "上传许可证",
|
||||
uploadChangeOk: '网元更新许可证成功,正在后台校验!',
|
||||
uploadChangeFail: "部分网元更新许可证失败,请检查服务终端环境是否可用!",
|
||||
},
|
||||
neConfPara5G: {
|
||||
save: '保存',
|
||||
reload: '刷新',
|
||||
title: '保存信息',
|
||||
sync: '同步到网元',
|
||||
syncNe: '选择网元',
|
||||
syncNeDone: '同步到网元终端完成',
|
||||
saveOk: '保存成功!',
|
||||
neConfigBackup: {
|
||||
name: "名称",
|
||||
downTip: '确认要下载备份文件【{txt}】吗?',
|
||||
title: "修改备份信息 {txt}",
|
||||
},
|
||||
neQuickSetup: {
|
||||
reloadPara5G: '刷新',
|
||||
stepPrev: '上一步',
|
||||
stepPrevTip: '确认要放弃当前变更返回上一步吗?',
|
||||
stepNext: '下一步',
|
||||
@@ -875,7 +882,8 @@ export default {
|
||||
micoTip: '签约的 MICO 业务标志位',
|
||||
rfspTip:'RFSP 索引,在 NG-RAN 中,特定 RRM 配置的索引,参数介于0到127之间',
|
||||
ueTypeTip: '运营商定义的用户 UE Usage Type,整型,参数介于0到127之间',
|
||||
epsFlagTip: '是否开启4G EPS 服务',
|
||||
cnFlag: '是否开启 5G Core Network 服务',
|
||||
epsFlagTip: '是否开启 4G EPS 服务',
|
||||
contextIdTip: '签约APN 上下文ID,必须从APN Context list 中选择。',
|
||||
apnContextTip: '手机可用的APN列表,最多六个,在HSS中定义。',
|
||||
staticIpTip: '指定手机用户上网时使用的静态IP地址,为"-"时表示使用动态IP地址',
|
||||
@@ -1598,7 +1606,7 @@ export default {
|
||||
loginIp: '登录地址',
|
||||
loginTime: '登录时间',
|
||||
status: '用户状态',
|
||||
userNameTip:'账号不能以数字开头,可包含大写小写字母,数字,且不少于5位',
|
||||
userNameTip:'账号只能包含大写字母、小写字母和数字的字符串,长度至少为6位',
|
||||
passwdTip:'密码至少包含大小写字母、数字、特殊符号,且不少于6位',
|
||||
nickNameTip:'昵称不少于2位',
|
||||
emailTip:'请输入正确的邮箱地址',
|
||||
@@ -1762,7 +1770,7 @@ export default {
|
||||
className:'部门名称',
|
||||
classId:'部门编号',
|
||||
classSort:'部门排序',
|
||||
status:'岗位状态',
|
||||
status:'部门状态',
|
||||
createTime:'创建时间',
|
||||
highClass:'上级部门',
|
||||
emailTip:'请输入正确的邮箱地址',
|
||||
@@ -1793,7 +1801,7 @@ export default {
|
||||
operate:{
|
||||
operId:'日志编号',
|
||||
moduleName:'模块名称',
|
||||
workType:'业务类型',
|
||||
workType:'操作类型',
|
||||
operUser:'操作人员',
|
||||
requestMe:'请求方式',
|
||||
host:'请求主机',
|
||||
@@ -1934,6 +1942,7 @@ export default {
|
||||
stepNeInfoStepNext: '确认要下一步进行网元配置参数?',
|
||||
stepPara5GTitle: "网元配置参数",
|
||||
stepPara5GDesc: "设置网元全局参数信息",
|
||||
savePara5GOk: '保存成功!',
|
||||
stepPara5GStepPrev: '确认要放弃当前变更返回上一步吗?',
|
||||
stepPara5GStepNext: '确认要下一步进行网元服务安装吗?',
|
||||
stepInstallTitle: "网元服务安装",
|
||||
|
||||
@@ -4,12 +4,20 @@ import {
|
||||
WaterMark,
|
||||
getMenuData,
|
||||
clearMenuItem,
|
||||
MenuDataItem,
|
||||
type MenuDataItem,
|
||||
} from 'antdv-pro-layout';
|
||||
import RightContent from './components/RightContent.vue';
|
||||
import Tabs from './components/Tabs.vue';
|
||||
import GlobalMask from '@/components/GlobalMask/index.vue';
|
||||
import { scriptUrl } from '@/assets/js/icon_font_8d5l8fzk5b87iudi';
|
||||
import { computed, reactive, watch, onMounted, onUnmounted } from 'vue';
|
||||
import {
|
||||
computed,
|
||||
reactive,
|
||||
watch,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
nextTick,
|
||||
} from 'vue';
|
||||
import useLayoutStore from '@/store/modules/layout';
|
||||
import useRouterStore from '@/store/modules/router';
|
||||
import useTabsStore from '@/store/modules/tabs';
|
||||
@@ -21,6 +29,7 @@ const { proConfig, waterMarkContent } = useLayoutStore();
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { getServerTime } from '@/api';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { parseUrlPath } from '@/plugins/file-static-url';
|
||||
const { t, currentLocale } = useI18n();
|
||||
@@ -159,8 +168,28 @@ function fnLocale(m: MenuDataItem) {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**检查系统名称是否超出范围进行滚动 */
|
||||
function fnCheckAppNameOverflow() {
|
||||
const container: HTMLDivElement | null = document.querySelector('.app-name');
|
||||
if (!container) return;
|
||||
const text: HTMLDivElement | null = container.querySelector('.marquee');
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => appStore.appName,
|
||||
() => nextTick(fnCheckAppNameOverflow)
|
||||
);
|
||||
|
||||
//
|
||||
onMounted(() => {
|
||||
fnCheckAppNameOverflow();
|
||||
fnGetServerTime();
|
||||
useAlarmStore().fnGetActiveAlarmInfo();
|
||||
});
|
||||
@@ -224,12 +253,10 @@ onUnmounted(() => {
|
||||
v-model:selectedKeys="layoutState.selectedKeys"
|
||||
v-model:openKeys="layoutState.openKeys"
|
||||
:menu-data="menuData"
|
||||
:breadcrumb="{ routes: breadcrumb } as any"
|
||||
disable-content-margin
|
||||
:breadcrumb="{ routes: breadcrumb }"
|
||||
v-bind="proConfig"
|
||||
:iconfont-url="scriptUrl"
|
||||
:sider-width="208"
|
||||
:locale="(fnLocale as any)"
|
||||
:locale="fnLocale"
|
||||
>
|
||||
<!--插槽-菜单头-->
|
||||
<template #menuHeaderRender>
|
||||
@@ -246,8 +273,10 @@ onUnmounted(() => {
|
||||
:alt="appStore.appName"
|
||||
:title="appStore.appName"
|
||||
/>
|
||||
<h1 class="title" :title="appStore.appName">
|
||||
{{ appStore.appName }}
|
||||
<h1 class="app-name" :title="appStore.appName">
|
||||
<span class="marquee app-name_scrollable">
|
||||
{{ appStore.appName }}
|
||||
</span>
|
||||
</h1>
|
||||
</template>
|
||||
<template v-if="appStore.logoType === 'brand'">
|
||||
@@ -265,7 +294,7 @@ onUnmounted(() => {
|
||||
<template #headerContentRender></template>
|
||||
|
||||
<!--插槽-顶部右侧-->
|
||||
<template #rightContentRender>
|
||||
<template #headerContentRightRender>
|
||||
<RightContent />
|
||||
</template>
|
||||
|
||||
@@ -300,9 +329,6 @@ onUnmounted(() => {
|
||||
</transition>
|
||||
</RouterView>
|
||||
|
||||
<!-- 锁屏遮罩 -->
|
||||
<LockScreen />
|
||||
|
||||
<!--插槽-内容底部-->
|
||||
<template #footerRender="{ width }">
|
||||
<footer class="footer">
|
||||
@@ -317,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') }}
|
||||
</a-button>
|
||||
<a-button type="link" size="small" @click="fnClickHelpDoc()">
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
v-perms:has="['system:setting:doc']"
|
||||
@click="fnClickHelpDoc()"
|
||||
>
|
||||
{{ t('loayouts.basic.helpDoc') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
@@ -329,6 +361,9 @@ onUnmounted(() => {
|
||||
</footer>
|
||||
</template>
|
||||
</ProLayout>
|
||||
|
||||
<!-- 全局遮罩 -->
|
||||
<GlobalMask />
|
||||
</WaterMark>
|
||||
</template>
|
||||
|
||||
@@ -349,18 +384,40 @@ onUnmounted(() => {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
.app-name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
// text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 130px;
|
||||
width: 148px;
|
||||
> .app-name_scrollable {
|
||||
padding-right: 12px;
|
||||
display: inline-block;
|
||||
animation: scrollable-animation linear 6s infinite both;
|
||||
&::after {
|
||||
content: attr(data-content);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -100%;
|
||||
transition: right 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes scrollable-animation {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(calc(-100% - 12px));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
z-index: 16;
|
||||
margin: 0px;
|
||||
width: auto;
|
||||
margin-top: 52px;
|
||||
margin-top: 32px;
|
||||
&-fixed {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import Modal from 'ant-design-vue/lib/modal/Modal';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import useAlarmStore from '@/store/modules/alarm';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
import { hasPermissions } from '@/plugins/auth-user';
|
||||
import { ref } from 'vue';
|
||||
const { isFullscreen, toggle } = useFullscreen();
|
||||
const { t, changeLocale, optionsLocale } = useI18n();
|
||||
const lockedStore = useLockedStore();
|
||||
const maskStore = useMaskStore();
|
||||
const userStore = useUserStore();
|
||||
const appStore = useAppStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
/**头像展开项点击 */
|
||||
@@ -31,15 +32,24 @@ function fnClick({ key }: MenuInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
/**锁屏确认 */
|
||||
const lockConfirm = ref<boolean>(false);
|
||||
/**锁屏密码 */
|
||||
const lockPasswd = ref<string>('');
|
||||
|
||||
/**锁屏按钮提示 */
|
||||
function fnClickLock() {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('loayouts.rightContent.lockTip'),
|
||||
onOk() {
|
||||
lockedStore.fnLock('lock');
|
||||
},
|
||||
});
|
||||
lockConfirm.value = true;
|
||||
lockPasswd.value = '';
|
||||
maskStore.lockPasswd = '';
|
||||
}
|
||||
|
||||
/**锁屏确认跳转锁屏页面 */
|
||||
function fnClickLockToPage() {
|
||||
lockConfirm.value = false;
|
||||
maskStore.lockPasswd = lockPasswd.value;
|
||||
maskStore.handleMaskType('lock');
|
||||
router.push({ name: 'LockScreen', query: { redirect: route.path } });
|
||||
}
|
||||
|
||||
/**告警数按钮提示跳转 */
|
||||
@@ -65,39 +75,72 @@ function fnChangeLocale(e: any) {
|
||||
|
||||
<template>
|
||||
<a-space :size="12" align="center">
|
||||
<a-button type="text" @click="fnClickAlarm">
|
||||
<a-button type="text" style="color: inherit" @click="fnClickAlarm">
|
||||
<template #icon>
|
||||
<a-badge
|
||||
:count="useAlarmStore().activeAlarmTotal"
|
||||
:overflow-count="99"
|
||||
status="warning"
|
||||
style="color: inherit"
|
||||
>
|
||||
<BellOutlined />
|
||||
</a-badge>
|
||||
</template>
|
||||
</a-button>
|
||||
|
||||
<a-tooltip placement="bottom" v-if="false">
|
||||
<template #title>{{ t('loayouts.rightContent.lock') }}</template>
|
||||
<a-button type="text" @click="fnClickLock">
|
||||
<template #icon>
|
||||
<LockOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<!-- 锁屏操作 -->
|
||||
<span v-perms:has="['system:setting:lock']">
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ t('loayouts.rightContent.lock') }}</template>
|
||||
<a-button type="text" style="color: inherit" @click="fnClickLock()">
|
||||
<template #icon>
|
||||
<LockOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="400"
|
||||
:minHeight="200"
|
||||
:mask-closable="false"
|
||||
v-model:visible="lockConfirm"
|
||||
:title="t('loayouts.rightContent.lockTip')"
|
||||
@ok="fnClickLockToPage()"
|
||||
>
|
||||
<a-space>
|
||||
{{ t('loayouts.rightContent.lockPasswd') }}:
|
||||
<a-input-password
|
||||
v-model:value="lockPasswd"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip
|
||||
:title="t('loayouts.rightContent.lockPasswdTip')"
|
||||
placement="topLeft"
|
||||
>
|
||||
<UnlockOutlined />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input-password>
|
||||
</a-space>
|
||||
</ProModal>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ t('loayouts.rightContent.helpDoc') }}</template>
|
||||
<a-button type="text" @click="fnClickHelpDoc()">
|
||||
<template #icon>
|
||||
<QuestionCircleOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<!-- 用户帮助手册 -->
|
||||
<span v-perms:has="['system:setting:doc']">
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ t('loayouts.rightContent.helpDoc') }}</template>
|
||||
<a-button type="text" style="color: inherit" @click="fnClickHelpDoc()">
|
||||
<template #icon>
|
||||
<QuestionCircleOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ t('loayouts.rightContent.fullscreen') }}</template>
|
||||
<a-button type="text" @click="toggle">
|
||||
<a-button type="text" style="color: inherit" @click="toggle">
|
||||
<template #icon>
|
||||
<FullscreenExitOutlined v-if="isFullscreen" />
|
||||
<FullscreenOutlined v-else />
|
||||
|
||||
@@ -4,7 +4,9 @@ import App from './App.vue';
|
||||
import router from './router';
|
||||
import directive from './directive';
|
||||
import i18n from './i18n';
|
||||
import ProModal from "antdv-pro-modal";
|
||||
import 'antdv-pro-layout/dist/style.css';
|
||||
import 'antdv-pro-modal/dist/style.css';
|
||||
import 'ant-design-vue/dist/antd.variable.min.css';
|
||||
|
||||
const app = createApp(App);
|
||||
@@ -12,5 +14,6 @@ app.use(store);
|
||||
app.use(router);
|
||||
app.use(directive);
|
||||
app.use(i18n);
|
||||
app.use(ProModal);
|
||||
|
||||
app.mount('#app');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Cookies from 'js-cookie';
|
||||
import { TOKEN_COOKIE } from '@/constants/token-constants';
|
||||
import { localRemove, localSet } from '@/utils/cache-local-utils';
|
||||
import { CACHE_LOCAL_LOCK } from '@/constants/cache-keys-constants';
|
||||
import { CACHE_LOCAL_LOCK_PASSWD, CACHE_LOCAL_MASK } from '@/constants/cache-keys-constants';
|
||||
|
||||
/**获取cookis中Token字符串 */
|
||||
export function getToken(): string {
|
||||
@@ -11,11 +11,12 @@ export function getToken(): string {
|
||||
/**设置cookis中Token字符串 */
|
||||
export function setToken(token: string): void {
|
||||
Cookies.set(TOKEN_COOKIE, token);
|
||||
localSet(CACHE_LOCAL_LOCK, 'none');
|
||||
localSet(CACHE_LOCAL_MASK, 'none');
|
||||
}
|
||||
|
||||
/**移除cookis中Token字符串,localStorage中锁屏字符串 */
|
||||
export function removeToken(): void {
|
||||
Cookies.remove(TOKEN_COOKIE);
|
||||
localRemove(CACHE_LOCAL_LOCK);
|
||||
localRemove(CACHE_LOCAL_MASK);
|
||||
localRemove(CACHE_LOCAL_LOCK_PASSWD);
|
||||
}
|
||||
|
||||
@@ -165,8 +165,8 @@ function beforeRequest(options: OptionsType): OptionsType | Promise<any> {
|
||||
}
|
||||
}
|
||||
|
||||
// get请求拼接地址栏参数
|
||||
if (options.method === 'get' && options.params) {
|
||||
// 请求拼接地址栏参数
|
||||
if (options.params) {
|
||||
let paramStr = '';
|
||||
const params = options.params;
|
||||
for (const key in params) {
|
||||
|
||||
@@ -93,6 +93,12 @@ const constantRoutes: RouteRecordRaw[] = [
|
||||
meta: { title: 'router.quickStart' },
|
||||
component: () => import('@/views/system/quick-start/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/lock-screen',
|
||||
name: 'LockScreen',
|
||||
meta: { title: 'router.lockScreen' },
|
||||
component: () => import('@/views/tool/lockScreen/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/redirect',
|
||||
name: 'Redirect',
|
||||
@@ -159,11 +165,15 @@ router.beforeEach(async (to, from, next) => {
|
||||
if (!appStore.loginBackground) {
|
||||
await appStore.fnSysConf();
|
||||
}
|
||||
|
||||
|
||||
// 需要系统引导跳转
|
||||
if (appStore.bootloader && to.path !== '/quick-start') {
|
||||
next({ name: 'QuickStart' });
|
||||
}
|
||||
// 不重复引导
|
||||
if (!appStore.bootloader && to.path === '/quick-start') {
|
||||
next({ name: 'Index' });
|
||||
}
|
||||
|
||||
const token = getToken();
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ const useDictStore = defineStore('dict', {
|
||||
{
|
||||
label: data.dictLabel,
|
||||
value: data.dictValue,
|
||||
elTagType: data.tagType,
|
||||
elTagClass: data.tagClass,
|
||||
tagType: data.tagType,
|
||||
tagClass: data.tagClass,
|
||||
},
|
||||
];
|
||||
},
|
||||
@@ -47,8 +47,8 @@ const useDictStore = defineStore('dict', {
|
||||
const dictData: DictType[] = res.data.map(d => ({
|
||||
label: d.dictLabel,
|
||||
value: d.dictValue,
|
||||
elTagType: d.tagType,
|
||||
elTagClass: d.tagClass,
|
||||
tagType: d.tagType,
|
||||
tagClass: d.tagClass,
|
||||
}));
|
||||
this.dicts.set(key, dictData);
|
||||
disct = dictData;
|
||||
|
||||
@@ -10,10 +10,10 @@ type LayoutStore = {
|
||||
proConfig: {
|
||||
/**导航布局 */
|
||||
layout: 'side' | 'top' | 'mix';
|
||||
/**导航菜单主题色 */
|
||||
navTheme: 'dark' | 'light';
|
||||
/**顶部导航主题,仅导航布局为mix时生效 */
|
||||
headerTheme: 'dark' | 'light';
|
||||
/**全局主题色,需要导入样式文件 */
|
||||
theme: 'dark' | 'light';
|
||||
/**菜单导航主题色 */
|
||||
menuTheme: 'dark' | 'light';
|
||||
/**固定顶部栏 */
|
||||
fixedHeader: boolean;
|
||||
/**固定菜单栏 */
|
||||
@@ -41,8 +41,8 @@ const proConfigLocal: LayoutStore['proConfig'] = localGetJSON(
|
||||
CACHE_LOCAL_PROCONFIG
|
||||
) || {
|
||||
layout: 'mix',
|
||||
headerTheme: 'light',
|
||||
navTheme: 'light',
|
||||
theme: 'light',
|
||||
menuTheme: 'light',
|
||||
fixSiderbar: true,
|
||||
fixedHeader: true,
|
||||
splitMenus: true,
|
||||
@@ -53,8 +53,8 @@ const useLayoutStore = defineStore('layout', {
|
||||
visible: false,
|
||||
proConfig: {
|
||||
layout: proConfigLocal.layout,
|
||||
navTheme: proConfigLocal.navTheme,
|
||||
headerTheme: proConfigLocal.headerTheme,
|
||||
theme: proConfigLocal.theme,
|
||||
menuTheme: proConfigLocal.menuTheme,
|
||||
fixedHeader: Boolean(proConfigLocal.fixedHeader),
|
||||
fixSiderbar: Boolean(proConfigLocal.fixSiderbar),
|
||||
splitMenus: Boolean(proConfigLocal.splitMenus),
|
||||
@@ -77,10 +77,6 @@ const useLayoutStore = defineStore('layout', {
|
||||
/**修改布局设置 */
|
||||
changeConf(key: string, value: boolean | string | number | undefined) {
|
||||
if (Reflect.has(this.proConfig, key)) {
|
||||
// 同时修改mix混合菜单的导航主题
|
||||
if (key === 'navTheme') {
|
||||
Reflect.set(this.proConfig, 'headerTheme', value);
|
||||
}
|
||||
Reflect.set(this.proConfig, key, value);
|
||||
localSetJSON(CACHE_LOCAL_PROCONFIG, this.proConfig);
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
import { getSysConf } from '@/api';
|
||||
import { CACHE_LOCAL_LOCK } from '@/constants/cache-keys-constants';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
/**锁屏信息类型 */
|
||||
type Locked = {
|
||||
/**锁屏类型 */
|
||||
type: 'none' | 'lock' | 'reload' | 'reset';
|
||||
/**lock 超时锁屏时间,秒*/
|
||||
lockTimeout: number;
|
||||
};
|
||||
|
||||
const useLockedStore = defineStore('locked', {
|
||||
state: (): Locked => ({
|
||||
type: (localGet(CACHE_LOCAL_LOCK) || 'none') as Locked['type'],
|
||||
lockTimeout: 0,
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// 重启等待-轮询
|
||||
async relaodWait() {
|
||||
try {
|
||||
const res = await getSysConf();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.fnLock('none');
|
||||
window.location.reload();
|
||||
}, 2_000);
|
||||
} else {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.relaodWait();
|
||||
}, 5_000);
|
||||
}
|
||||
} catch (error) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.relaodWait();
|
||||
}, 5_000);
|
||||
}
|
||||
},
|
||||
// 设置锁定
|
||||
async fnLock(type: Locked['type']) {
|
||||
this.type = type;
|
||||
localSet(CACHE_LOCAL_LOCK, type);
|
||||
if (type === 'reload') {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.relaodWait();
|
||||
}, 2_000);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default useLockedStore;
|
||||
70
src/store/modules/mask.ts
Normal file
70
src/store/modules/mask.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { getSysConf } from '@/api';
|
||||
import {
|
||||
CACHE_LOCAL_LOCK_PASSWD,
|
||||
CACHE_LOCAL_MASK,
|
||||
} from '@/constants/cache-keys-constants';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { localGet, localRemove, localSet } from '@/utils/cache-local-utils';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
/**全局遮罩信息类型 */
|
||||
type MaskStateType = {
|
||||
/**锁屏类型 */
|
||||
type: 'none' | 'lock' | 'reload' | 'reset';
|
||||
/**lock 锁屏密码*/
|
||||
lockPasswd: string;
|
||||
/**lock 超时锁屏时间,秒*/
|
||||
lockTimeout: number;
|
||||
};
|
||||
|
||||
const useMaskStore = defineStore('mask', {
|
||||
state: (): MaskStateType => ({
|
||||
type: (localGet(CACHE_LOCAL_MASK) || 'none') as MaskStateType['type'],
|
||||
lockPasswd: localGet(CACHE_LOCAL_LOCK_PASSWD) || '',
|
||||
lockTimeout: 0,
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// 检查服务等待-轮询
|
||||
async checkServiceWait() {
|
||||
try {
|
||||
const res = await getSysConf();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.handleMaskType('none');
|
||||
window.location.reload();
|
||||
}, 2_000);
|
||||
} else {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.checkServiceWait();
|
||||
}, 5_000);
|
||||
}
|
||||
} catch (error) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.checkServiceWait();
|
||||
}, 5_000);
|
||||
}
|
||||
},
|
||||
// 设置遮罩类型
|
||||
async handleMaskType(type: MaskStateType['type']) {
|
||||
this.type = type;
|
||||
localSet(CACHE_LOCAL_MASK, type);
|
||||
if (type === 'reload') {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.checkServiceWait();
|
||||
}, 5_000);
|
||||
}
|
||||
if (type === 'lock') {
|
||||
localSet(CACHE_LOCAL_LOCK_PASSWD, this.lockPasswd);
|
||||
} else {
|
||||
localRemove(CACHE_LOCAL_LOCK_PASSWD);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default useMaskStore;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import {
|
||||
import type {
|
||||
RouteComponent,
|
||||
RouteLocationRaw,
|
||||
RouteMeta,
|
||||
|
||||
@@ -9,6 +9,8 @@ import { parseUrlPath } from '@/plugins/file-static-url';
|
||||
|
||||
/**用户信息类型 */
|
||||
type UserInfo = {
|
||||
/**用户ID */
|
||||
userId: string;
|
||||
/**登录账号 */
|
||||
userName: string;
|
||||
/**用户角色 字符串数组 */
|
||||
@@ -31,6 +33,7 @@ type UserInfo = {
|
||||
|
||||
const useUserStore = defineStore('user', {
|
||||
state: (): UserInfo => ({
|
||||
userId: '',
|
||||
userName: '',
|
||||
roles: [],
|
||||
permissions: [],
|
||||
@@ -109,6 +112,7 @@ const useUserStore = defineStore('user', {
|
||||
const res = await getInfo();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
const { user, roles, permissions } = res.data;
|
||||
this.userId = user.userId;
|
||||
// 登录账号
|
||||
this.userName = user.userName;
|
||||
// 用户头像
|
||||
|
||||
4
src/typings/dict.d.ts
vendored
4
src/typings/dict.d.ts
vendored
@@ -2,6 +2,6 @@
|
||||
type DictType = {
|
||||
label: string;
|
||||
value: string;
|
||||
elTagType: string;
|
||||
elTagClass: string;
|
||||
tagType?: string;
|
||||
tagClass?: string;
|
||||
};
|
||||
|
||||
@@ -19,9 +19,9 @@ export const regExpPort =
|
||||
/**
|
||||
* 有效账号格式
|
||||
*
|
||||
* 账号不能以数字开头,可包含大写小写字母,数字,且不少于5位
|
||||
* 账号只能包含大写字母、小写字母和数字的字符串,长度至少为6位
|
||||
*/
|
||||
export const regExpUserName = /^[a-zA-Z][a-z0-9A-Z]{4,}$/;
|
||||
export const regExpUserName = /^[A-Za-z0-9]{6,}$/;
|
||||
|
||||
/**
|
||||
* 有效密码格式
|
||||
@@ -91,7 +91,7 @@ export function validURL(str: string) {
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (u.host.startsWith('.')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ const { getDict } = useDictStore();
|
||||
|
||||
/**用户性别字典 */
|
||||
let sysUserSex = ref<DictType[]>([
|
||||
{ label: '未知', value: '0', elTagType: '', elTagClass: '' },
|
||||
{ label: '男', value: '1', elTagType: '', elTagClass: '' },
|
||||
{ label: '女', value: '2', elTagType: '', elTagClass: '' },
|
||||
{ label: '未知', value: '0', tagType: '', tagClass: '' },
|
||||
{ label: '男', value: '1', tagType: '', tagClass: '' },
|
||||
{ label: '女', value: '2', tagType: '', tagClass: '' },
|
||||
]);
|
||||
|
||||
/**表单数据状态 */
|
||||
|
||||
@@ -72,9 +72,9 @@ function fnColorChange(e: Event) {
|
||||
<a-switch
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
:checked="proConfig.navTheme === 'dark'"
|
||||
:checked="proConfig.menuTheme === 'dark'"
|
||||
@change="
|
||||
(checked:any) => changeConf('navTheme', checked ? 'dark' : 'light')
|
||||
(checked:any) => changeConf('menuTheme', checked ? 'dark' : 'light')
|
||||
"
|
||||
></a-switch>
|
||||
</template>
|
||||
|
||||
@@ -481,8 +481,10 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -505,7 +507,7 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ export default function useOptions() {
|
||||
}
|
||||
switch (type) {
|
||||
case 'int':
|
||||
// filter: "0~128"
|
||||
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
const filterArr = filter.split('~');
|
||||
const minInt = parseInt(filterArr[0]);
|
||||
@@ -73,6 +75,8 @@ export default function useOptions() {
|
||||
}
|
||||
break;
|
||||
case 'bool':
|
||||
// filter: '{"0":"false", "1":"true"}'
|
||||
|
||||
if (filter && filter.indexOf('{') === 1) {
|
||||
let filterJson: Record<string, any> = {};
|
||||
try {
|
||||
@@ -90,6 +94,8 @@ export default function useOptions() {
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
// filter: "0~128"
|
||||
|
||||
// 字符串长度判断
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
try {
|
||||
@@ -127,6 +133,8 @@ export default function useOptions() {
|
||||
|
||||
break;
|
||||
case 'regex':
|
||||
// filter: "^[0-9]{3}$"
|
||||
|
||||
if (filter) {
|
||||
try {
|
||||
let regex = new RegExp(filter);
|
||||
|
||||
@@ -1455,8 +1455,10 @@ onMounted(() => {
|
||||
</a-row>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -1549,7 +1551,7 @@ onMounted(() => {
|
||||
</a-tooltip>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -430,8 +430,10 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 上传框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -487,7 +489,7 @@ onMounted(() => {
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
const lockedStore = useLockedStore();
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
const maskStore = useMaskStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**表格所需option */
|
||||
@@ -550,7 +550,7 @@ function fnRecordRestart(row: Record<string, any>) {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// OMC自升级
|
||||
if (row.neType.toLowerCase() === 'omc') {
|
||||
lockedStore.fnLock('reload');
|
||||
maskStore.handleMaskType('reload');
|
||||
return;
|
||||
}
|
||||
message.success({
|
||||
@@ -972,8 +972,10 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -1168,11 +1170,13 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 导入框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByImport"
|
||||
@@ -1259,7 +1263,7 @@ onMounted(() => {
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -167,7 +167,11 @@ function fnGetList(pageNum?: number) {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
if (tablePagination.total <=(queryParams.pageNum - 1) * tablePagination.pageSize &&queryParams.pageNum !== 1) {
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
@@ -197,15 +201,16 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="100%"
|
||||
wrap-class-name="full-modal"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:forceFullscreen="true"
|
||||
:destroyOnClose="true"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@cancel="fnModalCancel"
|
||||
:footer="null"
|
||||
:footer="false"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
@@ -265,7 +270,7 @@ watch(
|
||||
:pagination="tablePagination"
|
||||
>
|
||||
</a-table>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -273,22 +278,3 @@ watch(
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.full-modal {
|
||||
.ant-modal {
|
||||
max-width: 100%;
|
||||
top: 0;
|
||||
padding-bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.ant-modal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh);
|
||||
}
|
||||
.ant-modal-body {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -23,8 +23,8 @@ import useI18n from '@/hooks/useI18n';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { FileType } from 'ant-design-vue/lib/upload/interface';
|
||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
const lockedStore = useLockedStore();
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
const maskStore = useMaskStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**查询参数 */
|
||||
@@ -299,7 +299,7 @@ function fnFileModalOk() {
|
||||
if (type === 'run' && from.neType.toLowerCase() === 'omc') {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
fnFileModalCancel();
|
||||
lockedStore.fnLock('reload');
|
||||
maskStore.handleMaskType('reload');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${fileModalState.title} ${res.msg}`,
|
||||
@@ -919,8 +919,9 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 上传框 -->
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -1012,7 +1013,7 @@ onMounted(() => {
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 上传激活历史 -->
|
||||
<SoftwareHistory
|
||||
@@ -1022,8 +1023,8 @@ onMounted(() => {
|
||||
/>
|
||||
|
||||
<!-- 文件框 下发激活 -->
|
||||
<a-modal
|
||||
width="600px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="fileModalState.visible"
|
||||
@@ -1051,11 +1052,11 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 回退框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="fileModalState.visibleByBack"
|
||||
@@ -1086,7 +1087,7 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -11,8 +11,9 @@ import {
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { listAMFDataUE, delAMFDataUE } from '@/api/neData/amf';
|
||||
import { listAMFDataUE, delAMFDataUE, exportAMFDataUE } from '@/api/neData/amf';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import saveAs from 'file-saver';
|
||||
import PQueue from 'p-queue';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
@@ -33,15 +34,22 @@ let dict: {
|
||||
ueEventCmState: [],
|
||||
});
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'AMF',
|
||||
neId: '001',
|
||||
eventType: 'auth-result',
|
||||
eventType: '',
|
||||
imsi: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
@@ -50,20 +58,23 @@ let queryParams = reactive({
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
eventTypes.value = ['auth-result'];
|
||||
eventTypes.value = [];
|
||||
queryParams = Object.assign(queryParams, {
|
||||
eventType: 'auth-result',
|
||||
eventType: '',
|
||||
imsi: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**记录类型 */
|
||||
const eventTypes = ref<string[]>(['auth-result']);
|
||||
const eventTypes = ref<string[]>([]);
|
||||
|
||||
/**查询记录类型变更 */
|
||||
function fnQueryEventTypeChange(value: any) {
|
||||
@@ -241,6 +252,11 @@ function fnGetList(pageNum?: number) {
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listAMFDataUE(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
@@ -275,6 +291,39 @@ function fnGetList(pageNum?: number) {
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportAMFDataUE(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `amf_ue_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
@@ -290,7 +339,7 @@ function fnRealTime() {
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* UE会话事件-AMF (GroupID:1010)
|
||||
* AMF_UE会话事件(GroupID:1010)
|
||||
*/
|
||||
subGroupID: '1010',
|
||||
},
|
||||
@@ -321,7 +370,7 @@ function wsMessage(res: Record<string, any>) {
|
||||
if (!data?.groupId) {
|
||||
return;
|
||||
}
|
||||
// ueEvent CDR会话事件
|
||||
// ueEvent AMF_UE会话事件
|
||||
if (data.groupId === '1010') {
|
||||
const ueEvent = data.data;
|
||||
queue.add(async () => {
|
||||
@@ -399,7 +448,7 @@ onBeforeUnmount(() => {
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item label="IMSI" name="imsi ">
|
||||
<a-input
|
||||
v-model:value="queryParams.imsi"
|
||||
@@ -408,6 +457,22 @@ onBeforeUnmount(() => {
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
@@ -461,6 +526,11 @@ onBeforeUnmount(() => {
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
@@ -537,10 +607,7 @@ onBeforeUnmount(() => {
|
||||
:value="record.eventJSON.authCode"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
v-if="record.eventType === 'detach'"
|
||||
:title="record.eventJSON.detachTime"
|
||||
>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
<span>{{ t('views.dashboard.ue.resultOk') }}</span>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
@@ -592,11 +659,11 @@ onBeforeUnmount(() => {
|
||||
{{ t('views.dashboard.ue.ueInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.neName') }}: </span>
|
||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||
<span>{{ record.neName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.rmUID') }}: </span>
|
||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||
<span>{{ record.rmUID }}</span>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
@@ -636,7 +703,7 @@ onBeforeUnmount(() => {
|
||||
/>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
{{ t('views.dashboard.ue.resultOK') }}
|
||||
{{ t('views.dashboard.ue.resultOk') }}
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
<DictTag
|
||||
|
||||
@@ -11,9 +11,14 @@ import {
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { delIMSDataCDR, listIMSDataCDR } from '@/api/neData/ims';
|
||||
import {
|
||||
delIMSDataCDR,
|
||||
exportIMSDataCDR,
|
||||
listIMSDataCDR,
|
||||
} from '@/api/neData/ims';
|
||||
import { parseDateToStr, parseDuration } from '@/utils/date-utils';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import saveAs from 'file-saver';
|
||||
import PQueue from 'p-queue';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
@@ -31,16 +36,23 @@ let dict: {
|
||||
cdrCallType: [],
|
||||
});
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'IMS',
|
||||
neId: '001',
|
||||
recordType: 'MOC',
|
||||
recordType: '',
|
||||
callerParty: '',
|
||||
calledParty: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
@@ -49,21 +61,24 @@ let queryParams = reactive({
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
recordTypes.value = ['MOC'];
|
||||
recordTypes.value = [];
|
||||
queryParams = Object.assign(queryParams, {
|
||||
recordType: 'MOC',
|
||||
recordType: '',
|
||||
callerParty: '',
|
||||
calledParty: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**记录类型 */
|
||||
const recordTypes = ref<string[]>(['MOC']);
|
||||
const recordTypes = ref<string[]>([]);
|
||||
|
||||
/**查询记录类型变更 */
|
||||
function fnQueryRecordTypeChange(value: any) {
|
||||
@@ -279,6 +294,11 @@ function fnGetList(pageNum?: number) {
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listIMSDataCDR(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
@@ -313,6 +333,39 @@ function fnGetList(pageNum?: number) {
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportIMSDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `ims_cdr_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
@@ -328,7 +381,7 @@ function fnRealTime() {
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* CDR会话事件-IMS (GroupID:1005)
|
||||
* IMS_CDR会话事件(GroupID:1005)
|
||||
*/
|
||||
subGroupID: '1005',
|
||||
},
|
||||
@@ -455,6 +508,22 @@ onBeforeUnmount(() => {
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
@@ -508,6 +577,11 @@ onBeforeUnmount(() => {
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
@@ -565,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',
|
||||
@@ -585,7 +659,7 @@ onBeforeUnmount(() => {
|
||||
<DictTag
|
||||
:options="dict.cdrSipCode"
|
||||
:value="record.cdrJSON.cause"
|
||||
value-option="0"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
@@ -614,11 +688,11 @@ onBeforeUnmount(() => {
|
||||
{{ t('views.dashboard.cdr.cdrInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.cdr.neName') }}: </span>
|
||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||
<span>{{ record.neName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.cdr.rmUID') }}: </span>
|
||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||
<span>{{ record.rmUID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -656,7 +730,7 @@ onBeforeUnmount(() => {
|
||||
<DictTag
|
||||
:options="dict.cdrSipCode"
|
||||
:value="record.cdrJSON.cause"
|
||||
value-option="0"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
|
||||
693
src/views/dashboard/mmeUE/index.vue
Normal file
693
src/views/dashboard/mmeUE/index.vue
Normal file
@@ -0,0 +1,693 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, ref, onBeforeUnmount } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { message, Modal } from 'ant-design-vue/lib';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import {
|
||||
RESULT_CODE_ERROR,
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { listMMEDataUE, delMMEDataUE, exportMMEDataUE } from '@/api/neData/mme';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import saveAs from 'file-saver';
|
||||
import PQueue from 'p-queue';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
const ws = new WS();
|
||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
/**UE 事件认证代码类型 */
|
||||
ueAauthCode: DictType[];
|
||||
/**UE 事件类型 */
|
||||
ueEventType: DictType[];
|
||||
/**UE 事件CM状态 */
|
||||
ueEventCmState: DictType[];
|
||||
} = reactive({
|
||||
ueAauthCode: [],
|
||||
ueEventType: [],
|
||||
ueEventCmState: [],
|
||||
});
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'MME',
|
||||
neId: '001',
|
||||
eventType: '',
|
||||
imsi: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
eventTypes.value = [];
|
||||
queryParams = Object.assign(queryParams, {
|
||||
eventType: '',
|
||||
imsi: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**记录类型 */
|
||||
const eventTypes = ref<string[]>([]);
|
||||
|
||||
/**查询记录类型变更 */
|
||||
function fnQueryEventTypeChange(value: any) {
|
||||
if (Array.isArray(value)) {
|
||||
queryParams.eventType = value.join(',');
|
||||
}
|
||||
}
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: 'IMSI',
|
||||
dataIndex: 'eventJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const eventJSON = opt.value;
|
||||
return eventJSON.imsi;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.eventType'),
|
||||
dataIndex: 'eventType',
|
||||
key: 'eventType',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.result'),
|
||||
dataIndex: 'eventJSON',
|
||||
key: 'result',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.time'),
|
||||
dataIndex: 'eventJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return parseDateToStr(+cdrJSON.timestamp * 1000);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'id',
|
||||
align: 'left',
|
||||
},
|
||||
];
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
current: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
/**默认的每页条数 */
|
||||
defaultPageSize: 20,
|
||||
/**指定每页可以显示多少条 */
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
/**只有一页时是否隐藏分页器 */
|
||||
hideOnSinglePage: false,
|
||||
/**是否可以快速跳转至某页 */
|
||||
showQuickJumper: true,
|
||||
/**是否可以改变 pageSize */
|
||||
showSizeChanger: true,
|
||||
/**数据总数 */
|
||||
total: 0,
|
||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
||||
onChange: (page: number, pageSize: number) => {
|
||||
tablePagination.current = page;
|
||||
tablePagination.pageSize = pageSize;
|
||||
queryParams.pageNum = page;
|
||||
queryParams.pageSize = pageSize;
|
||||
fnGetList();
|
||||
},
|
||||
});
|
||||
|
||||
/**表格紧凑型变更操作 */
|
||||
function fnTableSize({ key }: MenuInfo) {
|
||||
tableState.size = key as SizeType;
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
/**最大ID值 */
|
||||
maxId: number;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
confirmLoading: false,
|
||||
maxId: 0,
|
||||
});
|
||||
|
||||
/**
|
||||
* 记录删除
|
||||
* @param id 编号
|
||||
*/
|
||||
function fnRecordDelete(id: string) {
|
||||
if (!id || modalState.confirmLoading) return;
|
||||
let msg = id;
|
||||
if (id === '0') {
|
||||
msg = `${id}... ${tableState.selectedRowKeys.length}`;
|
||||
id = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.delTip', { msg }),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
delMMEDataUE(id)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
fnGetList(1);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**查询列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listMMEDataUE(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
if (tableState.selectedRowKeys.length > 0) {
|
||||
tableState.selectedRowKeys = [];
|
||||
}
|
||||
tablePagination.total = res.total;
|
||||
// 遍历处理cdr字符串数据
|
||||
tableState.data = res.rows.map(item => {
|
||||
let eventJSON = item.eventJSON;
|
||||
if (!eventJSON) {
|
||||
Reflect.set(item, 'eventJSON', {});
|
||||
}
|
||||
|
||||
try {
|
||||
eventJSON = JSON.parse(eventJSON);
|
||||
Reflect.set(item, 'eventJSON', eventJSON);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Reflect.set(item, 'eventJSON', {});
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
// 取最大值ID用作实时累加
|
||||
if (res.total > 0) {
|
||||
modalState.maxId = Number(res.rows[0].id);
|
||||
}
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportMMEDataUE(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `mme_ue_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
/**
|
||||
* 实时数据
|
||||
*/
|
||||
function fnRealTime() {
|
||||
realTimeData.value = !realTimeData.value;
|
||||
if (realTimeData.value) {
|
||||
// 建立链接
|
||||
const options: OptionsType = {
|
||||
url: '/ws',
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* MME_UE会话事件(GroupID:1011)
|
||||
*/
|
||||
subGroupID: '1011',
|
||||
},
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
};
|
||||
ws.connect(options);
|
||||
} else {
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**接收数据后回调 */
|
||||
function wsError(ev: any) {
|
||||
// 接收数据后回调
|
||||
console.error(ev);
|
||||
}
|
||||
|
||||
/**接收数据后回调 */
|
||||
function wsMessage(res: Record<string, any>) {
|
||||
const { code, requestId, data } = res;
|
||||
if (code === RESULT_CODE_ERROR) {
|
||||
console.warn(res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// 订阅组信息
|
||||
if (!data?.groupId) {
|
||||
return;
|
||||
}
|
||||
// ueEvent MME_UE会话事件
|
||||
if (data.groupId === '1011') {
|
||||
const ueEvent = data.data;
|
||||
queue.add(async () => {
|
||||
modalState.maxId += 1;
|
||||
tableState.data.unshift({
|
||||
id: modalState.maxId,
|
||||
neType: ueEvent.neType,
|
||||
neName: ueEvent.neName, // 空
|
||||
rmUID: ueEvent.rmUID, // 空
|
||||
timestamp: ueEvent.timestamp,
|
||||
eventType: ueEvent.eventType,
|
||||
eventJSON: ueEvent.eventJSON,
|
||||
});
|
||||
tablePagination.total += 1;
|
||||
if (tableState.data.length > 100) {
|
||||
tableState.data.pop();
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([
|
||||
getDict('ue_auth_code'),
|
||||
getDict('ue_event_type'),
|
||||
getDict('ue_event_cm_state'),
|
||||
])
|
||||
.then(resArr => {
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
dict.ueAauthCode = resArr[0].value;
|
||||
}
|
||||
if (resArr[1].status === 'fulfilled') {
|
||||
dict.ueEventType = resArr[1].value;
|
||||
}
|
||||
if (resArr[2].status === 'fulfilled') {
|
||||
dict.ueEventCmState = resArr[2].value;
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (ws.state() !== -1) {
|
||||
ws.close();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.ue.eventType')"
|
||||
name="eventType "
|
||||
>
|
||||
<a-select
|
||||
v-model:value="eventTypes"
|
||||
mode="multiple"
|
||||
:options="dict.ueEventType"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
@change="fnQueryEventTypeChange"
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item label="IMSI" name="imsi ">
|
||||
<a-input
|
||||
v-model:value="queryParams.imsi"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-popconfirm
|
||||
placement="bottomLeft"
|
||||
:title="
|
||||
!realTimeData
|
||||
? t('views.dashboard.ue.realTimeDataStart')
|
||||
: t('views.dashboard.ue.realTimeDataStop')
|
||||
"
|
||||
ok-text="Yes"
|
||||
cancel-text="No"
|
||||
@confirm="fnRealTime()"
|
||||
>
|
||||
<a-button type="primary" :danger="realTimeData">
|
||||
<template #icon><FundOutlined /> </template>
|
||||
{{
|
||||
!realTimeData
|
||||
? t('views.dashboard.ue.realTimeDataStart')
|
||||
: t('views.dashboard.ue.realTimeDataStop')
|
||||
}}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
<a-button type="text">
|
||||
<template #icon><ColumnHeightOutlined /></template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="middle">
|
||||
{{ t('common.size.middle') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="small">
|
||||
{{ t('common.size.small') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
columnWidth: '48px',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'eventType'">
|
||||
<DictTag :options="dict.ueEventType" :value="record.eventType" />
|
||||
</template>
|
||||
<template v-if="column.key === 'result'">
|
||||
<span v-if="record.eventType === 'auth-result'">
|
||||
<DictTag
|
||||
:options="dict.ueAauthCode"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
<span>{{ t('views.dashboard.ue.resultOk') }}</span>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
<DictTag
|
||||
:options="dict.ueEventCmState"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'id'">
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.deleteText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.id)"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
<template #expandedRowRender="{ record }">
|
||||
<div style="width: 46%; padding-left: 32px; padding-bottom: 16px">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.ue.ueInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||
<span>{{ record.neName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||
<span>{{ record.rmUID }}</span>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.ue.rowInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.time') }}: </span>
|
||||
{{ parseDateToStr(record.eventJSON.timestamp * 1000) }}
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
|
||||
<DictTag :options="dict.ueEventType" :value="record.eventType" />
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.result') }}: </span>
|
||||
<span v-if="record.eventType === 'auth-result'">
|
||||
<DictTag
|
||||
:options="dict.ueAauthCode"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
{{ t('views.dashboard.ue.resultOk') }}
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
<DictTag
|
||||
:options="dict.ueEventCmState"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -56,8 +56,9 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
@@ -82,7 +83,7 @@ watch(
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@@ -10,7 +10,7 @@ import UserActivity from '../overview/components/UserActivity/index.vue';
|
||||
import AlarnTypeBar from './components/AlarnTypeBar/index.vue';
|
||||
import setting from './components/setting.vue';
|
||||
import UPFFlow from '../overview/components/UPFFlow/index.vue';
|
||||
import { listSub } from '@/api/neUser/sub';
|
||||
import { listUDMSub } from '@/api/neData/udm_sub';
|
||||
import { listUENumBySMF } from '@/api/neUser/smf';
|
||||
import { listUENumByIMS } from '@/api/neUser/ims';
|
||||
import { listBase5G } from '@/api/neUser/base5G';
|
||||
@@ -31,7 +31,7 @@ import { dbGetJSON } from '@/utils/cache-db-utils';
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const { t } = useI18n();
|
||||
const { wsSend, cdrEventSend, ueEventSend, upfTFSend } = useWS();
|
||||
const { wsSend, userActivitySend, upfTFSend } = useWS();
|
||||
|
||||
/**概览状态类型 */
|
||||
type SkimStateType = {
|
||||
@@ -97,7 +97,7 @@ function fnGetNeState() {
|
||||
/**获取概览信息 */
|
||||
async function fnGetSkim() {
|
||||
const resArr = await Promise.allSettled([
|
||||
listSub({
|
||||
listUDMSub({
|
||||
neid: '001',
|
||||
pageNum: 1,
|
||||
pageSize: 1,
|
||||
@@ -157,8 +157,7 @@ async function fnGetSkim() {
|
||||
/**初始数据函数 */
|
||||
function loadData() {
|
||||
fnGetNeState(); // 获取网元状态
|
||||
cdrEventSend();
|
||||
ueEventSend();
|
||||
userActivitySend();
|
||||
upfTFSend(0);
|
||||
upfTFSend(7);
|
||||
upfTFSend(30);
|
||||
|
||||
@@ -237,7 +237,7 @@ function handleRanderChart(
|
||||
|
||||
function fnChangeData(data: any[], itemID: string) {
|
||||
let info = data.find((item: any) => 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;
|
||||
@@ -277,6 +277,9 @@ function fnChangeData(data: any[], itemID: string) {
|
||||
if (men > 100) {
|
||||
men = +(men / 100).toFixed(2);
|
||||
}
|
||||
if (men > 100) {
|
||||
men = 100;
|
||||
}
|
||||
sysMemUsage = men;
|
||||
}
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -58,11 +58,11 @@ onMounted(() => {
|
||||
<template>
|
||||
<div class="activty">
|
||||
<template v-for="item in eventData" :key="item.eId">
|
||||
<!-- CDR事件 -->
|
||||
<!-- CDR事件IMS -->
|
||||
<div
|
||||
class="card-cdr"
|
||||
:class="{ active: item.eId === eventId }"
|
||||
v-if="item.eType === 'cdr'"
|
||||
v-if="item.eType === 'ims_cdr'"
|
||||
>
|
||||
<div class="card-cdr-item">
|
||||
<div>
|
||||
@@ -104,18 +104,22 @@ onMounted(() => {
|
||||
<div>
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span v-if="item.data.callType !== 'sms'">
|
||||
<DictTag :options="dict.cdrSipCode" :value="item.data.cause" value-option="0" />
|
||||
<DictTag
|
||||
:options="dict.cdrSipCode"
|
||||
:value="item.data.cause"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ t('views.dashboard.overview.userActivity.resultOK') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- UE事件 -->
|
||||
<!-- UE事件AMF -->
|
||||
<div
|
||||
class="card-ue"
|
||||
:class="{ active: item.eId === eventId }"
|
||||
v-if="item.eType === 'ue'"
|
||||
v-if="item.eType === 'amf_ue'"
|
||||
>
|
||||
<div class="card-ue-item">
|
||||
<div>
|
||||
@@ -155,6 +159,7 @@ onMounted(() => {
|
||||
TAC ID: <span>{{ item.data.tacID }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="item.type === 'auth-result'">
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span>
|
||||
@@ -172,96 +177,59 @@ onMounted(() => {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- UE事件MME -->
|
||||
<div
|
||||
class="card-ue"
|
||||
:class="{ active: item.eId === eventId }"
|
||||
v-if="item.eType === 'mme_ue'"
|
||||
>
|
||||
<div class="card-ue-item">
|
||||
<div>
|
||||
{{ t('views.dashboard.overview.userActivity.type') }}:
|
||||
<span>
|
||||
<DictTag :options="dict.ueEventType" :value="item.type" />
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
IMSI: <span :title="item.data.imsi">{{ item.data.imsi }}</span>
|
||||
</div>
|
||||
<div>
|
||||
{{ t('views.dashboard.overview.userActivity.time') }}:
|
||||
<span :title="item.data.timestamp">
|
||||
{{ parseDateToStr(+item.data.timestamp * 1000) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-ue-w33" v-if="item.type === 'auth-result'">
|
||||
<div>
|
||||
ENB ID: <span>{{ item.data.eNBID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
Cell ID: <span>{{ item.data.cellID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
TAC ID: <span>{{ item.data.tacID }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.type === 'auth-result'">
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span>
|
||||
<DictTag :options="dict.ueAauthCode" :value="item.data.result" />
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="item.type === 'detach'">
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span>{{ t('views.dashboard.overview.userActivity.resultOK') }}</span>
|
||||
</div>
|
||||
<div class="card-ue-w33" v-if="item.type === 'cm-state'">
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span>
|
||||
<DictTag :options="dict.ueEventCmState" :value="item.data.result" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- <div class="card-cdr active">
|
||||
<div class="card-cdr-item">
|
||||
<div>类型: <span>video</span></div>
|
||||
<div>时长: <span>123s</span></div>
|
||||
</div>
|
||||
<div class="card-cdr-item">
|
||||
<div>主叫: <span>12307550064</span></div>
|
||||
<div>被叫: <span>12307550064</span></div>
|
||||
</div>
|
||||
<div>结果: <span>200</span></div>
|
||||
</div>
|
||||
<div class="card-cdr">
|
||||
<div class="card-cdr-item">
|
||||
<div>类型: <span>audio</span></div>
|
||||
<div>时长: <span>123s</span></div>
|
||||
</div>
|
||||
<div class="card-cdr-item">
|
||||
<div>主叫: <span>12307550064</span></div>
|
||||
<div>被叫: <span>12307550064</span></div>
|
||||
</div>
|
||||
<div>结果: <span>200</span></div>
|
||||
</div>
|
||||
<div class="card-ue">
|
||||
<div class="card-ue-item">
|
||||
<div>类型: <span>auth-result</span></div>
|
||||
<div>Time: <span>2023-01-16 07:28:11</span></div>
|
||||
</div>
|
||||
<div>IMSI: <span>4600212141</span></div>
|
||||
<div class="card-ue-auth">
|
||||
<div>GNB ID: <span>31</span></div>
|
||||
<div>Cell ID: <span>17</span></div>
|
||||
<div>Tac ID: <span>98</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-ue">
|
||||
<div class="card-ue-item">
|
||||
<div>类型: <span>cm-state</span></div>
|
||||
<div>Time: <span>2023-01-16 07:28:11</span></div>
|
||||
</div>
|
||||
<div>IMSI: <span>4600212141</span></div>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="card-cdr">
|
||||
{ "recordType":"MOC", // MOC, MTC, MOSM, MTSM
|
||||
"seqNumber":81,
|
||||
"callReference":"Y6ecb69Bj@10.25.0.210",
|
||||
"callerParty":"7112",
|
||||
"calledParty":"7108",
|
||||
"serviceResult":"ok",
|
||||
"seizureTime":1706515269,
|
||||
"answerTime":1706515273,
|
||||
"releaseTime":1706515294,
|
||||
"callDuration":21
|
||||
"callType":"audio" // audio, video
|
||||
"fwdType": "CFB" // CFU,CFB, CFNR, CFNL
|
||||
"fwdParty":"7999",
|
||||
"cause": 200 // 200, 403, 408, 500 .... }
|
||||
|
||||
{"neType":"IMS","neName":"IMS_001","rmUID":"4400HX1IMS001","timestamp":1707124616,
|
||||
"CDR":{"recordType":"MOSM","seqNumber":1,"callReference":"IIocbkeoj@10.10.91.22",
|
||||
"callerParty":"12307551241","calledParty":"+8613800755000","serviceResult":"ok",
|
||||
"seizureTime":1707124616,"answerTime":1707124616,"releaseTime":1707124616,
|
||||
"callDuration":0,"callType":"text","fwdType":"","fwdParty":"","cause":200}}
|
||||
|
||||
https://telnyx.com/resources/sip-response-codes-need-know-2-minutes
|
||||
主叫:callerParty
|
||||
被叫:calledParty
|
||||
时长:callDuration
|
||||
呼叫类型:callType
|
||||
原因:cause
|
||||
信息: 主叫 -> 被叫
|
||||
</div>
|
||||
<div class="card-ue">ue
|
||||
事件类型:auth-result
|
||||
imei
|
||||
GNB ID
|
||||
Cell ID
|
||||
Tac ID
|
||||
authTime
|
||||
|
||||
事件类型:detach
|
||||
imsi
|
||||
detachTime
|
||||
|
||||
事件类型:cm-state
|
||||
imsi
|
||||
changeTime
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -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%;
|
||||
|
||||
@@ -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<FDType>({
|
||||
|
||||
/**UPF-流量数据 数据解析 */
|
||||
export function upfFlowParse(data: Record<string, string>) {
|
||||
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<string, string>) {
|
||||
export const upfTFActive = ref<number>(0);
|
||||
|
||||
/**属性复位 */
|
||||
export function upfTotalFlowReset() {
|
||||
export function upfTotalFlowReset() {
|
||||
upfFlowData.value = {
|
||||
lineXTime: [],
|
||||
lineYUp: [],
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
/**ueEvent UE会话事件 数据解析 */
|
||||
export function ueEventParse(item: Record<string, any>) {
|
||||
/**ueEventAMFParse UE会话事件AMF 数据解析 */
|
||||
function ueEventAMFParse(
|
||||
item: Record<string, any>
|
||||
): false | Record<string, any> {
|
||||
let evData: Record<string, any> = item.eventJSON;
|
||||
if (typeof evData === 'string') {
|
||||
try {
|
||||
@@ -12,8 +14,8 @@ export function ueEventParse(item: Record<string, any>) {
|
||||
}
|
||||
|
||||
return {
|
||||
eType: 'ue',
|
||||
eId: `ue_${item.id}_${Date.now()}`,
|
||||
eType: 'amf_ue',
|
||||
eId: `amf_ue_${item.id}_${Date.now()}`,
|
||||
eTime: +item.timestamp,
|
||||
id: item.id,
|
||||
type: item.eventType,
|
||||
@@ -21,8 +23,33 @@ export function ueEventParse(item: Record<string, any>) {
|
||||
};
|
||||
}
|
||||
|
||||
/**cdrEvent CDR会话事件 数据解析 */
|
||||
export function cdrEventParse(item: Record<string, any>) {
|
||||
/**ueEventMMEParse UE会话事件MME 数据解析 */
|
||||
function ueEventMMEParse(
|
||||
item: Record<string, any>
|
||||
): false | Record<string, any> {
|
||||
let evData: Record<string, any> = item.eventJSON;
|
||||
if (typeof evData === 'string') {
|
||||
try {
|
||||
evData = JSON.parse(evData);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
eType: 'mme_ue',
|
||||
eId: `mme_ue_${item.id}_${Date.now()}`,
|
||||
eTime: +item.timestamp,
|
||||
id: item.id,
|
||||
type: item.eventType,
|
||||
data: evData,
|
||||
};
|
||||
}
|
||||
|
||||
/**cdrEventIMSParse CDR会话事件IMS 数据解析 */
|
||||
function cdrEventIMSParse(
|
||||
item: Record<string, any>
|
||||
): false | Record<string, any> {
|
||||
let evData: Record<string, any> = item.cdrJSON || item.CDR;
|
||||
if (typeof evData === 'string') {
|
||||
try {
|
||||
@@ -39,14 +66,73 @@ export function cdrEventParse(item: Record<string, any>) {
|
||||
}
|
||||
|
||||
return {
|
||||
eType: 'cdr',
|
||||
eId: `cdr_${item.id}_${Date.now()}`,
|
||||
eType: 'ims_cdr',
|
||||
eId: `ims_cdr_${item.id}_${Date.now()}`,
|
||||
eTime: +item.timestamp,
|
||||
id: item.id,
|
||||
data: evData,
|
||||
};
|
||||
}
|
||||
|
||||
/**eventListParse 事件列表解析 */
|
||||
export function eventListParse(
|
||||
type: 'ims_cdr' | 'amf_ue' | 'mme_ue',
|
||||
data: any
|
||||
) {
|
||||
eventTotal.value += data.total;
|
||||
for (const item of data.rows) {
|
||||
let v: false | Record<string, any> = false;
|
||||
if (type === 'ims_cdr') {
|
||||
v = cdrEventIMSParse(item);
|
||||
}
|
||||
if (type === 'amf_ue') {
|
||||
v = ueEventAMFParse(item);
|
||||
}
|
||||
if (type === 'mme_ue') {
|
||||
v = ueEventMMEParse(item);
|
||||
}
|
||||
|
||||
if (v) {
|
||||
eventData.value.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
// 有数据进行排序
|
||||
if (eventData.value.length > 5) {
|
||||
eventData.value.sort((a, b) => b.eTime - a.eTime);
|
||||
}
|
||||
if (eventData.value.length > 0) {
|
||||
eventId.value = eventData.value[0].eId;
|
||||
}
|
||||
}
|
||||
|
||||
/**eventItemParseAndPush 事件项解析并添加 */
|
||||
export async function eventItemParseAndPush(
|
||||
type: 'ims_cdr' | 'amf_ue' | 'mme_ue',
|
||||
item: any
|
||||
) {
|
||||
let v: false | Record<string, any> = false;
|
||||
if (type === 'ims_cdr') {
|
||||
v = cdrEventIMSParse(item);
|
||||
}
|
||||
if (type === 'amf_ue') {
|
||||
v = ueEventAMFParse(item);
|
||||
}
|
||||
if (type === 'mme_ue') {
|
||||
v = ueEventMMEParse(item);
|
||||
}
|
||||
|
||||
if (v) {
|
||||
eventData.value.unshift(v);
|
||||
eventTotal.value += 1;
|
||||
eventId.value = v.eId;
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
if (eventData.value.length > 20) {
|
||||
eventData.value.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**CDR+UE事件数据 */
|
||||
export const eventData = ref<Record<string, any>[]>([]);
|
||||
/**CDR+UE事件总量 */
|
||||
|
||||
@@ -2,11 +2,8 @@ import { RESULT_CODE_ERROR } from '@/constants/result-constants';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import { onBeforeUnmount, onMounted } from 'vue';
|
||||
import {
|
||||
ueEventParse,
|
||||
cdrEventParse,
|
||||
eventData,
|
||||
eventTotal,
|
||||
eventId,
|
||||
eventListParse,
|
||||
eventItemParseAndPush,
|
||||
userActivityReset,
|
||||
} from './useUserActivity';
|
||||
import {
|
||||
@@ -52,44 +49,22 @@ export default function useWS() {
|
||||
|
||||
// 普通信息
|
||||
switch (requestId) {
|
||||
// ueEvent UE会话事件
|
||||
// AMF_UE会话事件
|
||||
case '1010':
|
||||
if (Array.isArray(data.rows)) {
|
||||
eventTotal.value += data.total;
|
||||
for (const item of data.rows) {
|
||||
const v = ueEventParse(item);
|
||||
if (v) {
|
||||
eventData.value.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
// 有数据进行排序
|
||||
if (eventData.value.length > 10) {
|
||||
eventData.value.sort((a, b) => b.eTime - a.eTime);
|
||||
}
|
||||
if (eventData.value.length > 0) {
|
||||
eventId.value = eventData.value[0].eId;
|
||||
}
|
||||
eventListParse('amf_ue', data);
|
||||
}
|
||||
break;
|
||||
//cdrEvent CDR会话事件
|
||||
// MME_UE会话事件
|
||||
case '1011':
|
||||
if (Array.isArray(data.rows)) {
|
||||
eventListParse('mme_ue', data);
|
||||
}
|
||||
break;
|
||||
// IMS_CDR会话事件
|
||||
case '1005':
|
||||
if (Array.isArray(data.rows)) {
|
||||
eventTotal.value += data.total;
|
||||
for (const item of data.rows) {
|
||||
const v = cdrEventParse(item);
|
||||
if (v) {
|
||||
eventData.value.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
// 有数据进行排序
|
||||
if (eventData.value.length > 10) {
|
||||
eventData.value.sort((a, b) => b.eTime - a.eTime);
|
||||
}
|
||||
if (eventData.value.length > 0) {
|
||||
eventId.value = eventData.value[0].eId;
|
||||
}
|
||||
eventListParse('ims_cdr', data);
|
||||
}
|
||||
break;
|
||||
//UPF-总流量数
|
||||
@@ -119,43 +94,27 @@ export default function useWS() {
|
||||
}
|
||||
switch (data.groupId) {
|
||||
// kpiEvent 指标UPF
|
||||
case '12':
|
||||
case '12_001':
|
||||
if (data.data) {
|
||||
upfFlowParse(data.data);
|
||||
}
|
||||
break;
|
||||
// ueEvent UE会话事件
|
||||
// AMF_UE会话事件
|
||||
case '1010':
|
||||
if (data.data) {
|
||||
queue.add(async () => {
|
||||
const v = ueEventParse(data.data);
|
||||
if (v) {
|
||||
eventData.value.unshift(v);
|
||||
eventTotal.value += 1;
|
||||
eventId.value = v.eId;
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
if (eventData.value.length > 20) {
|
||||
eventData.value.pop();
|
||||
}
|
||||
}
|
||||
});
|
||||
queue.add(() => eventItemParseAndPush('amf_ue', data.data));
|
||||
}
|
||||
break;
|
||||
// cdrEvent CDR会话事件
|
||||
// MME_UE会话事件
|
||||
case '1011':
|
||||
if (data.data) {
|
||||
queue.add(() => eventItemParseAndPush('mme_ue', data.data));
|
||||
}
|
||||
break;
|
||||
// IMS_CDR会话事件
|
||||
case '1005':
|
||||
if (data.data) {
|
||||
queue.add(async () => {
|
||||
const v = cdrEventParse(data.data);
|
||||
if (v) {
|
||||
eventData.value.unshift(v);
|
||||
eventTotal.value += 1;
|
||||
eventId.value = v.eId;
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
if (eventData.value.length > 20) {
|
||||
eventData.value.pop();
|
||||
}
|
||||
}
|
||||
});
|
||||
queue.add(() => eventItemParseAndPush('ims_cdr', data.data));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -188,27 +147,38 @@ export default function useWS() {
|
||||
});
|
||||
}
|
||||
|
||||
/**ueEvent UE会话事件 发消息*/
|
||||
function ueEventSend() {
|
||||
/**userActivitySend 用户行为事件基础列表数据 发消息*/
|
||||
function userActivitySend() {
|
||||
// AMF_UE会话事件
|
||||
ws.send({
|
||||
requestId: '1010',
|
||||
type: 'ue',
|
||||
type: 'amf_ue',
|
||||
data: {
|
||||
neType: 'AMF',
|
||||
neId: '001',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 5,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**cdrEvent CDR会话事件 发消息*/
|
||||
function cdrEventSend() {
|
||||
// MME_UE会话事件
|
||||
ws.send({
|
||||
requestId: '1011',
|
||||
type: 'mme_ue',
|
||||
data: {
|
||||
neType: 'MME',
|
||||
neId: '001',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
pageNum: 1,
|
||||
pageSize: 5,
|
||||
},
|
||||
});
|
||||
// IMS_CDR会话事件
|
||||
ws.send({
|
||||
requestId: '1005',
|
||||
type: 'cdr',
|
||||
type: 'ims_cdr',
|
||||
data: {
|
||||
neType: 'IMS',
|
||||
neId: '001',
|
||||
@@ -216,7 +186,7 @@ export default function useWS() {
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 5,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -227,11 +197,12 @@ export default function useWS() {
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* 指标UPF (GroupID:12)
|
||||
* UE会话事件-AMF (GroupID:1010)
|
||||
* CDR会话事件-IMS (GroupID:1005)
|
||||
* 指标UPF (GroupID:12_neId)
|
||||
* AMF_UE会话事件(GroupID:1010)
|
||||
* MME_UE会话事件(GroupID:1011)
|
||||
* IMS_CDR会话事件(GroupID:1005)
|
||||
*/
|
||||
subGroupID: '12,1010,1005',
|
||||
subGroupID: '12_001,1010,1011,1005',
|
||||
},
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
@@ -248,8 +219,7 @@ export default function useWS() {
|
||||
|
||||
return {
|
||||
wsSend,
|
||||
cdrEventSend,
|
||||
ueEventSend,
|
||||
userActivitySend,
|
||||
upfTFSend,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import NeResources from './components/NeResources/index.vue';
|
||||
import UserActivity from './components/UserActivity/index.vue';
|
||||
import AlarnTypeBar from './components/AlarnTypeBar/index.vue';
|
||||
import UPFFlow from './components/UPFFlow/index.vue';
|
||||
import { listSub } from '@/api/neUser/sub';
|
||||
import { listUDMSub } from '@/api/neData/udm_sub';
|
||||
import { listUENumBySMF } from '@/api/neUser/smf';
|
||||
import { listUENumByIMS } from '@/api/neUser/ims';
|
||||
import { listBase5G } from '@/api/neUser/base5G';
|
||||
@@ -29,7 +29,7 @@ import { useRouter } from 'vue-router';
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const { t } = useI18n();
|
||||
const { wsSend, cdrEventSend, ueEventSend, upfTFSend } = useWS();
|
||||
const { wsSend, userActivitySend, upfTFSend } = useWS();
|
||||
|
||||
/**概览状态类型 */
|
||||
type SkimStateType = {
|
||||
@@ -95,7 +95,7 @@ function fnGetNeState() {
|
||||
/**获取概览信息 */
|
||||
async function fnGetSkim() {
|
||||
const resArr = await Promise.allSettled([
|
||||
listSub({
|
||||
listUDMSub({
|
||||
neid: '001',
|
||||
pageNum: 1,
|
||||
pageSize: 1,
|
||||
@@ -155,8 +155,7 @@ async function fnGetSkim() {
|
||||
/**初始数据函数 */
|
||||
function loadData() {
|
||||
fnGetNeState(); // 获取网元状态
|
||||
cdrEventSend();
|
||||
ueEventSend();
|
||||
userActivitySend();
|
||||
upfTFSend(0);
|
||||
upfTFSend(7);
|
||||
upfTFSend(30);
|
||||
@@ -271,7 +270,7 @@ onBeforeUnmount(() => {
|
||||
<div class="skim panel base">
|
||||
<div class="inner">
|
||||
<h3>
|
||||
<GlobalOutlined style="color: #68d8fe" />
|
||||
<GlobalOutlined style="color: #68d8fe" /> 5G
|
||||
{{ t('views.dashboard.overview.skim.baseTitle') }}
|
||||
</h3>
|
||||
<div class="data">
|
||||
@@ -303,6 +302,14 @@ onBeforeUnmount(() => {
|
||||
<span>{{ t('views.dashboard.overview.skim.gnbUeNum') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="skim panel base">
|
||||
<div class="inner">
|
||||
<h3>
|
||||
<GlobalOutlined style="color: #68d8fe" /> 4G
|
||||
{{ t('views.dashboard.overview.skim.baseTitle') }}
|
||||
</h3>
|
||||
<div class="data">
|
||||
<div
|
||||
class="item toRouter"
|
||||
|
||||
785
src/views/dashboard/smfCDR/index.vue
Normal file
785
src/views/dashboard/smfCDR/index.vue
Normal file
@@ -0,0 +1,785 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, onBeforeUnmount, ref } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { Modal, message } from 'ant-design-vue/lib';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import {
|
||||
RESULT_CODE_ERROR,
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import {
|
||||
delSMFDataCDR,
|
||||
exportSMFDataCDR,
|
||||
listSMFDataCDR,
|
||||
} from '@/api/neData/smf';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import PQueue from 'p-queue';
|
||||
import saveAs from 'file-saver';
|
||||
const { t } = useI18n();
|
||||
const ws = new WS();
|
||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'SMF',
|
||||
neId: '001',
|
||||
subscriberID: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
queryParams = Object.assign(queryParams, {
|
||||
subscriberID: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfChargingID'), // 计费ID
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.chargingID;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfSubscriptionIDType'), // 订阅 ID 类型
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.subscriberIdentifier?.subscriptionIDType;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfSubscriptionIDData'), // 订阅 ID 数据
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.subscriberIdentifier?.subscriptionIDData;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfDataVolumeUplink'), // 数据量上行链路
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
const listOfMultipleUnitUsage = cdrJSON.listOfMultipleUnitUsage;
|
||||
if (
|
||||
!Array.isArray(listOfMultipleUnitUsage) ||
|
||||
listOfMultipleUnitUsage.length < 1
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
const usedUnitContainer = listOfMultipleUnitUsage[0].usedUnitContainer;
|
||||
if (!Array.isArray(usedUnitContainer) || usedUnitContainer.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
return usedUnitContainer[0].dataVolumeUplink;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfDataVolumeDownlink'), // 数据量下行链路
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 180,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
const listOfMultipleUnitUsage = cdrJSON.listOfMultipleUnitUsage;
|
||||
if (
|
||||
!Array.isArray(listOfMultipleUnitUsage) ||
|
||||
listOfMultipleUnitUsage.length < 1
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
const usedUnitContainer = listOfMultipleUnitUsage[0].usedUnitContainer;
|
||||
if (!Array.isArray(usedUnitContainer) || usedUnitContainer.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
return usedUnitContainer[0].dataVolumeDownlink;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfDataTotalVolume'), // 数据总量
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
const listOfMultipleUnitUsage = cdrJSON.listOfMultipleUnitUsage;
|
||||
if (
|
||||
!Array.isArray(listOfMultipleUnitUsage) ||
|
||||
listOfMultipleUnitUsage.length < 1
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
const usedUnitContainer = listOfMultipleUnitUsage[0].usedUnitContainer;
|
||||
if (!Array.isArray(usedUnitContainer) || usedUnitContainer.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
return usedUnitContainer[0].dataTotalVolume;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfDuration'), // 持续时间
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.duration;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfInvocationTime'), // 调用时间
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 200,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.invocationTimestamp;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'id',
|
||||
align: 'left',
|
||||
},
|
||||
];
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
current: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
/**默认的每页条数 */
|
||||
defaultPageSize: 20,
|
||||
/**指定每页可以显示多少条 */
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
/**只有一页时是否隐藏分页器 */
|
||||
hideOnSinglePage: false,
|
||||
/**是否可以快速跳转至某页 */
|
||||
showQuickJumper: true,
|
||||
/**是否可以改变 pageSize */
|
||||
showSizeChanger: true,
|
||||
/**数据总数 */
|
||||
total: 0,
|
||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
||||
onChange: (page: number, pageSize: number) => {
|
||||
tablePagination.current = page;
|
||||
tablePagination.pageSize = pageSize;
|
||||
queryParams.pageNum = page;
|
||||
queryParams.pageSize = pageSize;
|
||||
fnGetList();
|
||||
},
|
||||
});
|
||||
|
||||
/**表格紧凑型变更操作 */
|
||||
function fnTableSize({ key }: MenuInfo) {
|
||||
tableState.size = key as SizeType;
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
/**最大ID值 */
|
||||
maxId: number;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
confirmLoading: false,
|
||||
maxId: 0,
|
||||
});
|
||||
|
||||
/**
|
||||
* 记录删除
|
||||
* @param id 编号
|
||||
*/
|
||||
function fnRecordDelete(id: string) {
|
||||
if (!id || modalState.confirmLoading) return;
|
||||
let msg = id;
|
||||
if (id === '0') {
|
||||
msg = `${id}... ${tableState.selectedRowKeys.length}`;
|
||||
id = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.delTip', { msg }),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
delSMFDataCDR(id)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
fnGetList(1);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**查询列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listSMFDataCDR(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
if (tableState.selectedRowKeys.length > 0) {
|
||||
tableState.selectedRowKeys = [];
|
||||
}
|
||||
tablePagination.total = res.total;
|
||||
// 遍历处理cdr字符串数据
|
||||
tableState.data = res.rows.map(item => {
|
||||
let cdrJSON = item.cdrJSON;
|
||||
if (!cdrJSON) {
|
||||
Reflect.set(item, 'cdrJSON', {});
|
||||
}
|
||||
|
||||
try {
|
||||
cdrJSON = JSON.parse(cdrJSON);
|
||||
Reflect.set(item, 'cdrJSON', cdrJSON);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Reflect.set(item, 'cdrJSON', {});
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
// 取最大值ID用作实时累加
|
||||
if (res.total > 0) {
|
||||
modalState.maxId = Number(res.rows[0].id);
|
||||
}
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportSMFDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `smf_cdr_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
/**
|
||||
* 实时数据
|
||||
*/
|
||||
function fnRealTime() {
|
||||
realTimeData.value = !realTimeData.value;
|
||||
if (realTimeData.value) {
|
||||
// 建立链接
|
||||
const options: OptionsType = {
|
||||
url: '/ws',
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* CDR会话事件-SMF (GroupID:1006)
|
||||
*/
|
||||
subGroupID: '1006',
|
||||
},
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
};
|
||||
ws.connect(options);
|
||||
} else {
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**接收数据后回调 */
|
||||
function wsError(ev: any) {
|
||||
// 接收数据后回调
|
||||
console.error(ev);
|
||||
}
|
||||
|
||||
/**接收数据后回调 */
|
||||
function wsMessage(res: Record<string, any>) {
|
||||
const { code, requestId, data } = res;
|
||||
if (code === RESULT_CODE_ERROR) {
|
||||
console.warn(res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// 订阅组信息
|
||||
if (!data?.groupId) {
|
||||
return;
|
||||
}
|
||||
// cdrEvent CDR会话事件
|
||||
if (data.groupId === '1006') {
|
||||
const cdrEvent = data.data;
|
||||
queue.add(async () => {
|
||||
modalState.maxId += 1;
|
||||
tableState.data.unshift({
|
||||
id: modalState.maxId,
|
||||
neType: cdrEvent.neType,
|
||||
neName: cdrEvent.neName,
|
||||
rmUID: cdrEvent.rmUID,
|
||||
timestamp: cdrEvent.timestamp,
|
||||
cdrJSON: cdrEvent.CDR,
|
||||
});
|
||||
tablePagination.total += 1;
|
||||
if (tableState.data.length > 100) {
|
||||
tableState.data.pop();
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (ws.state() !== -1) {
|
||||
ws.close();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.smfSubscriptionIDData')"
|
||||
name="calledParty "
|
||||
>
|
||||
<a-input
|
||||
v-model:value="queryParams.subscriberID"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="40"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-popconfirm
|
||||
placement="bottomLeft"
|
||||
:title="
|
||||
!realTimeData
|
||||
? t('views.dashboard.cdr.realTimeDataStart')
|
||||
: t('views.dashboard.cdr.realTimeDataStop')
|
||||
"
|
||||
ok-text="Yes"
|
||||
cancel-text="No"
|
||||
@confirm="fnRealTime()"
|
||||
>
|
||||
<a-button type="primary" :danger="realTimeData">
|
||||
<template #icon><FundOutlined /> </template>
|
||||
{{
|
||||
!realTimeData
|
||||
? t('views.dashboard.cdr.realTimeDataStart')
|
||||
: t('views.dashboard.cdr.realTimeDataStop')
|
||||
}}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
<a-button type="text">
|
||||
<template #icon><ColumnHeightOutlined /></template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="middle">
|
||||
{{ t('common.size.middle') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="small">
|
||||
{{ t('common.size.small') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 150, y: 'calc(100vh - 480px)' }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
columnWidth: '48px',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'id'">
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.deleteText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.id)"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
<template #expandedRowRender="{ record }">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="8" :md="12" :xs="24" :offset="2">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.cdr.cdrInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||
<span>{{ record.neName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||
<span>{{ record.rmUID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.cdr.time') }}: </span>
|
||||
<span>{{ parseDateToStr(+record.timestamp * 1000) }}</span>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.cdr.rowInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>Record Network Function ID: </span>
|
||||
<span>{{ record.cdrJSON.recordingNetworkFunctionID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Record Type: </span>
|
||||
<span>{{ record.cdrJSON.recordType }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Record Opening Time: </span>
|
||||
<span>{{ record.cdrJSON.recordOpeningTime }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Charging ID: </span>
|
||||
<span>{{ record.cdrJSON.chargingID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Duration: </span>
|
||||
<span>{{ record.cdrJSON.duration }}</span>
|
||||
</div>
|
||||
<a-divider orientation="left"> Subscriber Identifier </a-divider>
|
||||
<div>
|
||||
<span>Subscription ID Type: </span>
|
||||
<span>
|
||||
{{ record.cdrJSON.subscriberIdentifier?.subscriptionIDType }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Subscription ID Data: </span>
|
||||
<span>
|
||||
{{ record.cdrJSON.subscriberIdentifier?.subscriptionIDData }}
|
||||
</span>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-divider orientation="left">
|
||||
List Of Multiple Unit Usage
|
||||
</a-divider>
|
||||
<div v-for="u in record.cdrJSON.listOfMultipleUnitUsage">
|
||||
<div>RatingGroup: {{ u.ratingGroup }}</div>
|
||||
<div v-for="udata in u.usedUnitContainer">
|
||||
<div>
|
||||
<span>Data Total Volume: </span>
|
||||
<span>{{ udata.dataTotalVolume }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Data Volume Downlink: </span>
|
||||
<span>{{ udata.dataVolumeDownlink }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Data Volume Uplink: </span>
|
||||
<span>{{ udata.dataVolumeUplink }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Time: </span>
|
||||
<span>{{ udata.time }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
PDU Session Charging Information
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>User Identifier: </span>
|
||||
<span>{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.userIdentifier
|
||||
}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>SSC Mode: </span>
|
||||
<span>{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.sSCMode
|
||||
}}</span>
|
||||
|
||||
<span>RAT Type: </span>
|
||||
<span>{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.rATType
|
||||
}}</span>
|
||||
|
||||
<span>DNN ID: </span>
|
||||
<span>
|
||||
{{ record.cdrJSON.pDUSessionChargingInformation?.dNNID }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>PDU Type: </span>
|
||||
<span>
|
||||
{{ record.cdrJSON.pDUSessionChargingInformation?.pDUType }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>PDU IPv4 Address: </span>
|
||||
<span>
|
||||
{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.pDUAddress
|
||||
?.pDUIPv4Address
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>PDU IPv6 Addres Swith Prefix: </span>
|
||||
<span>
|
||||
{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.pDUAddress
|
||||
?.pDUIPv6AddresswithPrefix
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -16,12 +16,14 @@ import {
|
||||
exportAll,
|
||||
} from '@/api/faultManage/actAlarm';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import saveAs from 'file-saver';
|
||||
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
||||
import { writeSheet } from '@/utils/execl-utils';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { readLoalXlsx } from '@/utils/execl-utils';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { getDict } = useDictStore();
|
||||
const { t, currentLocale } = useI18n();
|
||||
|
||||
@@ -741,6 +743,8 @@ onMounted(() => {
|
||||
dict.activeAlarmSeverity = resArr[3].value;
|
||||
}
|
||||
});
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore().fnNelist();
|
||||
fnGetList();
|
||||
});
|
||||
</script>
|
||||
@@ -758,9 +762,14 @@ onMounted(() => {
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.neType')"
|
||||
name="ne_type"
|
||||
name="neType"
|
||||
>
|
||||
<a-input v-model:value="queryParams.neType" allow-clear></a-input>
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="neInfoStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
@@ -1036,15 +1045,17 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 帮助文档 -->
|
||||
<a-modal
|
||||
width="100%"
|
||||
wrap-class-name="full-modal"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:forceFullscreen="true"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.helpShowView"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
:footer="null"
|
||||
:body-style="{ padding: '0px' }"
|
||||
:footer="false"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-table
|
||||
@@ -1055,14 +1066,15 @@ onMounted(() => {
|
||||
:data-source="alarmTableState.data"
|
||||
:size="alarmTableState.size"
|
||||
:pagination="false"
|
||||
:scroll="{ x: 1700, y: '82vh' }"
|
||||
:scroll="{ x: 1700, y: '88vh' }"
|
||||
>
|
||||
</a-table>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 详情框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:body-style="{ height: '520px', overflowY: 'scroll' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -1265,11 +1277,12 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 显示过滤框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByShowSet"
|
||||
@@ -1286,11 +1299,12 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.neType')"
|
||||
name="neType"
|
||||
>
|
||||
<a-input
|
||||
<a-auto-complete
|
||||
v-model:value="modalState.showSetFrom.ne_type"
|
||||
:options="neInfoStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1363,11 +1377,12 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 个性化设置框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByMyselfSet"
|
||||
@@ -1461,7 +1476,7 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@ import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import { listAct, exportAll } from '@/api/faultManage/eventAlarm';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import saveAs from 'file-saver';
|
||||
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
||||
import { writeSheet } from '@/utils/execl-utils';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { readLoalXlsx } from '@/utils/execl-utils';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { getDict } = useDictStore();
|
||||
const { t, currentLocale } = useI18n();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
@@ -431,6 +432,8 @@ onMounted(() => {
|
||||
dict.activeAlarmSeverity = resArr[3].value;
|
||||
}
|
||||
});
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore().fnNelist();
|
||||
fnGetList();
|
||||
});
|
||||
</script>
|
||||
@@ -448,9 +451,14 @@ onMounted(() => {
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.neType')"
|
||||
name="ne_type"
|
||||
name="neType "
|
||||
>
|
||||
<a-input v-model:value="queryParams.neType" allow-clear></a-input>
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="neInfoStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
@@ -665,8 +673,9 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 详情框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:body-style="{ height: '520px', overflowY: 'scroll' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -828,7 +837,7 @@ onMounted(() => {
|
||||
{{ modalState.from.specificProblem }}
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ function fnFormLogSetFinish() {
|
||||
|
||||
/**告警前转接口对象信息状态 */
|
||||
let forwardState: ModalStateType = reactive({
|
||||
title:t('views.faultManage.faultSetting.forwardSet'),
|
||||
title: t('views.faultManage.faultSetting.forwardSet'),
|
||||
from: {
|
||||
interface: 'email',
|
||||
emailObj: [],
|
||||
@@ -128,11 +128,15 @@ function fnFormForwardFinish() {
|
||||
forwardStateFrom.validate().then(() => {
|
||||
forwardState.confirmLoading = true;
|
||||
const from = toRaw(forwardState.from);
|
||||
console.log(from);
|
||||
updateForwardSet(from)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success( t('common.msgSuccess', { msg: t('views.faultManage.faultSetting.save')}), 3);
|
||||
message.success(
|
||||
t('common.msgSuccess', {
|
||||
msg: t('views.faultManage.faultSetting.save'),
|
||||
}),
|
||||
3
|
||||
);
|
||||
} else {
|
||||
message.warning(t('views.faultManage.faultSetting.noChange'), 3);
|
||||
}
|
||||
@@ -158,7 +162,6 @@ onMounted(() => {
|
||||
if (resArr[1].status === 'fulfilled') {
|
||||
const result = resArr[1].value;
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
console.log(result.data);
|
||||
let finalData: any = {
|
||||
emailObj: result.data[0]['to_user'],
|
||||
smsObj: result.data[1]['to_user'],
|
||||
@@ -273,12 +276,11 @@ onMounted(() => {
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<a-form
|
||||
name="forwardState"
|
||||
layout="horizontal"
|
||||
autocomplete="off"
|
||||
>
|
||||
<a-form-item :label="t('views.faultManage.faultSetting.interfaceType')" name="interface">
|
||||
<a-form name="forwardState" layout="horizontal" autocomplete="off">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.faultSetting.interfaceType')"
|
||||
name="interface"
|
||||
>
|
||||
<a-input value="Email" allow-clear disabled></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
@@ -292,7 +294,10 @@ onMounted(() => {
|
||||
:token-separators="[',']"
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('views.faultManage.faultSetting.interfaceType')" name="interface">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.faultSetting.interfaceType')"
|
||||
name="interface"
|
||||
>
|
||||
<a-input value="SMS" allow-clear disabled></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
|
||||
@@ -13,9 +13,11 @@ import {
|
||||
} from '@/api/faultManage/historyAlarm';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import saveAs from 'file-saver';
|
||||
import { writeSheet } from '@/utils/execl-utils';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { getDict } = useDictStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -555,6 +557,8 @@ onMounted(() => {
|
||||
dict.activeAlarmSeverity = resArr[3].value;
|
||||
}
|
||||
});
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore().fnNelist();
|
||||
fnGetList();
|
||||
});
|
||||
</script>
|
||||
@@ -574,10 +578,12 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.neType')"
|
||||
name="ne_type"
|
||||
>
|
||||
<a-input
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.ne_type"
|
||||
:options="neInfoStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
></a-input>
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
@@ -818,8 +824,9 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 详情框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:body-style="{ height: '520px', overflowY: 'scroll' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -1036,7 +1043,7 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -38,12 +38,12 @@ const statusBarChart = ref<any>(null);
|
||||
|
||||
/**网元状态字典数据 */
|
||||
let indexColor = ref<DictType[]>([
|
||||
{ label: 'Normal', value: 'normal', elTagType: '', elTagClass: '#91cc75' },
|
||||
{ label: 'Normal', value: 'normal', tagType: '', tagClass: '#91cc75' },
|
||||
{
|
||||
label: 'Abnormal',
|
||||
value: 'abnormal',
|
||||
elTagType: '',
|
||||
elTagClass: '#ee6666',
|
||||
tagType: '',
|
||||
tagClass: '#ee6666',
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -153,11 +153,10 @@ type nfStateType = {
|
||||
/**网元详细信息 */
|
||||
let pronInfo: nfStateType = reactive({
|
||||
hostName: '5gc',
|
||||
osInfo:
|
||||
'Linux 5gc 4.15.0-112-generic #113-Ubuntu SMP Thu Jul 9 23:41:39 UTC 2020 x86_64 GNU/Linux',
|
||||
dbInfo: 'adb v1.0.1',
|
||||
osInfo: 'Linux 5gc 4.15.0-112-generic 2020 x86_64 GNU/Linux',
|
||||
dbInfo: 'db v9.9.9',
|
||||
ipAddress: '-',
|
||||
port: 3030,
|
||||
port: 33030,
|
||||
version: '-',
|
||||
cpuUse: '-',
|
||||
memoryUse: '-',
|
||||
@@ -197,7 +196,7 @@ function fnGetList(one: boolean) {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
},
|
||||
color: indexColor.value.map(item => item.elTagClass),
|
||||
color: indexColor.value.map(item => item.tagClass),
|
||||
series: [
|
||||
{
|
||||
name: t('views.index.realNeStatus'),
|
||||
@@ -342,7 +341,7 @@ onBeforeUnmount(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer :breadcrumb="false">
|
||||
<PageContainer :breadcrumb="{}">
|
||||
<div>
|
||||
<a-drawer :visible="visible" @close="closeDrawer" :width="700">
|
||||
<a-descriptions bordered :column="1" :label-style="{ width: '160px' }">
|
||||
@@ -410,10 +409,7 @@ onBeforeUnmount(() => {
|
||||
</a-col>
|
||||
<a-col :lg="10" :md="8" :xs="24">
|
||||
<a-card :title="t('views.index.runStatus')" style="margin-bottom: 16px">
|
||||
<div
|
||||
style="width: 100%; min-height: 200px"
|
||||
ref="statusBar"
|
||||
></div>
|
||||
<div style="width: 100%; min-height: 200px" ref="statusBar"></div>
|
||||
</a-card>
|
||||
<a-card :title="t('views.index.mark')" style="margin-top: 16px">
|
||||
<a-descriptions
|
||||
|
||||
@@ -47,7 +47,7 @@ function fnFinish() {
|
||||
.fnLogin(toRaw(state.from))
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('views.login.loginSuccess'), 3);
|
||||
message.success(t('views.login.loginSuccess'), 1);
|
||||
/**登录后重定向页面 */
|
||||
const redirectPath = route.query?.redirect || '/index';
|
||||
router.push({ path: redirectPath as string });
|
||||
@@ -134,16 +134,6 @@ onMounted(() => {
|
||||
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');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -166,23 +156,6 @@ function fnClickHelpDoc(language?: string) {
|
||||
<img :src="logoUrl" class="logo-brand" :alt="appStore.appName" />
|
||||
</template>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<a-space direction="horizontal" :size="8">
|
||||
<a-button
|
||||
type="link"
|
||||
:href="appStore.officialUrl"
|
||||
target="_blank"
|
||||
size="small"
|
||||
v-if="appStore.officialUrl !== '#'"
|
||||
>
|
||||
{{ t('loayouts.basic.officialUrl') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="link" size="small" @click="fnClickHelpDoc()">
|
||||
{{ t('loayouts.basic.helpDoc') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<a-card :bordered="false" class="login-card">
|
||||
|
||||
@@ -551,7 +551,11 @@ function fnGetList(pageNum?: number) {
|
||||
}
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
if (tablePagination.total <=(queryParams.pageNum - 1) * tablePagination.pageSize &&queryParams.pageNum !== 1) {
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
@@ -841,8 +845,9 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 详情框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:visible="modalState.visibleByView"
|
||||
:title="modalState.title"
|
||||
@cancel="fnModalCancel"
|
||||
@@ -949,11 +954,13 @@ onMounted(() => {
|
||||
{{ t('common.close') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -1110,7 +1117,7 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 生成cron表达式 -->
|
||||
<CronModal
|
||||
|
||||
@@ -373,12 +373,16 @@ function fnGetList(pageNum?: number) {
|
||||
}
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
if (tablePagination.total <=(queryParams.pageNum - 1) * tablePagination.pageSize &&queryParams.pageNum !== 1) {
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
}
|
||||
tableState.loading = false;
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -628,8 +632,9 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 详情框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:visible="modalState.visibleByView"
|
||||
:title="modalState.title"
|
||||
@cancel="fnModalCancel"
|
||||
@@ -728,7 +733,7 @@ onMounted(() => {
|
||||
{{ t('common.close') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ let tableColumns: ColumnsType = [
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'num',
|
||||
width: '50px',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
customRender(opt) {
|
||||
const idxNum = (tablePagination.current - 1) * tablePagination.pageSize;
|
||||
return idxNum + opt.index + 1;
|
||||
@@ -54,17 +54,17 @@ let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('views.monitor.online.mettingId'),
|
||||
dataIndex: 'tokenId',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('views.monitor.online.account'),
|
||||
dataIndex: 'userName',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('views.monitor.online.host'),
|
||||
dataIndex: 'ipaddr',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
},
|
||||
// {
|
||||
// title: t('views.monitor.online.loginDes'),
|
||||
@@ -74,17 +74,17 @@ let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('views.monitor.online.os'),
|
||||
dataIndex: 'os',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('views.monitor.online.lib'),
|
||||
dataIndex: 'browser',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('views.monitor.online.loginTime'),
|
||||
dataIndex: 'loginTime',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
customRender(opt) {
|
||||
if (+opt.value <= 0) return '';
|
||||
return parseDateToStr(+opt.value);
|
||||
@@ -93,7 +93,7 @@ let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'tokenId',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -1566,9 +1566,6 @@ export function randerGroph(
|
||||
collapseArray
|
||||
);
|
||||
break;
|
||||
case 'restart':
|
||||
console.log('restart');
|
||||
break;
|
||||
case 'show':
|
||||
showItems(graph);
|
||||
break;
|
||||
|
||||
@@ -139,8 +139,7 @@ function fnGetList(refresh: boolean = false) {
|
||||
}
|
||||
})
|
||||
.then(hasNeList => {
|
||||
if (!hasNeList) return;
|
||||
console.log(graphG6Data)
|
||||
if (!hasNeList) return;
|
||||
if (refresh) {
|
||||
// graphG6.value.get('canvas').set('localRefresh', true);
|
||||
graphG6.value.destroy();
|
||||
|
||||
@@ -175,8 +175,10 @@ function fnModalCancel() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -1269,7 +1271,7 @@ function fnModalCancel() {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@@ -173,9 +173,7 @@ export default function useEdge() {
|
||||
edge.type = 'loop';
|
||||
}
|
||||
// 不存在fontWeight会触发异常
|
||||
if(!edge.labelCfg.style.fontWeight){
|
||||
console.log(edge)
|
||||
debugger
|
||||
if(!edge.labelCfg.style.fontWeight){
|
||||
edge.labelCfg.style.fontWeight = 500
|
||||
}
|
||||
// 存在更新,新增id是#不监听变化
|
||||
|
||||
@@ -94,7 +94,7 @@ export default function useGraph() {
|
||||
</div>`;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
console.log(target, item);
|
||||
// console.log(target, item);
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'create-edge':
|
||||
@@ -223,7 +223,7 @@ export default function useGraph() {
|
||||
`;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
console.log(target, item);
|
||||
// console.log(target, item);
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'edit':
|
||||
@@ -302,7 +302,7 @@ export default function useGraph() {
|
||||
`;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
console.log(target, item);
|
||||
// console.log(target, item);
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'edit':
|
||||
|
||||
@@ -142,7 +142,7 @@ function fnModalOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
// 根据类型选择函数
|
||||
const groupName = from.group.trim()
|
||||
const groupName = from.group.trim();
|
||||
saveGraphData(groupName, graphG6.value.save())
|
||||
.then((res: any) => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -325,8 +325,8 @@ onMounted(() => {
|
||||
<GraphEditModal></GraphEditModal>
|
||||
|
||||
<!-- 图保存图组名修改框 -->
|
||||
<a-modal
|
||||
width="500px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visible"
|
||||
@@ -359,7 +359,7 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { message } from 'ant-design-vue/lib';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import {
|
||||
getPara5GFilee,
|
||||
listNeInfo,
|
||||
savePara5GFile,
|
||||
updateNeInfo,
|
||||
} from '@/api/ne/neInfo';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import Para5GForm from './components/Para5GForm.vue';
|
||||
const { t } = useI18n();
|
||||
|
||||
/**对象信息信息状态类型 */
|
||||
type StateType = {
|
||||
/**保存选择同步到网元窗 */
|
||||
visible: boolean;
|
||||
/**网元选择 */
|
||||
neSelectOtions: any[];
|
||||
/**同步到网元 */
|
||||
sync: boolean;
|
||||
syncNe: string[];
|
||||
syncMsg: string;
|
||||
/**表单数据 */
|
||||
from: Record<string, any>;
|
||||
/**OMC信息,需修改当前的IP */
|
||||
omcInfo: Record<string, any>;
|
||||
/**根据网元显示配置项 */
|
||||
hasNE: {
|
||||
amf: boolean;
|
||||
upf: boolean;
|
||||
ims: boolean;
|
||||
mme: boolean;
|
||||
};
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
|
||||
/**对象信息状态 */
|
||||
let state: StateType = reactive({
|
||||
visible: false,
|
||||
neSelectOtions: [],
|
||||
sync: false,
|
||||
syncNe: [],
|
||||
syncMsg: '',
|
||||
from: {},
|
||||
omcInfo: {},
|
||||
hasNE: {
|
||||
amf: false,
|
||||
upf: false,
|
||||
ims: false,
|
||||
mme: false,
|
||||
},
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
/**对话框弹出确认执行函数*/
|
||||
function fnModalOk() {
|
||||
if (state.confirmLoading) return;
|
||||
state.confirmLoading = true;
|
||||
savePara5GFile({
|
||||
content: toRaw(state.from),
|
||||
syncNe: state.sync ? state.syncNe : [],
|
||||
})
|
||||
.then(res => {
|
||||
if (state.sync) {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
state.syncMsg = t('views.ne.neConfPara5G.syncNeDone');
|
||||
} else {
|
||||
state.syncMsg = res.msg;
|
||||
}
|
||||
} else {
|
||||
message.success(t('views.ne.neConfPara5G.saveOk'));
|
||||
// 更新omc_ip
|
||||
state.omcInfo.ip = state.from.sbi.omc_ip;
|
||||
updateNeInfo(toRaw(state.omcInfo));
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
state.confirmLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**对话框弹出关闭执行函数*/
|
||||
function fnModalCancel() {
|
||||
state.visible = false;
|
||||
state.sync = false;
|
||||
state.syncNe = [];
|
||||
state.syncMsg = '';
|
||||
}
|
||||
|
||||
/**保存文件数据*/
|
||||
function fnSaveData() {
|
||||
state.visible = true;
|
||||
}
|
||||
|
||||
/**获取文件数据*/
|
||||
function fnGetData() {
|
||||
state.confirmLoading = true;
|
||||
Promise.all([
|
||||
getPara5GFilee(),
|
||||
listNeInfo({
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
}),
|
||||
]).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].rows)
|
||||
) {
|
||||
for (const item of resArr[1].rows) {
|
||||
switch (item.neType) {
|
||||
case 'OMC':
|
||||
state.from.sbi.omc_ip = item.ip;
|
||||
Object.assign(state.omcInfo, item);
|
||||
break;
|
||||
case 'IMS':
|
||||
state.from.sbi.ims_ip = item.ip;
|
||||
// state.from.external.ims_sip_ip = item.ip;
|
||||
state.hasNE.ims = true;
|
||||
break;
|
||||
case 'AMF':
|
||||
state.from.sbi.amf_ip = item.ip;
|
||||
state.hasNE.amf = true;
|
||||
break;
|
||||
case 'AUSF':
|
||||
state.from.sbi.ausf_ip = item.ip;
|
||||
break;
|
||||
case 'UDM':
|
||||
state.from.sbi.udm_ip = item.ip;
|
||||
state.from.sbi.adb_ip = '0.0.0.0';
|
||||
break;
|
||||
case 'SMF':
|
||||
state.from.sbi.smf_ip = item.ip;
|
||||
break;
|
||||
case 'PCF':
|
||||
state.from.sbi.pcf_ip = item.ip;
|
||||
break;
|
||||
case 'NSSF':
|
||||
state.from.sbi.nssf_ip = item.ip;
|
||||
break;
|
||||
case 'NRF':
|
||||
state.from.sbi.nrf_ip = item.ip;
|
||||
break;
|
||||
case 'UPF':
|
||||
state.from.sbi.upf_ip = item.ip;
|
||||
state.hasNE.upf = true;
|
||||
break;
|
||||
case 'LMF':
|
||||
state.from.sbi.lmf_ip = item.ip;
|
||||
break;
|
||||
case 'NEF':
|
||||
state.from.sbi.nef_ip = item.ip;
|
||||
break;
|
||||
case 'MME':
|
||||
state.from.sbi.mme_ip = item.ip;
|
||||
if (item.ip.includes('.')) {
|
||||
state.from.external.mmes11_ip = item.ip + '/24';
|
||||
}
|
||||
state.hasNE.mme = true;
|
||||
break;
|
||||
case 'N3IWF':
|
||||
state.from.sbi.n3iwf_ip = item.ip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
state.confirmLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
useNeInfoStore()
|
||||
.fnNelist()
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
for (const row of res.data) {
|
||||
state.neSelectOtions.push({
|
||||
label: `[${row.neType} ${row.neId}] ${row.neName}`,
|
||||
value: `${row.neType}@${row.neId}`,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// 获取文件数据
|
||||
fnGetData();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card :bordered="false">
|
||||
<!-- 公共参数表单 -->
|
||||
<Para5GForm v-model:data="state.from" :ne="state.hasNE"></Para5GForm>
|
||||
|
||||
<div style="padding: 24px 12px 0; text-align: end">
|
||||
<a-space :size="8" align="center">
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="state.confirmLoading"
|
||||
@click="fnSaveData()"
|
||||
>
|
||||
<template #icon><SaveOutlined /></template>
|
||||
{{ t('views.ne.neConfPara5G.save') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="default"
|
||||
:loading="state.confirmLoading"
|
||||
@click.prevent="fnGetData()"
|
||||
>
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
{{ t('views.ne.neConfPara5G.reload') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-card>
|
||||
|
||||
<!-- 保存选择同步网元 -->
|
||||
<a-modal
|
||||
width="500px"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="state.visible"
|
||||
:title="t('views.ne.neConfPara5G.title')"
|
||||
:confirm-loading="state.confirmLoading"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="syncNeModal"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 5 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-form-item :label="t('views.ne.neConfPara5G.sync')" name="sync">
|
||||
<a-switch
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
v-model:checked="state.sync"
|
||||
:disabled="state.confirmLoading"
|
||||
></a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neConfPara5G.syncNe')"
|
||||
name="syncNe"
|
||||
v-if="state.sync"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="state.syncNe"
|
||||
mode="multiple"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:max-tag-count="3"
|
||||
:options="state.neSelectOtions"
|
||||
>
|
||||
<template #maxTagPlaceholder="omittedValues">
|
||||
<span>+ {{ omittedValues.length }} ...</span>
|
||||
</template>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="Sync Msg" name="syncMsg" v-if="state.syncMsg">
|
||||
<a-textarea
|
||||
:disabled="true"
|
||||
:value="state.syncMsg"
|
||||
:auto-size="{ minRows: 2, maxRows: 8 }"
|
||||
style="background-color: transparent; color: rgba(0, 0, 0, 0.85)"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
605
src/views/ne/neConfigBackup/index.vue
Normal file
605
src/views/ne/neConfigBackup/index.vue
Normal file
@@ -0,0 +1,605 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { Form, Modal, TableColumnsType, message } from 'ant-design-vue/lib';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import {
|
||||
delNeConfigBackup,
|
||||
downNeConfigBackup,
|
||||
listNeConfigBackup,
|
||||
updateNeConfigBackup,
|
||||
} from '@/api/ne/neConfigBackup';
|
||||
import saveAs from 'file-saver';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
|
||||
/**字典数据-状态 */
|
||||
let dictStatus = ref<DictType[]>([]);
|
||||
|
||||
/**网元参数 */
|
||||
let neOtions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: undefined,
|
||||
/**名称 */
|
||||
name: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
queryParams = Object.assign(queryParams, {
|
||||
neType: undefined,
|
||||
name: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: any[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: false,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<TableColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.common.neType'),
|
||||
dataIndex: 'neType',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.common.neId'),
|
||||
dataIndex: 'neId',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('common.createTime'),
|
||||
dataIndex: 'createTime',
|
||||
align: 'center',
|
||||
customRender(opt) {
|
||||
if (!opt.value) return '';
|
||||
return parseDateToStr(opt.value);
|
||||
},
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.neConfigBackup.name'),
|
||||
dataIndex: 'name',
|
||||
align: 'left',
|
||||
width: 200,
|
||||
resizable: true,
|
||||
minWidth: 100,
|
||||
maxWidth: 300,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: t('common.remark'),
|
||||
dataIndex: 'remark',
|
||||
key: 'remark',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
resizable: true,
|
||||
minWidth: 100,
|
||||
maxWidth: 300,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'id',
|
||||
align: 'left',
|
||||
},
|
||||
]);
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
current: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
/**默认的每页条数 */
|
||||
defaultPageSize: 20,
|
||||
/**指定每页可以显示多少条 */
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
/**只有一页时是否隐藏分页器 */
|
||||
hideOnSinglePage: false,
|
||||
/**是否可以快速跳转至某页 */
|
||||
showQuickJumper: true,
|
||||
/**是否可以改变 pageSize */
|
||||
showSizeChanger: true,
|
||||
/**数据总数 */
|
||||
total: 0,
|
||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
||||
onChange: (page: number, pageSize: number) => {
|
||||
tablePagination.current = page;
|
||||
tablePagination.pageSize = pageSize;
|
||||
queryParams.pageNum = page;
|
||||
queryParams.pageSize = pageSize;
|
||||
fnGetList();
|
||||
},
|
||||
});
|
||||
|
||||
/**表格紧凑型变更操作 */
|
||||
function fnTableSize({ key }: MenuInfo) {
|
||||
tableState.size = key as SizeType;
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
}
|
||||
|
||||
/**查询列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
listNeConfigBackup(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**信息文件下载 */
|
||||
function fnDownloadFile(row: Record<string, any>) {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.ne.neConfigBackup.downTip', { txt: row.name }),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
downNeConfigBackup(row.id)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 2,
|
||||
});
|
||||
saveAs(res.data, `${row.name}`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录删除
|
||||
* @param id 编号
|
||||
*/
|
||||
function fnRecordDelete(id: string) {
|
||||
if (!id || modalState.confirmLoading) return;
|
||||
let msg = id;
|
||||
if (id === '0') {
|
||||
msg = `...${tableState.selectedRowKeys.length}`;
|
||||
id = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.delTip', { msg }),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
delNeConfigBackup(id)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
fnGetList(1);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**新增框或修改框是否显示 */
|
||||
visibleByEdit: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**表单数据 */
|
||||
from: Record<string, any>;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
visibleByEdit: false,
|
||||
title: '备份记录',
|
||||
from: {
|
||||
id: undefined,
|
||||
name: '',
|
||||
remark: '',
|
||||
},
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
/**
|
||||
* 对话框弹出显示为 新增或者修改
|
||||
* @param noticeId 网元id, 不传为新增
|
||||
*/
|
||||
function fnModalVisibleByEdit(row: Record<string, any>) {
|
||||
if (modalState.confirmLoading) return;
|
||||
modalState.from.id = row.id;
|
||||
modalState.from.name = row.name;
|
||||
modalState.from.remark = row.remark;
|
||||
modalState.title = t('views.ne.neConfigBackup.title', { txt: row.id });
|
||||
modalState.visibleByEdit = true;
|
||||
}
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const modalStateFrom = Form.useForm(
|
||||
modalState.from,
|
||||
reactive({
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入名称',
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* 对话框弹出确认执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalOk() {
|
||||
modalStateFrom
|
||||
.validate()
|
||||
.then(e => {
|
||||
modalState.confirmLoading = true;
|
||||
const from = toRaw(modalState.from);
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
updateNeConfigBackup(from)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.msgSuccess', { msg: modalState.title }),
|
||||
duration: 3,
|
||||
});
|
||||
modalState.visibleByEdit = false;
|
||||
modalStateFrom.resetFields();
|
||||
fnGetList();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
fnGetList();
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出关闭执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.visibleByEdit = false;
|
||||
modalStateFrom.resetFields();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
getDict('ne_license_status').then(res => {
|
||||
dictStatus.value = res;
|
||||
});
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore()
|
||||
.fnNelist()
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
neOtions.value = useNeInfoStore().getNeSelectOtions;
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.common.neType')" name="neType ">
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="NE_TYPE_LIST.map(v => ({ value: v }))"
|
||||
:allow-clear="true"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.neConfigBackup.name')" name="name">
|
||||
<a-input
|
||||
v-model:value="queryParams.name"
|
||||
:allow-clear="true"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
v-perms:has="['ne:neConfigBackup:remove']"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="topRight">
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown placement="bottomRight" trigger="click">
|
||||
<a-button type="text">
|
||||
<template #icon><ColumnHeightOutlined /></template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="middle">
|
||||
{{ t('common.size.middle') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="small">
|
||||
{{ t('common.size.small') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 180 }"
|
||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
columnWidth: '48px',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'id'">
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.downloadText') }}</template>
|
||||
<a-button type="link" @click.prevent="fnDownloadFile(record)">
|
||||
<template #icon><DownloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.deleteText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.id)"
|
||||
v-perms:has="['ne:neConfigBackup:remove']"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.editText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalVisibleByEdit(record)"
|
||||
v-perms:has="['ne:neConfigBackup:edit']"
|
||||
>
|
||||
<template #icon><FormOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="512"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFrom"
|
||||
layout="horizontal"
|
||||
:wrapper-col="{ span: 18 }"
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neConfigBackup.name')"
|
||||
name="name"
|
||||
v-bind="modalStateFrom.validateInfos.name"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.name"
|
||||
:allow-clear="true"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('common.remark')"
|
||||
name="remark"
|
||||
v-bind="modalStateFrom.validateInfos.remark"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.remark"
|
||||
:auto-size="{ minRows: 2, maxRows: 6 }"
|
||||
:maxlength="400"
|
||||
:show-count="true"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -414,7 +414,7 @@ function fnModalTest() {
|
||||
const validateArr = ['title', 'addr', 'port', 'user'];
|
||||
if (form.authMode === '0') {
|
||||
validateArr.push('password');
|
||||
}
|
||||
}
|
||||
if (form.authMode === '1') {
|
||||
validateArr.push('privateKey');
|
||||
}
|
||||
@@ -626,8 +626,10 @@ onMounted(() => {
|
||||
</a-table>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -828,7 +830,7 @@ onMounted(() => {
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
@@ -497,8 +497,10 @@ onMounted(() => {
|
||||
</a-table>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -586,7 +588,7 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, toRaw, watch } from 'vue';
|
||||
import { Form, Modal, Upload, message } from 'ant-design-vue/lib';
|
||||
import { Form, Modal, Upload, message, notification } from 'ant-design-vue/lib';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||
import { FileType } from 'ant-design-vue/lib/upload/interface';
|
||||
import { FileType, UploadFile } from 'ant-design-vue/lib/upload/interface';
|
||||
import {
|
||||
exportSet,
|
||||
importFile,
|
||||
listServerFile,
|
||||
} from '@/api/configManage/neManage';
|
||||
exportNeConfigBackup,
|
||||
importNeConfigBackup,
|
||||
listNeConfigBackup,
|
||||
} from '@/api/ne/neConfigBackup';
|
||||
import saveAs from 'file-saver';
|
||||
import { uploadFile } from '@/api/tool/file';
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
|
||||
const props = defineProps({
|
||||
@@ -28,32 +30,49 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
/**表格所需option */
|
||||
const neManageOption = reactive({
|
||||
importType: [
|
||||
{ label: t('views.ne.neInfo.backConf.server'), value: 'server' },
|
||||
{ label: t('views.ne.neInfo.backConf.local'), value: 'local' },
|
||||
/**导入状态数据 */
|
||||
const importState = reactive({
|
||||
typeOption: [
|
||||
{ label: t('views.ne.neInfo.backConf.server'), value: 'backup' },
|
||||
{ label: t('views.ne.neInfo.backConf.local'), value: 'upload' },
|
||||
],
|
||||
serverFileName: <any[]>[],
|
||||
backupData: <any[]>[],
|
||||
});
|
||||
|
||||
/**查询网元远程服务器备份文件 */
|
||||
function typeChange(value: any) {
|
||||
if (value === 'server') {
|
||||
modalState.from.fileName = undefined;
|
||||
listServerFile(modalState.from).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
neManageOption.serverFileName = [];
|
||||
res.data.forEach((item: any) => {
|
||||
neManageOption.serverFileName.push({
|
||||
label: item.fileName,
|
||||
value: item.fileName,
|
||||
});
|
||||
function backupSearch(name?: string) {
|
||||
const { neType, neId } = modalState.from;
|
||||
listNeConfigBackup({
|
||||
neType,
|
||||
neId,
|
||||
name,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
}).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
importState.backupData = [];
|
||||
res.rows.forEach((item: any) => {
|
||||
importState.backupData.push({
|
||||
label: item.name,
|
||||
value: item.path,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
modalState.from.file = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**服务器备份文件选择切换 */
|
||||
function backupChange(value: any) {
|
||||
if (!value) {
|
||||
backupSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/**类型切换 */
|
||||
function typeChange(value: any) {
|
||||
modalState.from.path = undefined;
|
||||
if (value === 'backup') {
|
||||
backupSearch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,9 +86,8 @@ type ModalStateType = {
|
||||
from: {
|
||||
neType: string;
|
||||
neId: string;
|
||||
importType: 'local' | 'server';
|
||||
file: File | null;
|
||||
fileName: string | undefined;
|
||||
type: 'upload' | 'backup';
|
||||
path: string | undefined;
|
||||
};
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
@@ -84,9 +102,8 @@ let modalState: ModalStateType = reactive({
|
||||
from: {
|
||||
neType: '',
|
||||
neId: '',
|
||||
importType: 'local',
|
||||
file: null,
|
||||
fileName: undefined,
|
||||
type: 'upload',
|
||||
path: undefined,
|
||||
},
|
||||
confirmLoading: false,
|
||||
uploadFiles: [],
|
||||
@@ -96,16 +113,10 @@ let modalState: ModalStateType = reactive({
|
||||
const modalStateFrom = Form.useForm(
|
||||
modalState.from,
|
||||
reactive({
|
||||
file: [
|
||||
path: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.ne.neInfo.backConf.filePlease'),
|
||||
},
|
||||
],
|
||||
fileName: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.ne.neInfo.backConf.fileNamePlease'),
|
||||
message: t('views.ne.neInfo.backConf.pathPlease'),
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -117,21 +128,13 @@ const modalStateFrom = Form.useForm(
|
||||
*/
|
||||
function fnModalOk() {
|
||||
if (modalState.confirmLoading) return;
|
||||
|
||||
const from = toRaw(modalState.from);
|
||||
let validateName = ['importType'];
|
||||
if (from.importType === 'local') {
|
||||
validateName.push('file');
|
||||
} else {
|
||||
validateName.push('fileName');
|
||||
}
|
||||
|
||||
modalStateFrom
|
||||
.validate(validateName)
|
||||
.validate()
|
||||
.then(e => {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
importFile(from)
|
||||
importNeConfigBackup(from)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
@@ -168,6 +171,12 @@ function fnModalCancel() {
|
||||
emit('update:visible', false);
|
||||
}
|
||||
|
||||
/**表单上传前删除 */
|
||||
function fnBeforeRemoveFile(file: UploadFile) {
|
||||
modalState.from.path = undefined;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**表单上传前检查或转换压缩 */
|
||||
function fnBeforeUploadFile(file: FileType) {
|
||||
if (modalState.confirmLoading) return false;
|
||||
@@ -187,12 +196,30 @@ function fnBeforeUploadFile(file: FileType) {
|
||||
|
||||
/**表单上传文件 */
|
||||
function fnUploadFile(up: UploadRequestOption) {
|
||||
// 改为完成状态
|
||||
const file = modalState.uploadFiles[0];
|
||||
file.percent = 100;
|
||||
file.status = 'done';
|
||||
// 预置到表单
|
||||
modalState.from.file = up.file as File;
|
||||
// 发送请求
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
modalState.confirmLoading = true;
|
||||
let formData = new FormData();
|
||||
formData.append('file', up.file);
|
||||
formData.append('subPath', 'import');
|
||||
uploadFile(formData)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// 改为完成状态
|
||||
const file = modalState.uploadFiles[0];
|
||||
file.percent = 100;
|
||||
file.status = 'done';
|
||||
// 预置到表单
|
||||
const { fileName } = res.data;
|
||||
modalState.from.path = fileName;
|
||||
} else {
|
||||
message.error(res.msg, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
@@ -220,10 +247,17 @@ function fnExportConf(neType: string, neId: string) {
|
||||
content: t('views.ne.neInfo.backConf.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
exportSet({ neType, neId })
|
||||
exportNeConfigBackup({ neType, neId })
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('views.ne.neInfo.backConf.exportMsg'), 3);
|
||||
notification.success({
|
||||
message: t('common.tipTitle'),
|
||||
description: t('views.ne.neInfo.backConf.exportMsg'),
|
||||
});
|
||||
saveAs(
|
||||
res.data,
|
||||
`${neType}_${neId}_config_backup_${Date.now()}.zip`
|
||||
);
|
||||
} else {
|
||||
message.error(`${res.msg}`, 3);
|
||||
}
|
||||
@@ -244,8 +278,9 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -257,44 +292,44 @@ defineExpose({
|
||||
<a-form name="modalStateFrom" layout="horizontal" :label-col="{ span: 6 }">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.common.neType')"
|
||||
name="neType"
|
||||
v-bind="modalStateFrom.validateInfos.neType"
|
||||
>
|
||||
<a-form-item :label="t('views.ne.common.neType')" name="neType">
|
||||
{{ modalState.from.neType }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.backConf.importType')"
|
||||
name="importType"
|
||||
name="type"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.importType"
|
||||
v-model:value="modalState.from.type"
|
||||
default-value="server"
|
||||
:options="neManageOption.importType"
|
||||
:options="importState.typeOption"
|
||||
@change="typeChange"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.common.neId')"
|
||||
name="neId"
|
||||
v-bind="modalStateFrom.validateInfos.neId"
|
||||
>
|
||||
<a-form-item :label="t('views.ne.common.neId')" name="neId">
|
||||
{{ modalState.from.neId }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.backConf.server')"
|
||||
name="fileName"
|
||||
v-bind="modalStateFrom.validateInfos.fileName"
|
||||
v-if="modalState.from.importType === 'server'"
|
||||
v-bind="modalStateFrom.validateInfos.path"
|
||||
v-if="modalState.from.type === 'backup'"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.fileName"
|
||||
:options="neManageOption.serverFileName"
|
||||
v-model:value="modalState.from.path"
|
||||
:options="importState.backupData"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:show-search="true"
|
||||
:default-active-first-option="false"
|
||||
:show-arrow="false"
|
||||
:allow-clear="true"
|
||||
:filter-option="false"
|
||||
:not-found-content="null"
|
||||
@search="backupSearch"
|
||||
@change="backupChange"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
@@ -302,8 +337,8 @@ defineExpose({
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.backConf.local')"
|
||||
name="file"
|
||||
v-bind="modalStateFrom.validateInfos.file"
|
||||
v-if="modalState.from.importType === 'local'"
|
||||
v-bind="modalStateFrom.validateInfos.path"
|
||||
v-if="modalState.from.type === 'upload'"
|
||||
>
|
||||
<a-upload
|
||||
name="file"
|
||||
@@ -313,9 +348,10 @@ defineExpose({
|
||||
:max-count="1"
|
||||
:show-upload-list="{
|
||||
showPreviewIcon: false,
|
||||
showRemoveIcon: false,
|
||||
showRemoveIcon: true,
|
||||
showDownloadIcon: false,
|
||||
}"
|
||||
:remove="fnBeforeRemoveFile"
|
||||
:before-upload="fnBeforeUploadFile"
|
||||
:custom-request="fnUploadFile"
|
||||
:disabled="modalState.confirmLoading"
|
||||
@@ -331,7 +367,7 @@ defineExpose({
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { reactive, onMounted, toRaw, watch } from 'vue';
|
||||
import { message, Form, Modal } from 'ant-design-vue/lib';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
|
||||
import { getNeInfo, addNeInfo, updateNeInfo } from '@/api/ne/neInfo';
|
||||
@@ -124,9 +123,9 @@ let modalState: ModalStateType = reactive({
|
||||
title: 'SSH_NE_22',
|
||||
addr: '',
|
||||
port: 22,
|
||||
user: 'user',
|
||||
user: 'omcuser',
|
||||
authMode: '0',
|
||||
password: 'user',
|
||||
password: 'a9tU53r',
|
||||
privateKey: '',
|
||||
passPhrase: '',
|
||||
remark: '',
|
||||
@@ -138,9 +137,9 @@ let modalState: ModalStateType = reactive({
|
||||
title: 'Telnet_NE_4100',
|
||||
addr: '',
|
||||
port: 4100,
|
||||
user: 'user',
|
||||
user: 'admin',
|
||||
authMode: '0',
|
||||
password: 'user',
|
||||
password: 'admin',
|
||||
remark: '',
|
||||
},
|
||||
],
|
||||
@@ -250,9 +249,8 @@ function fnModalOk() {
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
// 刷新缓存的网元信息
|
||||
useNeInfoStore().fnRefreshNelist();
|
||||
emit('ok');
|
||||
// 返回无引用信息
|
||||
emit('ok', JSON.parse(JSON.stringify(from)));
|
||||
fnModalCancel();
|
||||
} else {
|
||||
message.error({
|
||||
@@ -349,8 +347,10 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -616,7 +616,9 @@ onMounted(() => {
|
||||
</a-divider>
|
||||
<a-collapse class="collapse" ghost>
|
||||
<a-collapse-panel
|
||||
v-for="host in modalState.from.hosts"
|
||||
v-for="host in modalState.from.hosts.filter(
|
||||
(s:any) => !(s.hostType === 'telnet' && modalState.from.neType === 'OMC')
|
||||
)"
|
||||
:key="host.title"
|
||||
:header="`${host.hostType.toUpperCase()} ${host.port}`"
|
||||
>
|
||||
@@ -755,7 +757,7 @@ onMounted(() => {
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@@ -161,8 +161,9 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DraggableModal
|
||||
width="500px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -290,7 +291,7 @@ watch(
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@@ -4,12 +4,12 @@ import useI18n from '@/hooks/useI18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { updateNeConfigReload } from '@/api/configManage/configParam';
|
||||
import { serviceNeAction } from '@/api/ne/neInfo';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
|
||||
export default function useNeOptions() {
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const lockedStore = useLockedStore();
|
||||
const maskStore = useMaskStore();
|
||||
|
||||
/**
|
||||
* 网元启动
|
||||
@@ -60,7 +60,7 @@ export default function useNeOptions() {
|
||||
// OMC自升级
|
||||
if (row.neType.toUpperCase() === 'OMC') {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
lockedStore.fnLock('reload');
|
||||
maskStore.handleMaskType('reload');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { listNeInfo, delNeInfo } from '@/api/ne/neInfo';
|
||||
import { listNeInfo, delNeInfo, stateNeInfo } from '@/api/ne/neInfo';
|
||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import useNeOptions from './hooks/useNeOptions';
|
||||
@@ -70,7 +70,7 @@ type TabeStateType = {
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
data: Record<string, any>[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
@@ -219,8 +219,33 @@ function fnModalVisibleByEdit(row?: Record<string, any>) {
|
||||
* 对话框弹出确认执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalEditOk() {
|
||||
fnGetList(1);
|
||||
function fnModalEditOk(from: Record<string, any>) {
|
||||
// 新增时刷新列表
|
||||
if (!from.id) {
|
||||
fnGetList();
|
||||
return;
|
||||
}
|
||||
// 编辑时局部更新信息
|
||||
stateNeInfo(from.neType, from.neId)
|
||||
.then(res => {
|
||||
// 找到编辑更新的网元
|
||||
const item = tableState.data.find(s => s.id === from.id);
|
||||
if (item && res.code === RESULT_CODE_SUCCESS) {
|
||||
item.neType = from.neType;
|
||||
item.neId = from.neId;
|
||||
item.rmUid = from.rmUid;
|
||||
item.neName = from.neName;
|
||||
item.ip = from.ip;
|
||||
item.port = from.port;
|
||||
item.status = res.data.online ? '1' : '0';
|
||||
Object.assign(item.serverState, res.data);
|
||||
const resouresUsage = parseResouresUsage(item.serverState);
|
||||
Reflect.set(item, 'resoures', resouresUsage);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
useNeInfoStore().fnRefreshNelist();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,6 +268,7 @@ function fnRecordDelete(id: string) {
|
||||
let msg = t('views.ne.neInfo.delTip');
|
||||
if (id === '0') {
|
||||
msg = `${msg} ...${tableState.selectedRowKeys.length}`;
|
||||
id = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
@@ -255,7 +281,16 @@ function fnRecordDelete(id: string) {
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
fnGetList(1);
|
||||
// 过滤掉删除的id
|
||||
tableState.data = tableState.data.filter(item => {
|
||||
if (id.indexOf(',') > -1) {
|
||||
return !tableState.selectedRowKeys.includes(item.id);
|
||||
} else {
|
||||
return item.id !== id;
|
||||
}
|
||||
});
|
||||
// 刷新缓存
|
||||
useNeInfoStore().fnRefreshNelist();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
@@ -330,56 +365,8 @@ function fnGetList(pageNum?: number) {
|
||||
// 遍历处理资源情况数值
|
||||
tableState.data = res.rows.map(item => {
|
||||
const neState = item.serverState;
|
||||
let sysCpuUsage = 0;
|
||||
let nfCpuUsage = 0;
|
||||
if (neState.cpu) {
|
||||
nfCpuUsage = neState.cpu.nfCpuUsage;
|
||||
if (nfCpuUsage > 100) {
|
||||
const nfCpu = +(neState.cpu.nfCpuUsage / 100);
|
||||
if (nfCpu > 100) {
|
||||
nfCpuUsage = 100;
|
||||
} else {
|
||||
nfCpuUsage = +nfCpu.toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
sysCpuUsage = neState.cpu.sysCpuUsage;
|
||||
if (sysCpuUsage > 100) {
|
||||
const sysCpu = +(neState.cpu.sysCpuUsage / 100);
|
||||
if (sysCpu > 100) {
|
||||
sysCpuUsage = 100;
|
||||
} else {
|
||||
sysCpuUsage = +sysCpu.toFixed(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let sysMemUsage = 0;
|
||||
if (neState.mem) {
|
||||
let men = neState.mem.sysMemUsage;
|
||||
if (men > 100) {
|
||||
men = +(men / 100).toFixed(2);
|
||||
}
|
||||
sysMemUsage = men;
|
||||
}
|
||||
|
||||
let sysDiskUsage = 0;
|
||||
if (neState.disk && Array.isArray(neState.disk.partitionInfo)) {
|
||||
let disks: any[] = neState.disk.partitionInfo;
|
||||
disks = disks.sort((a, b) => +b.used - +a.used);
|
||||
if (disks.length > 0) {
|
||||
const { total, used } = disks[0];
|
||||
sysDiskUsage = +((used / total) * 100).toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
Reflect.set(item, 'resoures', {
|
||||
sysDiskUsage,
|
||||
sysMemUsage,
|
||||
sysCpuUsage,
|
||||
nfCpuUsage,
|
||||
});
|
||||
|
||||
const resouresUsage = parseResouresUsage(neState);
|
||||
Reflect.set(item, 'resoures', resouresUsage);
|
||||
return item;
|
||||
});
|
||||
}
|
||||
@@ -387,6 +374,59 @@ function fnGetList(pageNum?: number) {
|
||||
});
|
||||
}
|
||||
|
||||
/**解析网元状态携带的资源利用率 */
|
||||
function parseResouresUsage(neState: Record<string, any>) {
|
||||
let sysCpuUsage = 0;
|
||||
let nfCpuUsage = 0;
|
||||
if (neState.cpu) {
|
||||
nfCpuUsage = neState.cpu.nfCpuUsage;
|
||||
if (nfCpuUsage > 100) {
|
||||
const nfCpu = +(neState.cpu.nfCpuUsage / 100);
|
||||
if (nfCpu > 100) {
|
||||
nfCpuUsage = 100;
|
||||
} else {
|
||||
nfCpuUsage = +nfCpu.toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
sysCpuUsage = neState.cpu.sysCpuUsage;
|
||||
if (sysCpuUsage > 100) {
|
||||
const sysCpu = +(neState.cpu.sysCpuUsage / 100);
|
||||
if (sysCpu > 100) {
|
||||
sysCpuUsage = 100;
|
||||
} else {
|
||||
sysCpuUsage = +sysCpu.toFixed(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let sysMemUsage = 0;
|
||||
if (neState.mem) {
|
||||
let men = neState.mem.sysMemUsage;
|
||||
if (men > 100) {
|
||||
men = +(men / 100).toFixed(2);
|
||||
}
|
||||
sysMemUsage = men;
|
||||
}
|
||||
|
||||
let sysDiskUsage = 0;
|
||||
if (neState.disk && Array.isArray(neState.disk.partitionInfo)) {
|
||||
let disks: any[] = neState.disk.partitionInfo;
|
||||
disks = disks.sort((a, b) => +b.used - +a.used);
|
||||
if (disks.length > 0) {
|
||||
const { total, used } = disks[0];
|
||||
sysDiskUsage = +((used / total) * 100).toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
sysDiskUsage,
|
||||
sysMemUsage,
|
||||
sysCpuUsage,
|
||||
nfCpuUsage,
|
||||
};
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([getDict('ne_info_status')]).then(resArr => {
|
||||
@@ -518,7 +558,7 @@ onMounted(() => {
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 150 }"
|
||||
:scroll="{ x: tableColumns.length * 120 }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
columnWidth: '48px',
|
||||
|
||||
@@ -282,8 +282,10 @@ onMounted(() => {});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -387,7 +389,7 @@ onMounted(() => {});
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@@ -97,6 +97,12 @@ async function fnModalOk() {
|
||||
]),
|
||||
duration: 4.5,
|
||||
});
|
||||
} else {
|
||||
notification.success({
|
||||
message: modalState.title,
|
||||
description: t('views.ne.neLicense.uploadChangeOk'),
|
||||
duration: 4.5,
|
||||
});
|
||||
}
|
||||
|
||||
// 结束
|
||||
@@ -179,8 +185,9 @@ onMounted(() => {});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="500px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByUploadFile"
|
||||
@@ -236,7 +243,7 @@ onMounted(() => {});
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@@ -64,9 +64,9 @@ let modalState: ModalStateType = reactive({
|
||||
title: 'SSH_NE_22',
|
||||
addr: '',
|
||||
port: 22,
|
||||
user: 'user',
|
||||
authMode: '0',
|
||||
password: 'user',
|
||||
user: 'omcuser',
|
||||
authMode: '2',
|
||||
password: '',
|
||||
privateKey: '',
|
||||
passPhrase: '',
|
||||
remark: '',
|
||||
|
||||
@@ -157,11 +157,7 @@ type StateType = {
|
||||
optionType: 'upload' | 'option';
|
||||
/**文件上传 */
|
||||
visibleByFile: boolean;
|
||||
/**
|
||||
* 依赖包类型
|
||||
* IMS-rtproxy/mf/adb
|
||||
* UDM-adb
|
||||
*/
|
||||
/**网元拓展包列表类型 */
|
||||
depType: string[];
|
||||
/**软件包信息数据 */
|
||||
from: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, watch } from 'vue';
|
||||
import { ref, watch } from 'vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['update:data']);
|
||||
@@ -21,109 +21,66 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type StateType = {
|
||||
/**表单数据 */
|
||||
from: Record<string, any>;
|
||||
/**根据网元显示配置项 */
|
||||
hasNE: {
|
||||
amf: boolean;
|
||||
upf: boolean;
|
||||
ims: boolean;
|
||||
mme: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let state: StateType = reactive({
|
||||
from: {
|
||||
basic: {
|
||||
plmnId: {
|
||||
mcc: '001',
|
||||
mnc: '01',
|
||||
},
|
||||
tac: '4388',
|
||||
snssai: {
|
||||
sst: '1',
|
||||
sd: '000001',
|
||||
},
|
||||
dnn_data: 'internet',
|
||||
dnn_ims: 'ims',
|
||||
/**表单信息状态 */
|
||||
let fromState = ref({
|
||||
basic: {
|
||||
plmnId: {
|
||||
mcc: '001',
|
||||
mnc: '01',
|
||||
},
|
||||
external: {
|
||||
amfn2_ip: '192.168.8.120',
|
||||
upfn3_ip: '192.168.8.190/24',
|
||||
upfn3_gw: '192.168.1.1',
|
||||
upfn6_ip: '192.168.8.191/24',
|
||||
upfn6_gw: '192.168.1.1',
|
||||
ue_pool: '10.2.1.0/24',
|
||||
// 非指定属性
|
||||
mmes1_ip: '192.168.8.220/20',
|
||||
mmes10_ip: '172.16.5.221/24',
|
||||
mmes11_ip: '172.16.5.220/24',
|
||||
ims_sip_ip: '192.168.8.110',
|
||||
upf_type: 'LightUPF',
|
||||
upfn3_pci: '0000:00:00.0',
|
||||
upfn3_mac: '00:00:00:00:00:00',
|
||||
upfn6_pci: '0000:00:00.0',
|
||||
upfn6_mac: '00:00:00:00:00:00',
|
||||
},
|
||||
sbi: {
|
||||
omc_ip: '172.16.5.100',
|
||||
ims_ip: '172.16.5.110',
|
||||
amf_ip: '172.16.5.120',
|
||||
ausf_ip: '172.16.5.130',
|
||||
udm_ip: '172.16.5.140',
|
||||
adb_ip: '0.0.0.0',
|
||||
smf_ip: '172.16.5.150',
|
||||
pcf_ip: '172.16.5.160',
|
||||
nssf_ip: '172.16.5.170',
|
||||
nrf_ip: '172.16.5.180',
|
||||
upf_ip: '172.16.5.190',
|
||||
lmf_ip: '172.16.5.200',
|
||||
nef_ip: '172.16.5.210',
|
||||
mme_ip: '172.16.5.220',
|
||||
n3iwf_ip: '172.16.5.230',
|
||||
tac: '4388',
|
||||
snssai: {
|
||||
sst: '1',
|
||||
sd: '000001',
|
||||
},
|
||||
dnn_data: 'internet',
|
||||
dnn_ims: 'ims',
|
||||
},
|
||||
hasNE: {
|
||||
amf: false,
|
||||
upf: false,
|
||||
ims: false,
|
||||
mme: false,
|
||||
external: {
|
||||
amfn2_ip: '192.168.8.120',
|
||||
upfn3_ip: '192.168.8.190/24',
|
||||
upfn3_gw: '192.168.1.1',
|
||||
upfn6_ip: '192.168.8.191/24',
|
||||
upfn6_gw: '192.168.1.1',
|
||||
ue_pool: '10.2.1.0/24',
|
||||
// 非指定属性
|
||||
mmes1_ip: '192.168.8.220/20',
|
||||
mmes10_ip: '172.16.5.221/24',
|
||||
mmes11_ip: '172.16.5.220/24',
|
||||
ims_sip_ip: '192.168.8.110',
|
||||
upf_type: 'LightUPF',
|
||||
upfn3_pci: '0000:00:00.0',
|
||||
upfn3_mac: '00:00:00:00:00:00',
|
||||
upfn6_pci: '0000:00:00.0',
|
||||
upfn6_mac: '00:00:00:00:00:00',
|
||||
},
|
||||
sbi: {
|
||||
omc_ip: '172.16.5.100',
|
||||
ims_ip: '172.16.5.110',
|
||||
amf_ip: '172.16.5.120',
|
||||
ausf_ip: '172.16.5.130',
|
||||
udm_ip: '172.16.5.140',
|
||||
db_ip: '0.0.0.0',
|
||||
smf_ip: '172.16.5.150',
|
||||
pcf_ip: '172.16.5.160',
|
||||
nssf_ip: '172.16.5.170',
|
||||
nrf_ip: '172.16.5.180',
|
||||
upf_ip: '172.16.5.190',
|
||||
lmf_ip: '172.16.5.200',
|
||||
nef_ip: '172.16.5.210',
|
||||
mme_ip: '172.16.5.220',
|
||||
n3iwf_ip: '172.16.5.230',
|
||||
},
|
||||
});
|
||||
|
||||
/**监听数据 */
|
||||
watch(
|
||||
() => props.data,
|
||||
val => {
|
||||
if (val) {
|
||||
Object.assign(state.from, val);
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.ne,
|
||||
val => {
|
||||
if (val) {
|
||||
Object.assign(state.hasNE, val);
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => state.from,
|
||||
() => fromState,
|
||||
val => {
|
||||
if (val) emit('update:data', val);
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -140,7 +97,7 @@ onMounted(() => {});
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="DNN_DATA" name="basic.dnn_data">
|
||||
<a-input
|
||||
v-model:value="state.from.basic.dnn_data"
|
||||
v-model:value="fromState.basic.dnn_data"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -155,13 +112,13 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
<a-form-item label="MCC" name="basic.plmnId.mcc">
|
||||
<a-input
|
||||
v-model:value="state.from.basic.plmnId.mcc"
|
||||
v-model:value="fromState.basic.plmnId.mcc"
|
||||
placeholder="1-65535"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="SST" name="basic.snssai.sst">
|
||||
<a-input-number
|
||||
v-model:value="state.from.basic.snssai.sst"
|
||||
v-model:value="fromState.basic.snssai.sst"
|
||||
:min="1"
|
||||
:max="3"
|
||||
placeholder="1-3"
|
||||
@@ -177,7 +134,7 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
<a-form-item label="TAC" name="basic.tac">
|
||||
<a-input
|
||||
v-model:value="state.from.basic.tac"
|
||||
v-model:value="fromState.basic.tac"
|
||||
placeholder="1-65535"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
@@ -185,7 +142,7 @@ onMounted(() => {});
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="DNN_IMS" name="basic.dnn_ims">
|
||||
<a-input
|
||||
v-model:value="state.from.basic.dnn_ims"
|
||||
v-model:value="fromState.basic.dnn_ims"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -194,13 +151,13 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
<a-form-item label="MNC" name="basic.plmnId.mnc">
|
||||
<a-input
|
||||
v-model:value="state.from.basic.plmnId.mnc"
|
||||
v-model:value="fromState.basic.plmnId.mnc"
|
||||
placeholder="1-65535"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="SD" name="basic.snssai.sd">
|
||||
<a-input
|
||||
v-model:value="state.from.basic.snssai.sd"
|
||||
v-model:value="fromState.basic.snssai.sd"
|
||||
placeholder="1-65535"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
@@ -213,14 +170,14 @@ onMounted(() => {});
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item
|
||||
label="EMS_IP"
|
||||
label="OMC_IP"
|
||||
name="sbi.omc_ip"
|
||||
:required="true"
|
||||
:validate-on-rule-change="false"
|
||||
:validateTrigger="[]"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="state.from.sbi.omc_ip"
|
||||
v-model:value="fromState.sbi.omc_ip"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -237,14 +194,13 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<template v-if="state.hasNE.amf">
|
||||
<template v-if="props.ne.amf">
|
||||
<a-divider orientation="left">AMF</a-divider>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="N2_IP" name="external.amfn2_ip">
|
||||
<a-input
|
||||
v-model:value="state.from.external.amfn2_ip"
|
||||
v-model:value="fromState.external.amfn2_ip"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -262,7 +218,7 @@ onMounted(() => {});
|
||||
</template>
|
||||
</a-col>
|
||||
|
||||
<a-col :lg="16" :md="16" :xs="24" v-if="state.hasNE.upf">
|
||||
<a-col :lg="16" :md="16" :xs="24" v-if="props.ne.upf">
|
||||
<a-divider orientation="left">UPF</a-divider>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -272,7 +228,7 @@ onMounted(() => {});
|
||||
help="Install of Standard or Light"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="state.from.external.upf_type"
|
||||
v-model:value="fromState.external.upf_type"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
>
|
||||
<a-select-option value="StandardUPF">
|
||||
@@ -285,7 +241,7 @@ onMounted(() => {});
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="UE_POOL" name="external.ue_pool">
|
||||
<a-input
|
||||
v-model:value="state.from.external.ue_pool"
|
||||
v-model:value="fromState.external.ue_pool"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -305,7 +261,7 @@ onMounted(() => {});
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="N3_IP" name="external.upfn3_ip">
|
||||
<a-input
|
||||
v-model:value="state.from.external.upfn3_ip"
|
||||
v-model:value="fromState.external.upfn3_ip"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -320,7 +276,7 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
<a-form-item label="N3_GW" name="external.upfn3_gw">
|
||||
<a-input
|
||||
v-model:value="state.from.external.upfn3_gw"
|
||||
v-model:value="fromState.external.upfn3_gw"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -334,10 +290,15 @@ onMounted(() => {});
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-col
|
||||
:lg="12"
|
||||
:md="12"
|
||||
:xs="24"
|
||||
v-if="fromState.external.upf_type === 'StandardUPF'"
|
||||
>
|
||||
<a-form-item label="N3_PCI" name="external.upfn3_pci">
|
||||
<a-input
|
||||
v-model:value="state.from.external.upfn3_pci"
|
||||
v-model:value="fromState.external.upfn3_pci"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -354,7 +315,7 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
<a-form-item label="N3_MAC" name="external.upfn3_mac">
|
||||
<a-input
|
||||
v-model:value="state.from.external.upfn3_mac"
|
||||
v-model:value="fromState.external.upfn3_mac"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -371,12 +332,12 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<template v-if="state.from.external.upf_type === 'StandardUPF'">
|
||||
<template v-if="fromState.external.upf_type === 'StandardUPF'">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="N6_IP" name="external.upfn6_ip">
|
||||
<a-input
|
||||
v-model:value="state.from.external.upfn6_ip"
|
||||
v-model:value="fromState.external.upfn6_ip"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -385,7 +346,7 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
<a-form-item label="N6_GW" name="external.upfn6_gw">
|
||||
<a-input
|
||||
v-model:value="state.from.external.upfn6_gw"
|
||||
v-model:value="fromState.external.upfn6_gw"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -396,7 +357,7 @@ onMounted(() => {});
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="N6_PCI" name="external.upfn6_pci">
|
||||
<a-input
|
||||
v-model:value="state.from.external.upfn6_pci"
|
||||
v-model:value="fromState.external.upfn6_pci"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -405,7 +366,7 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
<a-form-item label="N6_MAC" name="external.upfn6_mac">
|
||||
<a-input
|
||||
v-model:value="state.from.external.upfn6_mac"
|
||||
v-model:value="fromState.external.upfn6_mac"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -418,13 +379,13 @@ onMounted(() => {});
|
||||
</a-col>
|
||||
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<template v-if="state.hasNE.ims">
|
||||
<template v-if="props.ne.ims">
|
||||
<a-divider orientation="left">IMS</a-divider>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="SIP_IP" name="external.ims_sip_ip">
|
||||
<a-input
|
||||
v-model:value="state.from.external.ims_sip_ip"
|
||||
v-model:value="fromState.external.ims_sip_ip"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -441,13 +402,13 @@ onMounted(() => {});
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<template v-if="state.hasNE.mme">
|
||||
<template v-if="props.ne.mme">
|
||||
<a-divider orientation="left">MME</a-divider>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="S1_IP" name="external.mmes1_ip">
|
||||
<a-input
|
||||
v-model:value="state.from.external.mmes1_ip"
|
||||
v-model:value="fromState.external.mmes1_ip"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -466,7 +427,7 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
<a-form-item label="S10_IP" name="external.mmes10_ip">
|
||||
<a-input
|
||||
v-model:value="state.from.external.mmes10_ip"
|
||||
v-model:value="fromState.external.mmes10_ip"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
@@ -481,7 +442,7 @@ onMounted(() => {});
|
||||
</a-form-item>
|
||||
<a-form-item label="S11_IP" name="external.mmes11_ip">
|
||||
<a-input
|
||||
v-model:value="state.from.external.mmes11_ip"
|
||||
v-model:value="fromState.external.mmes11_ip"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user