Compare commits
216
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72fd372fe0 | ||
|
|
acdadcbb6f | ||
|
|
7a49de71ea | ||
|
|
56e4419e77 | ||
|
|
3abb4dd4bd | ||
|
|
726a284ab5 | ||
|
|
a45243390b | ||
|
|
1faed9bc3d | ||
|
|
9bd700eeb7 | ||
|
|
5cc3b9c8cf | ||
|
|
208895c7d5 | ||
|
|
46578ce97b | ||
|
|
0ff5bd5e20 | ||
|
|
f08e637e69 | ||
|
|
a600e056b8 | ||
|
|
671c80972e | ||
|
|
d07230b582 | ||
|
|
35c24407ac | ||
|
|
cf33756548 | ||
|
|
1ef98298bc | ||
|
|
b1c2a95ec4 | ||
|
|
147b2fad8d | ||
|
|
b629088406 | ||
|
|
430a067280 | ||
|
|
8a71e8f773 | ||
|
|
ff556ce1ec | ||
|
|
9ed7aed4b4 | ||
|
|
9e14297488 | ||
|
|
8e70706ed5 | ||
|
|
3e0529cf87 | ||
|
|
91af2bed92 | ||
|
|
1ecefb91dc | ||
|
|
72d9895902 | ||
|
|
41fa214137 | ||
|
|
1565f25a03 | ||
|
|
c5c2926d99 | ||
|
|
55456f9220 | ||
|
|
cf1686c348 | ||
|
|
f7833bcd9f | ||
|
|
5a621053a4 | ||
|
|
2a6451ef2a | ||
|
|
f1b440c8dd | ||
|
|
a67e54ca6e | ||
|
|
53d9e63c36 | ||
|
|
b4623d19e5 | ||
|
|
700bff6e38 | ||
|
|
d77c4e43d4 | ||
|
|
6e11d2b16a | ||
|
|
405842bc0b | ||
|
|
bf8d7f2124 | ||
|
|
ba98b37306 | ||
|
|
aa8ed65fd8 | ||
|
|
936a4410b3 | ||
|
|
58ec76f9e5 | ||
|
|
c1a77c8e48 | ||
|
|
477e8e4631 | ||
|
|
4f9d65a3a7 | ||
|
|
b1799d8ccb | ||
|
|
86833e7d6b | ||
|
|
59cf57898b | ||
|
|
fb9382e3a0 | ||
|
|
dae4697cd2 | ||
|
|
1b2e892f74 | ||
|
|
c66c640f75 | ||
|
|
30849416b6 | ||
|
|
5edcee8da5 | ||
|
|
311beed2a7 | ||
|
|
eb5fdfb635 | ||
|
|
78bcde9ef2 | ||
|
|
630e2a16ad | ||
|
|
e1fe031f25 | ||
|
|
855ba7dc9e | ||
|
|
3a72e73d5d | ||
|
|
4cb13a1419 | ||
|
|
8dd84a5255 | ||
|
|
c0e62f48b7 | ||
|
|
b992225e28 | ||
|
|
2f04562a34 | ||
|
|
d3a452cfd8 | ||
|
|
d81b8cdf38 | ||
|
|
39a417368a | ||
|
|
adfce5d2f7 | ||
|
|
977286d6b3 | ||
|
|
c33000045a | ||
|
|
b995ac378a | ||
|
|
6bea64f345 | ||
|
|
94886e255e | ||
|
|
45f66afe52 | ||
|
|
b9105c1e77 | ||
|
|
909d306942 | ||
|
|
f7273457e9 | ||
|
|
2e5ad2f65d | ||
|
|
776e9c5837 | ||
|
|
0d4979d3d9 | ||
|
|
686c7dd273 | ||
|
|
d41b308c6d | ||
|
|
84dac247d2 | ||
|
|
f8439bb40a | ||
|
|
d268d920e7 | ||
|
|
f730ef1e3a | ||
|
|
af1ce32063 | ||
|
|
678ff2d09d | ||
|
|
48f674b6ef | ||
|
|
02f0820a69 | ||
|
|
ca8605fd6e | ||
|
|
6d5e96421b | ||
|
|
bcc29007bf | ||
|
|
bdf904078d | ||
|
|
e37cfa5066 | ||
|
|
f1bff23bbc | ||
|
|
53106ddb5c | ||
|
|
3a04882fe5 | ||
|
|
19202a5e81 | ||
|
|
7b311ff673 | ||
|
|
9dba98e0ee | ||
|
|
71338670f0 | ||
|
|
7dcdfabce2 | ||
|
|
ddfe1723c9 | ||
|
|
57b5f76db7 | ||
|
|
9ac3524877 | ||
|
|
ca82a0a74b | ||
|
|
23007c3bf2 | ||
|
|
5d69d7612a | ||
|
|
ddd8930af4 | ||
|
|
757f2ec20a | ||
|
|
30caa79424 | ||
|
|
e3f83a0b98 | ||
|
|
147a3ed77b | ||
|
|
5d35d950b3 | ||
|
|
6874508d3f | ||
|
|
33f468209a | ||
|
|
e8ef2816df | ||
|
|
e38d7bbffa | ||
|
|
2f1265c47a | ||
|
|
66b6b60505 | ||
|
|
249d14320d | ||
|
|
313b90ad31 | ||
|
|
2ebc90e974 | ||
|
|
640257dd55 | ||
|
|
c1a3ce8068 | ||
|
|
0080e9c26e | ||
|
|
2ccafe622d | ||
|
|
d7a515ed9a | ||
|
|
cd82b71b77 | ||
|
|
9d6a7dcd9c | ||
|
|
46c2affcc8 | ||
|
|
3d00a80588 | ||
|
|
a3c1fe154f | ||
|
|
07dce5a27e | ||
|
|
255cf026a6 | ||
|
|
840ea56c42 | ||
|
|
09917cc9c9 | ||
|
|
4c9fe192f2 | ||
|
|
32ec55d44e | ||
|
|
527cf89d1a | ||
|
|
ac7b57c0ae | ||
|
|
8be1a8968e | ||
|
|
999ccf64ad | ||
|
|
03352f3aa8 | ||
|
|
61a58fc661 | ||
|
|
4268fa3198 | ||
|
|
f6b62c6c7e | ||
|
|
b4cbc1c190 | ||
|
|
1871f6f656 | ||
|
|
409f9836a6 | ||
|
|
b3f40ee683 | ||
|
|
aa07b51663 | ||
|
|
19b77ed005 | ||
|
|
06503fd079 | ||
|
|
2321dacd2a | ||
|
|
a8b4e91b95 | ||
|
|
a5075bef43 | ||
|
|
f4ffbc1c86 | ||
|
|
6cafa284c7 | ||
|
|
049c0e7a0f | ||
|
|
377ffc6e10 | ||
|
|
858431e86e | ||
|
|
70fca5ca41 | ||
|
|
e972d14a9a | ||
|
|
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 |
No files matched your search
+3
-3
@@ -5,13 +5,13 @@ VITE_HISTORY_HASH = false
|
|||||||
VITE_HISTORY_BASE_URL = "/"
|
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.240704"
|
VITE_APP_VERSION = "2.241018"
|
||||||
|
|
||||||
# 接口基础URL地址-不带/后缀
|
# 接口基础URL地址-不带/后缀
|
||||||
VITE_API_BASE_URL = "/omc-api"
|
VITE_API_BASE_URL = "/omc-api"
|
||||||
+3
-3
@@ -5,13 +5,13 @@ VITE_HISTORY_HASH = true
|
|||||||
VITE_HISTORY_BASE_URL = "/"
|
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.240704"
|
VITE_APP_VERSION = "2.241018"
|
||||||
|
|
||||||
# 接口基础URL地址-不带/后缀
|
# 接口基础URL地址-不带/后缀
|
||||||
VITE_API_BASE_URL = "/omc-api"
|
VITE_API_BASE_URL = "/omc-api"
|
||||||
@@ -8,14 +8,8 @@
|
|||||||
## 测试环境
|
## 测试环境
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Jenkins: http://192.168.2.166:3185/
|
|
||||||
Nginx: http://192.168.2.166:3188/#/index
|
Nginx: http://192.168.2.166:3188/#/index
|
||||||
后端暴露端口: http://192.168.2.166:33030
|
后端暴露端口: http://192.168.2.166:33030
|
||||||
|
|
||||||
|
|
||||||
新网管:192.168.5.13
|
|
||||||
旧网管:192.168.5.14
|
|
||||||
登录账户:manager/manager
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 程序命令
|
## 程序命令
|
||||||
@@ -59,16 +53,5 @@ export NODE_OPTIONS=--max-old-space-size=50000
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
https://192.168.5.23/
|
https://192.168.5.23/
|
||||||
admin
|
admin / admin
|
||||||
admin
|
|
||||||
```
|
|
||||||
|
|
||||||
## k8s
|
|
||||||
|
|
||||||
master 192.168.5.27 agtuser/admin123
|
|
||||||
|
|
||||||
https://192.168.5.27:31325/#/workloads?namespace=default
|
|
||||||
|
|
||||||
```text
|
|
||||||
eyJhbGciOiJSUzI1NiIsImtpZCI6ImZFVUhIb1puLW04M1dfSUYyRU8zWlZueXBpNUh4T0hTRVlzU19jNlVGQ0kifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLW44ZzRtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI2M2NmYjAyNS01ZmQ0LTQ0ZTgtOTdiNC0yYWRiYWIxNzc5M2MiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.R3GRygFOjngTj-mEMBAHDeBxm3lpsXZYvC6cdTxByONtLrcMXDebwNVeKtAZ1V9qh2OrjD8n9CIygjULGPdfV6S520vjMh7Oa2q68nOyW49DNWQyYD8xLo-dQ6sX07fI7X_I3H35YUWW80jJAXjJawqIGXBSMG5intlo4tLTUSXmjCfhoQvFsgeRWu0j76pDvhMAvLPcgEXfTCi9tyL3yqJBIKONcKwmMlJeaKSR3pQk3KiibqrBO0MZclRozpke6J0ulfzTemwDDyCqBZmLsRPZ2yDd5hVBIJ9bHEcK0a25NmSFFzmd8XWQPZwg3Y4IbbY-8UhByGq0p9xS-7pGCQ
|
|
||||||
```
|
```
|
||||||
+5
-2
@@ -18,7 +18,7 @@
|
|||||||
"@codemirror/lang-yaml": "^6.1.1",
|
"@codemirror/lang-yaml": "^6.1.1",
|
||||||
"@codemirror/merge": "^6.6.3",
|
"@codemirror/merge": "^6.6.3",
|
||||||
"@codemirror/theme-one-dark": "^6.1.2",
|
"@codemirror/theme-one-dark": "^6.1.2",
|
||||||
"@tato30/vue-pdf": "~1.9.7",
|
"@tato30/vue-pdf": "^1.10.0",
|
||||||
"@vueuse/core": "~10.10.1",
|
"@vueuse/core": "~10.10.1",
|
||||||
"@xterm/addon-fit": "^0.10.0",
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
"@xterm/xterm": "^5.5.0",
|
"@xterm/xterm": "^5.5.0",
|
||||||
@@ -26,10 +26,12 @@
|
|||||||
"antdv-pro-layout": "~3.3.5",
|
"antdv-pro-layout": "~3.3.5",
|
||||||
"antdv-pro-modal": "^3.1.0",
|
"antdv-pro-modal": "^3.1.0",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"echarts": "~5.5.0",
|
"echarts": "~5.5.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"intl-tel-input": "~23.0.12",
|
"grid-layout-plus": "^1.0.5",
|
||||||
|
"intl-tel-input": "^23.8.1",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
@@ -43,6 +45,7 @@
|
|||||||
"xlsx": "~0.18.5"
|
"xlsx": "~0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/node": "^18.0.0",
|
"@types/node": "^18.0.0",
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
*/
|
*/
|
||||||
(function () {
|
(function () {
|
||||||
// host = ip:port
|
// 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
|
// Service Address
|
||||||
sessionStorage.setItem('baseUrl', `http://${host}`);
|
sessionStorage.setItem('baseUrl', `http://${host}`);
|
||||||
|
|||||||
File renamed without changes.
Binary file not shown.
File diff suppressed because it is too large.
Load diff
Binary file not shown.
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,166 @@
|
|||||||
|
/**
|
||||||
|
* Wraps the WiregasmLib lib functionality and manages a single DissectSession
|
||||||
|
*/
|
||||||
|
class Wiregasm {
|
||||||
|
constructor() {
|
||||||
|
this.initialized = false;
|
||||||
|
this.session = null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initialize the wrapper and the Wiregasm module
|
||||||
|
*
|
||||||
|
* @param loader Loader function for the Emscripten module
|
||||||
|
* @param overrides Overrides
|
||||||
|
*/
|
||||||
|
async init(loader, overrides = {}, beforeInit = null) {
|
||||||
|
if (this.initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.lib = await loader(overrides);
|
||||||
|
this.uploadDir = this.lib.getUploadDirectory();
|
||||||
|
this.pluginsDir = this.lib.getPluginsDirectory();
|
||||||
|
if (beforeInit !== null) {
|
||||||
|
await beforeInit(this.lib);
|
||||||
|
}
|
||||||
|
this.lib.init();
|
||||||
|
this.initialized = true;
|
||||||
|
}
|
||||||
|
list_modules() {
|
||||||
|
return this.lib.listModules();
|
||||||
|
}
|
||||||
|
list_prefs(module) {
|
||||||
|
return this.lib.listPreferences(module);
|
||||||
|
}
|
||||||
|
apply_prefs() {
|
||||||
|
this.lib.applyPreferences();
|
||||||
|
}
|
||||||
|
set_pref(module, key, value) {
|
||||||
|
const ret = this.lib.setPref(module, key, value);
|
||||||
|
if (ret.code != PrefSetResult.PREFS_SET_OK) {
|
||||||
|
const message =
|
||||||
|
ret.error != '' ? ret.error : preferenceSetCodeToError(ret.code);
|
||||||
|
throw new Error(
|
||||||
|
`Failed to set preference (${module}.${key}): ${message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get_pref(module, key) {
|
||||||
|
const response = this.lib.getPref(module, key);
|
||||||
|
if (response.code != 0) {
|
||||||
|
throw new Error(`Failed to get preference (${module}.${key})`);
|
||||||
|
}
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Check the validity of a filter expression.
|
||||||
|
*
|
||||||
|
* @param filter A display filter expression
|
||||||
|
*/
|
||||||
|
test_filter(filter) {
|
||||||
|
return this.lib.checkFilter(filter);
|
||||||
|
}
|
||||||
|
complete_filter(filter) {
|
||||||
|
const out = this.lib.completeFilter(filter);
|
||||||
|
return {
|
||||||
|
err: out.err,
|
||||||
|
fields: vectorToArray(out.fields),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
reload_lua_plugins() {
|
||||||
|
this.lib.reloadLuaPlugins();
|
||||||
|
}
|
||||||
|
add_plugin(name, data, opts = {}) {
|
||||||
|
const path = this.pluginsDir + '/' + name;
|
||||||
|
this.lib.FS.writeFile(path, data, opts);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Load a packet trace file for analysis.
|
||||||
|
*
|
||||||
|
* @returns Response containing the status and summary
|
||||||
|
*/
|
||||||
|
load(name, data, opts = {}) {
|
||||||
|
if (this.session != null) {
|
||||||
|
this.session.delete();
|
||||||
|
}
|
||||||
|
const path = this.uploadDir + '/' + name;
|
||||||
|
this.lib.FS.writeFile(path, data, opts);
|
||||||
|
this.session = new this.lib.DissectSession(path);
|
||||||
|
return this.session.load();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get Packet List information for a range of packets.
|
||||||
|
*
|
||||||
|
* @param filter Output those frames that pass this filter expression
|
||||||
|
* @param skip Skip N frames
|
||||||
|
* @param limit Limit the output to N frames
|
||||||
|
*/
|
||||||
|
frames(filter, skip = 0, limit = 0) {
|
||||||
|
return this.session.getFrames(filter, skip, limit);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get full information about a frame including the protocol tree.
|
||||||
|
*
|
||||||
|
* @param number Frame number
|
||||||
|
*/
|
||||||
|
frame(num) {
|
||||||
|
return this.session.getFrame(num);
|
||||||
|
}
|
||||||
|
follow(follow, filter) {
|
||||||
|
return this.session.follow(follow, filter);
|
||||||
|
}
|
||||||
|
destroy() {
|
||||||
|
if (this.initialized) {
|
||||||
|
if (this.session !== null) {
|
||||||
|
this.session.delete();
|
||||||
|
this.session = null;
|
||||||
|
}
|
||||||
|
this.lib.destroy();
|
||||||
|
this.initialized = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the column headers
|
||||||
|
*/
|
||||||
|
columns() {
|
||||||
|
const vec = this.lib.getColumns();
|
||||||
|
// convert it from a vector to array
|
||||||
|
return vectorToArray(vec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Vector to a JS array
|
||||||
|
*
|
||||||
|
* @param vec Vector
|
||||||
|
* @returns JS array of the Vector contents
|
||||||
|
*/
|
||||||
|
function vectorToArray(vec) {
|
||||||
|
return new Array(vec.size()).fill(0).map((_, id) => vec.get(id));
|
||||||
|
}
|
||||||
|
function preferenceSetCodeToError(code) {
|
||||||
|
switch (code) {
|
||||||
|
case PrefSetResult.PREFS_SET_SYNTAX_ERR:
|
||||||
|
return 'Syntax error in string';
|
||||||
|
case PrefSetResult.PREFS_SET_NO_SUCH_PREF:
|
||||||
|
return 'No such preference';
|
||||||
|
case PrefSetResult.PREFS_SET_OBSOLETE:
|
||||||
|
return 'Preference used to exist but no longer does';
|
||||||
|
default:
|
||||||
|
return 'Unknown error';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof exports === 'object' && typeof module === 'object') {
|
||||||
|
module.exports = Wiregasm;
|
||||||
|
module.exports = vectorToArray;
|
||||||
|
} else if (typeof define === 'function' && define['amd']) {
|
||||||
|
define([], function () {
|
||||||
|
return Wiregasm;
|
||||||
|
});
|
||||||
|
define([], function () {
|
||||||
|
return vectorToArray;
|
||||||
|
});
|
||||||
|
} else if (typeof exports === 'object') {
|
||||||
|
exports['loadWiregasm'] = Wiregasm;
|
||||||
|
exports['vectorToArray'] = vectorToArray;
|
||||||
|
}
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
// load the Wiregasm library
|
||||||
|
importScripts(
|
||||||
|
'/wiregasm/wiregasm_new.js', // self-compilation es5
|
||||||
|
'/wiregasm/wiregasm_load.js'
|
||||||
|
// 'https://cdn.jsdelivr.net/npm/@goodtools/wiregasm/dist/wiregasm.js'
|
||||||
|
);
|
||||||
|
|
||||||
|
const wg = new Wiregasm();
|
||||||
|
|
||||||
|
const inflateRemoteBuffer = async url => {
|
||||||
|
const res = await fetch(url);
|
||||||
|
return await res.arrayBuffer();
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchPackages = async () => {
|
||||||
|
console.log('Fetching packages');
|
||||||
|
let [wasmBuffer, dataBuffer] = await Promise.all([
|
||||||
|
await inflateRemoteBuffer(
|
||||||
|
'/wiregasm/wiregasm.wasm'
|
||||||
|
// 'https://cdn.jsdelivr.net/npm/@goodtools/wiregasm/dist/wiregasm.wasm'
|
||||||
|
),
|
||||||
|
await inflateRemoteBuffer(
|
||||||
|
'/wiregasm/wiregasm.data'
|
||||||
|
// 'https://cdn.jsdelivr.net/npm/@goodtools/wiregasm/dist/wiregasm.data'
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return { wasmBuffer, dataBuffer };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load the Wiregasm Wasm data
|
||||||
|
fetchPackages()
|
||||||
|
.then(({ wasmBuffer, dataBuffer }) => {
|
||||||
|
return wg.init(loadWiregasm, {
|
||||||
|
wasmBinary: wasmBuffer,
|
||||||
|
getPreloadedPackage() {
|
||||||
|
return dataBuffer;
|
||||||
|
},
|
||||||
|
handleStatus: (type, status) => {
|
||||||
|
postMessage({ type: 'status', code: type, status: status });
|
||||||
|
},
|
||||||
|
printErr: error => {
|
||||||
|
postMessage({ type: 'error', error: error });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
postMessage({ type: 'init' });
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
postMessage({ type: 'error', error: e });
|
||||||
|
});
|
||||||
|
|
||||||
|
/**Converts a Vector to a JS array */
|
||||||
|
function replacer(key, value) {
|
||||||
|
if (value.constructor.name.startsWith('Vector')) {
|
||||||
|
return vectorToArray(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listener to receive messages from the main script
|
||||||
|
this.onmessage = ev => {
|
||||||
|
const data = ev.data;
|
||||||
|
switch (data.type) {
|
||||||
|
case 'close':
|
||||||
|
wg.destroy();
|
||||||
|
break;
|
||||||
|
case 'columns':
|
||||||
|
const columns = wg.columns();
|
||||||
|
if (Array.isArray(columns)) {
|
||||||
|
this.postMessage({ type: 'columns', data: columns });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'select': // select a frame
|
||||||
|
const number = data.number;
|
||||||
|
const frameData = wg.frame(number);
|
||||||
|
const frameDataToJSON = JSON.parse(JSON.stringify(frameData, replacer));
|
||||||
|
this.postMessage({
|
||||||
|
type: 'selected',
|
||||||
|
data: frameDataToJSON,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'frames': // get frames list
|
||||||
|
const skip = data.skip;
|
||||||
|
const limit = data.limit;
|
||||||
|
const filter = data.filter;
|
||||||
|
const framesData = wg.frames(filter, skip, limit);
|
||||||
|
const framesDataToJSON = JSON.parse(JSON.stringify(framesData, replacer));
|
||||||
|
this.postMessage({
|
||||||
|
type: 'frames',
|
||||||
|
data: framesDataToJSON,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'process-data':
|
||||||
|
const loadData = wg.load(data.name, new Uint8Array(data.data));
|
||||||
|
this.postMessage({ type: 'processed', data: loadData });
|
||||||
|
break;
|
||||||
|
case 'process':
|
||||||
|
const f = data.file;
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.addEventListener('load', event => {
|
||||||
|
// XXX: this blocks the worker thread
|
||||||
|
const loadData = wg.load(f.name, new Uint8Array(event.target.result));
|
||||||
|
postMessage({ type: 'processed', data: loadData });
|
||||||
|
});
|
||||||
|
reader.readAsArrayBuffer(f);
|
||||||
|
break;
|
||||||
|
case 'check-filter':
|
||||||
|
const filterStr = data.filter;
|
||||||
|
const checkFilterRes = wg.lib.checkFilter(filterStr);
|
||||||
|
this.postMessage({ type: 'filter', data: checkFilterRes });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.type === 'reload-quick') {
|
||||||
|
if (wg.session) {
|
||||||
|
// TODO: this is a hack, we should be able to reload the session
|
||||||
|
const name = data.name;
|
||||||
|
const res = wg.session.load();
|
||||||
|
|
||||||
|
postMessage({ type: 'processed', name: name, data: res });
|
||||||
|
}
|
||||||
|
} else if (data.type === 'module-tree') {
|
||||||
|
const res = wg.list_modules();
|
||||||
|
// send it to the correct port
|
||||||
|
event.ports[0].postMessage({
|
||||||
|
result: JSON.parse(JSON.stringify(res, replacer)),
|
||||||
|
});
|
||||||
|
} else if (data.type === 'module-prefs') {
|
||||||
|
const res = wg.list_prefs(data.name);
|
||||||
|
// send it to the correct port
|
||||||
|
event.ports[0].postMessage({
|
||||||
|
result: JSON.parse(JSON.stringify(res, replacer)),
|
||||||
|
});
|
||||||
|
} else if (data.type === 'upload-file') {
|
||||||
|
const f = data.file;
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.addEventListener('load', e => {
|
||||||
|
// XXX: this blocks the worker thread
|
||||||
|
const path = '/uploads/' + f.name;
|
||||||
|
wg.lib.FS.writeFile(path, Buffer.from(e.target.result));
|
||||||
|
event.ports[0].postMessage({ result: path });
|
||||||
|
});
|
||||||
|
reader.readAsArrayBuffer(f);
|
||||||
|
} else if (data.type === 'update-pref') {
|
||||||
|
try {
|
||||||
|
console.log(`set_pref(${data.module}, ${data.key}, ${data.value})`);
|
||||||
|
wg.set_pref(data.module, data.key, data.value);
|
||||||
|
event.ports[0].postMessage({ result: 'ok' });
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
`set_pref(${data.module}, ${data.key}, ${data.value}) failed: ${e.message}`
|
||||||
|
);
|
||||||
|
event.ports[0].postMessage({ error: e.message });
|
||||||
|
}
|
||||||
|
} else if (data.type === 'apply-prefs') {
|
||||||
|
console.log(`apply_prefs()`);
|
||||||
|
wg.apply_prefs();
|
||||||
|
event.ports[0].postMessage({ result: 'ok' });
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import {
|
|
||||||
RESULT_CODE_ERROR,
|
|
||||||
RESULT_CODE_SUCCESS,
|
|
||||||
RESULT_MSG_ERROR,
|
|
||||||
} from '@/constants/result-constants';
|
|
||||||
import { language, request } from '@/plugins/http-fetch';
|
|
||||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询配置详细
|
|
||||||
* @param tag 配置ID
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function getConfigInfo(tag: string) {
|
|
||||||
// 发起请求
|
|
||||||
const result = await request({
|
|
||||||
url: `/api/rest/databaseManagement/v1/omc_db/config`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
SQL: `SELECT * FROM config WHERE config_tag = '${tag}'`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
|
||||||
let data = result.data.data[0];
|
|
||||||
return Object.assign(result, {
|
|
||||||
data: parseObjLineToHump(data['config'][0]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改配置
|
|
||||||
* @param data 配置对象
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function updateConfig(tag: string, data: Record<string, any>) {
|
|
||||||
const result = await request({
|
|
||||||
url: `/api/rest/databaseManagement/v1/omc_db/config?WHERE=config_tag='${tag}'`,
|
|
||||||
method: 'put',
|
|
||||||
data: { data },
|
|
||||||
});
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS && result.data.data) {
|
|
||||||
let rows = result.data.data.affectedRows;
|
|
||||||
if (rows) {
|
|
||||||
delete result.data;
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return { code: RESULT_CODE_ERROR, msg: RESULT_MSG_ERROR[language] };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@@ -2,315 +2,8 @@ import {
|
|||||||
RESULT_CODE_ERROR,
|
RESULT_CODE_ERROR,
|
||||||
RESULT_CODE_SUCCESS,
|
RESULT_CODE_SUCCESS,
|
||||||
RESULT_MSG_ERROR,
|
RESULT_MSG_ERROR,
|
||||||
RESULT_MSG_SUCCESS,
|
|
||||||
} from '@/constants/result-constants';
|
} from '@/constants/result-constants';
|
||||||
import { language, request } from '@/plugins/http-fetch';
|
import { language, request } from '@/plugins/http-fetch';
|
||||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询配置参数标签栏
|
|
||||||
* @param neType 网元类型
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function getParamConfigTopTab(neType: string) {
|
|
||||||
// 发起请求
|
|
||||||
const result = await request({
|
|
||||||
url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/param_config`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
SQL: `SELECT id,top_display,top_tag,method FROM param_config WHERE ne_type = '${neType}' ORDER BY id ASC`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
|
||||||
let data = result.data.data[0];
|
|
||||||
data = data['param_config'];
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
return Object.assign(result, {
|
|
||||||
data: parseObjLineToHump(data),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return Object.assign(result, {
|
|
||||||
data: [],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询配置参数标签栏对应信息和规则
|
|
||||||
* @param neType 网元类型
|
|
||||||
* @param topTag
|
|
||||||
* @param neId
|
|
||||||
* @returns object { wrRule, dataArr }
|
|
||||||
*/
|
|
||||||
async function getParamConfigInfoAndRule(
|
|
||||||
neType: string,
|
|
||||||
topTag: string,
|
|
||||||
neId: string
|
|
||||||
) {
|
|
||||||
return await Promise.allSettled([
|
|
||||||
// 获取参数规则
|
|
||||||
request({
|
|
||||||
url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/param_config`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
SQL: `SELECT param_json FROM param_config WHERE ne_type = '${neType}' AND top_tag='${topTag}'`,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
// 获取对应信息
|
|
||||||
request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/${neType.toLowerCase()}/objectType/config/${topTag}`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
ne_id: neId,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]).then(resArr => {
|
|
||||||
let wrRule: Record<string, any> = {};
|
|
||||||
// 规则数据
|
|
||||||
if (resArr[0].status === 'fulfilled') {
|
|
||||||
const itemV = resArr[0].value;
|
|
||||||
// 解析数据
|
|
||||||
if (
|
|
||||||
itemV.code === RESULT_CODE_SUCCESS &&
|
|
||||||
Array.isArray(itemV.data?.data)
|
|
||||||
) {
|
|
||||||
let itemData = itemV.data.data;
|
|
||||||
const data = itemData[0]['param_config'];
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
const v = data[0]['param_json'];
|
|
||||||
try {
|
|
||||||
itemData = parseObjLineToHump(JSON.parse(v));
|
|
||||||
wrRule = itemData;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let dataArr: Record<string, any>[] = [];
|
|
||||||
// 对应信息
|
|
||||||
if (resArr[1].status === 'fulfilled') {
|
|
||||||
const itemV = resArr[1].value;
|
|
||||||
// 解析数据
|
|
||||||
if (
|
|
||||||
itemV.code === RESULT_CODE_SUCCESS &&
|
|
||||||
Array.isArray(itemV.data?.data)
|
|
||||||
) {
|
|
||||||
let itemData = itemV.data.data;
|
|
||||||
dataArr = parseObjLineToHump(itemData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { wrRule, dataArr };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询配置参数标签栏对应信息-表单结构处理
|
|
||||||
* @param neType 网元类型
|
|
||||||
* @param topTag
|
|
||||||
* @param neId
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function getParamConfigInfoForm(
|
|
||||||
neType: string,
|
|
||||||
topTag: string,
|
|
||||||
neId: string
|
|
||||||
) {
|
|
||||||
const { wrRule, dataArr } = await getParamConfigInfoAndRule(
|
|
||||||
neType,
|
|
||||||
topTag,
|
|
||||||
neId
|
|
||||||
);
|
|
||||||
|
|
||||||
// 拼装数据
|
|
||||||
const result = {
|
|
||||||
code: RESULT_CODE_SUCCESS,
|
|
||||||
msg: RESULT_MSG_SUCCESS,
|
|
||||||
data: {
|
|
||||||
type: 'list' as 'list' | 'array',
|
|
||||||
data: [] as Record<string, any>[],
|
|
||||||
dataRule: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// kv单列表
|
|
||||||
if (Reflect.has(wrRule, 'list')) {
|
|
||||||
result.data.type = 'list';
|
|
||||||
const ruleArr = Object.freeze(wrRule['list']);
|
|
||||||
|
|
||||||
// 列表项数据
|
|
||||||
const dataList = [];
|
|
||||||
for (const item of dataArr) {
|
|
||||||
for (const key in item) {
|
|
||||||
// 规则为准
|
|
||||||
for (const rule of ruleArr) {
|
|
||||||
if (rule['name'] === key) {
|
|
||||||
const ruleItem = Object.assign({ optional: 'true' }, rule, {
|
|
||||||
value: item[key],
|
|
||||||
});
|
|
||||||
dataList.push(ruleItem);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.data.data = dataList;
|
|
||||||
}
|
|
||||||
// 多列表
|
|
||||||
if (Reflect.has(wrRule, 'array')) {
|
|
||||||
result.data.type = 'array';
|
|
||||||
const ruleArr = Object.freeze(wrRule['array']);
|
|
||||||
// 列表项数据
|
|
||||||
const dataArray = [];
|
|
||||||
for (const item of dataArr) {
|
|
||||||
const index = item['index'];
|
|
||||||
let record: Record<string, any>[] = [];
|
|
||||||
for (const key in item) {
|
|
||||||
// 规则为准
|
|
||||||
for (const rule of ruleArr) {
|
|
||||||
if (rule['name'] === key) {
|
|
||||||
const ruleItem = Object.assign({ optional: 'true' }, rule, {
|
|
||||||
value: item[key],
|
|
||||||
});
|
|
||||||
record.push(ruleItem);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dataArray.push({ title: `Index-${index}`, key: index, record });
|
|
||||||
}
|
|
||||||
result.data.data = dataArray;
|
|
||||||
|
|
||||||
// 无数据时,用于新增
|
|
||||||
result.data.dataRule = { title: `Index-0`, key: 0, record: ruleArr };
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询配置参数标签栏对应信息
|
|
||||||
* @param neType 网元类型
|
|
||||||
* @param topTag
|
|
||||||
* @param neId
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function getParamConfigInfo(
|
|
||||||
neType: string,
|
|
||||||
topTag: string,
|
|
||||||
neId: string
|
|
||||||
) {
|
|
||||||
// 发起请求
|
|
||||||
const result = await request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/${neType.toLowerCase()}/objectType/config/${topTag}`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
ne_id: neId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
|
||||||
return Object.assign(result, {
|
|
||||||
data: parseObjLineToHump(result.data.data),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询配置参数标签栏对应信息子节点
|
|
||||||
* @param neType 网元类型
|
|
||||||
* @param topTag
|
|
||||||
* @param neId
|
|
||||||
* @param loc 子节点(index/字段) 1/dnnList
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export async function getParamConfigInfoChild(
|
|
||||||
neType: string,
|
|
||||||
topTag: string,
|
|
||||||
neId: string,
|
|
||||||
loc: string
|
|
||||||
) {
|
|
||||||
// 发起请求
|
|
||||||
const result = await request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/${neType.toLowerCase()}/objectType/config/${topTag}`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
ne_id: neId,
|
|
||||||
loc: loc,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
|
||||||
return Object.assign(result, {
|
|
||||||
data: parseObjLineToHump(result.data.data),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改配置参数标签栏对应信息
|
|
||||||
* @param args 对象 {neType,neId,topTag,loc}
|
|
||||||
* @param data 对象 {修改的数据kv}
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export function updateParamConfigInfo(
|
|
||||||
type: 'list' | 'array',
|
|
||||||
args: Record<string, any>,
|
|
||||||
data: Record<string, any>
|
|
||||||
) {
|
|
||||||
let url = `/api/rest/systemManagement/v1/elementType/${args.neType.toLowerCase()}/objectType/config/${
|
|
||||||
args.topTag
|
|
||||||
}?ne_id=${args.neId}`;
|
|
||||||
|
|
||||||
// 多列表需要loc
|
|
||||||
if (type === 'array') {
|
|
||||||
url += `&loc=${args.loc}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return request({
|
|
||||||
url,
|
|
||||||
method: 'put',
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增配置参数标签栏对应信息
|
|
||||||
* @param args 对象 {neType,neId,topTag,loc}
|
|
||||||
* @param data 行记录对象
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export function addParamConfigInfo(
|
|
||||||
args: Record<string, any>,
|
|
||||||
data: Record<string, any>
|
|
||||||
) {
|
|
||||||
return request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/${args.neType.toLowerCase()}/objectType/config/${
|
|
||||||
args.topTag
|
|
||||||
}?ne_id=${args.neId}&loc=${args.loc}`,
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除配置参数标签栏对应信息
|
|
||||||
* @param args 对象 {neType,neId,topTag,loc}
|
|
||||||
* loc 多层表的定位信息{index0}/{paraName1}/{index1}
|
|
||||||
* @param data 行记录对象
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export function delParamConfigInfo(args: Record<string, any>) {
|
|
||||||
return request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/${args.neType.toLowerCase()}/objectType/config/${
|
|
||||||
args.topTag
|
|
||||||
}?ne_id=${args.neId}&loc=${args.loc}`,
|
|
||||||
method: 'delete',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新网元配置重新载入
|
* 更新网元配置重新载入
|
||||||
@@ -343,141 +36,50 @@ export async function updateNeConfigReload(neType: string, neId: string) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 从参数配置PCF中获取对应信息提供给PCC用户策略输入框
|
* 从参数配置PCF中获取对应信息提供给PCC用户策略输入框
|
||||||
* @param neType 网元类型
|
|
||||||
* @param topTag
|
|
||||||
* @param neId
|
* @param neId
|
||||||
* @returns object { wrRule, dataArr }
|
* @returns object {pccRules,sessionRules,qosTemplate,headerEnrichTemplate,serviceAreaRestriction}
|
||||||
*/
|
*/
|
||||||
export async function getPCCRule(neId: any) {
|
export async function getPCCRule(neId: any) {
|
||||||
return await Promise.allSettled([
|
const paramNameArr = [
|
||||||
// 获取参数规则
|
'pccRules',
|
||||||
|
'sessionRules',
|
||||||
|
'qosTemplate',
|
||||||
|
'headerEnrichTemplate',
|
||||||
|
'serviceAreaRestriction',
|
||||||
|
];
|
||||||
|
const reqArr = [];
|
||||||
|
for (const paramName of paramNameArr) {
|
||||||
|
reqArr.push(
|
||||||
request({
|
request({
|
||||||
url: `/api/rest/systemManagement/v1/elementType/pcf/objectType/config/pccRules`,
|
url: `/ne/config/data`,
|
||||||
|
params: { neType: 'PCF', neId, paramName },
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: {
|
})
|
||||||
ne_id: neId,
|
);
|
||||||
},
|
}
|
||||||
timeout: 1_000,
|
return await Promise.allSettled(reqArr).then(resArr => {
|
||||||
}),
|
|
||||||
// 获取对应信息
|
|
||||||
request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/pcf/objectType/config/sessionRules`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
ne_id: neId,
|
|
||||||
},
|
|
||||||
timeout: 1_000,
|
|
||||||
}),
|
|
||||||
request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/pcf/objectType/config/qosTemplate`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
ne_id: neId,
|
|
||||||
},
|
|
||||||
timeout: 1_000,
|
|
||||||
}),
|
|
||||||
request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/pcf/objectType/config/headerEnrichTemplate`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
ne_id: neId,
|
|
||||||
},
|
|
||||||
timeout: 1_000,
|
|
||||||
}),
|
|
||||||
request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/pcf/objectType/config/serviceAreaRestriction`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
ne_id: neId,
|
|
||||||
},
|
|
||||||
timeout: 1_000,
|
|
||||||
}),
|
|
||||||
]).then(resArr => {
|
|
||||||
let pccJson: any = new Map();
|
|
||||||
let sessJson: any = new Map();
|
|
||||||
let qosJson: any = new Map();
|
|
||||||
let headerJson: any = new Map();
|
|
||||||
let sarJson: any = new Map();
|
|
||||||
// 规则数据
|
// 规则数据
|
||||||
if (resArr[0].status === 'fulfilled') {
|
const obj: any = {};
|
||||||
const itemV = resArr[0].value;
|
resArr.forEach((item, i: number) => {
|
||||||
// 解析数据
|
if (item.status === 'fulfilled') {
|
||||||
if (
|
const res = item.value;
|
||||||
itemV.code === RESULT_CODE_SUCCESS &&
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
Array.isArray(itemV.data?.data)
|
const key = paramNameArr[i];
|
||||||
) {
|
obj[key] = res.data.map((item: any) => {
|
||||||
let itemData = itemV.data.data;
|
if ('qosTemplate' === key) {
|
||||||
itemData.forEach((item: any) => {
|
return { value: item.qosId, label: item.qosId };
|
||||||
pccJson.set(item.ruleId, { value: item.ruleId, label: item.ruleId });
|
}
|
||||||
|
if ('headerEnrichTemplate' === key) {
|
||||||
|
return { value: item.templateName, label: item.templateName };
|
||||||
|
}
|
||||||
|
if ('serviceAreaRestriction' === key) {
|
||||||
|
return { value: item.name, label: item.name };
|
||||||
|
}
|
||||||
|
return { value: item.ruleId, label: item.ruleId };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resArr[1].status === 'fulfilled') {
|
|
||||||
const itemV = resArr[1].value;
|
|
||||||
// 解析数据
|
|
||||||
if (
|
|
||||||
itemV.code === RESULT_CODE_SUCCESS &&
|
|
||||||
Array.isArray(itemV.data?.data)
|
|
||||||
) {
|
|
||||||
let itemData = itemV.data.data;
|
|
||||||
itemData.forEach((item: any) => {
|
|
||||||
sessJson.set(item.ruleId, { value: item.ruleId, label: item.ruleId });
|
|
||||||
});
|
});
|
||||||
}
|
return obj;
|
||||||
}
|
|
||||||
|
|
||||||
if (resArr[2].status === 'fulfilled') {
|
|
||||||
const itemV = resArr[2].value;
|
|
||||||
// 解析数据
|
|
||||||
if (
|
|
||||||
itemV.code === RESULT_CODE_SUCCESS &&
|
|
||||||
Array.isArray(itemV.data?.data)
|
|
||||||
) {
|
|
||||||
let itemData = itemV.data.data;
|
|
||||||
itemData.forEach((item: any) => {
|
|
||||||
qosJson.set(item.qosId, { value: item.qosId, label: item.qosId });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resArr[3].status === 'fulfilled') {
|
|
||||||
const itemV = resArr[3].value;
|
|
||||||
// 解析数据
|
|
||||||
if (
|
|
||||||
itemV.code === RESULT_CODE_SUCCESS &&
|
|
||||||
Array.isArray(itemV.data?.data)
|
|
||||||
) {
|
|
||||||
let itemData = itemV.data.data;
|
|
||||||
itemData.forEach((item: any) => {
|
|
||||||
headerJson.set(item.templateName, {
|
|
||||||
value: item.templateName,
|
|
||||||
label: item.templateName,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resArr[4].status === 'fulfilled') {
|
|
||||||
const itemV = resArr[4].value;
|
|
||||||
// 解析数据
|
|
||||||
if (
|
|
||||||
itemV.code === RESULT_CODE_SUCCESS &&
|
|
||||||
Array.isArray(itemV.data?.data)
|
|
||||||
) {
|
|
||||||
let itemData = itemV.data.data;
|
|
||||||
itemData.forEach((item: any) => {
|
|
||||||
sarJson.set(item.name, { value: item.name, label: item.name });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pccJson = Array.from(pccJson.values());
|
|
||||||
sessJson = Array.from(sessJson.values());
|
|
||||||
qosJson = Array.from(qosJson.values());
|
|
||||||
headerJson = Array.from(headerJson.values());
|
|
||||||
sarJson = Array.from(sarJson.values());
|
|
||||||
|
|
||||||
return { pccJson, sessJson, qosJson, headerJson, sarJson };
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
|
||||||
import { request } from '@/plugins/http-fetch';
|
|
||||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询软件列表
|
|
||||||
* @param query 查询参数
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function listLicense(query: Record<string, any>) {
|
|
||||||
let totalSQL = 'select count(id) as total from ne_license ';
|
|
||||||
let rowsSQL = ' select * from ne_license ';
|
|
||||||
|
|
||||||
// 查询
|
|
||||||
let querySQL = 'where 1=1';
|
|
||||||
if (query.neType) {
|
|
||||||
querySQL += ` and ne_type like '%${query.neType}%' `;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const pageNum = (query.pageNum - 1) * query.pageSize;
|
|
||||||
const limtSql = ` order by create_time desc limit ${pageNum},${query.pageSize} `;
|
|
||||||
|
|
||||||
// 发起请求
|
|
||||||
const result = await request({
|
|
||||||
url: `/api/rest/databaseManagement/v1/select/omc_db/ne_license`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
totalSQL: totalSQL + querySQL,
|
|
||||||
rowsSQL: rowsSQL + querySQL + limtSql,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS) {
|
|
||||||
const data: DataList = {
|
|
||||||
total: 0,
|
|
||||||
rows: [],
|
|
||||||
code: result.code,
|
|
||||||
msg: result.msg,
|
|
||||||
};
|
|
||||||
result.data.data.forEach((item: any) => {
|
|
||||||
const itemData = item['ne_license'];
|
|
||||||
if (Array.isArray(itemData)) {
|
|
||||||
if (itemData.length === 1 && itemData[0]['total'] >= 0) {
|
|
||||||
data.total = itemData[0]['total'];
|
|
||||||
} else {
|
|
||||||
data.rows = itemData.map(v => parseObjLineToHump(v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上传文件
|
|
||||||
* @param data 表单数据对象
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export function uploadLicense(data: FormData) {
|
|
||||||
return request({
|
|
||||||
url: `/api/rest/systemManagement/v1/elementType/${data.get(
|
|
||||||
'nfType'
|
|
||||||
)}/objectType/license?neId=${data.get('nfId')}`,
|
|
||||||
method: 'post',
|
|
||||||
data,
|
|
||||||
dataType: 'form-data',
|
|
||||||
timeout: 180_000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -241,6 +241,7 @@ export function listSync() {
|
|||||||
return request({
|
return request({
|
||||||
url: `/api/rest/faultManagement/v1/elementType/all/objectType/alarms`,
|
url: `/api/rest/faultManagement/v1/elementType/all/objectType/alarms`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
timeout: 180_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import { parseObjLineToHump } from '@/utils/parse-utils';
|
|||||||
import { parseDateToStr } from '@/utils/date-utils';
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
import useUserStore from '@/store/modules/user';
|
import useUserStore from '@/store/modules/user';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询列表
|
* 查询列表
|
||||||
* @param query 查询参数
|
* @param query 查询参数
|
||||||
@@ -28,8 +26,6 @@ export async function listAct(query: Record<string, any>) {
|
|||||||
querySQL += ` and pv_flag = '${query.pvFlag}' `;
|
querySQL += ` and pv_flag = '${query.pvFlag}' `;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query.neId) {
|
if (query.neId) {
|
||||||
querySQL += ` and ne_id like '%${query.neId}%' `;
|
querySQL += ` and ne_id like '%${query.neId}%' `;
|
||||||
}
|
}
|
||||||
@@ -69,7 +65,6 @@ export async function listAct(query: Record<string, any>) {
|
|||||||
msg: result.msg,
|
msg: result.msg,
|
||||||
};
|
};
|
||||||
result.data.data.forEach((item: any) => {
|
result.data.data.forEach((item: any) => {
|
||||||
console.log(item)
|
|
||||||
const itemData = item['alarm_event'];
|
const itemData = item['alarm_event'];
|
||||||
if (Array.isArray(itemData)) {
|
if (Array.isArray(itemData)) {
|
||||||
if (itemData.length === 1 && itemData[0]['total'] >= 0) {
|
if (itemData.length === 1 && itemData[0]['total'] >= 0) {
|
||||||
@@ -84,12 +79,6 @@ export async function listAct(query: Record<string, any>) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 事件告警导出
|
* 事件告警导出
|
||||||
* @param query 查询参数
|
* @param query 查询参数
|
||||||
@@ -133,7 +122,3 @@ export async function exportAll(query: Record<string, any>) {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取下拉框数据
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function getBakFile() {
|
||||||
|
return request({
|
||||||
|
url: '/lm/table/list',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取对应类型的文件列表
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function getBakFileList(query: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/lm/file/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载远端文件
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function downFile(query: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: `/lm/file/${query.fileName}`,
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 180_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除远端获取文件
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function delFile(query: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: `/lm/file/${query.fileName}`,
|
||||||
|
method: 'delete',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ export function login(data: Record<string, string>) {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
whithToken: false,
|
whithToken: false,
|
||||||
|
crypto: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ export function register(data: Record<string, any>) {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
whithToken: false,
|
whithToken: false,
|
||||||
|
crypto: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,5 +6,6 @@ export function getLoad(query: Record<string, any>) {
|
|||||||
url: '/monitor/load',
|
url: '/monitor/load',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
|
timeout: 60_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -5,5 +5,6 @@ export function getSystemInfo() {
|
|||||||
return request({
|
return request({
|
||||||
url: '/monitor/system-info',
|
url: '/monitor/system-info',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
timeout: 60_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网元参数配置可用属性值列表指定网元类型全部无分页
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function getAllNeConfig(neType: string) {
|
||||||
|
return request({
|
||||||
|
url: `/ne/config/list/${neType}`,
|
||||||
|
method: 'get',
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网元参数配置数据信息
|
||||||
|
* @param params 数据 {neType,neId,paramName}
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function getNeConfigData(params: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: `/ne/config/data`,
|
||||||
|
params,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网元参数配置数据更新
|
||||||
|
* @param data 数据 {neType,neId,paramName:"参数名",paramData:{参数},loc:"层级index仅array"}
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function editNeConfigData(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: `/ne/config/data`,
|
||||||
|
method: 'put',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网元参数配置数据新增(array)
|
||||||
|
* @param data 数据 {neType,neId,paramName:"参数名",paramData:{参数},loc:"层级index"}
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function addNeConfigData(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: `/ne/config/data`,
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网元参数配置数据删除(array)
|
||||||
|
* @param params 数据 {neType,neId,paramName:"参数名",loc:"层级index"}
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function delNeConfigData(params: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: `/ne/config/data`,
|
||||||
|
method: 'delete',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -36,6 +36,8 @@ export function addNeInfo(data: Record<string, any>) {
|
|||||||
url: `/ne/info`,
|
url: `/ne/info`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
|
crypto: true,
|
||||||
|
timeout: 30_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +51,8 @@ export function updateNeInfo(data: Record<string, any>) {
|
|||||||
url: `/ne/info`,
|
url: `/ne/info`,
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data,
|
data: data,
|
||||||
|
crypto: true,
|
||||||
|
timeout: 30_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,3 +40,16 @@ export function exportSMFDataCDR(data: Record<string, any>) {
|
|||||||
timeout: 60_000,
|
timeout: 60_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMF-在线订阅用户列表信息
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function listSMFSubscribers(query: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/neData/smf/subscribers',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询SMSC-CDR会话事件
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function listSMSCDataCDR(query: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/neData/smsc/cdr/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMSC-CDR会话删除
|
||||||
|
* @param id 信息ID
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function delSMSCDataCDR(cdrIds: string | number) {
|
||||||
|
return request({
|
||||||
|
url: `/neData/smsc/cdr/${cdrIds}`,
|
||||||
|
method: 'delete',
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMSC-CDR会话列表导出
|
||||||
|
* @param data 查询列表条件
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function exportSMSCDataCDR(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/neData/smsc/cdr/export',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -113,7 +113,6 @@ export function batchDelUDMAuth(neId: string, imsi: string, num: number) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* UDM鉴权用户导入
|
* UDM鉴权用户导入
|
||||||
* @param neId 网元ID
|
|
||||||
* @param data 表单数据对象
|
* @param data 表单数据对象
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -52,9 +52,11 @@ export async function listUENumByIMS(neId: String) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
});
|
});
|
||||||
if (result.code === RESULT_CODE_SUCCESS) {
|
if (result.code === RESULT_CODE_SUCCESS) {
|
||||||
return Object.assign(result, {
|
let num = result.data['ueNum'] || 0;
|
||||||
data: result.data['ueNum'],
|
if (num === 0) {
|
||||||
});
|
num = result.data.data['ueNum'] || 0;
|
||||||
|
}
|
||||||
|
return Object.assign(result, { data: num });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 模拟数据
|
// 模拟数据
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||||
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新 查询自定义指标数据
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export async function listCustomData(query: Record<string, any>) {
|
||||||
|
// 发起请求
|
||||||
|
const result = await request({
|
||||||
|
url: `/pm/kpiC/report`,
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -8,57 +8,72 @@ import { parseDateToStr } from '@/utils/date-utils';
|
|||||||
* @param query 查询参数
|
* @param query 查询参数
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
export async function listCustom(query: Record<string, any>) {
|
// export async function listCustom(query: Record<string, any>) {
|
||||||
let totalSQL = 'select count(*) as total from pm_custom_title where 1=1 ';
|
// let totalSQL = 'select count(*) as total from pm_custom_title where 1=1 ';
|
||||||
let rowsSQL = 'select * from pm_custom_title where 1=1 ';
|
// let rowsSQL = 'select * from pm_custom_title where 1=1 ';
|
||||||
|
|
||||||
// 查询
|
// // 查询
|
||||||
let querySQL = '';
|
// let querySQL = '';
|
||||||
if (query.neType) {
|
// if (query.neType) {
|
||||||
querySQL += ` and ne_type like '%${query.neType}%' `;
|
// querySQL += ` and ne_type like '%${query.neType}%' `;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 排序
|
// // 排序
|
||||||
let sortSql = ' order by update_time ';
|
// let sortSql = ' order by update_time ';
|
||||||
if (query.sortOrder === 'asc') {
|
// if (query.sortOrder === 'asc') {
|
||||||
sortSql += ' asc ';
|
// sortSql += ' asc ';
|
||||||
} else {
|
// } else {
|
||||||
sortSql += ' desc ';
|
// sortSql += ' desc ';
|
||||||
}
|
// }
|
||||||
// 分页
|
// // 分页
|
||||||
const pageNum = (query.pageNum - 1) * query.pageSize;
|
// const pageNum = (query.pageNum - 1) * query.pageSize;
|
||||||
const limtSql = ` limit ${pageNum},${query.pageSize} `;
|
// const limtSql = ` limit ${pageNum},${query.pageSize} `;
|
||||||
|
|
||||||
|
// // 发起请求
|
||||||
|
// const result = await request({
|
||||||
|
// url: `/api/rest/databaseManagement/v1/select/omc_db/pm_custom_title`,
|
||||||
|
// method: 'get',
|
||||||
|
// params: {
|
||||||
|
// totalSQL: totalSQL + querySQL,
|
||||||
|
// rowsSQL: rowsSQL + querySQL + sortSql + limtSql,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // 解析数据
|
||||||
|
// if (result.code === RESULT_CODE_SUCCESS) {
|
||||||
|
// const data: DataList = {
|
||||||
|
// total: 0,
|
||||||
|
// rows: [],
|
||||||
|
// code: result.code,
|
||||||
|
// msg: result.msg,
|
||||||
|
// };
|
||||||
|
// result.data.data.forEach((item: any) => {
|
||||||
|
// const itemData = item['pm_custom_title'];
|
||||||
|
// if (Array.isArray(itemData)) {
|
||||||
|
// if (itemData.length === 1 && itemData[0]['total'] >= 0) {
|
||||||
|
// data.total = itemData[0]['total'];
|
||||||
|
// } else {
|
||||||
|
// data.rows = itemData.map(v => parseObjLineToHump(v));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// return data;
|
||||||
|
// }
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新 查询自定义指标
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export async function listCustom(query?: Record<string, any>) {
|
||||||
// 发起请求
|
// 发起请求
|
||||||
const result = await request({
|
const result = await request({
|
||||||
url: `/api/rest/databaseManagement/v1/select/omc_db/pm_custom_title`,
|
url: `/pm/kpiC/title/totalList`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: {
|
params: query,
|
||||||
totalSQL: totalSQL + querySQL,
|
|
||||||
rowsSQL: rowsSQL + querySQL + sortSql + limtSql,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS) {
|
|
||||||
const data: DataList = {
|
|
||||||
total: 0,
|
|
||||||
rows: [],
|
|
||||||
code: result.code,
|
|
||||||
msg: result.msg,
|
|
||||||
};
|
|
||||||
result.data.data.forEach((item: any) => {
|
|
||||||
const itemData = item['pm_custom_title'];
|
|
||||||
if (Array.isArray(itemData)) {
|
|
||||||
if (itemData.length === 1 && itemData[0]['total'] >= 0) {
|
|
||||||
data.total = itemData[0]['total'];
|
|
||||||
} else {
|
|
||||||
data.rows = itemData.map(v => parseObjLineToHump(v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,22 +83,10 @@ export async function listCustom(query: Record<string, any>) {
|
|||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
export async function getCustom(id: string | number) {
|
export async function getCustom(id: string | number) {
|
||||||
// 发起请求
|
return request({
|
||||||
const result = await request({
|
url: `/pm/kpiC/title/${id}`,
|
||||||
url: `/api/rest/databaseManagement/v1/select/omc_db/pm_custom_title`,
|
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: {
|
|
||||||
SQL: `select * from pm_custom_title where id = ${id}`,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
|
||||||
let data = result.data.data[0];
|
|
||||||
return Object.assign(result, {
|
|
||||||
data: parseObjLineToHump(data['pm_custom_title'][0]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,21 +95,10 @@ export async function getCustom(id: string | number) {
|
|||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
export function addCustom(data: Record<string, any>) {
|
export function addCustom(data: Record<string, any>) {
|
||||||
let obj: any = {
|
|
||||||
title: data.title,
|
|
||||||
ne_type: data.neType,
|
|
||||||
kpi_id: data.kpiId,
|
|
||||||
object_type: data.objectType,
|
|
||||||
expression: data.expression,
|
|
||||||
period: data.period,
|
|
||||||
description: data.description,
|
|
||||||
kpi_set: data.kpiSet,
|
|
||||||
};
|
|
||||||
|
|
||||||
return request({
|
return request({
|
||||||
url: `/api/rest/databaseManagement/v1/omc_db/pm_custom_title`,
|
url: `/pm/kpiC/title`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: { 'data': [obj] },
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,20 +108,10 @@ export function addCustom(data: Record<string, any>) {
|
|||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
export function updateCustom(data: Record<string, any>) {
|
export function updateCustom(data: Record<string, any>) {
|
||||||
let obj: any = {
|
|
||||||
title: data.title,
|
|
||||||
ne_type: data.neType,
|
|
||||||
kpi_id: data.kpiId,
|
|
||||||
object_type: data.objectType,
|
|
||||||
expression: data.expression,
|
|
||||||
period: data.period,
|
|
||||||
description: data.description,
|
|
||||||
kpi_set: data.kpiSet,
|
|
||||||
};
|
|
||||||
return request({
|
return request({
|
||||||
url: `/api/rest/databaseManagement/v1/omc_db/pm_custom_title?WHERE=id=${data.id}`,
|
url: `/pm/kpiC/title/${data.id}`,
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: { data: obj },
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,8 +121,7 @@ export function updateCustom(data: Record<string, any>) {
|
|||||||
*/
|
*/
|
||||||
export async function delCustom(data: Record<string, any>) {
|
export async function delCustom(data: Record<string, any>) {
|
||||||
return request({
|
return request({
|
||||||
url: `/api/rest/databaseManagement/v1/omc_db/pm_custom_title?WHERE=id=${data.id}`,
|
url: `/pm/kpiC/title/${data.id}`,
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
|
// iperf 版本信息
|
||||||
|
export function iperfV(data: Record<string, string>) {
|
||||||
|
return request({
|
||||||
|
url: '/tool/iperf/v',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// iperf 软件安装
|
||||||
|
export function iperfI(data: Record<string, string>) {
|
||||||
|
return request({
|
||||||
|
url: '/tool/iperf/i',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
+23
-2
@@ -1,7 +1,7 @@
|
|||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询文件列表列表
|
* 查询网元端文件列表
|
||||||
* @param query 查询参数
|
* @param query 查询参数
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
@@ -14,7 +14,7 @@ export function listNeFiles(query: Record<string, any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从网元端获取文件
|
* 从网元到本地获取文件
|
||||||
* @param query 查询参数
|
* @param query 查询参数
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
@@ -27,3 +27,24 @@ export function getNeFile(query: Record<string, any>) {
|
|||||||
timeout: 180_000,
|
timeout: 180_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从网元到本地获取目录压缩为ZIP
|
||||||
|
export function getNeDirZip(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/ne/action/pullDirZip',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看网元端文件内容
|
||||||
|
export function getNeViewFile(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/ne/action/viewFile',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
|
// ping 网元端版本信息
|
||||||
|
export function pingV(data: Record<string, string>) {
|
||||||
|
return request({
|
||||||
|
url: '/tool/ping/v',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
File renamed without changes.
@@ -0,0 +1,64 @@
|
|||||||
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 信令跟踪网卡设备列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function packetDevices() {
|
||||||
|
return request({
|
||||||
|
url: '/trace/packet/devices',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 信令跟踪开始
|
||||||
|
* @param data 对象
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function packetStart(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/packet/start',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 信令跟踪结束
|
||||||
|
* @param data 对象
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function packetStop(taskNo: string) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/packet/stop',
|
||||||
|
method: 'post',
|
||||||
|
data: { taskNo },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 信令跟踪过滤
|
||||||
|
* @param data 对象
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function packetFilter(taskNo: string, expr: string) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/packet/filter',
|
||||||
|
method: 'put',
|
||||||
|
data: { taskNo, expr },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 信令跟踪续期保活
|
||||||
|
* @param data 对象
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function packetKeep(taskNo: string, duration: number = 120) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/packet/keep-alive',
|
||||||
|
method: 'put',
|
||||||
|
data: { taskNo, duration },
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ export function dumpStart(data: Record<string, string>) {
|
|||||||
url: '/trace/tcpdump/start',
|
url: '/trace/tcpdump/start',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
|
timeout: 60_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,14 +16,16 @@ export function dumpStop(data: Record<string, string>) {
|
|||||||
url: '/trace/tcpdump/stop',
|
url: '/trace/tcpdump/stop',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
|
timeout: 60_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// UPF标准版内部抓包
|
// UPF标准版内部抓包
|
||||||
export function traceUPF(data: Record<string, string>) {
|
export function traceUPF(data: Record<string, string>) {
|
||||||
return request({
|
return request({
|
||||||
url: '/trace/tcpdump/traceUPF',
|
url: '/trace/tcpdump/upf',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
|
timeout: 60_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询跟踪任务列表
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export async function listTraceTask(query: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/task/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询跟踪任务信息
|
||||||
|
* @param id 网元ID
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export async function getTraceTask(id: string | number) {
|
||||||
|
return request({
|
||||||
|
url: `/trace/task/${id}`,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增任务
|
||||||
|
* @param data 网元对象
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function addTraceTask(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: `/trace/task`,
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改任务
|
||||||
|
* @param data 网元对象
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function updateTraceTask(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: `/trace/task`,
|
||||||
|
method: 'put',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跟踪任务删除
|
||||||
|
* @param ids ID多个逗号分隔
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export async function delTraceTask(ids: string) {
|
||||||
|
return request({
|
||||||
|
url: `/trace/task/${ids}`,
|
||||||
|
method: 'delete',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跟踪任务文件
|
||||||
|
* @param query 对象
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function filePullTask(traceId: string) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/task/filePull',
|
||||||
|
method: 'get',
|
||||||
|
params: { traceId },
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取网元跟踪接口列表
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export async function getNeTraceInterfaceAll() {
|
||||||
|
// 发起请求
|
||||||
|
const result = await request({
|
||||||
|
url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/ne_info`,
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
SQL: `SELECT ne_type,interface FROM trace_info GROUP BY ne_type,interface`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// 解析数据
|
||||||
|
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
||||||
|
let data = result.data.data[0];
|
||||||
|
return Object.assign(result, {
|
||||||
|
data: parseObjLineToHump(data['trace_info']),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询跟踪任务列表
|
||||||
|
* @param query 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function listTaskHLR(query: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/task/hlr/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跟踪任务删除
|
||||||
|
* @param ids 任务ID
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function delTaskHLR(ids: string | number) {
|
||||||
|
return request({
|
||||||
|
url: `/trace/task/hlr/${ids}`,
|
||||||
|
method: 'delete',
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跟踪任务创建
|
||||||
|
* @param data 对象
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function startTaskHLR(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/task/hlr/start',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跟踪任务停止
|
||||||
|
* @param data 对象
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function stopTaskHLR(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/task/hlr/stop',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跟踪任务文件
|
||||||
|
* @param data 对象
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function fileTaskHLR(data: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/task/hlr/file',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跟踪任务文件从网元到本地
|
||||||
|
* @param query 对象
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function filePullTaskHLR(query: Record<string, any>) {
|
||||||
|
return request({
|
||||||
|
url: '/trace/task/hlr/filePull',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
|
||||||
import { request } from '@/plugins/http-fetch';
|
|
||||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询任务列表
|
|
||||||
* @param query 查询参数
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function listTraceTask(query: Record<string, any>) {
|
|
||||||
let totalSQL = 'select count(*) as total from trace_task where 1=1 ';
|
|
||||||
let rowsSQL = 'select * from trace_task where 1=1 ';
|
|
||||||
|
|
||||||
// 查询
|
|
||||||
let querySQL = '';
|
|
||||||
if (query.imsi) {
|
|
||||||
querySQL += ` and imsi like '%${query.imsi}%' `;
|
|
||||||
}
|
|
||||||
if (query.beginTime) {
|
|
||||||
querySQL += ` and start_time >= '${query.beginTime}' `;
|
|
||||||
}
|
|
||||||
if (query.endTime) {
|
|
||||||
querySQL += ` and end_time <= '${query.endTime}' `;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const pageNum = (query.pageNum - 1) * query.pageSize;
|
|
||||||
const limtSql = ` limit ${pageNum},${query.pageSize} `;
|
|
||||||
|
|
||||||
// 排序
|
|
||||||
let sortSql = ' order by start_time ';
|
|
||||||
if (query.sortOrder === 'asc') {
|
|
||||||
sortSql += ' asc ';
|
|
||||||
} else {
|
|
||||||
sortSql += ' desc ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发起请求
|
|
||||||
const result = await request({
|
|
||||||
url: `/api/rest/databaseManagement/v1/select/omc_db/trace_task`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
totalSQL: totalSQL + querySQL,
|
|
||||||
rowsSQL: rowsSQL + querySQL + sortSql + limtSql,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS) {
|
|
||||||
const data: DataList = {
|
|
||||||
total: 0,
|
|
||||||
rows: [],
|
|
||||||
code: result.code,
|
|
||||||
msg: result.msg,
|
|
||||||
};
|
|
||||||
result.data.data.forEach((item: any) => {
|
|
||||||
const itemData = item['trace_task'];
|
|
||||||
if (Array.isArray(itemData)) {
|
|
||||||
if (itemData.length === 1 && itemData[0]['total'] >= 0) {
|
|
||||||
data.total = itemData[0]['total'];
|
|
||||||
} else {
|
|
||||||
data.rows = itemData.map(v => parseObjLineToHump(v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询任务详细
|
|
||||||
* @param id 网元ID
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function getTraceTask(id: string | number) {
|
|
||||||
// 发起请求
|
|
||||||
const result = await request({
|
|
||||||
url: `/api/rest/databaseManagement/v1/select/omc_db/trace_task`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
SQL: `select * from trace_task where id = ${id}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
|
||||||
let data = result.data.data[0];
|
|
||||||
return Object.assign(result, {
|
|
||||||
data: parseObjLineToHump(data['trace_task'][0]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增任务
|
|
||||||
* @param data 网元对象
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export function addTraceTask(data: Record<string, any>) {
|
|
||||||
return request({
|
|
||||||
url: `/api/rest/traceManagement/v1/subscriptions`,
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改任务
|
|
||||||
* @param data 网元对象
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export function updateTraceTask(data: Record<string, any>) {
|
|
||||||
return request({
|
|
||||||
url: `/api/rest/traceManagement/v1/subscriptions`,
|
|
||||||
method: 'put',
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除任务
|
|
||||||
* @param noticeId 网元ID
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function delTraceTask(id: string) {
|
|
||||||
return request({
|
|
||||||
url: `/api/rest/traceManagement/v1/subscriptions?id=${id}`,
|
|
||||||
method: 'delete',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取网元跟踪接口列表
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function getNeTraceInterfaceAll() {
|
|
||||||
// 发起请求
|
|
||||||
const result = await request({
|
|
||||||
url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/ne_info`,
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
SQL: `SELECT ne_type,interface FROM trace_info GROUP BY ne_type,interface`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// 解析数据
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
|
||||||
let data = result.data.data[0];
|
|
||||||
return Object.assign(result, {
|
|
||||||
data: parseObjLineToHump(data['trace_info']),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* worker文件-静态资源文件路径
|
||||||
|
*/
|
||||||
|
const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
|
||||||
|
export const scriptUrl = `${
|
||||||
|
baseUrl.length === 1 && baseUrl.indexOf('/') === 0
|
||||||
|
? ''
|
||||||
|
: baseUrl.indexOf('/') === -1
|
||||||
|
? '/' + baseUrl
|
||||||
|
: baseUrl
|
||||||
|
}/wiregasm/worker.js`;
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||||
|
import { FitAddon } from '@xterm/addon-fit';
|
||||||
|
import { Terminal } from '@xterm/xterm';
|
||||||
|
import '@xterm/xterm/css/xterm.css';
|
||||||
|
import { RESULT_CODE_ERROR } from '@/constants/result-constants';
|
||||||
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
|
const ws = new WS();
|
||||||
|
const emit = defineEmits(['connect', 'close', 'message']);
|
||||||
|
const props = defineProps({
|
||||||
|
/**终端ID,必传 */
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**ws连接地址,必传 如/ws/view */
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**网元类型,必传 */
|
||||||
|
neType: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**网元ID,必传 */
|
||||||
|
neId: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**窗口单行字符数 */
|
||||||
|
cols: {
|
||||||
|
type: Number,
|
||||||
|
default: 80,
|
||||||
|
},
|
||||||
|
/**窗口行数 */
|
||||||
|
rows: {
|
||||||
|
type: Number,
|
||||||
|
default: 40,
|
||||||
|
},
|
||||||
|
/**ws发送requestId前缀 如ssh_id */
|
||||||
|
prefix: {
|
||||||
|
type: String,
|
||||||
|
default: 'ssh',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**终端输入DOM节点实例对象 */
|
||||||
|
const terminalDom = ref<HTMLElement | undefined>(undefined);
|
||||||
|
|
||||||
|
/**终端输入实例对象 */
|
||||||
|
const terminal = ref<any>(null);
|
||||||
|
|
||||||
|
/**终端输入渲染 */
|
||||||
|
function handleRanderXterm(container: HTMLElement | undefined) {
|
||||||
|
if (!container) return;
|
||||||
|
const xterm = new Terminal({
|
||||||
|
cols: props.cols,
|
||||||
|
rows: props.rows,
|
||||||
|
lineHeight: 1.2,
|
||||||
|
fontSize: 12,
|
||||||
|
fontFamily: "Monaco, Menlo, Consolas, 'Courier New', monospace",
|
||||||
|
theme: {
|
||||||
|
background: '#000000',
|
||||||
|
},
|
||||||
|
cursorBlink: true, // 光标闪烁
|
||||||
|
cursorStyle: 'block',
|
||||||
|
scrollback: 1000, // 设置历史缓冲区大小为 1000 行
|
||||||
|
scrollSensitivity: 15,
|
||||||
|
tabStopWidth: 4,
|
||||||
|
disableStdin: true, // 禁止输入
|
||||||
|
});
|
||||||
|
// 挂载
|
||||||
|
xterm.open(container);
|
||||||
|
// 自适应尺寸
|
||||||
|
const fitAddon = new FitAddon();
|
||||||
|
xterm.loadAddon(fitAddon);
|
||||||
|
// 终端尺寸变化触发
|
||||||
|
xterm.onResize(({ cols, rows }) => {
|
||||||
|
// console.log('尺寸', cols, rows);
|
||||||
|
ws.send({
|
||||||
|
requestId: `resize_${props.id}`,
|
||||||
|
type: 'resize',
|
||||||
|
data: { cols, rows },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建 ResizeObserver 实例
|
||||||
|
var observer = new ResizeObserver(entries => {
|
||||||
|
fitAddon.fit();
|
||||||
|
});
|
||||||
|
// 监听元素大小变化
|
||||||
|
observer.observe(container);
|
||||||
|
|
||||||
|
terminal.value = xterm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**连接打开后回调 */
|
||||||
|
function wsOpen(ev: any) {
|
||||||
|
// console.info('wsOpen', ev);
|
||||||
|
nextTick(() => {
|
||||||
|
handleRanderXterm(terminalDom.value);
|
||||||
|
// 连接事件
|
||||||
|
emit('connect', {
|
||||||
|
timeStamp: ev.timeStamp,
|
||||||
|
cols: terminal.value.cols,
|
||||||
|
rows: terminal.value.rows,
|
||||||
|
neType: props.neType,
|
||||||
|
neId: props.neId,
|
||||||
|
id: props.id,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**连接错误后回调 */
|
||||||
|
function wsError(ev: any) {
|
||||||
|
console.error('wsError', ev);
|
||||||
|
if (terminal.value != null) {
|
||||||
|
let message = 'disconnected';
|
||||||
|
terminal.value.write(`\x1b[31m${message}\x1b[m\r\n`);
|
||||||
|
} else if (terminalDom.value) {
|
||||||
|
terminalDom.value.style.background = '#000';
|
||||||
|
terminalDom.value.style.color = '#ff4d4f';
|
||||||
|
terminalDom.value.style.height = '60%';
|
||||||
|
terminalDom.value.innerText = 'disconnected';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**连接关闭后回调 */
|
||||||
|
function wsClose(code: number) {
|
||||||
|
// console.warn('wsClose', code);
|
||||||
|
if (terminal.value != null) {
|
||||||
|
let message = 'disconnected ' + code;
|
||||||
|
terminal.value.write(`\x1b[31m${message}\x1b[m\r\n`);
|
||||||
|
}
|
||||||
|
// 关闭事件
|
||||||
|
emit('close', {
|
||||||
|
code: code,
|
||||||
|
neType: props.neType,
|
||||||
|
neId: props.neId,
|
||||||
|
id: props.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**接收消息后回调 */
|
||||||
|
function wsMessage(res: Record<string, any>) {
|
||||||
|
emit('message', res);
|
||||||
|
// console.log('wsMessage', res);
|
||||||
|
const { code, requestId, data } = res;
|
||||||
|
if (code === RESULT_CODE_ERROR) {
|
||||||
|
console.warn(res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!requestId) return;
|
||||||
|
if (terminal.value != null) {
|
||||||
|
// 查找的开始输出标记
|
||||||
|
const parts: string[] = data.split('\u001b[?2004l\r');
|
||||||
|
if (parts.length > 0) {
|
||||||
|
let text = parts[parts.length - 1];
|
||||||
|
// 找到最后输出标记
|
||||||
|
let lestIndex = text.lastIndexOf('\u001b[?2004h\u001b]0;');
|
||||||
|
if (lestIndex !== -1) {
|
||||||
|
text = text.substring(0, lestIndex);
|
||||||
|
}
|
||||||
|
if (text === '' || text === '\r\n' || text.startsWith('^C\r\n')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 是否还有最后输出标记
|
||||||
|
lestIndex = text.lastIndexOf('\u001b[?2004h');
|
||||||
|
if (lestIndex !== -1) {
|
||||||
|
text = text.substring(0, lestIndex);
|
||||||
|
}
|
||||||
|
// console.log({ parts, text });
|
||||||
|
terminal.value.write(text);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 无标记
|
||||||
|
terminal.value.write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.neType && props.neId) {
|
||||||
|
// 建立链接
|
||||||
|
const options: OptionsType = {
|
||||||
|
url: props.url,
|
||||||
|
params: {
|
||||||
|
neType: props.neType,
|
||||||
|
neId: props.neId,
|
||||||
|
cols: props.cols,
|
||||||
|
rows: props.rows,
|
||||||
|
},
|
||||||
|
onmessage: wsMessage,
|
||||||
|
onerror: wsError,
|
||||||
|
onopen: wsOpen,
|
||||||
|
onclose: wsClose,
|
||||||
|
};
|
||||||
|
ws.connect(options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (ws.state() === WebSocket.OPEN) ws.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 给组件设置属性 ref="xxxTerminal"
|
||||||
|
// setup内使用 const xxxTerminal = ref();
|
||||||
|
defineExpose({
|
||||||
|
/**清除 */
|
||||||
|
clear: () => {
|
||||||
|
if (terminal.value != null) {
|
||||||
|
terminal.value.clear();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**发送命令 */
|
||||||
|
send: (type: string, data: Record<string, any>) => {
|
||||||
|
ws.send({
|
||||||
|
requestId: `${props.prefix}_${props.id}`,
|
||||||
|
type,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**模拟按下 Ctrl+C */
|
||||||
|
ctrlC: () => {
|
||||||
|
ws.send({
|
||||||
|
requestId: `${props.prefix}_${props.id}`,
|
||||||
|
type: 'ctrl-c',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="terminalDom" :id="id" class="terminal"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.terminal {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -119,7 +119,7 @@ function fnAutoCompleteKeydown(evt: any) {
|
|||||||
ws.send({
|
ws.send({
|
||||||
requestId: `telnet_${props.hostId}`,
|
requestId: `telnet_${props.hostId}`,
|
||||||
type: 'telnet',
|
type: 'telnet',
|
||||||
data: `${cmdStr}\r\n'`,
|
data: `${cmdStr}\r\n`,
|
||||||
});
|
});
|
||||||
terminalState.text = ' ';
|
terminalState.text = ' ';
|
||||||
|
|
||||||
@@ -155,6 +155,15 @@ function handleRanderXterm(container: HTMLElement | undefined) {
|
|||||||
// 自适应尺寸
|
// 自适应尺寸
|
||||||
const fitAddon = new FitAddon();
|
const fitAddon = new FitAddon();
|
||||||
xterm.loadAddon(fitAddon);
|
xterm.loadAddon(fitAddon);
|
||||||
|
// 终端尺寸变化触发
|
||||||
|
xterm.onResize(({ cols, rows }) => {
|
||||||
|
// console.log('尺寸', cols, rows);
|
||||||
|
ws.send({
|
||||||
|
requestId: `telnet_resize_${props.hostId}`,
|
||||||
|
type: 'telnet_resize',
|
||||||
|
data: { cols, rows },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// 创建 ResizeObserver 实例
|
// 创建 ResizeObserver 实例
|
||||||
var observer = new ResizeObserver(entries => {
|
var observer = new ResizeObserver(entries => {
|
||||||
@@ -280,7 +289,7 @@ defineExpose({
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="terminal">
|
<div class="terminal">
|
||||||
<div ref="terminalDom" style="height: 78%" :id="id"></div>
|
<div ref="terminalDom" style="height: calc(100% - 36px)" :id="id"></div>
|
||||||
<a-auto-complete
|
<a-auto-complete
|
||||||
v-model:value="terminalState.text"
|
v-model:value="terminalState.text"
|
||||||
:dropdown-match-select-width="500"
|
:dropdown-match-select-width="500"
|
||||||
|
|||||||
@@ -0,0 +1,204 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref, computed, unref, onUpdated, watchEffect } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
/**列表高度 */
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 300,
|
||||||
|
},
|
||||||
|
/**列表项高度 */
|
||||||
|
itemHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 30,
|
||||||
|
},
|
||||||
|
/**数据 */
|
||||||
|
data: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
/**预先兜底缓存数量 */
|
||||||
|
cache: {
|
||||||
|
type: Number,
|
||||||
|
default: 2,
|
||||||
|
},
|
||||||
|
/**是否动态加载 */
|
||||||
|
dynamic: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = reactive<any>({
|
||||||
|
start: 0,
|
||||||
|
end: 10,
|
||||||
|
scrollOffset: 0,
|
||||||
|
cacheData: [],
|
||||||
|
});
|
||||||
|
const virtualListRef = ref();
|
||||||
|
|
||||||
|
const getWrapperStyle = computed(() => {
|
||||||
|
const { height } = props;
|
||||||
|
return {
|
||||||
|
height: `${height}px`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const getInnerStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
height: `${unref(getTotalHeight)}px`,
|
||||||
|
width: '100%',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const getListStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
willChange: 'transform',
|
||||||
|
transform: `translateY(${state.scrollOffset}px)`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 数据数量
|
||||||
|
const total = computed(() => {
|
||||||
|
return props.data.length;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 总体高度
|
||||||
|
const getTotalHeight = computed(() => {
|
||||||
|
if (!props.dynamic) return unref(total) * props.itemHeight;
|
||||||
|
return getCurrentTop(unref(total));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 当前屏幕显示的数量
|
||||||
|
const clientCount = computed(() => {
|
||||||
|
return Math.ceil(props.height / props.itemHeight);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 当前屏幕显示的数据
|
||||||
|
const clientData = computed(() => {
|
||||||
|
return props.data.slice(state.start, state.end);
|
||||||
|
});
|
||||||
|
|
||||||
|
const onScroll = (e: any) => {
|
||||||
|
const { scrollTop } = e.target;
|
||||||
|
if (state.scrollOffset === scrollTop) return;
|
||||||
|
const { cache, dynamic, itemHeight } = props;
|
||||||
|
const cacheCount = Math.max(1, cache);
|
||||||
|
|
||||||
|
let startIndex = dynamic
|
||||||
|
? getStartIndex(scrollTop)
|
||||||
|
: Math.floor(scrollTop / itemHeight);
|
||||||
|
|
||||||
|
const endIndex = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(unref(total), startIndex + unref(clientCount) + cacheCount)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (startIndex > cacheCount) {
|
||||||
|
startIndex = startIndex - cacheCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 偏移量
|
||||||
|
const offset = dynamic
|
||||||
|
? getCurrentTop(startIndex)
|
||||||
|
: scrollTop - (scrollTop % itemHeight);
|
||||||
|
|
||||||
|
Object.assign(state, {
|
||||||
|
start: startIndex,
|
||||||
|
end: endIndex,
|
||||||
|
scrollOffset: offset,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 二分法去查找对应的index
|
||||||
|
const getStartIndex = (scrollTop = 0): number => {
|
||||||
|
let low = 0;
|
||||||
|
let high = state.cacheData.length - 1;
|
||||||
|
while (low <= high) {
|
||||||
|
const middle = low + Math.floor((high - low) / 2);
|
||||||
|
const middleTopValue = getCurrentTop(middle);
|
||||||
|
const middleBottomValue = getCurrentTop(middle + 1);
|
||||||
|
|
||||||
|
if (middleTopValue <= scrollTop && scrollTop <= middleBottomValue) {
|
||||||
|
return middle;
|
||||||
|
} else if (middleBottomValue < scrollTop) {
|
||||||
|
low = middle + 1;
|
||||||
|
} else if (middleBottomValue > scrollTop) {
|
||||||
|
high = middle - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Math.min(
|
||||||
|
unref(total) - unref(clientCount),
|
||||||
|
Math.floor(scrollTop / props.itemHeight)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCurrentTop = (index: number) => {
|
||||||
|
const lastIndex = state.cacheData.length - 1;
|
||||||
|
|
||||||
|
if (Object.hasOwn(state.cacheData, index)) {
|
||||||
|
return state.cacheData[index].top;
|
||||||
|
} else if (Object.hasOwn(state.cacheData, index - 1)) {
|
||||||
|
return state.cacheData[index - 1].bottom;
|
||||||
|
} else if (index > lastIndex) {
|
||||||
|
return (
|
||||||
|
state.cacheData[lastIndex].bottom +
|
||||||
|
Math.max(0, index - state.cacheData[lastIndex].index) * props.itemHeight
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return index * props.itemHeight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onUpdated(() => {
|
||||||
|
if (!props.dynamic) return;
|
||||||
|
const childrenList = virtualListRef.value.children || [];
|
||||||
|
[...childrenList].forEach((node: any, index: number) => {
|
||||||
|
const height = node.getBoundingClientRect().height;
|
||||||
|
const currentIndex = state.start + index;
|
||||||
|
if (state.cacheData[currentIndex].height === height) return;
|
||||||
|
|
||||||
|
state.cacheData[currentIndex].height = height;
|
||||||
|
state.cacheData[currentIndex].top = getCurrentTop(currentIndex);
|
||||||
|
state.cacheData[currentIndex].bottom =
|
||||||
|
state.cacheData[currentIndex].top + state.cacheData[currentIndex].height;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
clientData.value.forEach((_, index) => {
|
||||||
|
const currentIndex = state.start + index;
|
||||||
|
if (Object.hasOwn(state.cacheData, currentIndex)) return;
|
||||||
|
state.cacheData[currentIndex] = {
|
||||||
|
top: currentIndex * props.itemHeight,
|
||||||
|
height: props.itemHeight,
|
||||||
|
bottom: (currentIndex + 1) * props.itemHeight,
|
||||||
|
index: currentIndex,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="virtual-list-wrapper"
|
||||||
|
ref="wrapperRef"
|
||||||
|
:style="getWrapperStyle"
|
||||||
|
@scroll="onScroll"
|
||||||
|
>
|
||||||
|
<div class="virtual-list-inner" ref="innerRef" :style="getInnerStyle">
|
||||||
|
<div class="virtual-list" :style="getListStyle" ref="virtualListRef">
|
||||||
|
<div v-for="(item, index) in clientData" :key="index + state.start">
|
||||||
|
<slot name="default" :item="item"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.virtual-list-wrapper {
|
||||||
|
position: relative;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -3,3 +3,6 @@ export const APP_REQUEST_HEADER_CODE = 'X-App-Code';
|
|||||||
|
|
||||||
/**应用-请求头-系统版本 */
|
/**应用-请求头-系统版本 */
|
||||||
export const APP_REQUEST_HEADER_VERSION = 'X-App-Version';
|
export const APP_REQUEST_HEADER_VERSION = 'X-App-Version';
|
||||||
|
|
||||||
|
/**应用-请求数据-密钥 */
|
||||||
|
export const APP_DATA_API_KEY = 'T9ox2DCzpLfJIPzkH9pKhsOTMOEMJcFv';
|
||||||
@@ -16,11 +16,12 @@ export const NE_TYPE_LIST = [
|
|||||||
'N3IWF',
|
'N3IWF',
|
||||||
'MOCNGW',
|
'MOCNGW',
|
||||||
'SMSC',
|
'SMSC',
|
||||||
|
'CBC',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网元拓展包列表,默认顺序
|
* 网元拓展包列表,默认顺序
|
||||||
* IMS-adb/rtproxy/mf
|
* IMS-adb/kvdb/rtproxy/mf
|
||||||
* UDM-adb
|
* UDM-adb/kvdb
|
||||||
*/
|
*/
|
||||||
export const NE_EXPAND_LIST = ['ADB', 'RTPROXY', 'MF'];
|
export const NE_EXPAND_LIST = ['ADB', 'KVDB', 'RTPROXY', 'MF'];
|
||||||
@@ -1,3 +1,12 @@
|
|||||||
|
/**响应-code加密数据 */
|
||||||
|
export const RESULT_CODE_ENCRYPT = 2;
|
||||||
|
|
||||||
|
/**响应-msg加密数据 */
|
||||||
|
export const RESULT_MSG_ENCRYPT: Record<string, string> = {
|
||||||
|
zh_CN: '加密!',
|
||||||
|
en_US: 'encrypt!',
|
||||||
|
};
|
||||||
|
|
||||||
/**响应-code正常成功 */
|
/**响应-code正常成功 */
|
||||||
export const RESULT_CODE_SUCCESS = 1;
|
export const RESULT_CODE_SUCCESS = 1;
|
||||||
|
|
||||||
|
|||||||
+140
-43
@@ -149,6 +149,7 @@ export default {
|
|||||||
page403: 'No Access',
|
page403: 'No Access',
|
||||||
page404: 'Match Page Not Found',
|
page404: 'Match Page Not Found',
|
||||||
helpDoc: 'System User Documentation',
|
helpDoc: 'System User Documentation',
|
||||||
|
traceTaskHLR: 'Tracking Tasks HLR',
|
||||||
lockScreen: 'Lock Screen',
|
lockScreen: 'Lock Screen',
|
||||||
account: {
|
account: {
|
||||||
index: "Personal Center",
|
index: "Personal Center",
|
||||||
@@ -185,11 +186,11 @@ export default {
|
|||||||
helpDoc: 'Doc',
|
helpDoc: 'Doc',
|
||||||
},
|
},
|
||||||
rightContent: {
|
rightContent: {
|
||||||
|
alarm: "Active Alarms",
|
||||||
lock: "Lock Screen",
|
lock: "Lock Screen",
|
||||||
lockTip: "Confirmation of the lock screen?",
|
lockTip: "Confirmation of the lock screen?",
|
||||||
lockPasswd: "Unlock Password",
|
lockPasswd: "Unlock Password",
|
||||||
lockPasswdTip: "No password can be set",
|
lockPasswdTip: "No password can be set",
|
||||||
helpDoc: "System User Documentation",
|
|
||||||
fullscreen: "Full Screen",
|
fullscreen: "Full Screen",
|
||||||
logout: "Logout",
|
logout: "Logout",
|
||||||
profile: "Profile",
|
profile: "Profile",
|
||||||
@@ -569,6 +570,8 @@ export default {
|
|||||||
caller: "Caller",
|
caller: "Caller",
|
||||||
called: "Called",
|
called: "Called",
|
||||||
result: "Result",
|
result: "Result",
|
||||||
|
resultOk: "Success",
|
||||||
|
resultFail: "Fail",
|
||||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
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.)",
|
exportTip: "Do you confirm to export the current query conditions of the CDR data? (Maximum 10,000 items can be exported.)",
|
||||||
smfChargingID: 'Charging ID',
|
smfChargingID: 'Charging ID',
|
||||||
@@ -658,6 +661,7 @@ export default {
|
|||||||
kpiEnable: 'Report',
|
kpiEnable: 'Report',
|
||||||
kpiTimer: 'Reporting Cycle',
|
kpiTimer: 'Reporting Cycle',
|
||||||
kpiTimerPlease: 'Please enter the reporting period (in seconds)',
|
kpiTimerPlease: 'Please enter the reporting period (in seconds)',
|
||||||
|
omcIP: 'OMC IP',
|
||||||
},
|
},
|
||||||
backConf: {
|
backConf: {
|
||||||
export: 'Config Export',
|
export: 'Config Export',
|
||||||
@@ -668,9 +672,8 @@ export default {
|
|||||||
local:'Local File',
|
local:'Local File',
|
||||||
localUpload:'Local Upload',
|
localUpload:'Local Upload',
|
||||||
exportTip:'Confirm that you want to export the network element configuration file?',
|
exportTip:'Confirm that you want to export the network element configuration file?',
|
||||||
exportMsg:'Exported successfully, please download from [Backup Management].',
|
exportMsg:'Exporting Network Element Configuration Information to a File Succeeded',
|
||||||
filePlease: "Please upload a file",
|
pathPlease: 'No Backup File Found',
|
||||||
fileNamePlease: 'Please select the server file',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
neHost: {
|
neHost: {
|
||||||
@@ -682,11 +685,12 @@ export default {
|
|||||||
addrPlease: "Please fill in the host IP address correctly",
|
addrPlease: "Please fill in the host IP address correctly",
|
||||||
port: "Port",
|
port: "Port",
|
||||||
portPlease: "Please fill in the host port number correctly",
|
portPlease: "Please fill in the host port number correctly",
|
||||||
user: "Login User",
|
user: "User",
|
||||||
userPlease: "Please fill in the host login user correctly",
|
userPlease: "Please fill in the host user correctly",
|
||||||
|
database: "DataBase",
|
||||||
authMode: "Auth Mode",
|
authMode: "Auth Mode",
|
||||||
password: "Password",
|
password: "Password",
|
||||||
passwordPlease: "Please fill in the host login password correctly",
|
passwordPlease: "Please fill in the host password correctly",
|
||||||
privateKey: "Private Key",
|
privateKey: "Private Key",
|
||||||
privateKeyPlease: "Please fill in the private key characters correctly ~/.ssh/id_rsa",
|
privateKeyPlease: "Please fill in the private key characters correctly ~/.ssh/id_rsa",
|
||||||
passPhrase: "Private Key Cipher",
|
passPhrase: "Private Key Cipher",
|
||||||
@@ -736,11 +740,11 @@ export default {
|
|||||||
upgrade: "Upgrade To New Version",
|
upgrade: "Upgrade To New Version",
|
||||||
upgradeTip: "Confirmed to upgrade to the new version?",
|
upgradeTip: "Confirmed to upgrade to the new version?",
|
||||||
upgradeTipEmpty: "There are currently no new versions available",
|
upgradeTipEmpty: "There are currently no new versions available",
|
||||||
upgradeTipEqual: "Current version is the same as the new version",
|
upgradeTipEqual: "The current version is the same as the new version, confirmed to update?",
|
||||||
rollback: 'Switch to previous version',
|
rollback: 'Switch to previous version',
|
||||||
rollbackTip: "Confirm switching to the previous version?",
|
rollbackTip: "Confirm switching to the previous version?",
|
||||||
rollbackTipEmpty: "There is currently no previous version available",
|
rollbackTipEmpty: "There is currently no previous version available",
|
||||||
rollbackTipEqual: 'The current version is the same as the previous version',
|
rollbackTipEqual: 'The current version is the same as the previous version, are you sure you want to make the switch?',
|
||||||
version: "Current Version",
|
version: "Current Version",
|
||||||
preVersion: "Previous Version",
|
preVersion: "Previous Version",
|
||||||
newVersion: "New Version",
|
newVersion: "New Version",
|
||||||
@@ -770,18 +774,38 @@ export default {
|
|||||||
uploadChangeOk: 'Network Element renewed license successfully and is being calibrated in the background!',
|
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!",
|
uploadChangeFail: "Some network elements failed to update the license, please check whether the service terminal environment is available!",
|
||||||
},
|
},
|
||||||
neConfPara5G: {
|
neConfig: {
|
||||||
headerTip: 'Check and save the public parameter properties of the network element before performing the installation of the network element, and make sure that the latest parameter properties are applied.',
|
treeTitle: "Navigation Configuration",
|
||||||
headerTipToPage: 'Jump Installation',
|
treeSelectTip: "Select configuration item information in the left configuration navigation!",
|
||||||
save: 'Save',
|
neType: 'NE Type',
|
||||||
reload: 'Reload',
|
neTypePleace: "Please select the network element type",
|
||||||
title: 'Save Info',
|
noConfigData: "No data on configuration items",
|
||||||
sync: 'Sync to NE',
|
updateValue: "[ {num} ] parameter value modified successfully.",
|
||||||
syncNe: 'Select NE',
|
updateValueErr: "Attribute value modification failure",
|
||||||
syncNeDone: 'Synchronization to network element terminals complete',
|
updateItem: "Modify Index to {num}.",
|
||||||
saveOk: 'Save Success!',
|
updateItemErr: "Record modification failure",
|
||||||
|
delItemOk: "Deleting Index as {num} succeeded",
|
||||||
|
addItemOk: "Add Index as {num} Record Succeeded",
|
||||||
|
addItemErr: "Record addition failure",
|
||||||
|
requireUn: "[ {display} ] input value is of unknown type",
|
||||||
|
requireString: "[ {display} ] parameter value is invalid.",
|
||||||
|
requireInt: "[ {display} ] parameter value not in reasonable range {filter}",
|
||||||
|
requireIpv4: "[ {display} ] not a legitimate IPV4 address",
|
||||||
|
requireIpv6: "[ {display} ] not a legitimate IPV6 address.",
|
||||||
|
requireEnum: "[ {display} ] is not a reasonable enumeration value.",
|
||||||
|
requireBool: "[ {display} ] is not a reasonable boolean value.",
|
||||||
|
editOkTip: "Confirm updating the value of this [ {num} ] attribute?",
|
||||||
|
updateItemTip: "Confirm updating the data item with Index [{num}]?",
|
||||||
|
delItemTip: "Confirm deleting the data item with Index [{num}]?",
|
||||||
|
arrayMore: "Expand",
|
||||||
|
},
|
||||||
|
neConfigBackup: {
|
||||||
|
name: "Name",
|
||||||
|
downTip: 'Confirmed to download the backup file [{txt}]?',
|
||||||
|
title: "Modify Backup {txt}",
|
||||||
},
|
},
|
||||||
neQuickSetup: {
|
neQuickSetup: {
|
||||||
|
reloadPara5G: 'Reload',
|
||||||
stepPrev: 'Previous',
|
stepPrev: 'Previous',
|
||||||
stepPrevTip: 'Confirm that you want to abandon the current change and return to the previous step?',
|
stepPrevTip: 'Confirm that you want to abandon the current change and return to the previous step?',
|
||||||
stepNext: 'Next',
|
stepNext: 'Next',
|
||||||
@@ -854,9 +878,10 @@ export default {
|
|||||||
imsiTip3: 'MSIN = Mobile Subscriber Identification Number, consisting of 10 equal digits.',
|
imsiTip3: 'MSIN = Mobile Subscriber Identification Number, consisting of 10 equal digits.',
|
||||||
amfTip: 'Authentication management field, maximum parameter length is 4',
|
amfTip: 'Authentication management field, maximum parameter length is 4',
|
||||||
algoIndexTip: 'Algorithm index, between 0 and 15',
|
algoIndexTip: 'Algorithm index, between 0 and 15',
|
||||||
kiTip: 'User signing key information, the maximum length of 32',
|
kiTip: 'User signing key information, the length can only be 32',
|
||||||
opcTip: 'The authentication key, OPC, is calculated from Ki and OP, OP is the root key of the operator, ki is the authentication key, and the maximum length is 32.',
|
opcTip: 'The authentication key, OPC, is calculated from Ki and OP, OP is the root key of the operator, ki is the authentication key, and the maximum length is 32.',
|
||||||
delSure:'Are you sure you want to delete the user with IMSI number: {imsi} ?',
|
delSure:'Are you sure you want to delete the user with IMSI number: {imsi} ?',
|
||||||
|
imsiConfirm:'The length of the IMSI must be 15',
|
||||||
},
|
},
|
||||||
sub: {
|
sub: {
|
||||||
subInfo:' Subscription Info',
|
subInfo:' Subscription Info',
|
||||||
@@ -874,8 +899,8 @@ export default {
|
|||||||
checkDel: 'Check Delete',
|
checkDel: 'Check Delete',
|
||||||
batchAddText: 'Batch Add',
|
batchAddText: 'Batch Add',
|
||||||
batchDelText: 'Batch Delete',
|
batchDelText: 'Batch Delete',
|
||||||
enable:'Enable',
|
enable:'Enabled',
|
||||||
disable:'Disable',
|
disable:'Disabled',
|
||||||
startIMSI: 'Start IMSI',
|
startIMSI: 'Start IMSI',
|
||||||
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
||||||
imsiTip1: 'MCC=Mobile Country Code, consisting of three digits.',
|
imsiTip1: 'MCC=Mobile Country Code, consisting of three digits.',
|
||||||
@@ -888,7 +913,8 @@ export default {
|
|||||||
micoTip: 'Signed MICO business flag bits',
|
micoTip: 'Signed MICO business flag bits',
|
||||||
rfspTip:'RFSP index, in NG-RAN, the index of a specific RRM configuration, parameter between 0 and 127',
|
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',
|
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.',
|
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.',
|
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.',
|
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.',
|
||||||
@@ -1027,6 +1053,7 @@ export default {
|
|||||||
},
|
},
|
||||||
customTarget:{
|
customTarget:{
|
||||||
kpiId:' Custom Indicator',
|
kpiId:' Custom Indicator',
|
||||||
|
kpiIdTip:'This Ne has no custom indicators',
|
||||||
period:' Granularity',
|
period:' Granularity',
|
||||||
title:' Custom Indicator Title',
|
title:' Custom Indicator Title',
|
||||||
objectType:' Object type',
|
objectType:' Object type',
|
||||||
@@ -1038,7 +1065,26 @@ export default {
|
|||||||
addCustom:' Add custom indicator',
|
addCustom:' Add custom indicator',
|
||||||
editCustom:' Edit Custom indicator',
|
editCustom:' Edit Custom indicator',
|
||||||
errorCustomInfo: 'Failed to get information',
|
errorCustomInfo: 'Failed to get information',
|
||||||
}
|
status: 'Status',
|
||||||
|
active:'Active',
|
||||||
|
inactive:'Inactive',
|
||||||
|
symbol:'Symbol',
|
||||||
|
element:'Element',
|
||||||
|
granularity:'Granularity',
|
||||||
|
unit:'Unit',
|
||||||
|
},
|
||||||
|
kpiKeyTarget:{
|
||||||
|
"fullWidthLayout":"Full Width",
|
||||||
|
"twoColumnLayout":"Two Column",
|
||||||
|
"saveLayout": "Save Layout",
|
||||||
|
"restoreSaved": "Restore Layout",
|
||||||
|
"saveSuccess": " '{name}' saved successfully",
|
||||||
|
"restoreSavedSuccess": " '{name}' restored successfully",
|
||||||
|
"noSavedLayout": "No saved layout found for '{name}'",
|
||||||
|
"layout1": "Layout 1",
|
||||||
|
"layout2": "Layout 2",
|
||||||
|
"layout3": "Layout 3"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
traceManage: {
|
traceManage: {
|
||||||
analysis: {
|
analysis: {
|
||||||
@@ -1063,18 +1109,23 @@ export default {
|
|||||||
pcap: {
|
pcap: {
|
||||||
capArgPlease: 'Please enter tcpdump -i any support parameter',
|
capArgPlease: 'Please enter tcpdump -i any support parameter',
|
||||||
cmd: 'Command',
|
cmd: 'Command',
|
||||||
execCmd: "Generic tcpdump packet capture command",
|
execCmd: "Common Command Options",
|
||||||
execCmdsSctp: "Generic tcpdump filter sctp and port commands",
|
execCmd2: "Filter Protocol Port Command",
|
||||||
execUPFCmdA: 'Suitable for anomalous packet capture of other NE',
|
execCmd3: "File Split By Time units of seconds (-G 10), Generated Max File Number (-W 7)",
|
||||||
execUPFCmdB: 'Suitable for UPF anomaly packet capture analysis',
|
execUPFCmdA: 'Standard Edition - UPF with other NE anomalous packet capture analysis',
|
||||||
|
execUPFCmdB: 'Standard Edition - UPF anomalies requiring packet capture analysis',
|
||||||
|
batchOper: 'Batch Operations',
|
||||||
|
batchStartText: 'Batch Start',
|
||||||
|
batchStopText: 'Batch Stop',
|
||||||
|
batchDownText: 'Batch Download',
|
||||||
|
fileView: 'Historical Packet Capture Files',
|
||||||
|
fileUPF: 'Standard Edition',
|
||||||
|
fileUPFTip: 'UPF internal packet capture and analysis packet',
|
||||||
textStart: "Start",
|
textStart: "Start",
|
||||||
textStartBatch: "Batch Start",
|
|
||||||
textStop: "Stop",
|
textStop: "Stop",
|
||||||
textStopBatch: "Batch Stop",
|
textLog: "LogFile",
|
||||||
textLog: "Log",
|
textLogMsg: "LogFile Info",
|
||||||
textLogMsg: "Log Info",
|
|
||||||
textDown: "Download",
|
textDown: "Download",
|
||||||
textDownBatch: "Batch Download",
|
|
||||||
downTip: "Are you sure you want to download the {title} capture data file?",
|
downTip: "Are you sure you want to download the {title} capture data file?",
|
||||||
downOk: "{title} file download complete",
|
downOk: "{title} file download complete",
|
||||||
downErr: "{title} file download exception",
|
downErr: "{title} file download exception",
|
||||||
@@ -1088,12 +1139,13 @@ export default {
|
|||||||
stopNotRun: "{title} not running",
|
stopNotRun: "{title} not running",
|
||||||
},
|
},
|
||||||
task: {
|
task: {
|
||||||
neTypePlease: 'Query network element type',
|
traceId: 'Tracing No',
|
||||||
neType: 'NE Type',
|
|
||||||
neID: 'NE ID',
|
|
||||||
trackType: 'Tracing Type',
|
trackType: 'Tracing Type',
|
||||||
trackTypePlease: 'Please select a tracing type',
|
trackTypePlease: 'Please select a tracing type',
|
||||||
creater: 'Created by',
|
creater: 'Created by',
|
||||||
|
textStop: "Stop",
|
||||||
|
status: 'Status',
|
||||||
|
time: 'Time',
|
||||||
startTime: 'Start Time',
|
startTime: 'Start Time',
|
||||||
endTime: 'End Time',
|
endTime: 'End Time',
|
||||||
msisdn: 'MSISDN',
|
msisdn: 'MSISDN',
|
||||||
@@ -1103,26 +1155,31 @@ export default {
|
|||||||
imsiPlease: 'Please enter IMSI',
|
imsiPlease: 'Please enter IMSI',
|
||||||
imsiTip: 'Mobile communication IMSI number',
|
imsiTip: 'Mobile communication IMSI number',
|
||||||
srcIp: 'Source IP Address',
|
srcIp: 'Source IP Address',
|
||||||
srcIpPlease: 'Please enter the source IP address',
|
srcIpPlease: 'Please enter the IP address',
|
||||||
srcIpTip: 'Current sender IPv4 address',
|
srcIpTip: 'Current sender IPv4 address',
|
||||||
dstIp: 'Destination IP Address',
|
dstIp: 'Destination IP Address',
|
||||||
dstIpPlease: 'Please enter the destination IP address',
|
dstIpPlease: 'Please enter the IP address',
|
||||||
dstIpTip: 'IPv4 address of the receiving end of the other party',
|
dstIpTip: 'IPv4 address of the receiving end of the other party',
|
||||||
interfaces: 'Signaling Interface',
|
interfaces: 'Signaling Interface',
|
||||||
interfacesPlease: 'Please enter the signaling interface',
|
interfacesPlease: 'Please enter the signaling interface',
|
||||||
signalPort: 'Signal Port',
|
signalPort: 'Signal Port',
|
||||||
signalPortPlease: 'Please enter the signaling port',
|
signalPortPlease: 'Please enter the signaling port',
|
||||||
signalPortTip: 'Port corresponding to the interface',
|
signalPortTip: 'Port of the side corresponding to the destination IP address or source IP address',
|
||||||
rangePicker: 'Start/End Time',
|
rangePicker: 'Start/End Time',
|
||||||
rangePickerPlease: 'Please select the start and end time of the task',
|
rangePickerPlease: 'Please select the start and end time of the task',
|
||||||
comment: 'Task Description',
|
remark: 'Remark',
|
||||||
commentPlease: 'Task description can be entered',
|
remarkPlease: 'Task description can be entered',
|
||||||
addTask: 'Add Task',
|
addTask: 'Add Task',
|
||||||
editTask: 'Modify Task',
|
editTask: 'Modify Task',
|
||||||
viewTask: 'View Task',
|
viewTask: 'View Task',
|
||||||
errorTaskInfo: 'Failed to obtain task information',
|
errorTaskInfo: 'Failed to obtain task information',
|
||||||
delTask: 'Successfully deleted task {num}',
|
delTaskTip: 'Are you sure to delete the data item with record ID {id} ?',
|
||||||
delTaskTip: 'Are you sure to delete the data item with record number {num}?',
|
stopTask: 'Successful cessation of tasks {id}',
|
||||||
|
stopTaskTip: 'Confirm stopping the task with record ID {id} ?',
|
||||||
|
pcapView: "Tracking Data Analysis",
|
||||||
|
traceFile: "Tracking File",
|
||||||
|
errMsg: "Error Message",
|
||||||
|
imsiORmsisdn: "imsi or msisdn is null, cannot start task",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
faultManage: {
|
faultManage: {
|
||||||
@@ -1235,7 +1292,20 @@ export default {
|
|||||||
downTip: "Confirm the download file name is [{fileName}] File?",
|
downTip: "Confirm the download file name is [{fileName}] File?",
|
||||||
downTipErr: "Failed to get file",
|
downTipErr: "Failed to get file",
|
||||||
dirCd: "Enter Dir",
|
dirCd: "Enter Dir",
|
||||||
|
viewAs: 'View Action',
|
||||||
|
reload: "Reload",
|
||||||
|
follow: 'Monitoring Content',
|
||||||
|
tailChar: 'End Characters',
|
||||||
|
tailLines: 'End Lines',
|
||||||
},
|
},
|
||||||
|
exportFile:{
|
||||||
|
fileName:'File Source',
|
||||||
|
downTip: "Confirm the download file name is [{fileName}] File?",
|
||||||
|
downTipErr: "Failed to get file",
|
||||||
|
deleteTip: "Confirm the delete file name is [{fileName}] File?",
|
||||||
|
deleteTipErr: "Failed to delete file",
|
||||||
|
selectTip:"Please select File Name",
|
||||||
|
}
|
||||||
},
|
},
|
||||||
monitor: {
|
monitor: {
|
||||||
session: {
|
session: {
|
||||||
@@ -1725,6 +1795,10 @@ export default {
|
|||||||
reset: "System Reset",
|
reset: "System Reset",
|
||||||
resetInstruction: "A system reset will erase all data in the current system, please proceed with caution!!!!",
|
resetInstruction: "A system reset will erase all data in the current system, please proceed with caution!!!!",
|
||||||
resetTipContent: 'Are you sure you want to clear all data from the current system and insist on continuing?',
|
resetTipContent: 'Are you sure you want to clear all data from the current system and insist on continuing?',
|
||||||
|
homeInstruction:'Set the home page',
|
||||||
|
home: 'Home Page',
|
||||||
|
homeTip:'Do you want to submit the current interface as the system interface?',
|
||||||
|
homeSet:'Home Page Settings',
|
||||||
},
|
},
|
||||||
role:{
|
role:{
|
||||||
allScopeOptions:'All data permissions',
|
allScopeOptions:'All data permissions',
|
||||||
@@ -1947,6 +2021,7 @@ export default {
|
|||||||
stepNeInfoStepNext: 'Confirm that you want to proceed to the next step to configure the parameters of the network element?',
|
stepNeInfoStepNext: 'Confirm that you want to proceed to the next step to configure the parameters of the network element?',
|
||||||
stepPara5GTitle: "Configuration Parameter",
|
stepPara5GTitle: "Configuration Parameter",
|
||||||
stepPara5GDesc: "Setting network element global parameter information",
|
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?',
|
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?',
|
stepPara5GStepNext: 'Confirm that you want to proceed to the next step for the network element service installation?',
|
||||||
stepInstallTitle: "Service Install",
|
stepInstallTitle: "Service Install",
|
||||||
@@ -2047,6 +2122,28 @@ export default {
|
|||||||
hostSelectMore: "Load More {num}",
|
hostSelectMore: "Load More {num}",
|
||||||
hostSelectHeader: "Host List",
|
hostSelectHeader: "Host List",
|
||||||
},
|
},
|
||||||
|
ps:{
|
||||||
|
realTimeHigh:"High",
|
||||||
|
realTimeLow:"Low",
|
||||||
|
realTimeRegular:"Regular",
|
||||||
|
realTimeStop:"Stop",
|
||||||
|
realTime:"Real Time Speed",
|
||||||
|
pid:"PID",
|
||||||
|
name:"Program name",
|
||||||
|
username:"User Name",
|
||||||
|
runTime:"Run Time",
|
||||||
|
numThreads:"Thread",
|
||||||
|
cpuPercent:"CPU Percent",
|
||||||
|
diskRead:"Disk Read",
|
||||||
|
diskWrite:"Disk Write",
|
||||||
|
},
|
||||||
|
net:{
|
||||||
|
localAddr:"Local Address",
|
||||||
|
remoteAddr:"Foreign Address",
|
||||||
|
status:"State",
|
||||||
|
proto:"Proto",
|
||||||
|
port:"Port",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
+134
-37
@@ -149,6 +149,7 @@ export default {
|
|||||||
page403: '没有访问权限',
|
page403: '没有访问权限',
|
||||||
page404: '找不到匹配页面',
|
page404: '找不到匹配页面',
|
||||||
helpDoc: '系统使用文档',
|
helpDoc: '系统使用文档',
|
||||||
|
traceTaskHLR: '跟踪任务 HLR',
|
||||||
lockScreen: '锁屏',
|
lockScreen: '锁屏',
|
||||||
account: {
|
account: {
|
||||||
index: "个人中心",
|
index: "个人中心",
|
||||||
@@ -185,11 +186,11 @@ export default {
|
|||||||
helpDoc: '使用手册',
|
helpDoc: '使用手册',
|
||||||
},
|
},
|
||||||
rightContent: {
|
rightContent: {
|
||||||
|
alarm: "活动告警",
|
||||||
lock: "锁屏",
|
lock: "锁屏",
|
||||||
lockTip: "确认要进行锁屏吗?",
|
lockTip: "确认要进行锁屏吗?",
|
||||||
lockPasswd: "解锁密码",
|
lockPasswd: "解锁密码",
|
||||||
lockPasswdTip: "可不设置密码",
|
lockPasswdTip: "可不设置密码",
|
||||||
helpDoc: "系统使用文档",
|
|
||||||
fullscreen: "全屏显示",
|
fullscreen: "全屏显示",
|
||||||
logout: "退出登录",
|
logout: "退出登录",
|
||||||
profile: "个人中心",
|
profile: "个人中心",
|
||||||
@@ -569,6 +570,8 @@ export default {
|
|||||||
caller: "主叫",
|
caller: "主叫",
|
||||||
called: "被叫",
|
called: "被叫",
|
||||||
result: "结果",
|
result: "结果",
|
||||||
|
resultOk: "成功",
|
||||||
|
resultFail: "失败",
|
||||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||||
exportTip: "确认导出当前查询条件的话单数据吗?(导出最大支持一万条)",
|
exportTip: "确认导出当前查询条件的话单数据吗?(导出最大支持一万条)",
|
||||||
smfChargingID: '计费ID',
|
smfChargingID: '计费ID',
|
||||||
@@ -658,6 +661,7 @@ export default {
|
|||||||
kpiEnable: '上报',
|
kpiEnable: '上报',
|
||||||
kpiTimer: '上报周期',
|
kpiTimer: '上报周期',
|
||||||
kpiTimerPlease: '请输入上报周期(单位秒)',
|
kpiTimerPlease: '请输入上报周期(单位秒)',
|
||||||
|
omcIP: 'OMC IP',
|
||||||
},
|
},
|
||||||
backConf: {
|
backConf: {
|
||||||
export: '配置导出',
|
export: '配置导出',
|
||||||
@@ -668,9 +672,8 @@ export default {
|
|||||||
local:'本地文件',
|
local:'本地文件',
|
||||||
localUpload:'本地上传',
|
localUpload:'本地上传',
|
||||||
exportTip:'确认要导出网元配置信息到文件?',
|
exportTip:'确认要导出网元配置信息到文件?',
|
||||||
exportMsg:'导出成功,请到【备份管理】进行下载',
|
exportMsg:'导出网元配置信息到文件成功',
|
||||||
filePlease: "请上传文件",
|
pathPlease: '未发现文件',
|
||||||
fileNamePlease: '请选择服务器文件',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
neHost: {
|
neHost: {
|
||||||
@@ -683,10 +686,11 @@ export default {
|
|||||||
port: "端口",
|
port: "端口",
|
||||||
portPlease: "请正确填写主机端口号",
|
portPlease: "请正确填写主机端口号",
|
||||||
user: "用户名",
|
user: "用户名",
|
||||||
userPlease: "请正确填写主机登录用户",
|
userPlease: "请正确填写主机用户",
|
||||||
|
database: "数据库",
|
||||||
authMode: "认证模式",
|
authMode: "认证模式",
|
||||||
password: "密码",
|
password: "密码",
|
||||||
passwordPlease: "请正确填写主机登录密码",
|
passwordPlease: "请正确填写主机密码",
|
||||||
privateKey: "私钥",
|
privateKey: "私钥",
|
||||||
privateKeyPlease: "请正确填写私钥字符内容 ~/.ssh/id_rsa",
|
privateKeyPlease: "请正确填写私钥字符内容 ~/.ssh/id_rsa",
|
||||||
passPhrase: "私钥密码",
|
passPhrase: "私钥密码",
|
||||||
@@ -736,11 +740,11 @@ export default {
|
|||||||
upgrade: "升级到新版本",
|
upgrade: "升级到新版本",
|
||||||
upgradeTip: "确认要升级到新版本吗?",
|
upgradeTip: "确认要升级到新版本吗?",
|
||||||
upgradeTipEmpty: "当前没有可用的新版本",
|
upgradeTipEmpty: "当前没有可用的新版本",
|
||||||
upgradeTipEqual: "当前版本与新版本相同",
|
upgradeTipEqual: "当前版本与新版本相同,确认要进行更新吗?",
|
||||||
rollback: '切换到上一个版本',
|
rollback: '切换到上一个版本',
|
||||||
rollbackTip: "确认切换到上一个版本吗?",
|
rollbackTip: "确认切换到上一个版本吗?",
|
||||||
rollbackTipEmpty: "目前没有可用的上一个版本",
|
rollbackTipEmpty: "目前没有可用的上一个版本",
|
||||||
rollbackTipEqual: '当前版本与之前版本相同',
|
rollbackTipEqual: '当前版本与之前版本相同,确认要进行切换吗?',
|
||||||
version: "当前版本",
|
version: "当前版本",
|
||||||
preVersion: "上一个版本",
|
preVersion: "上一个版本",
|
||||||
newVersion: "新版本",
|
newVersion: "新版本",
|
||||||
@@ -770,18 +774,38 @@ export default {
|
|||||||
uploadChangeOk: '网元更新许可证成功,正在后台校验!',
|
uploadChangeOk: '网元更新许可证成功,正在后台校验!',
|
||||||
uploadChangeFail: "部分网元更新许可证失败,请检查服务终端环境是否可用!",
|
uploadChangeFail: "部分网元更新许可证失败,请检查服务终端环境是否可用!",
|
||||||
},
|
},
|
||||||
neConfPara5G: {
|
neConfig: {
|
||||||
headerTip: '进行网元安装前检查并保存网元公共参数属性,确认应用为最新参数属性',
|
treeTitle: "配置导航",
|
||||||
headerTipToPage: '跳转安装',
|
treeSelectTip: "左侧配置导航中选择配置项信息!",
|
||||||
save: '保存',
|
neType: "网元类型",
|
||||||
reload: '刷新',
|
neTypePleace: "请选择网元类型",
|
||||||
title: '保存信息',
|
noConfigData: "暂无配置项数据",
|
||||||
sync: '同步到网元',
|
updateValue: "【 {num} 】 属性值修改成功",
|
||||||
syncNe: '选择网元',
|
updateValueErr: "属性值修改失败",
|
||||||
syncNeDone: '同步到网元终端完成',
|
updateItem: "修改 Index 为 {num} 记录成功",
|
||||||
saveOk: '保存成功!',
|
updateItemErr: "记录修改失败",
|
||||||
|
delItemOk: "删除 Index 为 {num} 记录成功",
|
||||||
|
addItemOk: "新增 Index 为 {num} 记录成功",
|
||||||
|
addItemErr: "记录新增失败",
|
||||||
|
requireUn: "【 {display} 】输入值是未知类型",
|
||||||
|
requireString: "【 {display} 】参数值不合理",
|
||||||
|
requireInt: "【 {display} 】参数值不在合理范围 {filter}",
|
||||||
|
requireIpv4: "【 {display} 】不是合法的IPV4地址",
|
||||||
|
requireIpv6: "【 {display} 】不是合法的IPV6地址",
|
||||||
|
requireEnum: "【 {display} 】不是合理的枚举值",
|
||||||
|
requireBool: "【 {display} 】不是合理的布尔类型的值",
|
||||||
|
editOkTip: "确认更新该【 {num} 】属性值吗?",
|
||||||
|
updateItemTip: "确认更新Index为 【{num}】 的数据项?",
|
||||||
|
delItemTip: "确认删除Index为 【{num}】 的数据项?",
|
||||||
|
arrayMore: "展开",
|
||||||
|
},
|
||||||
|
neConfigBackup: {
|
||||||
|
name: "名称",
|
||||||
|
downTip: '确认要下载备份文件【{txt}】吗?',
|
||||||
|
title: "修改备份信息 {txt}",
|
||||||
},
|
},
|
||||||
neQuickSetup: {
|
neQuickSetup: {
|
||||||
|
reloadPara5G: '刷新',
|
||||||
stepPrev: '上一步',
|
stepPrev: '上一步',
|
||||||
stepPrevTip: '确认要放弃当前变更返回上一步吗?',
|
stepPrevTip: '确认要放弃当前变更返回上一步吗?',
|
||||||
stepNext: '下一步',
|
stepNext: '下一步',
|
||||||
@@ -854,9 +878,10 @@ export default {
|
|||||||
imsiTip3: 'MSIN=移动客户识别码,采用等长10位数字构成',
|
imsiTip3: 'MSIN=移动客户识别码,采用等长10位数字构成',
|
||||||
amfTip: '鉴权管理域,参数最大长度为 4',
|
amfTip: '鉴权管理域,参数最大长度为 4',
|
||||||
algoIndexTip: '算法索引,介于0到15之间',
|
algoIndexTip: '算法索引,介于0到15之间',
|
||||||
kiTip: '用户签权密钥信息,最大长度为32',
|
kiTip: '用户签权密钥信息,长度只能是32',
|
||||||
opcTip: '鉴权秘钥,OPC是由Ki和OP经过计算得来的,OP为运营商的根秘钥,ki是鉴权秘钥,最大长度为32',
|
opcTip: '鉴权秘钥,OPC是由Ki和OP经过计算得来的,OP为运营商的根秘钥,ki是鉴权秘钥,最大长度为32',
|
||||||
delSure:'确认删除IMSI编号为: {imsi} 的用户吗?',
|
delSure:'确认删除IMSI编号为: {imsi} 的用户吗?',
|
||||||
|
imsiConfirm:'IMSI的长度必须为15',
|
||||||
},
|
},
|
||||||
sub: {
|
sub: {
|
||||||
subInfo:'签约信息',
|
subInfo:'签约信息',
|
||||||
@@ -888,6 +913,7 @@ export default {
|
|||||||
micoTip: '签约的 MICO 业务标志位',
|
micoTip: '签约的 MICO 业务标志位',
|
||||||
rfspTip:'RFSP 索引,在 NG-RAN 中,特定 RRM 配置的索引,参数介于0到127之间',
|
rfspTip:'RFSP 索引,在 NG-RAN 中,特定 RRM 配置的索引,参数介于0到127之间',
|
||||||
ueTypeTip: '运营商定义的用户 UE Usage Type,整型,参数介于0到127之间',
|
ueTypeTip: '运营商定义的用户 UE Usage Type,整型,参数介于0到127之间',
|
||||||
|
cnFlag: '是否开启 5G Core Network 服务',
|
||||||
epsFlagTip: '是否开启 4G EPS 服务',
|
epsFlagTip: '是否开启 4G EPS 服务',
|
||||||
contextIdTip: '签约APN 上下文ID,必须从APN Context list 中选择。',
|
contextIdTip: '签约APN 上下文ID,必须从APN Context list 中选择。',
|
||||||
apnContextTip: '手机可用的APN列表,最多六个,在HSS中定义。',
|
apnContextTip: '手机可用的APN列表,最多六个,在HSS中定义。',
|
||||||
@@ -1027,6 +1053,7 @@ export default {
|
|||||||
},
|
},
|
||||||
customTarget:{
|
customTarget:{
|
||||||
kpiId:'自定义指标项',
|
kpiId:'自定义指标项',
|
||||||
|
kpiIdTip:'该网元没有自定义指标',
|
||||||
period:'颗粒度',
|
period:'颗粒度',
|
||||||
title:'自定义指标项标题',
|
title:'自定义指标项标题',
|
||||||
objectType:'对象类型',
|
objectType:'对象类型',
|
||||||
@@ -1038,7 +1065,26 @@ export default {
|
|||||||
addCustom:'添加自定义指标',
|
addCustom:'添加自定义指标',
|
||||||
editCustom:'编辑自定义指标',
|
editCustom:'编辑自定义指标',
|
||||||
errorCustomInfo: '获取信息失败',
|
errorCustomInfo: '获取信息失败',
|
||||||
}
|
status: '状态',
|
||||||
|
active:'正常',
|
||||||
|
inactive:'停用',
|
||||||
|
symbol:"符号",
|
||||||
|
element:'元素',
|
||||||
|
granularity:'颗粒度',
|
||||||
|
unit:'单位',
|
||||||
|
},
|
||||||
|
kpiKeyTarget:{
|
||||||
|
"fullWidthLayout":"全宽布局",
|
||||||
|
"twoColumnLayout":"两列布局",
|
||||||
|
"saveLayout": "保存布局",
|
||||||
|
"restoreSaved": "恢复布局",
|
||||||
|
"saveSuccess": " {name} 保存成功",
|
||||||
|
"restoreSavedSuccess": " {name} 恢复成功",
|
||||||
|
"noSavedLayout": "没有找到保存的布局 {name}",
|
||||||
|
"layout1": "布局1",
|
||||||
|
"layout2": "布局2",
|
||||||
|
"layout3": "布局3"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
traceManage: {
|
traceManage: {
|
||||||
analysis: {
|
analysis: {
|
||||||
@@ -1063,18 +1109,23 @@ export default {
|
|||||||
pcap: {
|
pcap: {
|
||||||
capArgPlease: '请输入tcpdump -i any支持参数',
|
capArgPlease: '请输入tcpdump -i any支持参数',
|
||||||
cmd: '命令',
|
cmd: '命令',
|
||||||
execCmd: "通用tcpdump抓包命令",
|
execCmd: "通用命令选项",
|
||||||
execCmdsSctp: "过滤sctp和port命令",
|
execCmd2: "过滤协议端口命令",
|
||||||
execUPFCmdA: '适合其他网元异常,UPF配合抓包的情况',
|
execCmd3: "分割文件按时间单位秒 (-G 10 ),最多生成文件数量 (-W 7)",
|
||||||
execUPFCmdB: '适合UPF异常需要抓包分析的情况',
|
execUPFCmdA: '标准版-UPF配合其他网元异常抓包分析',
|
||||||
|
execUPFCmdB: '标准版-UPF异常需要抓包分析',
|
||||||
|
batchOper: '批量操作',
|
||||||
|
batchStartText: '批量开始',
|
||||||
|
batchStopText: '批量停止',
|
||||||
|
batchDownText: '批量下载',
|
||||||
|
fileView: '历史抓包文件',
|
||||||
|
fileUPF: '标准版',
|
||||||
|
fileUPFTip: 'UPF内部抓包分析包',
|
||||||
textStart: "开始",
|
textStart: "开始",
|
||||||
textStartBatch: "批量开始",
|
|
||||||
textStop: "停止",
|
textStop: "停止",
|
||||||
textStopBatch: "批量停止",
|
textLog: "日志文件",
|
||||||
textLog: "日志",
|
textLogMsg: "日志文件信息",
|
||||||
textLogMsg: "日志信息",
|
|
||||||
textDown: "下载",
|
textDown: "下载",
|
||||||
textDownBatch: "批量下载",
|
|
||||||
downTip: "确认要下载 {title} 抓包数据文件吗?",
|
downTip: "确认要下载 {title} 抓包数据文件吗?",
|
||||||
downOk: "{title} 文件下载完成",
|
downOk: "{title} 文件下载完成",
|
||||||
downErr: "{title} 文件下载异常",
|
downErr: "{title} 文件下载异常",
|
||||||
@@ -1088,12 +1139,13 @@ export default {
|
|||||||
stopNotRun: "{title} 任务未运行",
|
stopNotRun: "{title} 任务未运行",
|
||||||
},
|
},
|
||||||
task: {
|
task: {
|
||||||
neTypePlease: '请选择网元类型',
|
traceId: '跟踪编号',
|
||||||
neType: '网元类型',
|
|
||||||
neID: '网元内部标识',
|
|
||||||
trackType: '跟踪类型',
|
trackType: '跟踪类型',
|
||||||
trackTypePlease: '请选择跟踪类型',
|
trackTypePlease: '请选择跟踪类型',
|
||||||
creater: '创建人',
|
creater: '创建人',
|
||||||
|
textStop: "停止",
|
||||||
|
status: '状态',
|
||||||
|
time: '时间',
|
||||||
startTime: '开始时间',
|
startTime: '开始时间',
|
||||||
endTime: '结束时间',
|
endTime: '结束时间',
|
||||||
msisdn: 'MSISDN',
|
msisdn: 'MSISDN',
|
||||||
@@ -1112,17 +1164,22 @@ export default {
|
|||||||
interfacesPlease: '请输入信令接口',
|
interfacesPlease: '请输入信令接口',
|
||||||
signalPort: '信令端口',
|
signalPort: '信令端口',
|
||||||
signalPortPlease: '请输入信令端口',
|
signalPortPlease: '请输入信令端口',
|
||||||
signalPortTip: '接口对应的端口',
|
signalPortTip: '目标IP地址或源IP地址对应一方的端口',
|
||||||
rangePicker: '开始结束时间',
|
rangePicker: '开始结束时间',
|
||||||
rangePickerPlease: '请选择任务时间开始结束时间',
|
rangePickerPlease: '请选择任务时间开始结束时间',
|
||||||
comment: '任务说明',
|
remark: '说明',
|
||||||
commentPlease: '可输入任务说明',
|
remarkPlease: '可输入任务说明',
|
||||||
addTask: '添加任务',
|
addTask: '添加任务',
|
||||||
editTask: '修改任务',
|
editTask: '修改任务',
|
||||||
viewTask: '查看任务',
|
viewTask: '查看任务',
|
||||||
errorTaskInfo: '获取任务信息失败',
|
errorTaskInfo: '获取任务信息失败',
|
||||||
delTask: '成功删除任务 {num}',
|
delTaskTip: '确认删除记录编号为 {id} 的数据项?',
|
||||||
delTaskTip: '确认删除记录编号为 {num} 的数据项?',
|
stopTask: '成功停止任务 {id}',
|
||||||
|
stopTaskTip: '确认停止记录编号为 {id} 的任务?',
|
||||||
|
pcapView: "跟踪数据分析",
|
||||||
|
traceFile: "跟踪文件",
|
||||||
|
errMsg: "错误信息",
|
||||||
|
imsiORmsisdn: "imsi 或 msisdn 是空值,不能开始任务",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
faultManage: {
|
faultManage: {
|
||||||
@@ -1235,7 +1292,20 @@ export default {
|
|||||||
downTip: "确认下载文件名为 【{fileName}】 文件?",
|
downTip: "确认下载文件名为 【{fileName}】 文件?",
|
||||||
downTipErr: "文件获取失败",
|
downTipErr: "文件获取失败",
|
||||||
dirCd: "进入目录",
|
dirCd: "进入目录",
|
||||||
|
viewAs: '查看操作',
|
||||||
|
reload: "重载",
|
||||||
|
follow: '监视内容变化',
|
||||||
|
tailChar: '末尾字数',
|
||||||
|
tailLines: '末尾行数',
|
||||||
},
|
},
|
||||||
|
exportFile:{
|
||||||
|
fileName:'文件来源',
|
||||||
|
downTip: "确认下载文件名为 【{fileName}】 文件?",
|
||||||
|
downTipErr: "文件获取失败",
|
||||||
|
deleteTip: "确认删除文件名为 【{fileName}】 文件?",
|
||||||
|
deleteTipErr: "文件删除失败",
|
||||||
|
selectTip:"请选择文件名",
|
||||||
|
}
|
||||||
},
|
},
|
||||||
monitor: {
|
monitor: {
|
||||||
session: {
|
session: {
|
||||||
@@ -1725,6 +1795,10 @@ export default {
|
|||||||
reset: "系统重置",
|
reset: "系统重置",
|
||||||
resetInstruction: "系统重置将会清除当前系统内所有数据,请谨慎操作!!!",
|
resetInstruction: "系统重置将会清除当前系统内所有数据,请谨慎操作!!!",
|
||||||
resetTipContent: '确认要清除当前系统内所有数据并坚持继续吗?',
|
resetTipContent: '确认要清除当前系统内所有数据并坚持继续吗?',
|
||||||
|
homeInstruction:'设置系统首页界面',
|
||||||
|
home: '系统首页',
|
||||||
|
homeTip:'确认要提交当前界面为系统界面吗?',
|
||||||
|
homeSet:'系统首页设置',
|
||||||
},
|
},
|
||||||
role:{
|
role:{
|
||||||
allScopeOptions:'全部数据权限',
|
allScopeOptions:'全部数据权限',
|
||||||
@@ -1947,6 +2021,7 @@ export default {
|
|||||||
stepNeInfoStepNext: '确认要下一步进行网元配置参数?',
|
stepNeInfoStepNext: '确认要下一步进行网元配置参数?',
|
||||||
stepPara5GTitle: "网元配置参数",
|
stepPara5GTitle: "网元配置参数",
|
||||||
stepPara5GDesc: "设置网元全局参数信息",
|
stepPara5GDesc: "设置网元全局参数信息",
|
||||||
|
savePara5GOk: '保存成功!',
|
||||||
stepPara5GStepPrev: '确认要放弃当前变更返回上一步吗?',
|
stepPara5GStepPrev: '确认要放弃当前变更返回上一步吗?',
|
||||||
stepPara5GStepNext: '确认要下一步进行网元服务安装吗?',
|
stepPara5GStepNext: '确认要下一步进行网元服务安装吗?',
|
||||||
stepInstallTitle: "网元服务安装",
|
stepInstallTitle: "网元服务安装",
|
||||||
@@ -2047,6 +2122,28 @@ export default {
|
|||||||
hostSelectMore: "加载更多 {num}",
|
hostSelectMore: "加载更多 {num}",
|
||||||
hostSelectHeader: "主机列表",
|
hostSelectHeader: "主机列表",
|
||||||
},
|
},
|
||||||
|
ps:{
|
||||||
|
realTimeHigh:"高",
|
||||||
|
realTimeLow:"低",
|
||||||
|
realTimeRegular:"常规",
|
||||||
|
realTimeStop:"已暂停",
|
||||||
|
realTime:"实时更新速度",
|
||||||
|
pid:"PID",
|
||||||
|
name:"应用名称",
|
||||||
|
username:"用户名",
|
||||||
|
runTime:"运行时间",
|
||||||
|
numThreads:"线程数",
|
||||||
|
cpuPercent:"CPU使用率",
|
||||||
|
diskRead:"磁盘读取",
|
||||||
|
diskWrite:"磁盘写入",
|
||||||
|
},
|
||||||
|
net:{
|
||||||
|
localAddr:"本地地址",
|
||||||
|
remoteAddr:"远程地址",
|
||||||
|
status:"状态",
|
||||||
|
proto:"协议",
|
||||||
|
port:"端口",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -59,7 +59,7 @@ watch(
|
|||||||
// 路由地址含有内嵌地址标识又是隐藏菜单需要处理打开高亮菜单栏
|
// 路由地址含有内嵌地址标识又是隐藏菜单需要处理打开高亮菜单栏
|
||||||
if (v.path.includes(MENU_PATH_INLINE) && v.meta.hideInMenu) {
|
if (v.path.includes(MENU_PATH_INLINE) && v.meta.hideInMenu) {
|
||||||
const idx = v.path.lastIndexOf(MENU_PATH_INLINE);
|
const idx = v.path.lastIndexOf(MENU_PATH_INLINE);
|
||||||
layoutState.openKeys.splice(-1);
|
layoutState.openKeys = layoutState.selectedKeys.slice(0, -1);
|
||||||
layoutState.selectedKeys[matched.length - 1] = v.path.slice(0, idx);
|
layoutState.selectedKeys[matched.length - 1] = v.path.slice(0, idx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -176,6 +176,7 @@ function fnCheckAppNameOverflow() {
|
|||||||
if (!text) return;
|
if (!text) return;
|
||||||
if (text.offsetWidth > container.offsetWidth) {
|
if (text.offsetWidth > container.offsetWidth) {
|
||||||
text.classList.add('app-name_scrollable');
|
text.classList.add('app-name_scrollable');
|
||||||
|
text.setAttribute('data-content', text.innerText);
|
||||||
} else {
|
} else {
|
||||||
text.classList.remove('app-name_scrollable');
|
text.classList.remove('app-name_scrollable');
|
||||||
}
|
}
|
||||||
@@ -342,11 +343,17 @@ onUnmounted(() => {
|
|||||||
:href="appStore.officialUrl"
|
:href="appStore.officialUrl"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
size="small"
|
size="small"
|
||||||
|
v-perms:has="['system:setting:official']"
|
||||||
v-if="appStore.officialUrl !== '#'"
|
v-if="appStore.officialUrl !== '#'"
|
||||||
>
|
>
|
||||||
{{ t('loayouts.basic.officialUrl') }}
|
{{ t('loayouts.basic.officialUrl') }}
|
||||||
</a-button>
|
</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') }}
|
{{ t('loayouts.basic.helpDoc') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
@@ -382,20 +389,26 @@ onUnmounted(() => {
|
|||||||
// text-overflow: ellipsis;
|
// text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 148px;
|
width: 148px;
|
||||||
|
> .app-name_scrollable {
|
||||||
&_scrollable {
|
padding-right: 12px;
|
||||||
// padding-left: 100%;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
animation: scrollable-animation linear 6s infinite both;
|
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 {
|
@keyframes scrollable-animation {
|
||||||
0% {
|
0% {
|
||||||
transform: translate3d(0, 0, 0);
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: translate3d(-100%, 0, 0);
|
transform: translateX(calc(-100% - 12px));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,7 +435,8 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
& #serverTimeDom {
|
& #serverTimeDom {
|
||||||
color: #00000085;
|
color: inherit;
|
||||||
|
opacity: 0.85;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,16 +57,6 @@ function fnClickAlarm() {
|
|||||||
router.push({ name: 'ActiveAlarm_2088' });
|
router.push({ name: 'ActiveAlarm_2088' });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**系统使用手册跳转 */
|
|
||||||
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**改变多语言 */
|
/**改变多语言 */
|
||||||
function fnChangeLocale(e: any) {
|
function fnChangeLocale(e: any) {
|
||||||
changeLocale(e.key);
|
changeLocale(e.key);
|
||||||
@@ -75,6 +65,8 @@ function fnChangeLocale(e: any) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a-space :size="12" align="center">
|
<a-space :size="12" align="center">
|
||||||
|
<a-tooltip placement="bottom">
|
||||||
|
<template #title>{{ t('loayouts.rightContent.alarm') }}</template>
|
||||||
<a-button type="text" style="color: inherit" @click="fnClickAlarm">
|
<a-button type="text" style="color: inherit" @click="fnClickAlarm">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<a-badge
|
<a-badge
|
||||||
@@ -87,8 +79,10 @@ function fnChangeLocale(e: any) {
|
|||||||
</a-badge>
|
</a-badge>
|
||||||
</template>
|
</template>
|
||||||
</a-button>
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
|
||||||
<!-- 锁屏操作 -->
|
<!-- 锁屏操作 -->
|
||||||
|
<span v-perms:has="['system:setting:lock']">
|
||||||
<a-tooltip placement="bottom">
|
<a-tooltip placement="bottom">
|
||||||
<template #title>{{ t('loayouts.rightContent.lock') }}</template>
|
<template #title>{{ t('loayouts.rightContent.lock') }}</template>
|
||||||
<a-button type="text" style="color: inherit" @click="fnClickLock()">
|
<a-button type="text" style="color: inherit" @click="fnClickLock()">
|
||||||
@@ -123,15 +117,7 @@ function fnChangeLocale(e: any) {
|
|||||||
</a-space>
|
</a-space>
|
||||||
</ProModal>
|
</ProModal>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
</span>
|
||||||
<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>
|
|
||||||
|
|
||||||
<a-tooltip placement="bottom">
|
<a-tooltip placement="bottom">
|
||||||
<template #title>{{ t('loayouts.rightContent.fullscreen') }}</template>
|
<template #title>{{ t('loayouts.rightContent.fullscreen') }}</template>
|
||||||
|
|||||||
+57
-12
@@ -13,10 +13,13 @@ import {
|
|||||||
import {
|
import {
|
||||||
APP_REQUEST_HEADER_CODE,
|
APP_REQUEST_HEADER_CODE,
|
||||||
APP_REQUEST_HEADER_VERSION,
|
APP_REQUEST_HEADER_VERSION,
|
||||||
|
APP_DATA_API_KEY,
|
||||||
} from '@/constants/app-constants';
|
} from '@/constants/app-constants';
|
||||||
import {
|
import {
|
||||||
|
RESULT_CODE_ENCRYPT,
|
||||||
RESULT_CODE_ERROR,
|
RESULT_CODE_ERROR,
|
||||||
RESULT_CODE_SUCCESS,
|
RESULT_CODE_SUCCESS,
|
||||||
|
RESULT_MSG_ENCRYPT,
|
||||||
RESULT_MSG_ERROR,
|
RESULT_MSG_ERROR,
|
||||||
RESULT_MSG_NOT_TYPE,
|
RESULT_MSG_NOT_TYPE,
|
||||||
RESULT_MSG_SERVER_ERROR,
|
RESULT_MSG_SERVER_ERROR,
|
||||||
@@ -25,11 +28,12 @@ import {
|
|||||||
RESULT_MSG_URL_NOTFOUND,
|
RESULT_MSG_URL_NOTFOUND,
|
||||||
RESULT_MSG_URL_RESUBMIT,
|
RESULT_MSG_URL_RESUBMIT,
|
||||||
} from '@/constants/result-constants';
|
} from '@/constants/result-constants';
|
||||||
|
import { decryptAES, encryptAES } from '@/utils/encrypt-utils';
|
||||||
|
|
||||||
/**响应结果类型 */
|
/**响应结果类型 */
|
||||||
export type ResultType = {
|
export type ResultType = {
|
||||||
/**响应码 */
|
/**响应码 */
|
||||||
code: number | 1 | 0;
|
code: number;
|
||||||
/**信息 */
|
/**信息 */
|
||||||
msg: string;
|
msg: string;
|
||||||
/**数据 */
|
/**数据 */
|
||||||
@@ -76,6 +80,8 @@ type OptionsType = {
|
|||||||
body?: BodyInit;
|
body?: BodyInit;
|
||||||
/**防止数据重复提交 */
|
/**防止数据重复提交 */
|
||||||
repeatSubmit?: boolean;
|
repeatSubmit?: boolean;
|
||||||
|
/**接口数据加密 */
|
||||||
|
crypto?: boolean;
|
||||||
/**携带授权Token请求头 */
|
/**携带授权Token请求头 */
|
||||||
whithToken?: boolean;
|
whithToken?: boolean;
|
||||||
/**中断控制信号,timeout不会生效 */
|
/**中断控制信号,timeout不会生效 */
|
||||||
@@ -165,26 +171,43 @@ function beforeRequest(options: OptionsType): OptionsType | Promise<any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get请求拼接地址栏参数
|
// 请求拼接地址栏参数
|
||||||
if (options.method === 'get' && options.params) {
|
if (options.params) {
|
||||||
let paramStr = '';
|
|
||||||
const params = options.params;
|
const params = options.params;
|
||||||
|
const queryParams: string[] = [];
|
||||||
for (const key in params) {
|
for (const key in params) {
|
||||||
const value = params[key];
|
const value = params[key];
|
||||||
// 空字符或未定义的值不作为参数发送
|
// 空字符或未定义的值不作为参数发送
|
||||||
if (value === '' || value === undefined) continue;
|
if (value === '' || value === undefined) continue;
|
||||||
paramStr += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
const str = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
||||||
|
queryParams.push(str);
|
||||||
|
}
|
||||||
|
const paramStr = queryParams.join('&');
|
||||||
|
if (paramStr) {
|
||||||
|
const separator = options.url.includes('?') ? '&' : '?';
|
||||||
|
// 请求加密
|
||||||
|
if (options.crypto) {
|
||||||
|
const data = encryptAES(JSON.stringify(paramStr), APP_DATA_API_KEY);
|
||||||
|
options.url += `${separator}data=${encodeURIComponent(data)}`;
|
||||||
|
} else {
|
||||||
|
options.url += `${separator}${paramStr}`;
|
||||||
}
|
}
|
||||||
if (paramStr && paramStr.startsWith('&')) {
|
|
||||||
options.url = `${options.url}?${paramStr.substring(1)}`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.method === 'get') return options;
|
||||||
|
|
||||||
// 非get参数提交
|
// 非get参数提交
|
||||||
if (options.data instanceof FormData) {
|
let body = options.data
|
||||||
options.body = options.data;
|
if (body instanceof FormData) {
|
||||||
} else {
|
options.body = body;
|
||||||
options.body = JSON.stringify(options.data);
|
} else if (body) {
|
||||||
|
// 请求加密
|
||||||
|
if (options.crypto) {
|
||||||
|
const data = encryptAES(JSON.stringify(body), APP_DATA_API_KEY);
|
||||||
|
body = { data };
|
||||||
|
}
|
||||||
|
options.body = JSON.stringify(body);
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
@@ -199,6 +222,28 @@ function interceptorResponse(res: ResultType): ResultType | Promise<any> {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 响应数据解密
|
||||||
|
if (res.code === RESULT_CODE_ENCRYPT) {
|
||||||
|
const str = decryptAES(res.data, APP_DATA_API_KEY);
|
||||||
|
let data = {};
|
||||||
|
try {
|
||||||
|
data = JSON.parse(str);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
if (Object.keys(data).length === 0) {
|
||||||
|
return Promise.resolve({
|
||||||
|
code: RESULT_CODE_ERROR,
|
||||||
|
msg: RESULT_MSG_ENCRYPT[language],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve({
|
||||||
|
code: RESULT_CODE_SUCCESS,
|
||||||
|
msg: RESULT_MSG_SUCCESS[language],
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 风格处理
|
// 风格处理
|
||||||
if (!Reflect.has(res, 'code')) {
|
if (!Reflect.has(res, 'code')) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
@@ -266,7 +311,7 @@ export async function request(options: OptionsType): Promise<ResultType> {
|
|||||||
case 'text': // 文本数据
|
case 'text': // 文本数据
|
||||||
const str = await res.text();
|
const str = await res.text();
|
||||||
return {
|
return {
|
||||||
code: 1,
|
code: RESULT_CODE_SUCCESS,
|
||||||
msg: str,
|
msg: str,
|
||||||
};
|
};
|
||||||
case 'json': // json格式数据
|
case 'json': // json格式数据
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
/**连接参数类型 */
|
||||||
|
export type OptionsType = {
|
||||||
|
/**
|
||||||
|
* 线路工作服务地址
|
||||||
|
*
|
||||||
|
* self.onmessage = error => {} - 接收消息
|
||||||
|
*
|
||||||
|
* self.postMessage() -回复消息
|
||||||
|
*/
|
||||||
|
url: string;
|
||||||
|
/**message事件的回调函数 */
|
||||||
|
onmessage: (data: any) => void;
|
||||||
|
/**error事件的回调函数 */
|
||||||
|
onerror: Function;
|
||||||
|
/**close事件的回调函数 */
|
||||||
|
onclose?: (code: number) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web Worker 使用方法
|
||||||
|
*
|
||||||
|
* import { WK, OptionsType } from '@/plugins/wk-worker';
|
||||||
|
*
|
||||||
|
* const wk = new WK();
|
||||||
|
*
|
||||||
|
* 创建连接
|
||||||
|
* const options: OptionsType = { };
|
||||||
|
* wk.connect(options);
|
||||||
|
*
|
||||||
|
* 手动关闭
|
||||||
|
* wk.close();
|
||||||
|
*/
|
||||||
|
export class WK {
|
||||||
|
/**wk 实例 */
|
||||||
|
private wk: Worker | null = null;
|
||||||
|
/**wk 连接参数 */
|
||||||
|
private options: OptionsType | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @param {object} params 构造函数参数
|
||||||
|
*/
|
||||||
|
constructor(options?: OptionsType) {
|
||||||
|
if (!window.Worker) {
|
||||||
|
// 检测浏览器支持
|
||||||
|
console.error('Sorry! Browser does not support Web Workers');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
options && this.connect(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建链接
|
||||||
|
* @param {object} options 连接参数
|
||||||
|
*/
|
||||||
|
public connect(options: OptionsType) {
|
||||||
|
this.options = options;
|
||||||
|
try {
|
||||||
|
const wk = new Worker(options.url);
|
||||||
|
// 用于收到来自其消息时的回调函数。
|
||||||
|
wk.onmessage = ev => {
|
||||||
|
// 解析文本消息
|
||||||
|
if (ev.type === 'message') {
|
||||||
|
try {
|
||||||
|
if (typeof options.onmessage === 'function') {
|
||||||
|
options.onmessage(ev.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('worker message formatting error', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 用于发生错误关闭后的回调函数。
|
||||||
|
wk.onmessageerror = ev => {
|
||||||
|
console.error('worker message error anomaly', ev);
|
||||||
|
|
||||||
|
if (typeof options.onclose === 'function') {
|
||||||
|
options.onerror(ev);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 用于发生错误后的回调函数。
|
||||||
|
wk.onerror = ev => {
|
||||||
|
console.error('worker error anomaly', ev);
|
||||||
|
|
||||||
|
if (typeof options.onerror === 'function') {
|
||||||
|
options.onerror(ev);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.wk = wk;
|
||||||
|
} catch (error) {
|
||||||
|
if (typeof options.onerror === 'function') {
|
||||||
|
options.onerror(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息
|
||||||
|
* @param data JSON数据
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public send(data: Record<string, any>): boolean {
|
||||||
|
if (!this.wk) {
|
||||||
|
console.warn('worker unavailable');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wk.postMessage(data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手动关闭会被立即终止
|
||||||
|
public close() {
|
||||||
|
if (!this.wk) {
|
||||||
|
console.warn('worker unavailable');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.wk.terminate();
|
||||||
|
// 用于关闭后的回调函数。
|
||||||
|
if (this.options && typeof this.options.onclose === 'function') {
|
||||||
|
this.options.onclose(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ export type OptionsType = {
|
|||||||
/**
|
/**
|
||||||
* WebSocket 使用方法
|
* WebSocket 使用方法
|
||||||
*
|
*
|
||||||
* import WS from '@/plugins/ws-websocket.ts';
|
* import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
*
|
*
|
||||||
* const ws = new WS();
|
* const ws = new WS();
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ const constantRoutes: RouteRecordRaw[] = [
|
|||||||
meta: { title: 'router.helpDoc' },
|
meta: { title: 'router.helpDoc' },
|
||||||
component: () => import('@/views/tool/help/index.vue'),
|
component: () => import('@/views/tool/help/index.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/trace-task-hlr',
|
||||||
|
name: 'TraceTaskHLR',
|
||||||
|
meta: { title: 'router.traceTaskHLR' },
|
||||||
|
component: () => import('@/views/traceManage/task-hlr/index.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/quick-start',
|
path: '/quick-start',
|
||||||
name: 'QuickStart',
|
name: 'QuickStart',
|
||||||
@@ -154,6 +160,7 @@ const WHITE_LIST: string[] = [
|
|||||||
'/help',
|
'/help',
|
||||||
'/register',
|
'/register',
|
||||||
'/quick-start',
|
'/quick-start',
|
||||||
|
'/trace-task-hlr',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**全局路由-前置守卫 */
|
/**全局路由-前置守卫 */
|
||||||
@@ -170,6 +177,10 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
if (appStore.bootloader && to.path !== '/quick-start') {
|
if (appStore.bootloader && to.path !== '/quick-start') {
|
||||||
next({ name: 'QuickStart' });
|
next({ name: 'QuickStart' });
|
||||||
}
|
}
|
||||||
|
// 不重复引导
|
||||||
|
if (!appStore.bootloader && to.path === '/quick-start') {
|
||||||
|
next({ name: 'Index' });
|
||||||
|
}
|
||||||
|
|
||||||
const token = getToken();
|
const token = getToken();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
|
|||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { listAllNeInfo } from '@/api/ne/neInfo';
|
import { listAllNeInfo } from '@/api/ne/neInfo';
|
||||||
import { parseDataToOptions } from '@/utils/parse-tree-utils';
|
import { parseDataToOptions } from '@/utils/parse-tree-utils';
|
||||||
import { getNeTraceInterfaceAll } from '@/api/traceManage/task';
|
import { getNeTraceInterfaceAll } from '@/api/trace/task';
|
||||||
import { getNePerformanceList } from '@/api/perfManage/taskManage';
|
import { getNePerformanceList } from '@/api/perfManage/taskManage';
|
||||||
|
|
||||||
/**网元信息类型 */
|
/**网元信息类型 */
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import CryptoJS from 'crypto-js';
|
||||||
|
import { isValid, decode } from 'js-base64';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES 加密并转为 base64
|
||||||
|
* @param plaintext 数据字符串
|
||||||
|
* @param aeskey 密钥
|
||||||
|
* @returns 加密字符串
|
||||||
|
*/
|
||||||
|
export function encryptAES(plaintext: string, aeskey: string): string {
|
||||||
|
const nowRoaund = new Date().getTime().toString(6);
|
||||||
|
const key = CryptoJS.enc.Utf8.parse(aeskey);
|
||||||
|
const iv = CryptoJS.enc.Utf8.parse(nowRoaund);
|
||||||
|
const encrypted = CryptoJS.AES.encrypt(`${nowRoaund}${plaintext}`, key, {
|
||||||
|
iv: iv,
|
||||||
|
blockSize: 16,
|
||||||
|
mode: CryptoJS.mode.CBC,
|
||||||
|
padding: CryptoJS.pad.Pkcs7,
|
||||||
|
format: CryptoJS.format.OpenSSL,
|
||||||
|
});
|
||||||
|
return encrypted.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES 解密
|
||||||
|
* @param ciphertext 加密字符串
|
||||||
|
* @param aeskey 密钥
|
||||||
|
* @returns 数据字符串
|
||||||
|
*/
|
||||||
|
export function decryptAES(ciphertext: string, aeskey: string): string {
|
||||||
|
const nowRoaund = new Date().getTime().toString(6);
|
||||||
|
const key = CryptoJS.enc.Utf8.parse(aeskey);
|
||||||
|
const iv = CryptoJS.enc.Utf8.parse(nowRoaund);
|
||||||
|
const decrypted = CryptoJS.AES.decrypt(ciphertext, key, {
|
||||||
|
iv: iv,
|
||||||
|
blockSize: 16,
|
||||||
|
mode: CryptoJS.mode.CBC,
|
||||||
|
padding: CryptoJS.pad.Pkcs7,
|
||||||
|
format: CryptoJS.format.OpenSSL,
|
||||||
|
});
|
||||||
|
const base64Str = decrypted.toString(CryptoJS.enc.Base64);
|
||||||
|
if (isValid(base64Str)) {
|
||||||
|
const str = decode(base64Str);
|
||||||
|
const idx = str.indexOf(':)', 10);
|
||||||
|
if (idx > 10) {
|
||||||
|
return str.substring(idx + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
@@ -37,7 +37,10 @@ export function parseStrLineToHump(str: string): string {
|
|||||||
*/
|
*/
|
||||||
export function parseStrHumpToLine(str: string): string {
|
export function parseStrHumpToLine(str: string): string {
|
||||||
if (!str) return str;
|
if (!str) return str;
|
||||||
return str.replace(/([A-Z])/g, '_$1').toLowerCase();
|
return str
|
||||||
|
.replace(/([A-Z])/g, '_$1')
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/^_/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,6 +95,22 @@ export function parseObjLineToHump(obj: any): any {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化文件大小
|
||||||
|
* @param bytes 字节数
|
||||||
|
* @param decimalPlaces 保留小数位,默认2位
|
||||||
|
* @returns 单位 xB
|
||||||
|
*/
|
||||||
|
export function parseSizeFromFile(bytes: number, decimalPlaces: number = 2) {
|
||||||
|
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
|
let i = 0;
|
||||||
|
while (bytes >= 1024 && i < units.length - 1) {
|
||||||
|
bytes /= 1024;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return `${bytes.toFixed(decimalPlaces || 1)} ${units[i]}`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换磁盘容量
|
* 转换磁盘容量
|
||||||
* @param size 数值大小
|
* @param size 数值大小
|
||||||
@@ -153,15 +172,16 @@ export function parseSizeFromKbs(sizeByte: number, timeInterval: number): any {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 字节数转换单位
|
* 字节数转换单位
|
||||||
* @param bits 字节Bit大小
|
* @param bits 字节Bit大小 64009540 = 512.08 MB
|
||||||
* @returns MB
|
* @returns xx B / KB / MB / GB / TB / PB / EB / ZB / YB
|
||||||
*/
|
*/
|
||||||
export function parseSizeFromBits(bits: number | string): string {
|
export function parseSizeFromBits(bits: number | string): string {
|
||||||
bits = Number(bits) || 0;
|
bits = Number(bits) || 0;
|
||||||
if (bits <= 0) return '0 B';
|
if (bits <= 0) return '0 B';
|
||||||
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
bits = bits * 8;
|
||||||
|
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
const unitIndex = Math.floor(Math.log2(bits) / 10);
|
const unitIndex = Math.floor(Math.log2(bits) / 10);
|
||||||
const value = (bits / Math.pow(1024, unitIndex)).toFixed(2);
|
const value = (bits / Math.pow(1000, unitIndex)).toFixed(2);
|
||||||
const unti = units[unitIndex];
|
const unti = units[unitIndex];
|
||||||
return `${value} ${unti}`;
|
return `${value} ${unti}`;
|
||||||
}
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import { getParamConfigInfo } from '@/api/configManage/configParam';
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
export default function useSMFOptions() {
|
|
||||||
/**upfId可选择 */
|
|
||||||
const optionsUPFIds = ref<{ value: string; label: string }[]>([]);
|
|
||||||
|
|
||||||
/**初始加载upfId */
|
|
||||||
function initUPFIds() {
|
|
||||||
getParamConfigInfo('smf', 'upfConfig', '001').then(res => {
|
|
||||||
optionsUPFIds.value = [];
|
|
||||||
for (const s of res.data) {
|
|
||||||
optionsUPFIds.value.push({
|
|
||||||
value: s.id,
|
|
||||||
label: s.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return { initUPFIds, optionsUPFIds };
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,437 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
|
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||||
|
import { message } from 'ant-design-vue/lib';
|
||||||
|
import { reactive, toRaw, ref, onMounted, onBeforeUnmount, markRaw } from 'vue';
|
||||||
|
import { listMain } from '@/api/index';
|
||||||
|
import useI18n from '@/hooks/useI18n';
|
||||||
|
import { TooltipComponent } from 'echarts/components';
|
||||||
|
import { GaugeChart } from 'echarts/charts';
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
import * as echarts from 'echarts/core';
|
||||||
|
import { TitleComponent, LegendComponent } from 'echarts/components';
|
||||||
|
import { PieChart } from 'echarts/charts';
|
||||||
|
import { LabelLayout } from 'echarts/features';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import useAppStore from '@/store/modules/app';
|
||||||
|
import useDictStore from '@/store/modules/dict';
|
||||||
|
const { getDict } = useDictStore();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
echarts.use([
|
||||||
|
TooltipComponent,
|
||||||
|
GaugeChart,
|
||||||
|
TitleComponent,
|
||||||
|
LegendComponent,
|
||||||
|
PieChart,
|
||||||
|
CanvasRenderer,
|
||||||
|
LabelLayout,
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**图DOM节点实例对象 */
|
||||||
|
const statusBar = ref<HTMLElement | undefined>(undefined);
|
||||||
|
|
||||||
|
/**图实例对象 */
|
||||||
|
const statusBarChart = ref<any>(null);
|
||||||
|
|
||||||
|
/**网元状态字典数据 */
|
||||||
|
let indexColor = ref<DictType[]>([
|
||||||
|
{ label: 'Normal', value: 'normal', tagType: '', tagClass: '#91cc75' },
|
||||||
|
{
|
||||||
|
label: 'Abnormal',
|
||||||
|
value: 'abnormal',
|
||||||
|
tagType: '',
|
||||||
|
tagClass: '#ee6666',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**表格字段列 */
|
||||||
|
//customRender(){} ----单元格处理
|
||||||
|
let tableColumns: ColumnsType = [
|
||||||
|
{
|
||||||
|
title: t('views.index.object'),
|
||||||
|
dataIndex: 'name',
|
||||||
|
align: 'center',
|
||||||
|
key: 'status',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.index.realNeStatus'),
|
||||||
|
dataIndex: 'status',
|
||||||
|
align: 'center',
|
||||||
|
customRender(opt) {
|
||||||
|
if (opt.value == 'Normal') return t('views.index.normal');
|
||||||
|
return t('views.index.abnormal');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.index.reloadTime'),
|
||||||
|
dataIndex: 'refresh',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.index.version'),
|
||||||
|
dataIndex: 'version',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.index.serialNum'),
|
||||||
|
dataIndex: 'serialNum',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.index.expiryDate'),
|
||||||
|
dataIndex: 'expiryDate',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.index.ipAddress'),
|
||||||
|
dataIndex: 'ipAddress',
|
||||||
|
key: 'groupName',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
/**表格状态类型 */
|
||||||
|
type TabeStateType = {
|
||||||
|
/**加载等待 */
|
||||||
|
loading: boolean;
|
||||||
|
/**紧凑型 */
|
||||||
|
size: string;
|
||||||
|
/**搜索栏 */
|
||||||
|
seached: boolean;
|
||||||
|
/**记录数据 */
|
||||||
|
data: object[];
|
||||||
|
/**勾选记录 */
|
||||||
|
selectedRowKeys: (string | number)[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**表格状态 */
|
||||||
|
let tableState: TabeStateType = reactive({
|
||||||
|
loading: false,
|
||||||
|
size: 'middle',
|
||||||
|
seached: false,
|
||||||
|
data: [],
|
||||||
|
selectedRowKeys: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
/**表格状态 */
|
||||||
|
let nfInfo: any = reactive({
|
||||||
|
obj: 'OMC',
|
||||||
|
version: appStore.version,
|
||||||
|
status: t('views.index.normal'),
|
||||||
|
outTimeDate: '',
|
||||||
|
serialNum: appStore.serialNum,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**表格状态类型 */
|
||||||
|
type nfStateType = {
|
||||||
|
/**主机名 */
|
||||||
|
hostName: string;
|
||||||
|
/**操作系统信息 */
|
||||||
|
osInfo: string;
|
||||||
|
/**数据库信息 */
|
||||||
|
dbInfo: string;
|
||||||
|
/**IP地址 */
|
||||||
|
ipAddress: string;
|
||||||
|
/**端口 */
|
||||||
|
port: number;
|
||||||
|
/**版本 */
|
||||||
|
version: string;
|
||||||
|
/**CPU利用率 */
|
||||||
|
cpuUse: string;
|
||||||
|
/**内存使用 */
|
||||||
|
memoryUse: string;
|
||||||
|
/**用户容量 */
|
||||||
|
capability: number;
|
||||||
|
/**序列号 */
|
||||||
|
serialNum: string;
|
||||||
|
/**许可证到期日期 */
|
||||||
|
/* selectedRowKeys: (string | number)[];*/
|
||||||
|
expiryDate: string;
|
||||||
|
};
|
||||||
|
/**网元详细信息 */
|
||||||
|
let pronInfo: nfStateType = reactive({
|
||||||
|
hostName: '5gc',
|
||||||
|
osInfo: 'Linux 5gc 4.15.0-112-generic 2020 x86_64 GNU/Linux',
|
||||||
|
dbInfo: 'db v9.9.9',
|
||||||
|
ipAddress: '-',
|
||||||
|
port: 33030,
|
||||||
|
version: '-',
|
||||||
|
cpuUse: '-',
|
||||||
|
memoryUse: '-',
|
||||||
|
capability: 0,
|
||||||
|
serialNum: '-',
|
||||||
|
expiryDate: '-',
|
||||||
|
});
|
||||||
|
|
||||||
|
/**查询网元状态列表 */
|
||||||
|
function fnGetList(one: boolean) {
|
||||||
|
if (tableState.loading) return;
|
||||||
|
one && (tableState.loading = true);
|
||||||
|
listMain().then(res => {
|
||||||
|
tableState.data = res;
|
||||||
|
tableState.loading = false;
|
||||||
|
var rightNum = 0;
|
||||||
|
var errorNum = 0;
|
||||||
|
// if (res.length) nfInfo.serialNum = res[0].serialNum;
|
||||||
|
for (let i = 0; i < res.length; i++) {
|
||||||
|
if (res[i].status == '正常' || res[i].status == 'Normal') {
|
||||||
|
rightNum++;
|
||||||
|
} else {
|
||||||
|
errorNum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionData: any = {
|
||||||
|
title: {
|
||||||
|
text: '',
|
||||||
|
subtext: '',
|
||||||
|
left: 'center',
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'left',
|
||||||
|
},
|
||||||
|
color: indexColor.value.map(item => item.tagClass),
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: t('views.index.realNeStatus'),
|
||||||
|
type: 'pie',
|
||||||
|
radius: '70%',
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
data: [
|
||||||
|
{ value: rightNum, name: t('views.index.normal') },
|
||||||
|
{ value: errorNum, name: t('views.index.abnormal') },
|
||||||
|
],
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
label: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
fnDesign(statusBar.value, optionData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fnDesign(container: HTMLElement | undefined, option: any) {
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
if (!statusBarChart.value) {
|
||||||
|
statusBarChart.value = markRaw(echarts.init(container, 'light'));
|
||||||
|
}
|
||||||
|
option && statusBarChart.value.setOption(option);
|
||||||
|
|
||||||
|
// 创建 ResizeObserver 实例
|
||||||
|
var observer = new ResizeObserver(entries => {
|
||||||
|
if (statusBarChart.value) {
|
||||||
|
statusBarChart.value.resize();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 监听元素大小变化
|
||||||
|
observer.observe(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**抽屉 网元详细信息 */
|
||||||
|
const visible = ref(false);
|
||||||
|
const closeDrawer = () => {
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
/**抽屉 网元详细信息 */
|
||||||
|
|
||||||
|
/**监听表格行事件*/
|
||||||
|
function rowClick(record: any, index: any) {
|
||||||
|
return {
|
||||||
|
onClick: (event: any) => {
|
||||||
|
if (
|
||||||
|
toRaw(record).status == '异常' ||
|
||||||
|
toRaw(record).status == 'Abnormal'
|
||||||
|
) {
|
||||||
|
message.error(t('views.index.neStatus'), 2);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
let pronData = toRaw(record);
|
||||||
|
const totalMemInKB = pronData.memUsage?.totalMem;
|
||||||
|
const nfUsedMemInKB = pronData.memUsage?.nfUsedMem;
|
||||||
|
const sysMemUsageInKB = pronData.memUsage?.sysMemUsage;
|
||||||
|
|
||||||
|
// 将KB转换为MB
|
||||||
|
const totalMemInMB = Math.round((totalMemInKB / 1024) * 100) / 100;
|
||||||
|
const nfUsedMemInMB = Math.round((nfUsedMemInKB / 1024) * 100) / 100;
|
||||||
|
const sysMemUsageInMB =
|
||||||
|
Math.round((sysMemUsageInKB / 1024) * 100) / 100;
|
||||||
|
|
||||||
|
//渲染详细信息
|
||||||
|
pronInfo = {
|
||||||
|
hostName: pronData.hostName,
|
||||||
|
osInfo: pronData.osInfo,
|
||||||
|
dbInfo: pronData.dbInfo,
|
||||||
|
ipAddress: pronData.ipAddress,
|
||||||
|
port: pronData.port,
|
||||||
|
version: pronData.version,
|
||||||
|
cpuUse:
|
||||||
|
pronData.name +
|
||||||
|
':' +
|
||||||
|
pronData.cpuUsage?.nfCpuUsage / 100 +
|
||||||
|
'%; ' +
|
||||||
|
'SYS:' +
|
||||||
|
pronData.cpuUsage?.sysCpuUsage / 100 +
|
||||||
|
'%',
|
||||||
|
memoryUse:
|
||||||
|
'Total:' +
|
||||||
|
totalMemInMB +
|
||||||
|
'MB; ' +
|
||||||
|
pronData.name +
|
||||||
|
':' +
|
||||||
|
nfUsedMemInMB +
|
||||||
|
'MB; SYS:' +
|
||||||
|
sysMemUsageInMB +
|
||||||
|
'MB',
|
||||||
|
capability: pronData.capability,
|
||||||
|
serialNum: pronData.serialNum,
|
||||||
|
expiryDate: pronData.expiryDate,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
visible.value = true;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let timer: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 国际化翻译转换
|
||||||
|
*/
|
||||||
|
function fnLocale() {
|
||||||
|
let title = route.meta.title as string;
|
||||||
|
if (title.indexOf('router.') !== -1) {
|
||||||
|
title = t(title);
|
||||||
|
}
|
||||||
|
appStore.setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getDict('index_status')
|
||||||
|
.then(res => {
|
||||||
|
if (res.length > 0) {
|
||||||
|
indexColor.value = res;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
fnLocale();
|
||||||
|
fnGetList(true);
|
||||||
|
timer = setInterval(() => fnGetList(false), 10000); // 每隔10秒执行一次
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 在组件卸载之前清除定时器
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearInterval(timer);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<PageContainer :breadcrumb="{}">
|
||||||
|
<div>
|
||||||
|
<a-drawer :visible="visible" @close="closeDrawer" :width="700">
|
||||||
|
<a-descriptions bordered :column="1" :label-style="{ width: '160px' }">
|
||||||
|
<a-descriptions-item :label="t('views.index.hostName')">{{
|
||||||
|
pronInfo.hostName
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.osInfo')">{{
|
||||||
|
pronInfo.osInfo
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.ipAddress')">{{
|
||||||
|
pronInfo.ipAddress
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.version')">{{
|
||||||
|
pronInfo.version
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.cpuUse')">{{
|
||||||
|
pronInfo.cpuUse
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.memoryUse')">{{
|
||||||
|
pronInfo.memoryUse
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.serialNum')">{{
|
||||||
|
pronInfo.serialNum
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.expiryDate')">{{
|
||||||
|
pronInfo.expiryDate
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
</a-drawer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :lg="14" :md="16" :xs="24">
|
||||||
|
<!-- 表格列表 -->
|
||||||
|
<a-table
|
||||||
|
class="table"
|
||||||
|
row-key="id"
|
||||||
|
:columns="tableColumns"
|
||||||
|
:loading="tableState.loading"
|
||||||
|
:data-source="tableState.data"
|
||||||
|
:pagination="false"
|
||||||
|
:scroll="{ x: true }"
|
||||||
|
:customRow="rowClick"
|
||||||
|
>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<div v-if="record.status == '正常' || record.status == 'Normal'">
|
||||||
|
<a-tag color="blue">{{ record.name }}</a-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<a-tag color="pink">{{ record.name }}</a-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</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>
|
||||||
|
</a-card>
|
||||||
|
<a-card :title="t('views.index.mark')" style="margin-top: 16px">
|
||||||
|
<a-descriptions
|
||||||
|
bordered
|
||||||
|
:column="1"
|
||||||
|
:label-style="{ width: '160px' }"
|
||||||
|
>
|
||||||
|
<a-descriptions-item :label="t('views.index.object')">{{
|
||||||
|
nfInfo.obj
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<template v-if="nfInfo.obj === 'OMC'">
|
||||||
|
<a-descriptions-item :label="t('views.index.versionNum')">{{
|
||||||
|
nfInfo.version
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.systemStatus')">{{
|
||||||
|
nfInfo.status
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<a-descriptions-item :label="t('views.index.serialNum')">{{
|
||||||
|
nfInfo.serialNum
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.expiryDate')">{{
|
||||||
|
nfInfo.outTimeDate
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
</template>
|
||||||
|
</a-descriptions>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</PageContainer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
@@ -425,8 +425,6 @@ function fnGetList(pageNum?: number) {
|
|||||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||||
queryParams.pageNum !== 1
|
queryParams.pageNum !== 1
|
||||||
) {
|
) {
|
||||||
debugger;
|
|
||||||
|
|
||||||
tableState.loading = false;
|
tableState.loading = false;
|
||||||
fnGetList(queryParams.pageNum - 1);
|
fnGetList(queryParams.pageNum - 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ let queryParams = reactive({
|
|||||||
/**网元类型 */
|
/**网元类型 */
|
||||||
neType: 'AMF',
|
neType: 'AMF',
|
||||||
neId: '001',
|
neId: '001',
|
||||||
eventType: 'auth-result',
|
eventType: '',
|
||||||
imsi: '',
|
imsi: '',
|
||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
@@ -58,9 +58,9 @@ let queryParams = reactive({
|
|||||||
|
|
||||||
/**查询参数重置 */
|
/**查询参数重置 */
|
||||||
function fnQueryReset() {
|
function fnQueryReset() {
|
||||||
eventTypes.value = ['auth-result'];
|
eventTypes.value = [];
|
||||||
queryParams = Object.assign(queryParams, {
|
queryParams = Object.assign(queryParams, {
|
||||||
eventType: 'auth-result',
|
eventType: '',
|
||||||
imsi: '',
|
imsi: '',
|
||||||
startTime: '',
|
startTime: '',
|
||||||
endTime: '',
|
endTime: '',
|
||||||
@@ -74,7 +74,7 @@ function fnQueryReset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**记录类型 */
|
/**记录类型 */
|
||||||
const eventTypes = ref<string[]>(['auth-result']);
|
const eventTypes = ref<string[]>([]);
|
||||||
|
|
||||||
/**查询记录类型变更 */
|
/**查询记录类型变更 */
|
||||||
function fnQueryEventTypeChange(value: any) {
|
function fnQueryEventTypeChange(value: any) {
|
||||||
@@ -607,10 +607,7 @@ onBeforeUnmount(() => {
|
|||||||
:value="record.eventJSON.authCode"
|
:value="record.eventJSON.authCode"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span v-if="record.eventType === 'detach'">
|
||||||
v-if="record.eventType === 'detach'"
|
|
||||||
:title="record.eventJSON.detachTime"
|
|
||||||
>
|
|
||||||
<span>{{ t('views.dashboard.ue.resultOk') }}</span>
|
<span>{{ t('views.dashboard.ue.resultOk') }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="record.eventType === 'cm-state'">
|
<span v-if="record.eventType === 'cm-state'">
|
||||||
@@ -706,7 +703,7 @@ onBeforeUnmount(() => {
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="record.eventType === 'detach'">
|
<span v-if="record.eventType === 'detach'">
|
||||||
{{ t('views.dashboard.ue.resultOK') }}
|
{{ t('views.dashboard.ue.resultOk') }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="record.eventType === 'cm-state'">
|
<span v-if="record.eventType === 'cm-state'">
|
||||||
<DictTag
|
<DictTag
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
RESULT_CODE_SUCCESS,
|
RESULT_CODE_SUCCESS,
|
||||||
} from '@/constants/result-constants';
|
} from '@/constants/result-constants';
|
||||||
import useDictStore from '@/store/modules/dict';
|
import useDictStore from '@/store/modules/dict';
|
||||||
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
import {
|
import {
|
||||||
delIMSDataCDR,
|
delIMSDataCDR,
|
||||||
exportIMSDataCDR,
|
exportIMSDataCDR,
|
||||||
@@ -36,6 +37,9 @@ let dict: {
|
|||||||
cdrCallType: [],
|
cdrCallType: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**网元可选 */
|
||||||
|
let neOtions = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
/**开始结束时间 */
|
/**开始结束时间 */
|
||||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||||
|
|
||||||
@@ -44,7 +48,7 @@ let queryParams = reactive({
|
|||||||
/**网元类型 */
|
/**网元类型 */
|
||||||
neType: 'IMS',
|
neType: 'IMS',
|
||||||
neId: '001',
|
neId: '001',
|
||||||
recordType: 'MOC',
|
recordType: '',
|
||||||
callerParty: '',
|
callerParty: '',
|
||||||
calledParty: '',
|
calledParty: '',
|
||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
@@ -61,9 +65,9 @@ let queryParams = reactive({
|
|||||||
|
|
||||||
/**查询参数重置 */
|
/**查询参数重置 */
|
||||||
function fnQueryReset() {
|
function fnQueryReset() {
|
||||||
recordTypes.value = ['MOC'];
|
recordTypes.value = [];
|
||||||
queryParams = Object.assign(queryParams, {
|
queryParams = Object.assign(queryParams, {
|
||||||
recordType: 'MOC',
|
recordType: '',
|
||||||
callerParty: '',
|
callerParty: '',
|
||||||
calledParty: '',
|
calledParty: '',
|
||||||
startTime: '',
|
startTime: '',
|
||||||
@@ -78,7 +82,7 @@ function fnQueryReset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**记录类型 */
|
/**记录类型 */
|
||||||
const recordTypes = ref<string[]>(['MOC']);
|
const recordTypes = ref<string[]>([]);
|
||||||
|
|
||||||
/**查询记录类型变更 */
|
/**查询记录类型变更 */
|
||||||
function fnQueryRecordTypeChange(value: any) {
|
function fnQueryRecordTypeChange(value: any) {
|
||||||
@@ -135,17 +139,6 @@ let tableColumns: ColumnsType = [
|
|||||||
align: 'left',
|
align: 'left',
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: t('views.dashboard.cdr.called'),
|
|
||||||
dataIndex: 'cdrJSON',
|
|
||||||
key: 'calledParty',
|
|
||||||
align: 'left',
|
|
||||||
width: 120,
|
|
||||||
customRender(opt) {
|
|
||||||
const cdrJSON = opt.value;
|
|
||||||
return cdrJSON.calledParty;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: t('views.dashboard.cdr.caller'),
|
title: t('views.dashboard.cdr.caller'),
|
||||||
dataIndex: 'cdrJSON',
|
dataIndex: 'cdrJSON',
|
||||||
@@ -157,6 +150,17 @@ let tableColumns: ColumnsType = [
|
|||||||
return cdrJSON.callerParty;
|
return cdrJSON.callerParty;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t('views.dashboard.cdr.called'),
|
||||||
|
dataIndex: 'cdrJSON',
|
||||||
|
key: 'calledParty',
|
||||||
|
align: 'left',
|
||||||
|
width: 120,
|
||||||
|
customRender(opt) {
|
||||||
|
const cdrJSON = opt.value;
|
||||||
|
return cdrJSON.calledParty;
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t('views.dashboard.cdr.duration'),
|
title: t('views.dashboard.cdr.duration'),
|
||||||
dataIndex: 'cdrJSON',
|
dataIndex: 'cdrJSON',
|
||||||
@@ -375,6 +379,7 @@ const realTimeData = ref<boolean>(false);
|
|||||||
function fnRealTime() {
|
function fnRealTime() {
|
||||||
realTimeData.value = !realTimeData.value;
|
realTimeData.value = !realTimeData.value;
|
||||||
if (realTimeData.value) {
|
if (realTimeData.value) {
|
||||||
|
tableState.seached = false;
|
||||||
// 建立链接
|
// 建立链接
|
||||||
const options: OptionsType = {
|
const options: OptionsType = {
|
||||||
url: '/ws',
|
url: '/ws',
|
||||||
@@ -383,7 +388,7 @@ function fnRealTime() {
|
|||||||
*
|
*
|
||||||
* IMS_CDR会话事件(GroupID:1005)
|
* IMS_CDR会话事件(GroupID:1005)
|
||||||
*/
|
*/
|
||||||
subGroupID: '1005',
|
subGroupID: `1005_${queryParams.neId}`,
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: wsError,
|
onerror: wsError,
|
||||||
@@ -391,6 +396,8 @@ function fnRealTime() {
|
|||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
} else {
|
} else {
|
||||||
ws.close();
|
ws.close();
|
||||||
|
tableState.seached = true;
|
||||||
|
fnGetList(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,7 +420,7 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// cdrEvent CDR会话事件
|
// cdrEvent CDR会话事件
|
||||||
if (data.groupId === '1005') {
|
if (data.groupId === `1005_${queryParams.neId}`) {
|
||||||
const cdrEvent = data.data;
|
const cdrEvent = data.data;
|
||||||
queue.add(async () => {
|
queue.add(async () => {
|
||||||
modalState.maxId += 1;
|
modalState.maxId += 1;
|
||||||
@@ -436,14 +443,39 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 初始字典数据
|
// 初始字典数据
|
||||||
Promise.allSettled([getDict('cdr_sip_code'), getDict('cdr_call_type')])
|
Promise.allSettled([getDict('cdr_sip_code'), getDict('cdr_call_type')]).then(
|
||||||
.then(resArr => {
|
resArr => {
|
||||||
if (resArr[0].status === 'fulfilled') {
|
if (resArr[0].status === 'fulfilled') {
|
||||||
dict.cdrSipCode = resArr[0].value;
|
dict.cdrSipCode = resArr[0].value;
|
||||||
}
|
}
|
||||||
if (resArr[1].status === 'fulfilled') {
|
if (resArr[1].status === 'fulfilled') {
|
||||||
dict.cdrCallType = resArr[1].value;
|
dict.cdrCallType = resArr[1].value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// 获取网元网元列表
|
||||||
|
useNeInfoStore()
|
||||||
|
.fnNelist()
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
let arr: Record<string, any>[] = [];
|
||||||
|
res.data.forEach(i => {
|
||||||
|
if (i.neType === 'IMS') {
|
||||||
|
arr.push({ value: i.neId, label: i.neName });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
neOtions.value = arr;
|
||||||
|
if (arr.length > 0) {
|
||||||
|
queryParams.neId = arr[0].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('common.noData'),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
// 获取列表数据
|
// 获取列表数据
|
||||||
@@ -468,6 +500,53 @@ onBeforeUnmount(() => {
|
|||||||
<!-- 表格搜索栏 -->
|
<!-- 表格搜索栏 -->
|
||||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item label="IMS" name="neId ">
|
||||||
|
<a-select
|
||||||
|
v-model:value="queryParams.neId"
|
||||||
|
:options="neOtions"
|
||||||
|
:placeholder="t('common.selectPlease')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.dashboard.cdr.called')"
|
||||||
|
name="calledParty"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:value="queryParams.calledParty"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.dashboard.cdr.caller')"
|
||||||
|
name="callerParty "
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:value="queryParams.callerParty"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
></a-input>
|
||||||
|
</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-col :lg="8" :md="12" :xs="24">
|
<a-col :lg="8" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.dashboard.cdr.recordType')"
|
:label="t('views.dashboard.cdr.recordType')"
|
||||||
@@ -484,30 +563,6 @@ onBeforeUnmount(() => {
|
|||||||
></a-select>
|
></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="4" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.dashboard.cdr.called')"
|
|
||||||
name="calledParty "
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="queryParams.calledParty"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="4" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.dashboard.cdr.caller')"
|
|
||||||
name="callerParty "
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="queryParams.callerParty"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="8" :md="12" :xs="24">
|
<a-col :lg="8" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.dashboard.cdr.time')"
|
:label="t('views.dashboard.cdr.time')"
|
||||||
@@ -524,20 +579,6 @@ onBeforeUnmount(() => {
|
|||||||
></a-range-picker>
|
></a-range-picker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</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-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-card>
|
</a-card>
|
||||||
@@ -595,6 +636,7 @@ onBeforeUnmount(() => {
|
|||||||
:checked-children="t('common.switch.show')"
|
:checked-children="t('common.switch.show')"
|
||||||
:un-checked-children="t('common.switch.hide')"
|
:un-checked-children="t('common.switch.hide')"
|
||||||
size="small"
|
size="small"
|
||||||
|
:disabled="realTimeData"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
@@ -639,7 +681,7 @@ onBeforeUnmount(() => {
|
|||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
:scroll="{ x: tableColumns.length * 150, y: 'calc(100vh - 480px)' }"
|
||||||
:row-selection="{
|
:row-selection="{
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
columnWidth: '48px',
|
columnWidth: '48px',
|
||||||
@@ -663,7 +705,7 @@ onBeforeUnmount(() => {
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{ t('views.dashboard.overview.userActivity.resultOK') }}
|
{{ t('views.dashboard.cdr.resultOk') }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="column.key === 'id'">
|
<template v-if="column.key === 'id'">
|
||||||
@@ -734,7 +776,7 @@ onBeforeUnmount(() => {
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{ t('views.dashboard.overview.userActivity.resultOK') }}
|
{{ t('views.dashboard.cdr.resultOk') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
RESULT_CODE_SUCCESS,
|
RESULT_CODE_SUCCESS,
|
||||||
} from '@/constants/result-constants';
|
} from '@/constants/result-constants';
|
||||||
import useDictStore from '@/store/modules/dict';
|
import useDictStore from '@/store/modules/dict';
|
||||||
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
import { listMMEDataUE, delMMEDataUE, exportMMEDataUE } from '@/api/neData/mme';
|
import { listMMEDataUE, delMMEDataUE, exportMMEDataUE } from '@/api/neData/mme';
|
||||||
import { parseDateToStr } from '@/utils/date-utils';
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
@@ -21,6 +22,12 @@ const { getDict } = useDictStore();
|
|||||||
const ws = new WS();
|
const ws = new WS();
|
||||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||||
|
|
||||||
|
/**网元可选 */
|
||||||
|
let neOtions = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
|
/**event Type */
|
||||||
|
let mmeEventType = ref<DictType[]>([]);
|
||||||
|
|
||||||
/**字典数据 */
|
/**字典数据 */
|
||||||
let dict: {
|
let dict: {
|
||||||
/**UE 事件认证代码类型 */
|
/**UE 事件认证代码类型 */
|
||||||
@@ -43,7 +50,7 @@ let queryParams = reactive({
|
|||||||
/**网元类型 */
|
/**网元类型 */
|
||||||
neType: 'MME',
|
neType: 'MME',
|
||||||
neId: '001',
|
neId: '001',
|
||||||
eventType: 'auth-result',
|
eventType: '',
|
||||||
imsi: '',
|
imsi: '',
|
||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
@@ -59,9 +66,9 @@ let queryParams = reactive({
|
|||||||
|
|
||||||
/**查询参数重置 */
|
/**查询参数重置 */
|
||||||
function fnQueryReset() {
|
function fnQueryReset() {
|
||||||
eventTypes.value = ['auth-result'];
|
eventTypes.value = [];
|
||||||
queryParams = Object.assign(queryParams, {
|
queryParams = Object.assign(queryParams, {
|
||||||
eventType: 'auth-result',
|
eventType: '',
|
||||||
imsi: '',
|
imsi: '',
|
||||||
startTime: '',
|
startTime: '',
|
||||||
endTime: '',
|
endTime: '',
|
||||||
@@ -75,7 +82,7 @@ function fnQueryReset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**记录类型 */
|
/**记录类型 */
|
||||||
const eventTypes = ref<string[]>(['auth-result']);
|
const eventTypes = ref<string[]>([]);
|
||||||
|
|
||||||
/**查询记录类型变更 */
|
/**查询记录类型变更 */
|
||||||
function fnQueryEventTypeChange(value: any) {
|
function fnQueryEventTypeChange(value: any) {
|
||||||
@@ -337,6 +344,7 @@ const realTimeData = ref<boolean>(false);
|
|||||||
function fnRealTime() {
|
function fnRealTime() {
|
||||||
realTimeData.value = !realTimeData.value;
|
realTimeData.value = !realTimeData.value;
|
||||||
if (realTimeData.value) {
|
if (realTimeData.value) {
|
||||||
|
tableState.seached = false;
|
||||||
// 建立链接
|
// 建立链接
|
||||||
const options: OptionsType = {
|
const options: OptionsType = {
|
||||||
url: '/ws',
|
url: '/ws',
|
||||||
@@ -345,7 +353,7 @@ function fnRealTime() {
|
|||||||
*
|
*
|
||||||
* MME_UE会话事件(GroupID:1011)
|
* MME_UE会话事件(GroupID:1011)
|
||||||
*/
|
*/
|
||||||
subGroupID: '1011',
|
subGroupID: `1011_${queryParams.neId}`,
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: wsError,
|
onerror: wsError,
|
||||||
@@ -353,6 +361,8 @@ function fnRealTime() {
|
|||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
} else {
|
} else {
|
||||||
ws.close();
|
ws.close();
|
||||||
|
tableState.seached = true;
|
||||||
|
fnGetList(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +385,7 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ueEvent MME_UE会话事件
|
// ueEvent MME_UE会话事件
|
||||||
if (data.groupId === '1011') {
|
if (data.groupId === `1011_${queryParams.neId}`) {
|
||||||
const ueEvent = data.data;
|
const ueEvent = data.data;
|
||||||
queue.add(async () => {
|
queue.add(async () => {
|
||||||
modalState.maxId += 1;
|
modalState.maxId += 1;
|
||||||
@@ -403,17 +413,48 @@ onMounted(() => {
|
|||||||
getDict('ue_auth_code'),
|
getDict('ue_auth_code'),
|
||||||
getDict('ue_event_type'),
|
getDict('ue_event_type'),
|
||||||
getDict('ue_event_cm_state'),
|
getDict('ue_event_cm_state'),
|
||||||
])
|
]).then(resArr => {
|
||||||
.then(resArr => {
|
|
||||||
if (resArr[0].status === 'fulfilled') {
|
if (resArr[0].status === 'fulfilled') {
|
||||||
dict.ueAauthCode = resArr[0].value;
|
dict.ueAauthCode = resArr[0].value;
|
||||||
}
|
}
|
||||||
if (resArr[1].status === 'fulfilled') {
|
if (resArr[1].status === 'fulfilled') {
|
||||||
dict.ueEventType = resArr[1].value;
|
resArr[1].value.map(item => {
|
||||||
|
const realJson = JSON.parse(JSON.stringify(item));
|
||||||
|
|
||||||
|
if (realJson.value === 'cm-state') {
|
||||||
|
realJson.label = realJson.label.replace('CM', 'ECM');
|
||||||
|
}
|
||||||
|
mmeEventType.value.push(realJson);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (resArr[2].status === 'fulfilled') {
|
if (resArr[2].status === 'fulfilled') {
|
||||||
dict.ueEventCmState = resArr[2].value;
|
dict.ueEventCmState = resArr[2].value;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取网元网元列表
|
||||||
|
useNeInfoStore()
|
||||||
|
.fnNelist()
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
let arr: Record<string, any>[] = [];
|
||||||
|
res.data.forEach(i => {
|
||||||
|
if (i.neType === 'MME') {
|
||||||
|
arr.push({ value: i.neId, label: i.neName });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
neOtions.value = arr;
|
||||||
|
if (arr.length > 0) {
|
||||||
|
queryParams.neId = arr[0].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('common.noData'),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
// 获取列表数据
|
// 获取列表数据
|
||||||
@@ -438,6 +479,15 @@ onBeforeUnmount(() => {
|
|||||||
<!-- 表格搜索栏 -->
|
<!-- 表格搜索栏 -->
|
||||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item label="MME" name="neId ">
|
||||||
|
<a-select
|
||||||
|
v-model:value="queryParams.neId"
|
||||||
|
:options="neOtions"
|
||||||
|
:placeholder="t('common.selectPlease')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.dashboard.ue.eventType')"
|
:label="t('views.dashboard.ue.eventType')"
|
||||||
@@ -446,7 +496,7 @@ onBeforeUnmount(() => {
|
|||||||
<a-select
|
<a-select
|
||||||
v-model:value="eventTypes"
|
v-model:value="eventTypes"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
:options="dict.ueEventType"
|
:options="mmeEventType"
|
||||||
:placeholder="t('common.selectPlease')"
|
:placeholder="t('common.selectPlease')"
|
||||||
@change="fnQueryEventTypeChange"
|
@change="fnQueryEventTypeChange"
|
||||||
></a-select>
|
></a-select>
|
||||||
@@ -548,6 +598,7 @@ onBeforeUnmount(() => {
|
|||||||
:checked-children="t('common.switch.show')"
|
:checked-children="t('common.switch.show')"
|
||||||
:un-checked-children="t('common.switch.hide')"
|
:un-checked-children="t('common.switch.hide')"
|
||||||
size="small"
|
size="small"
|
||||||
|
:disabled="realTimeData"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
@@ -602,7 +653,7 @@ onBeforeUnmount(() => {
|
|||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'eventType'">
|
<template v-if="column.key === 'eventType'">
|
||||||
<DictTag :options="dict.ueEventType" :value="record.eventType" />
|
<DictTag :options="mmeEventType" :value="record.eventType" />
|
||||||
</template>
|
</template>
|
||||||
<template v-if="column.key === 'result'">
|
<template v-if="column.key === 'result'">
|
||||||
<span v-if="record.eventType === 'auth-result'">
|
<span v-if="record.eventType === 'auth-result'">
|
||||||
@@ -659,7 +710,7 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
|
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
|
||||||
<DictTag :options="dict.ueEventType" :value="record.eventType" />
|
<DictTag :options="mmeEventType" :value="record.eventType" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>{{ t('views.dashboard.ue.result') }}: </span>
|
<span>{{ t('views.dashboard.ue.result') }}: </span>
|
||||||
@@ -670,7 +721,7 @@ onBeforeUnmount(() => {
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="record.eventType === 'detach'">
|
<span v-if="record.eventType === 'detach'">
|
||||||
{{ t('views.dashboard.ue.resultOK') }}
|
{{ t('views.dashboard.ue.resultOk') }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="record.eventType === 'cm-state'">
|
<span v-if="record.eventType === 'cm-state'">
|
||||||
<DictTag
|
<DictTag
|
||||||
|
|||||||
@@ -158,21 +158,25 @@ async function fnGetSkim() {
|
|||||||
function loadData() {
|
function loadData() {
|
||||||
fnGetNeState(); // 获取网元状态
|
fnGetNeState(); // 获取网元状态
|
||||||
userActivitySend();
|
userActivitySend();
|
||||||
upfTFSend(0);
|
upfTFSend('0');
|
||||||
upfTFSend(7);
|
upfTFSend('7');
|
||||||
upfTFSend(30);
|
upfTFSend('30');
|
||||||
|
|
||||||
|
clearInterval(interval10s.value);
|
||||||
interval10s.value = setInterval(() => {
|
interval10s.value = setInterval(() => {
|
||||||
upfTFActive.value = upfTFActive.value >= 2 ? 0 : upfTFActive.value + 1;
|
if (upfTFActive.value === '0') {
|
||||||
if (upfTFActive.value === 0) {
|
upfTFSend('7');
|
||||||
upfTFSend(7);
|
upfTFActive.value = '7';
|
||||||
} else if (upfTFActive.value === 1) {
|
} else if (upfTFActive.value === '7') {
|
||||||
upfTFSend(30);
|
upfTFSend('30');
|
||||||
} else if (upfTFActive.value === 2) {
|
upfTFActive.value = '30';
|
||||||
upfTFSend(0);
|
} else if (upfTFActive.value === '30') {
|
||||||
|
upfTFSend('0');
|
||||||
|
upfTFActive.value = '0';
|
||||||
}
|
}
|
||||||
}, 10_000);
|
}, 10_000);
|
||||||
|
|
||||||
|
clearInterval(interval5s.value);
|
||||||
interval5s.value = setInterval(() => {
|
interval5s.value = setInterval(() => {
|
||||||
fnGetSkim(); // 获取概览信息
|
fnGetSkim(); // 获取概览信息
|
||||||
fnGetNeState(); // 获取网元状态
|
fnGetNeState(); // 获取网元状态
|
||||||
@@ -425,12 +429,12 @@ function fnRightClick() {
|
|||||||
<div class="filter">
|
<div class="filter">
|
||||||
<span
|
<span
|
||||||
:data-key="v"
|
:data-key="v"
|
||||||
:class="{ active: upfTFActive === i }"
|
:class="{ active: upfTFActive === v }"
|
||||||
v-for="(v, i) in ['0', '7', '30']"
|
v-for="v in ['0', '7', '30']"
|
||||||
:key="v"
|
:key="v"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
upfTFActive = i;
|
upfTFActive = v;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -450,14 +454,14 @@ function fnRightClick() {
|
|||||||
<ArrowUpOutlined style="color: #597ef7" />
|
<ArrowUpOutlined style="color: #597ef7" />
|
||||||
{{ t('views.dashboard.overview.upfFlowTotal.up') }}
|
{{ t('views.dashboard.overview.upfFlowTotal.up') }}
|
||||||
</span>
|
</span>
|
||||||
<h4>{{ upfTotalFlow[upfTFActive].up }}</h4>
|
<h4>{{ upfTotalFlow[upfTFActive].upFrom }}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<span>
|
<span>
|
||||||
<ArrowDownOutlined style="color: #52c41a" />
|
<ArrowDownOutlined style="color: #52c41a" />
|
||||||
{{ t('views.dashboard.overview.upfFlowTotal.down') }}
|
{{ t('views.dashboard.overview.upfFlowTotal.down') }}
|
||||||
</span>
|
</span>
|
||||||
<h4>{{ upfTotalFlow[upfTFActive].down }}</h4>
|
<h4>{{ upfTotalFlow[upfTFActive].downFrom }}</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ function handleRanderChart(
|
|||||||
|
|
||||||
function fnChangeData(data: any[], itemID: string) {
|
function fnChangeData(data: any[], itemID: string) {
|
||||||
let info = data.find((item: any) => item.id === itemID);
|
let info = data.find((item: any) => item.id === itemID);
|
||||||
if (!info.neState.online) return;
|
if (!info || !info.neState.online) return;
|
||||||
// if (!info.neState.online) {
|
// if (!info.neState.online) {
|
||||||
// info = data.find((item: any) => item.id === itemID);
|
// info = data.find((item: any) => item.id === itemID);
|
||||||
// graphNodeClickID.value = itemID;
|
// graphNodeClickID.value = itemID;
|
||||||
@@ -251,36 +251,27 @@ function fnChangeData(data: any[], itemID: string) {
|
|||||||
let nfCpuUsage = 0;
|
let nfCpuUsage = 0;
|
||||||
if (info.neState.cpu) {
|
if (info.neState.cpu) {
|
||||||
nfCpuUsage = info.neState.cpu.nfCpuUsage;
|
nfCpuUsage = info.neState.cpu.nfCpuUsage;
|
||||||
if (nfCpuUsage > 100) {
|
|
||||||
const nfCpu = +(info.neState.cpu.nfCpuUsage / 100);
|
const nfCpu = +(info.neState.cpu.nfCpuUsage / 100);
|
||||||
if (nfCpu > 100) {
|
|
||||||
nfCpuUsage = 100;
|
|
||||||
} else {
|
|
||||||
nfCpuUsage = +nfCpu.toFixed(2);
|
nfCpuUsage = +nfCpu.toFixed(2);
|
||||||
}
|
if (nfCpuUsage > 100) {
|
||||||
|
nfCpuUsage = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
sysCpuUsage = info.neState.cpu.sysCpuUsage;
|
sysCpuUsage = info.neState.cpu.sysCpuUsage;
|
||||||
if (sysCpuUsage > 100) {
|
let sysCpu = +(info.neState.cpu.sysCpuUsage / 100);
|
||||||
const sysCpu = +(info.neState.cpu.sysCpuUsage / 100);
|
|
||||||
if (sysCpu > 100) {
|
|
||||||
sysCpuUsage = 100;
|
|
||||||
} else {
|
|
||||||
sysCpuUsage = +sysCpu.toFixed(2);
|
sysCpuUsage = +sysCpu.toFixed(2);
|
||||||
}
|
if (sysCpuUsage > 100) {
|
||||||
|
sysCpuUsage = 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sysMemUsage = 0;
|
let sysMemUsage = 0;
|
||||||
if (info.neState.mem) {
|
if (info.neState.mem) {
|
||||||
let men = info.neState.mem.sysMemUsage;
|
const men = info.neState.mem.sysMemUsage;
|
||||||
if (men > 100) {
|
sysMemUsage = +(men / 100).toFixed(2);
|
||||||
men = +(men / 100).toFixed(2);
|
if (sysMemUsage > 100) {
|
||||||
|
sysMemUsage = 100;
|
||||||
}
|
}
|
||||||
if (men > 100) {
|
|
||||||
men = 100;
|
|
||||||
}
|
|
||||||
sysMemUsage = men;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sysDiskUsage = 0;
|
let sysDiskUsage = 0;
|
||||||
|
|||||||
@@ -203,17 +203,14 @@ function handleRanderChart() {
|
|||||||
|
|
||||||
/**查询初始UPF数据 */
|
/**查询初始UPF数据 */
|
||||||
function fnGetInitData() {
|
function fnGetInitData() {
|
||||||
// 查询10分钟前的
|
// 查询5分钟前的
|
||||||
const nowDate: Date = new Date();
|
const nowDate = new Date().getTime();
|
||||||
const tenMinutesAgo = new Date(nowDate.getTime() - 5 * 60 * 1000);
|
|
||||||
|
|
||||||
listKPIData({
|
listKPIData({
|
||||||
neType: 'UPF',
|
neType: 'UPF',
|
||||||
neId: '001',
|
neId: '001',
|
||||||
startTime: parseDateToStr(tenMinutesAgo),
|
startTime: nowDate - 5 * 60 * 1000,
|
||||||
endTime: parseDateToStr(nowDate),
|
endTime: nowDate,
|
||||||
// startTime: '2024-03-20 19:50:00',
|
|
||||||
// endTime: '2024-03-20 19:55:00',
|
|
||||||
interval: 5, // 5秒
|
interval: 5, // 5秒
|
||||||
sortField: 'timeGroup',
|
sortField: 'timeGroup',
|
||||||
sortOrder: 'asc',
|
sortOrder: 'asc',
|
||||||
|
|||||||
@@ -186,7 +186,14 @@ onMounted(() => {
|
|||||||
<div class="card-ue-item">
|
<div class="card-ue-item">
|
||||||
<div>
|
<div>
|
||||||
{{ t('views.dashboard.overview.userActivity.type') }}:
|
{{ t('views.dashboard.overview.userActivity.type') }}:
|
||||||
<span>
|
<span v-if="item.type === 'cm-state'">
|
||||||
|
{{
|
||||||
|
dict.ueEventType
|
||||||
|
.find(s => s.value === item.type)
|
||||||
|
?.label.replace('CM', 'ECM')
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
<DictTag :options="dict.ueEventType" :value="item.type" />
|
<DictTag :options="dict.ueEventType" :value="item.type" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -159,14 +159,14 @@
|
|||||||
|
|
||||||
/* 概览区域 衍生基站信息 */
|
/* 概览区域 衍生基站信息 */
|
||||||
.skim.base {
|
.skim.base {
|
||||||
height: 20.6%;
|
height: 12%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skim.base .inner .data {
|
.skim.base .inner .data {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 45%;
|
height: 75%;
|
||||||
}
|
}
|
||||||
.skim.base .inner .data .item {
|
.skim.base .inner .data .item {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -178,7 +178,7 @@
|
|||||||
/* 用户行为 */
|
/* 用户行为 */
|
||||||
.userActivity {
|
.userActivity {
|
||||||
/* min-height: 35.8rem; */
|
/* min-height: 35.8rem; */
|
||||||
height: 60%;
|
height: 54.6%;
|
||||||
}
|
}
|
||||||
.userActivity .inner .chart {
|
.userActivity .inner .chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const notNeNodes = [
|
|||||||
/**图状态 */
|
/**图状态 */
|
||||||
export const graphState = reactive<Record<string, any>>({
|
export const graphState = reactive<Record<string, any>>({
|
||||||
/**当前图组名 */
|
/**当前图组名 */
|
||||||
group: '5GC System Architecture5',
|
group: '5GC System Architecture',
|
||||||
/**图数据 */
|
/**图数据 */
|
||||||
data: {
|
data: {
|
||||||
combos: [],
|
combos: [],
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils';
|
import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ export const upfFlowData = ref<FDType>({
|
|||||||
|
|
||||||
/**UPF-流量数据 数据解析 */
|
/**UPF-流量数据 数据解析 */
|
||||||
export function upfFlowParse(data: Record<string, string>) {
|
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);
|
const upN3 = parseSizeFromKbs(+data['UPF.03'], 5);
|
||||||
upfFlowData.value.lineYUp.push(upN3[0]);
|
upfFlowData.value.lineYUp.push(upN3[0]);
|
||||||
const downN6 = parseSizeFromKbs(+data['UPF.06'], 5);
|
const downN6 = parseSizeFromKbs(+data['UPF.06'], 5);
|
||||||
@@ -35,47 +36,63 @@ export function upfFlowParse(data: Record<string, string>) {
|
|||||||
upfFlowData.value.lineYDown.shift();
|
upfFlowData.value.lineYDown.shift();
|
||||||
upfFlowData.value.cap -= 1;
|
upfFlowData.value.cap -= 1;
|
||||||
}
|
}
|
||||||
|
// UPF-总流量数0天 当天24小时
|
||||||
|
upfTFParse('0', {
|
||||||
|
up: upfTotalFlow.value['0'].up + +data['UPF.03'],
|
||||||
|
down: upfTotalFlow.value['0'].down + +data['UPF.06'],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
type TFType = {
|
type TFType = {
|
||||||
/**上行 N3 */
|
/**上行 N3 */
|
||||||
up: string;
|
up: number;
|
||||||
|
upFrom: string;
|
||||||
/**下行 N6 */
|
/**下行 N6 */
|
||||||
down: string;
|
down: number;
|
||||||
|
downFrom: string;
|
||||||
/**请求标记 */
|
/**请求标记 */
|
||||||
requestFlag: boolean;
|
requestFlag: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**UPF-总流量数 */
|
/**UPF-总流量数 */
|
||||||
export const upfTotalFlow = ref<TFType[]>([
|
export const upfTotalFlow = ref<Record<string, TFType>>({
|
||||||
// 0天 当天24小时
|
'0': {
|
||||||
{
|
up: 0,
|
||||||
up: '0 B',
|
upFrom: '0 B',
|
||||||
down: '0 B',
|
down: 0,
|
||||||
|
downFrom: '0 B',
|
||||||
requestFlag: false,
|
requestFlag: false,
|
||||||
},
|
},
|
||||||
{
|
'7': {
|
||||||
up: '0 B',
|
up: 0,
|
||||||
down: '0 B',
|
upFrom: '0 B',
|
||||||
|
down: 0,
|
||||||
|
downFrom: '0 B',
|
||||||
requestFlag: false,
|
requestFlag: false,
|
||||||
},
|
},
|
||||||
{
|
'30': {
|
||||||
up: '0 B',
|
up: 0,
|
||||||
down: '0 B',
|
upFrom: '0 B',
|
||||||
|
down: 0,
|
||||||
|
downFrom: '0 B',
|
||||||
requestFlag: false,
|
requestFlag: false,
|
||||||
},
|
},
|
||||||
]);
|
});
|
||||||
|
|
||||||
/**UPF-总流量数 数据解析 */
|
/**UPF-总流量数 数据解析 */
|
||||||
export function upfTFParse(data: Record<string, string>) {
|
export function upfTFParse(day: string, data: Record<string, number>) {
|
||||||
let { up, down } = data;
|
let { up, down } = data;
|
||||||
up = parseSizeFromBits(up);
|
upfTotalFlow.value[day] = {
|
||||||
down = parseSizeFromBits(down);
|
up: up,
|
||||||
return { up, down };
|
upFrom: parseSizeFromBits(up),
|
||||||
|
down: down,
|
||||||
|
downFrom: parseSizeFromBits(down),
|
||||||
|
requestFlag: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**UPF-总流量数 选中 */
|
/**UPF-总流量数 选中 */
|
||||||
export const upfTFActive = ref<number>(0);
|
export const upfTFActive = ref<string>('0');
|
||||||
|
|
||||||
/**属性复位 */
|
/**属性复位 */
|
||||||
export function upfTotalFlowReset() {
|
export function upfTotalFlowReset() {
|
||||||
@@ -85,23 +102,14 @@ export function upfTotalFlowReset() {
|
|||||||
lineYDown: [],
|
lineYDown: [],
|
||||||
cap: 0,
|
cap: 0,
|
||||||
};
|
};
|
||||||
upfTotalFlow.value = [
|
for (const key of Object.keys(upfTotalFlow.value)) {
|
||||||
// 0天 当天24小时
|
upfTotalFlow.value[key] = {
|
||||||
{
|
up: 0,
|
||||||
up: '0 B',
|
upFrom: '0 B',
|
||||||
down: '0 B',
|
down: 0,
|
||||||
|
downFrom: '0 B',
|
||||||
requestFlag: false,
|
requestFlag: false,
|
||||||
},
|
};
|
||||||
{
|
}
|
||||||
up: '0 B',
|
upfTFActive.value = '0';
|
||||||
down: '0 B',
|
|
||||||
requestFlag: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
up: '0 B',
|
|
||||||
down: '0 B',
|
|
||||||
requestFlag: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
upfTFActive.value = 0;
|
|
||||||
}
|
}
|
||||||
@@ -25,12 +25,6 @@ export default function useWS() {
|
|||||||
ws.send(data);
|
ws.send(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**接收数据后回调 */
|
|
||||||
function wsError(ev: any) {
|
|
||||||
// 接收数据后回调
|
|
||||||
console.error(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**接收数据后回调 */
|
/**接收数据后回调 */
|
||||||
function wsMessage(res: Record<string, any>) {
|
function wsMessage(res: Record<string, any>) {
|
||||||
// console.log(res);
|
// console.log(res);
|
||||||
@@ -50,41 +44,32 @@ export default function useWS() {
|
|||||||
// 普通信息
|
// 普通信息
|
||||||
switch (requestId) {
|
switch (requestId) {
|
||||||
// AMF_UE会话事件
|
// AMF_UE会话事件
|
||||||
case '1010':
|
case 'amf_1010':
|
||||||
if (Array.isArray(data.rows)) {
|
if (Array.isArray(data.rows)) {
|
||||||
eventListParse('amf_ue', data);
|
eventListParse('amf_ue', data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// MME_UE会话事件
|
// MME_UE会话事件
|
||||||
case '1011':
|
case 'mme_1011_001':
|
||||||
if (Array.isArray(data.rows)) {
|
if (Array.isArray(data.rows)) {
|
||||||
eventListParse('mme_ue', data);
|
eventListParse('mme_ue', data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// IMS_CDR会话事件
|
// IMS_CDR会话事件
|
||||||
case '1005':
|
case 'ims_1005_001':
|
||||||
if (Array.isArray(data.rows)) {
|
if (Array.isArray(data.rows)) {
|
||||||
eventListParse('ims_cdr', data);
|
eventListParse('ims_cdr', data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
//UPF-总流量数
|
//UPF-总流量数
|
||||||
case '1030_0':
|
case 'upf_001_0':
|
||||||
const v0 = upfTFParse(data);
|
upfTFParse('0', data);
|
||||||
upfTotalFlow.value[0].up = v0.up;
|
|
||||||
upfTotalFlow.value[0].down = v0.down;
|
|
||||||
upfTotalFlow.value[0].requestFlag = false;
|
|
||||||
break;
|
break;
|
||||||
case '1030_7':
|
case 'upf_001_7':
|
||||||
const v7 = upfTFParse(data);
|
upfTFParse('7', data);
|
||||||
upfTotalFlow.value[1].up = v7.up;
|
|
||||||
upfTotalFlow.value[1].down = v7.down;
|
|
||||||
upfTotalFlow.value[1].requestFlag = false;
|
|
||||||
break;
|
break;
|
||||||
case '1030_30':
|
case 'upf_001_30':
|
||||||
const v30 = upfTFParse(data);
|
upfTFParse('30', data);
|
||||||
upfTotalFlow.value[2].up = v30.up;
|
|
||||||
upfTotalFlow.value[2].down = v30.down;
|
|
||||||
upfTotalFlow.value[2].requestFlag = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +79,7 @@ export default function useWS() {
|
|||||||
}
|
}
|
||||||
switch (data.groupId) {
|
switch (data.groupId) {
|
||||||
// kpiEvent 指标UPF
|
// kpiEvent 指标UPF
|
||||||
case '12':
|
case '12_001':
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
upfFlowParse(data.data);
|
upfFlowParse(data.data);
|
||||||
}
|
}
|
||||||
@@ -106,13 +91,13 @@ export default function useWS() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// MME_UE会话事件
|
// MME_UE会话事件
|
||||||
case '1011':
|
case '1011_001':
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
queue.add(() => eventItemParseAndPush('mme_ue', data.data));
|
queue.add(() => eventItemParseAndPush('mme_ue', data.data));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// IMS_CDR会话事件
|
// IMS_CDR会话事件
|
||||||
case '1005':
|
case '1005_001':
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
queue.add(() => eventItemParseAndPush('ims_cdr', data.data));
|
queue.add(() => eventItemParseAndPush('ims_cdr', data.data));
|
||||||
}
|
}
|
||||||
@@ -121,28 +106,20 @@ export default function useWS() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**UPF-总流量数 发消息*/
|
/**UPF-总流量数 发消息*/
|
||||||
function upfTFSend(day: 0 | 7 | 30) {
|
function upfTFSend(day: '0' | '7' | '30') {
|
||||||
// 请求标记检查避免重复发送
|
// 请求标记检查避免重复发送
|
||||||
let index = 0;
|
if (upfTotalFlow.value[day].requestFlag) {
|
||||||
if (day === 0) {
|
|
||||||
index = 0;
|
|
||||||
} else if (day === 7) {
|
|
||||||
index = 1;
|
|
||||||
} else if (day === 30) {
|
|
||||||
index = 2;
|
|
||||||
}
|
|
||||||
if (upfTotalFlow.value[index].requestFlag) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
upfTotalFlow.value[index].requestFlag = true;
|
upfTotalFlow.value[day].requestFlag = true;
|
||||||
|
|
||||||
ws.send({
|
ws.send({
|
||||||
requestId: `1030_${day}`,
|
requestId: `upf_001_${day}`,
|
||||||
type: 'upf_tf',
|
type: 'upf_tf',
|
||||||
data: {
|
data: {
|
||||||
neType: 'UPF',
|
neType: 'UPF',
|
||||||
neId: '001',
|
neId: '001',
|
||||||
day: day,
|
day: Number(day),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -151,7 +128,7 @@ export default function useWS() {
|
|||||||
function userActivitySend() {
|
function userActivitySend() {
|
||||||
// AMF_UE会话事件
|
// AMF_UE会话事件
|
||||||
ws.send({
|
ws.send({
|
||||||
requestId: '1010',
|
requestId: 'amf_1010',
|
||||||
type: 'amf_ue',
|
type: 'amf_ue',
|
||||||
data: {
|
data: {
|
||||||
neType: 'AMF',
|
neType: 'AMF',
|
||||||
@@ -164,7 +141,7 @@ export default function useWS() {
|
|||||||
});
|
});
|
||||||
// MME_UE会话事件
|
// MME_UE会话事件
|
||||||
ws.send({
|
ws.send({
|
||||||
requestId: '1011',
|
requestId: 'mme_1011_001',
|
||||||
type: 'mme_ue',
|
type: 'mme_ue',
|
||||||
data: {
|
data: {
|
||||||
neType: 'MME',
|
neType: 'MME',
|
||||||
@@ -177,7 +154,7 @@ export default function useWS() {
|
|||||||
});
|
});
|
||||||
// IMS_CDR会话事件
|
// IMS_CDR会话事件
|
||||||
ws.send({
|
ws.send({
|
||||||
requestId: '1005',
|
requestId: 'ims_1005_001',
|
||||||
type: 'ims_cdr',
|
type: 'ims_cdr',
|
||||||
data: {
|
data: {
|
||||||
neType: 'IMS',
|
neType: 'IMS',
|
||||||
@@ -197,15 +174,17 @@ export default function useWS() {
|
|||||||
params: {
|
params: {
|
||||||
/**订阅通道组
|
/**订阅通道组
|
||||||
*
|
*
|
||||||
* 指标UPF (GroupID:12)
|
* 指标UPF (GroupID:12_neId)
|
||||||
* AMF_UE会话事件(GroupID:1010)
|
* AMF_UE会话事件(GroupID:1010)
|
||||||
* MME_UE会话事件(GroupID:1011)
|
* MME_UE会话事件(GroupID:1011_neId)
|
||||||
* IMS_CDR会话事件(GroupID:1005)
|
* IMS_CDR会话事件(GroupID:1005_neId)
|
||||||
*/
|
*/
|
||||||
subGroupID: '12,1010,1011,1005',
|
subGroupID: '12_001,1010,1011_001,1005_001',
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: wsError,
|
onerror: (ev: any) => {
|
||||||
|
console.error(ev);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -156,19 +156,21 @@ async function fnGetSkim() {
|
|||||||
function loadData() {
|
function loadData() {
|
||||||
fnGetNeState(); // 获取网元状态
|
fnGetNeState(); // 获取网元状态
|
||||||
userActivitySend();
|
userActivitySend();
|
||||||
upfTFSend(0);
|
upfTFSend('0');
|
||||||
upfTFSend(7);
|
upfTFSend('7');
|
||||||
upfTFSend(30);
|
upfTFSend('30');
|
||||||
|
|
||||||
clearInterval(interval10s.value);
|
clearInterval(interval10s.value);
|
||||||
interval10s.value = setInterval(() => {
|
interval10s.value = setInterval(() => {
|
||||||
upfTFActive.value = upfTFActive.value >= 2 ? 0 : upfTFActive.value + 1;
|
if (upfTFActive.value === '0') {
|
||||||
if (upfTFActive.value === 0) {
|
upfTFSend('7');
|
||||||
upfTFSend(7);
|
upfTFActive.value = '7';
|
||||||
} else if (upfTFActive.value === 1) {
|
} else if (upfTFActive.value === '7') {
|
||||||
upfTFSend(30);
|
upfTFSend('30');
|
||||||
} else if (upfTFActive.value === 2) {
|
upfTFActive.value = '30';
|
||||||
upfTFSend(0);
|
} else if (upfTFActive.value === '30') {
|
||||||
|
upfTFSend('0');
|
||||||
|
upfTFActive.value = '0';
|
||||||
}
|
}
|
||||||
}, 10_000);
|
}, 10_000);
|
||||||
|
|
||||||
@@ -270,7 +272,7 @@ onBeforeUnmount(() => {
|
|||||||
<div class="skim panel base">
|
<div class="skim panel base">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>
|
<h3>
|
||||||
<GlobalOutlined style="color: #68d8fe" />
|
<GlobalOutlined style="color: #68d8fe" /> 5G
|
||||||
{{ t('views.dashboard.overview.skim.baseTitle') }}
|
{{ t('views.dashboard.overview.skim.baseTitle') }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="data">
|
<div class="data">
|
||||||
@@ -302,6 +304,14 @@ onBeforeUnmount(() => {
|
|||||||
<span>{{ t('views.dashboard.overview.skim.gnbUeNum') }}</span>
|
<span>{{ t('views.dashboard.overview.skim.gnbUeNum') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</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="data">
|
||||||
<div
|
<div
|
||||||
class="item toRouter"
|
class="item toRouter"
|
||||||
@@ -403,12 +413,12 @@ onBeforeUnmount(() => {
|
|||||||
<div class="filter">
|
<div class="filter">
|
||||||
<span
|
<span
|
||||||
:data-key="v"
|
:data-key="v"
|
||||||
:class="{ active: upfTFActive === i }"
|
:class="{ active: upfTFActive === v }"
|
||||||
v-for="(v, i) in ['0', '7', '30']"
|
v-for="v in ['0', '7', '30']"
|
||||||
:key="v"
|
:key="v"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
upfTFActive = i;
|
upfTFActive = v;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -428,14 +438,14 @@ onBeforeUnmount(() => {
|
|||||||
<ArrowUpOutlined style="color: #597ef7" />
|
<ArrowUpOutlined style="color: #597ef7" />
|
||||||
{{ t('views.dashboard.overview.upfFlowTotal.up') }}
|
{{ t('views.dashboard.overview.upfFlowTotal.up') }}
|
||||||
</span>
|
</span>
|
||||||
<h4>{{ upfTotalFlow[upfTFActive].up }}</h4>
|
<h4>{{ upfTotalFlow[upfTFActive].upFrom }}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<span>
|
<span>
|
||||||
<ArrowDownOutlined style="color: #52c41a" />
|
<ArrowDownOutlined style="color: #52c41a" />
|
||||||
{{ t('views.dashboard.overview.upfFlowTotal.down') }}
|
{{ t('views.dashboard.overview.upfFlowTotal.down') }}
|
||||||
</span>
|
</span>
|
||||||
<h4>{{ upfTotalFlow[upfTFActive].down }}</h4>
|
<h4>{{ upfTotalFlow[upfTFActive].downFrom }}</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Modal, message } from 'ant-design-vue/lib';
|
|||||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||||
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import {
|
import {
|
||||||
RESULT_CODE_ERROR,
|
RESULT_CODE_ERROR,
|
||||||
@@ -23,6 +24,9 @@ const { t } = useI18n();
|
|||||||
const ws = new WS();
|
const ws = new WS();
|
||||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||||
|
|
||||||
|
/**网元可选 */
|
||||||
|
let neOtions = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
/**开始结束时间 */
|
/**开始结束时间 */
|
||||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||||
|
|
||||||
@@ -197,7 +201,7 @@ let tableColumns: ColumnsType = [
|
|||||||
title: t('views.dashboard.cdr.smfInvocationTime'), // 调用时间
|
title: t('views.dashboard.cdr.smfInvocationTime'), // 调用时间
|
||||||
dataIndex: 'cdrJSON',
|
dataIndex: 'cdrJSON',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 250,
|
width: 200,
|
||||||
customRender(opt) {
|
customRender(opt) {
|
||||||
const cdrJSON = opt.value;
|
const cdrJSON = opt.value;
|
||||||
return cdrJSON.invocationTimestamp;
|
return cdrJSON.invocationTimestamp;
|
||||||
@@ -391,6 +395,7 @@ const realTimeData = ref<boolean>(false);
|
|||||||
function fnRealTime() {
|
function fnRealTime() {
|
||||||
realTimeData.value = !realTimeData.value;
|
realTimeData.value = !realTimeData.value;
|
||||||
if (realTimeData.value) {
|
if (realTimeData.value) {
|
||||||
|
tableState.seached = false;
|
||||||
// 建立链接
|
// 建立链接
|
||||||
const options: OptionsType = {
|
const options: OptionsType = {
|
||||||
url: '/ws',
|
url: '/ws',
|
||||||
@@ -399,7 +404,7 @@ function fnRealTime() {
|
|||||||
*
|
*
|
||||||
* CDR会话事件-SMF (GroupID:1006)
|
* CDR会话事件-SMF (GroupID:1006)
|
||||||
*/
|
*/
|
||||||
subGroupID: '1006',
|
subGroupID: `1006_${queryParams.neId}`,
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: wsError,
|
onerror: wsError,
|
||||||
@@ -407,6 +412,8 @@ function fnRealTime() {
|
|||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
} else {
|
} else {
|
||||||
ws.close();
|
ws.close();
|
||||||
|
tableState.seached = true;
|
||||||
|
fnGetList(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,7 +436,7 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// cdrEvent CDR会话事件
|
// cdrEvent CDR会话事件
|
||||||
if (data.groupId === '1006') {
|
if (data.groupId === `1006_${queryParams.neId}`) {
|
||||||
const cdrEvent = data.data;
|
const cdrEvent = data.data;
|
||||||
queue.add(async () => {
|
queue.add(async () => {
|
||||||
modalState.maxId += 1;
|
modalState.maxId += 1;
|
||||||
@@ -451,9 +458,35 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
// 获取网元网元列表
|
||||||
|
useNeInfoStore()
|
||||||
|
.fnNelist()
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
let arr: Record<string, any>[] = [];
|
||||||
|
res.data.forEach(i => {
|
||||||
|
if (i.neType === 'SMF') {
|
||||||
|
arr.push({ value: i.neId, label: i.neName });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
neOtions.value = arr;
|
||||||
|
if (arr.length > 0) {
|
||||||
|
queryParams.neId = arr[0].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('common.noData'),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
// 获取列表数据
|
// 获取列表数据
|
||||||
fnGetList();
|
fnGetList();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
if (ws.state() !== -1) {
|
if (ws.state() !== -1) {
|
||||||
@@ -472,10 +505,19 @@ onBeforeUnmount(() => {
|
|||||||
<!-- 表格搜索栏 -->
|
<!-- 表格搜索栏 -->
|
||||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item label="SMF" name="neId ">
|
||||||
|
<a-select
|
||||||
|
v-model:value="queryParams.neId"
|
||||||
|
:options="neOtions"
|
||||||
|
:placeholder="t('common.selectPlease')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.dashboard.cdr.smfSubscriptionIDData')"
|
:label="t('views.dashboard.cdr.smfSubscriptionIDData')"
|
||||||
name="calledParty "
|
name="subscriberID"
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="queryParams.subscriberID"
|
v-model:value="queryParams.subscriberID"
|
||||||
@@ -572,6 +614,7 @@ onBeforeUnmount(() => {
|
|||||||
:checked-children="t('common.switch.show')"
|
:checked-children="t('common.switch.show')"
|
||||||
:un-checked-children="t('common.switch.hide')"
|
:un-checked-children="t('common.switch.hide')"
|
||||||
size="small"
|
size="small"
|
||||||
|
:disabled="realTimeData"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
@@ -616,7 +659,7 @@ onBeforeUnmount(() => {
|
|||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
:scroll="{ x: tableColumns.length * 150, y: 'calc(100vh - 480px)' }"
|
||||||
:row-selection="{
|
:row-selection="{
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
columnWidth: '48px',
|
columnWidth: '48px',
|
||||||
@@ -770,6 +813,13 @@ onBeforeUnmount(() => {
|
|||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Network Function IPv4: </span>
|
||||||
|
<span>{{
|
||||||
|
record.cdrJSON.nFunctionConsumerInformation
|
||||||
|
.networkFunctionIPv4Address
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -0,0 +1,760 @@
|
|||||||
|
<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 useDictStore from '@/store/modules/dict';
|
||||||
|
import useI18n from '@/hooks/useI18n';
|
||||||
|
import {
|
||||||
|
RESULT_CODE_ERROR,
|
||||||
|
RESULT_CODE_SUCCESS,
|
||||||
|
} from '@/constants/result-constants';
|
||||||
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
|
import {
|
||||||
|
delSMSCDataCDR,
|
||||||
|
exportSMSCDataCDR,
|
||||||
|
listSMSCDataCDR,
|
||||||
|
} from '@/api/neData/smsc';
|
||||||
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
|
import saveAs from 'file-saver';
|
||||||
|
import PQueue from 'p-queue';
|
||||||
|
const { getDict } = useDictStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const ws = new WS();
|
||||||
|
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||||
|
|
||||||
|
/**字典数据 */
|
||||||
|
let dict: {
|
||||||
|
/**CDR 响应原因代码类别类型 */
|
||||||
|
cdrCauseCode: DictType[];
|
||||||
|
} = reactive({
|
||||||
|
cdrCauseCode: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
/**网元可选 */
|
||||||
|
let neOtions = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
|
/**开始结束时间 */
|
||||||
|
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||||
|
|
||||||
|
/**查询参数 */
|
||||||
|
let queryParams = reactive({
|
||||||
|
/**网元类型 */
|
||||||
|
neType: 'SMSC',
|
||||||
|
neId: '001',
|
||||||
|
recordType: '',
|
||||||
|
callerParty: '',
|
||||||
|
calledParty: '',
|
||||||
|
sortField: 'timestamp',
|
||||||
|
sortOrder: 'desc',
|
||||||
|
/**开始时间 */
|
||||||
|
startTime: '',
|
||||||
|
/**结束时间 */
|
||||||
|
endTime: '',
|
||||||
|
/**当前页数 */
|
||||||
|
pageNum: 1,
|
||||||
|
/**每页条数 */
|
||||||
|
pageSize: 20,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**查询参数重置 */
|
||||||
|
function fnQueryReset() {
|
||||||
|
recordTypes.value = [];
|
||||||
|
queryParams = Object.assign(queryParams, {
|
||||||
|
recordType: '',
|
||||||
|
callerParty: '',
|
||||||
|
calledParty: '',
|
||||||
|
startTime: '',
|
||||||
|
endTime: '',
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
});
|
||||||
|
queryRangePicker.value = ['', ''];
|
||||||
|
tablePagination.current = 1;
|
||||||
|
tablePagination.pageSize = 20;
|
||||||
|
fnGetList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**记录类型 */
|
||||||
|
const recordTypes = ref<string[]>([]);
|
||||||
|
|
||||||
|
/**查询记录类型变更 */
|
||||||
|
function fnQueryRecordTypeChange(value: any) {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
queryParams.recordType = 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: t('views.dashboard.cdr.recordType'),
|
||||||
|
dataIndex: 'cdrJSON',
|
||||||
|
align: 'left',
|
||||||
|
width: 150,
|
||||||
|
customRender(opt) {
|
||||||
|
const cdrJSON = opt.value;
|
||||||
|
return cdrJSON.recordType;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.dashboard.cdr.type'),
|
||||||
|
dataIndex: 'cdrJSON',
|
||||||
|
align: 'left',
|
||||||
|
width: 150,
|
||||||
|
customRender(opt) {
|
||||||
|
const cdrJSON = opt.value;
|
||||||
|
return cdrJSON.serviceType;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.dashboard.cdr.caller'),
|
||||||
|
dataIndex: 'cdrJSON',
|
||||||
|
key: 'callerParty',
|
||||||
|
align: 'left',
|
||||||
|
width: 120,
|
||||||
|
customRender(opt) {
|
||||||
|
const cdrJSON = opt.value;
|
||||||
|
return cdrJSON.callerParty;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.dashboard.cdr.called'),
|
||||||
|
dataIndex: 'cdrJSON',
|
||||||
|
key: 'calledParty',
|
||||||
|
align: 'left',
|
||||||
|
width: 120,
|
||||||
|
customRender(opt) {
|
||||||
|
const cdrJSON = opt.value;
|
||||||
|
return cdrJSON.calledParty;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: t('views.dashboard.cdr.result'),
|
||||||
|
dataIndex: 'cdrJSON',
|
||||||
|
key: 'cause',
|
||||||
|
align: 'left',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.dashboard.cdr.time'),
|
||||||
|
dataIndex: 'cdrJSON',
|
||||||
|
align: 'left',
|
||||||
|
width: 150,
|
||||||
|
customRender(opt) {
|
||||||
|
const cdrJSON = opt.value;
|
||||||
|
return parseDateToStr(+cdrJSON.updateTime * 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.cdr.delTip', { msg }),
|
||||||
|
onOk() {
|
||||||
|
modalState.confirmLoading = true;
|
||||||
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
|
delSMSCDataCDR(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];
|
||||||
|
listSMSCDataCDR(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;
|
||||||
|
exportSMSCDataCDR(querys)
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('common.operateOk'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
saveAs(res.data, `smsc_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) {
|
||||||
|
tableState.seached = false;
|
||||||
|
// 建立链接
|
||||||
|
const options: OptionsType = {
|
||||||
|
url: '/ws',
|
||||||
|
params: {
|
||||||
|
/**订阅通道组
|
||||||
|
*
|
||||||
|
* SMSC_CDR会话事件(GroupID:1007_neId)
|
||||||
|
*/
|
||||||
|
subGroupID: `1007_${queryParams.neId}`,
|
||||||
|
},
|
||||||
|
onmessage: wsMessage,
|
||||||
|
onerror: wsError,
|
||||||
|
};
|
||||||
|
ws.connect(options);
|
||||||
|
} else {
|
||||||
|
ws.close();
|
||||||
|
tableState.seached = true;
|
||||||
|
fnGetList(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**接收数据后回调 */
|
||||||
|
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 === `1007_${queryParams.neId}`) {
|
||||||
|
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(() => {
|
||||||
|
// 初始字典数据
|
||||||
|
Promise.allSettled([getDict('cdr_cause_code')]).then(resArr => {
|
||||||
|
if (resArr[0].status === 'fulfilled') {
|
||||||
|
dict.cdrCauseCode = resArr[0].value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 获取网元网元列表
|
||||||
|
useNeInfoStore()
|
||||||
|
.fnNelist()
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
let arr: Record<string, any>[] = [];
|
||||||
|
res.data.forEach(i => {
|
||||||
|
if (i.neType === 'SMSC') {
|
||||||
|
arr.push({ value: i.neId, label: i.neName });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
neOtions.value = arr;
|
||||||
|
if (arr.length > 0) {
|
||||||
|
queryParams.neId = arr[0].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('common.noData'),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.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="SMSC" name="neId ">
|
||||||
|
<a-select
|
||||||
|
v-model:value="queryParams.neId"
|
||||||
|
:options="neOtions"
|
||||||
|
:placeholder="t('common.selectPlease')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.dashboard.cdr.called')"
|
||||||
|
name="calledParty"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:value="queryParams.calledParty"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.dashboard.cdr.caller')"
|
||||||
|
name="callerParty "
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:value="queryParams.callerParty"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
></a-input>
|
||||||
|
</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-col :lg="8" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.dashboard.cdr.recordType')"
|
||||||
|
name="recordType"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model:value="recordTypes"
|
||||||
|
mode="multiple"
|
||||||
|
:options="['MOSM', 'MTSM'].map(v => ({ value: v }))"
|
||||||
|
:placeholder="t('common.selectPlease')"
|
||||||
|
@change="fnQueryRecordTypeChange"
|
||||||
|
></a-select>
|
||||||
|
</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-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"
|
||||||
|
:disabled="realTimeData"
|
||||||
|
/>
|
||||||
|
</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 === 'cause'">
|
||||||
|
<span v-if="record.cdrJSON.result === 0">
|
||||||
|
{{ t('views.dashboard.cdr.resultFail') }},
|
||||||
|
<DictTag
|
||||||
|
:options="dict.cdrCauseCode"
|
||||||
|
:value="record.cdrJSON.cause"
|
||||||
|
value-default="0"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
{{ t('views.dashboard.cdr.resultOk') }}
|
||||||
|
</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.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>{{ t('views.dashboard.cdr.type') }}: </span>
|
||||||
|
<span>{{ record.cdrJSON.serviceType }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{ t('views.dashboard.cdr.caller') }}: </span>
|
||||||
|
<span>{{ record.cdrJSON.callerParty }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{ t('views.dashboard.cdr.called') }}: </span>
|
||||||
|
<span>{{ record.cdrJSON.calledParty }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{ t('views.dashboard.cdr.result') }}: </span>
|
||||||
|
<span v-if="record.cdrJSON.result === 0">
|
||||||
|
{{ t('views.dashboard.cdr.resultFail') }},
|
||||||
|
<DictTag
|
||||||
|
:options="dict.cdrCauseCode"
|
||||||
|
:value="record.cdrJSON.cause"
|
||||||
|
value-default="0"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
{{ t('views.dashboard.cdr.resultOk') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
</PageContainer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.table :deep(.ant-pagination) {
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -142,30 +142,6 @@ let alarmTableState: TabeStateType = reactive({
|
|||||||
|
|
||||||
/**表格字段列 */
|
/**表格字段列 */
|
||||||
let tableColumns: ColumnsType = [
|
let tableColumns: ColumnsType = [
|
||||||
{
|
|
||||||
title: t('views.faultManage.activeAlarm.alarmId'),
|
|
||||||
dataIndex: 'alarmId',
|
|
||||||
align: 'center',
|
|
||||||
width: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.faultManage.activeAlarm.neId'),
|
|
||||||
dataIndex: 'neId',
|
|
||||||
align: 'center',
|
|
||||||
width: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.faultManage.activeAlarm.neName'),
|
|
||||||
dataIndex: 'neName',
|
|
||||||
align: 'center',
|
|
||||||
width: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.faultManage.activeAlarm.neType'),
|
|
||||||
dataIndex: 'neType',
|
|
||||||
align: 'center',
|
|
||||||
width: 5,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.origLevel'),
|
title: t('views.faultManage.activeAlarm.origLevel'),
|
||||||
align: 'center',
|
align: 'center',
|
||||||
@@ -173,18 +149,18 @@ let tableColumns: ColumnsType = [
|
|||||||
dataIndex: 'origSeverity',
|
dataIndex: 'origSeverity',
|
||||||
width: 5,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: t('views.faultManage.activeAlarm.alarmCode'),
|
|
||||||
dataIndex: 'alarmCode',
|
|
||||||
align: 'center',
|
|
||||||
width: 5,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmTitle'),
|
title: t('views.faultManage.activeAlarm.alarmTitle'),
|
||||||
dataIndex: 'alarmTitle',
|
dataIndex: 'alarmTitle',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 5,
|
width: 5,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.neType'),
|
||||||
|
dataIndex: 'neType',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.eventTime'),
|
title: t('views.faultManage.activeAlarm.eventTime'),
|
||||||
dataIndex: 'eventTime',
|
dataIndex: 'eventTime',
|
||||||
@@ -192,6 +168,12 @@ let tableColumns: ColumnsType = [
|
|||||||
sorter: (a: any, b: any) => 1,
|
sorter: (a: any, b: any) => 1,
|
||||||
width: 5,
|
width: 5,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.alarmCode'),
|
||||||
|
dataIndex: 'alarmCode',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmType'),
|
title: t('views.faultManage.activeAlarm.alarmType'),
|
||||||
dataIndex: 'alarmType',
|
dataIndex: 'alarmType',
|
||||||
@@ -199,12 +181,31 @@ let tableColumns: ColumnsType = [
|
|||||||
align: 'left',
|
align: 'left',
|
||||||
width: 5,
|
width: 5,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.neName'),
|
||||||
|
dataIndex: 'neName',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.neId'),
|
||||||
|
dataIndex: 'neId',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.pvFlag'),
|
title: t('views.faultManage.activeAlarm.pvFlag'),
|
||||||
dataIndex: 'pvFlag',
|
dataIndex: 'pvFlag',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 5,
|
width: 5,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.alarmId'),
|
||||||
|
dataIndex: 'alarmId',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.ackState'),
|
title: t('views.faultManage.activeAlarm.ackState'),
|
||||||
dataIndex: 'ackState',
|
dataIndex: 'ackState',
|
||||||
@@ -610,6 +611,20 @@ function fnShowSet() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// key替换中文title
|
||||||
|
function mapKeysWithReduce(data: any[], titleMapping: Record<string, string>) {
|
||||||
|
return data.map((item: any) => {
|
||||||
|
if (typeof item !== 'object' || item === null) {
|
||||||
|
return item; // 如果不是对象,直接返回原值
|
||||||
|
}
|
||||||
|
return Object.keys(item).reduce((newItem: Record<string, any>, key: string) => {
|
||||||
|
const title = titleMapping[key] || key;
|
||||||
|
newItem[title] = item[key];
|
||||||
|
return newItem;
|
||||||
|
}, {}); // 确保初始值是一个空对象
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出全部
|
* 导出全部
|
||||||
*/
|
*/
|
||||||
@@ -621,39 +636,57 @@ function fnExportAll() {
|
|||||||
const key = 'exportAlarm';
|
const key = 'exportAlarm';
|
||||||
message.loading({ content: t('common.loading'), key });
|
message.loading({ content: t('common.loading'), key });
|
||||||
let sortArr: any = [];
|
let sortArr: any = [];
|
||||||
|
let writeSheetOpt: any = [];
|
||||||
|
let mappArr: any = {};
|
||||||
tableColumnsDnd.value.forEach((item: any) => {
|
tableColumnsDnd.value.forEach((item: any) => {
|
||||||
if (item.dataIndex) sortArr.push(item.dataIndex);
|
if (item.dataIndex) {
|
||||||
|
sortArr.push(item.dataIndex);
|
||||||
|
writeSheetOpt.push(item.title);
|
||||||
|
mappArr[item.dataIndex] = item.title;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
//提供给writeSheet排序参数
|
||||||
// 排序字段
|
|
||||||
const sortData = {
|
const sortData = {
|
||||||
header: sortArr,
|
header: writeSheetOpt,
|
||||||
};
|
};
|
||||||
|
|
||||||
exportAll(queryParams).then(res => {
|
exportAll(queryParams).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
res.data = res.data.map((objA: any) => {
|
res.data = res.data.map((objA: any) => {
|
||||||
let filteredObj: any = {};
|
let filteredObj: any = {};
|
||||||
|
//sort Data
|
||||||
sortArr.forEach((key: any) => {
|
sortArr.forEach((key: any) => {
|
||||||
if (objA.hasOwnProperty(key)) {
|
if (objA.hasOwnProperty(key)) {
|
||||||
filteredObj[key] = objA[key];
|
filteredObj[key] = objA[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dict.activeAckState.map((item: any) => {
|
const mapProps = (dict: any, key: string) => {
|
||||||
if (item.value === `${filteredObj.ackState}`)
|
const item = dict.find(
|
||||||
filteredObj.ackState = item.label;
|
(item: any) => item.value === `${filteredObj[key]}`
|
||||||
});
|
);
|
||||||
|
if (item) {
|
||||||
|
filteredObj[key] = item.label;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mapProps(dict.activeAckState, 'ackState');
|
||||||
|
mapProps(dict.activeClearType, 'clearType');
|
||||||
|
mapProps(dict.activeAlarmSeverity, 'origSeverity');
|
||||||
|
mapProps(dict.activeAlarmType, 'alarmType');
|
||||||
|
|
||||||
return filteredObj;
|
return filteredObj;
|
||||||
});
|
});
|
||||||
|
console.log(mappArr);
|
||||||
|
|
||||||
|
res.data = mapKeysWithReduce(res.data, mappArr);
|
||||||
|
writeSheet(res.data, 'alarm', sortData).then(fileBlob => {
|
||||||
|
saveAs(fileBlob, `alarm_${Date.now()}.xlsx`);
|
||||||
message.success({
|
message.success({
|
||||||
content: t('common.msgSuccess', { msg: t('common.export') }),
|
content: t('common.msgSuccess', { msg: t('common.export') }),
|
||||||
key,
|
key,
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
writeSheet(res.data, 'alarm', sortData).then(fileBlob =>
|
});
|
||||||
saveAs(fileBlob, `alarm_${Date.now()}.xlsx`)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
message.error({
|
message.error({
|
||||||
content: `${res.msg}`,
|
content: `${res.msg}`,
|
||||||
|
|||||||
@@ -308,6 +308,17 @@ const onSelectChange = (
|
|||||||
state.selectedRow = record;
|
state.selectedRow = record;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// key替换中文title
|
||||||
|
function mapKeysWithReduce(data: any, titleMapping: any) {
|
||||||
|
return data.map((item:any) => {
|
||||||
|
return Object.keys(item).reduce((newItem:any, key:any) => {
|
||||||
|
const title = titleMapping[key] || key;
|
||||||
|
newItem[title] = item[key];
|
||||||
|
return newItem;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出全部
|
* 导出全部
|
||||||
*/
|
*/
|
||||||
@@ -319,13 +330,18 @@ function fnExportAll() {
|
|||||||
const key = 'exportAlarm';
|
const key = 'exportAlarm';
|
||||||
message.loading({ content: t('common.loading'), key });
|
message.loading({ content: t('common.loading'), key });
|
||||||
let sortArr: any = [];
|
let sortArr: any = [];
|
||||||
|
let writeSheetOpt: any = [];
|
||||||
|
let mappArr: any = {};
|
||||||
tableColumnsDnd.value.forEach((item: any) => {
|
tableColumnsDnd.value.forEach((item: any) => {
|
||||||
if (item.dataIndex) sortArr.push(item.dataIndex);
|
if (item.dataIndex) {
|
||||||
|
sortArr.push(item.dataIndex);
|
||||||
|
writeSheetOpt.push(item.title);
|
||||||
|
mappArr[item.dataIndex] = item.title;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 排序字段
|
// 排序字段
|
||||||
const sortData = {
|
const sortData = {
|
||||||
header: sortArr,
|
header: writeSheetOpt,
|
||||||
};
|
};
|
||||||
|
|
||||||
exportAll(queryParams).then(res => {
|
exportAll(queryParams).then(res => {
|
||||||
@@ -337,21 +353,20 @@ function fnExportAll() {
|
|||||||
filteredObj[key] = objA[key];
|
filteredObj[key] = objA[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dict.activeAckState.map((item: any) => {
|
|
||||||
if (item.value === `${filteredObj.ackState}`)
|
|
||||||
filteredObj.ackState = item.label;
|
|
||||||
});
|
|
||||||
|
|
||||||
return filteredObj;
|
return filteredObj;
|
||||||
});
|
});
|
||||||
|
res.data = mapKeysWithReduce(res.data, mappArr);
|
||||||
|
|
||||||
|
writeSheet(res.data, 'alarm', sortData).then(fileBlob => {
|
||||||
|
saveAs(fileBlob, `evnet_${Date.now()}.xlsx`);
|
||||||
|
|
||||||
message.success({
|
message.success({
|
||||||
content: t('common.msgSuccess', { msg: t('common.export') }),
|
content: t('common.msgSuccess', { msg: t('common.export') }),
|
||||||
key,
|
key,
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
writeSheet(res.data, 'alarm', sortData).then(fileBlob =>
|
});
|
||||||
saveAs(fileBlob, `evnet_${Date.now()}.xlsx`)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
message.error({
|
message.error({
|
||||||
content: `${res.msg}`,
|
content: `${res.msg}`,
|
||||||
@@ -625,11 +640,6 @@ onMounted(() => {
|
|||||||
:loading="tableState.loading"
|
:loading="tableState.loading"
|
||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:row-selection="{
|
|
||||||
columnWidth: 2,
|
|
||||||
selectedRowKeys: state.selectedRowKeys,
|
|
||||||
onChange: onSelectChange,
|
|
||||||
}"
|
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: 2500, y: 400 }"
|
:scroll="{ x: 2500, y: 400 }"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -426,6 +426,20 @@ function fnCancelConfirm() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// key替换中文title
|
||||||
|
function mapKeysWithReduce(data: any[], titleMapping: Record<string, string>) {
|
||||||
|
return data.map((item: any) => {
|
||||||
|
if (typeof item !== 'object' || item === null) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return Object.keys(item).reduce((newItem: Record<string, any>, key: string) => {
|
||||||
|
const title = titleMapping[key] || key;
|
||||||
|
newItem[title] = item[key];
|
||||||
|
return newItem;
|
||||||
|
}, {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出全部
|
* 导出全部
|
||||||
*/
|
*/
|
||||||
@@ -437,12 +451,18 @@ function fnExportAll() {
|
|||||||
const key = 'exportAlarmHis';
|
const key = 'exportAlarmHis';
|
||||||
message.loading({ content: t('common.loading'), key });
|
message.loading({ content: t('common.loading'), key });
|
||||||
let sortArr: any = [];
|
let sortArr: any = [];
|
||||||
|
let writeSheetOpt: any = [];
|
||||||
|
let mappArr: any = {};
|
||||||
tableColumnsDnd.value.forEach((item: any) => {
|
tableColumnsDnd.value.forEach((item: any) => {
|
||||||
if (item.dataIndex) sortArr.push(item.dataIndex);
|
if (item.dataIndex) {
|
||||||
|
sortArr.push(item.dataIndex);
|
||||||
|
writeSheetOpt.push(item.title);
|
||||||
|
mappArr[item.dataIndex] = item.title;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// 排序字段
|
//提供给writeSheet排序参数
|
||||||
const sortData = {
|
const sortData = {
|
||||||
header: sortArr,
|
header: writeSheetOpt,
|
||||||
};
|
};
|
||||||
exportAll(queryParams).then(res => {
|
exportAll(queryParams).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
@@ -470,14 +490,17 @@ function fnExportAll() {
|
|||||||
|
|
||||||
return filteredObj;
|
return filteredObj;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
res.data = mapKeysWithReduce(res.data, mappArr);
|
||||||
|
|
||||||
|
writeSheet(res.data, 'alarm', sortData).then(fileBlob => {
|
||||||
|
saveAs(fileBlob, `history-alarm_${Date.now()}.xlsx`);
|
||||||
message.success({
|
message.success({
|
||||||
content: t('common.msgSuccess', { msg: t('common.export') }),
|
content: t('common.msgSuccess', { msg: t('common.export') }),
|
||||||
key,
|
key,
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
writeSheet(res.data, 'alarm', sortData).then(fileBlob =>
|
});
|
||||||
saveAs(fileBlob, `history-alarm_${Date.now()}.xlsx`)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
message.error({
|
message.error({
|
||||||
content: `${res.msg}`,
|
content: `${res.msg}`,
|
||||||
|
|||||||
+56
-426
@@ -1,447 +1,77 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
import {
|
||||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
defineAsyncComponent,
|
||||||
import { message } from 'ant-design-vue/lib';
|
onMounted,
|
||||||
import { reactive, toRaw, ref, onMounted, onBeforeUnmount, markRaw } from 'vue';
|
ref,
|
||||||
import { listMain } from '@/api/index';
|
shallowRef,
|
||||||
import useI18n from '@/hooks/useI18n';
|
type Component,
|
||||||
import { TooltipComponent } from 'echarts/components';
|
} from 'vue';
|
||||||
import { GaugeChart } from 'echarts/charts';
|
import { getConfigKey, changeValue } from '@/api/system/config';
|
||||||
import { CanvasRenderer } from 'echarts/renderers';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import * as echarts from 'echarts/core';
|
|
||||||
import { TitleComponent, LegendComponent } from 'echarts/components';
|
|
||||||
import { PieChart } from 'echarts/charts';
|
|
||||||
import { LabelLayout } from 'echarts/features';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import useAppStore from '@/store/modules/app';
|
|
||||||
import useDictStore from '@/store/modules/dict';
|
|
||||||
const { getDict } = useDictStore();
|
|
||||||
const appStore = useAppStore();
|
|
||||||
const route = useRoute();
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
echarts.use([
|
const currentComponent = shallowRef<Component | null>(null);
|
||||||
TooltipComponent,
|
|
||||||
GaugeChart,
|
|
||||||
TitleComponent,
|
|
||||||
LegendComponent,
|
|
||||||
PieChart,
|
|
||||||
CanvasRenderer,
|
|
||||||
LabelLayout,
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**图DOM节点实例对象 */
|
const spinning = ref<boolean>(true);
|
||||||
const statusBar = ref<HTMLElement | undefined>(undefined);
|
|
||||||
|
|
||||||
/**图实例对象 */
|
/**匹配views里面所有的.vue或.tsx文件 */
|
||||||
const statusBarChart = ref<any>(null);
|
const views = import.meta.glob('../views/**/*.{vue,tsx}') as Record<
|
||||||
|
string,
|
||||||
/**网元状态字典数据 */
|
() => Promise<Component>
|
||||||
let indexColor = ref<DictType[]>([
|
>;
|
||||||
{ label: 'Normal', value: 'normal', tagType: '', tagClass: '#91cc75' },
|
|
||||||
{
|
|
||||||
label: 'Abnormal',
|
|
||||||
value: 'abnormal',
|
|
||||||
tagType: '',
|
|
||||||
tagClass: '#ee6666',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**表格字段列 */
|
|
||||||
//customRender(){} ----单元格处理
|
|
||||||
let tableColumns: ColumnsType = [
|
|
||||||
{
|
|
||||||
title: t('views.index.object'),
|
|
||||||
dataIndex: 'name',
|
|
||||||
align: 'center',
|
|
||||||
key: 'status',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.index.realNeStatus'),
|
|
||||||
dataIndex: 'status',
|
|
||||||
align: 'center',
|
|
||||||
customRender(opt) {
|
|
||||||
if (opt.value == 'Normal') return t('views.index.normal');
|
|
||||||
return t('views.index.abnormal');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.index.reloadTime'),
|
|
||||||
dataIndex: 'refresh',
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.index.version'),
|
|
||||||
dataIndex: 'version',
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.index.serialNum'),
|
|
||||||
dataIndex: 'serialNum',
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.index.expiryDate'),
|
|
||||||
dataIndex: 'expiryDate',
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.index.ipAddress'),
|
|
||||||
dataIndex: 'ipAddress',
|
|
||||||
key: 'groupName',
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
/**表格状态类型 */
|
|
||||||
type TabeStateType = {
|
|
||||||
/**加载等待 */
|
|
||||||
loading: boolean;
|
|
||||||
/**紧凑型 */
|
|
||||||
size: string;
|
|
||||||
/**搜索栏 */
|
|
||||||
seached: boolean;
|
|
||||||
/**记录数据 */
|
|
||||||
data: object[];
|
|
||||||
/**勾选记录 */
|
|
||||||
selectedRowKeys: (string | number)[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**表格状态 */
|
|
||||||
let tableState: TabeStateType = reactive({
|
|
||||||
loading: false,
|
|
||||||
size: 'middle',
|
|
||||||
seached: false,
|
|
||||||
data: [],
|
|
||||||
selectedRowKeys: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**表格状态 */
|
|
||||||
let nfInfo: any = reactive({
|
|
||||||
obj: 'OMC',
|
|
||||||
version: appStore.version,
|
|
||||||
status: t('views.index.normal'),
|
|
||||||
outTimeDate: '',
|
|
||||||
serialNum: appStore.serialNum,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**表格状态类型 */
|
|
||||||
type nfStateType = {
|
|
||||||
/**主机名 */
|
|
||||||
hostName: string;
|
|
||||||
/**操作系统信息 */
|
|
||||||
osInfo: string;
|
|
||||||
/**数据库信息 */
|
|
||||||
dbInfo: string;
|
|
||||||
/**IP地址 */
|
|
||||||
ipAddress: string;
|
|
||||||
/**端口 */
|
|
||||||
port: number;
|
|
||||||
/**版本 */
|
|
||||||
version: string;
|
|
||||||
/**CPU利用率 */
|
|
||||||
cpuUse: string;
|
|
||||||
/**内存使用 */
|
|
||||||
memoryUse: string;
|
|
||||||
/**用户容量 */
|
|
||||||
capability: number;
|
|
||||||
/**序列号 */
|
|
||||||
serialNum: string;
|
|
||||||
/**许可证到期日期 */
|
|
||||||
/* selectedRowKeys: (string | number)[];*/
|
|
||||||
expiryDate: string;
|
|
||||||
};
|
|
||||||
/**网元详细信息 */
|
|
||||||
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',
|
|
||||||
ipAddress: '-',
|
|
||||||
port: 3030,
|
|
||||||
version: '-',
|
|
||||||
cpuUse: '-',
|
|
||||||
memoryUse: '-',
|
|
||||||
capability: 0,
|
|
||||||
serialNum: '-',
|
|
||||||
expiryDate: '-',
|
|
||||||
});
|
|
||||||
|
|
||||||
/**查询网元状态列表 */
|
|
||||||
function fnGetList(one: boolean) {
|
|
||||||
if (tableState.loading) return;
|
|
||||||
one && (tableState.loading = true);
|
|
||||||
listMain().then(res => {
|
|
||||||
tableState.data = res;
|
|
||||||
tableState.loading = false;
|
|
||||||
var rightNum = 0;
|
|
||||||
var errorNum = 0;
|
|
||||||
// if (res.length) nfInfo.serialNum = res[0].serialNum;
|
|
||||||
for (let i = 0; i < res.length; i++) {
|
|
||||||
if (res[i].status == '正常' || res[i].status == 'Normal') {
|
|
||||||
rightNum++;
|
|
||||||
} else {
|
|
||||||
errorNum++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const optionData: any = {
|
|
||||||
title: {
|
|
||||||
text: '',
|
|
||||||
subtext: '',
|
|
||||||
left: 'center',
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
orient: 'vertical',
|
|
||||||
left: 'left',
|
|
||||||
},
|
|
||||||
color: indexColor.value.map(item => item.tagClass),
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: t('views.index.realNeStatus'),
|
|
||||||
type: 'pie',
|
|
||||||
radius: '70%',
|
|
||||||
center: ['50%', '50%'],
|
|
||||||
data: [
|
|
||||||
{ value: rightNum, name: t('views.index.normal') },
|
|
||||||
{ value: errorNum, name: t('views.index.abnormal') },
|
|
||||||
],
|
|
||||||
emphasis: {
|
|
||||||
itemStyle: {
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowOffsetX: 0,
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
label: {},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
fnDesign(statusBar.value, optionData);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function fnDesign(container: HTMLElement | undefined, option: any) {
|
|
||||||
if (!container) return;
|
|
||||||
|
|
||||||
if (!statusBarChart.value) {
|
|
||||||
statusBarChart.value = markRaw(echarts.init(container, 'light'));
|
|
||||||
}
|
|
||||||
option && statusBarChart.value.setOption(option);
|
|
||||||
|
|
||||||
// 创建 ResizeObserver 实例
|
|
||||||
var observer = new ResizeObserver(entries => {
|
|
||||||
if (statusBarChart.value) {
|
|
||||||
statusBarChart.value.resize();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 监听元素大小变化
|
|
||||||
observer.observe(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**抽屉 网元详细信息 */
|
|
||||||
const visible = ref(false);
|
|
||||||
const closeDrawer = () => {
|
|
||||||
visible.value = false;
|
|
||||||
};
|
|
||||||
/**抽屉 网元详细信息 */
|
|
||||||
|
|
||||||
/**监听表格行事件*/
|
|
||||||
function rowClick(record: any, index: any) {
|
|
||||||
return {
|
|
||||||
onClick: (event: any) => {
|
|
||||||
if (
|
|
||||||
toRaw(record).status == '异常' ||
|
|
||||||
toRaw(record).status == 'Abnormal'
|
|
||||||
) {
|
|
||||||
message.error(t('views.index.neStatus'), 2);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
let pronData = toRaw(record);
|
|
||||||
const totalMemInKB = pronData.memUsage?.totalMem;
|
|
||||||
const nfUsedMemInKB = pronData.memUsage?.nfUsedMem;
|
|
||||||
const sysMemUsageInKB = pronData.memUsage?.sysMemUsage;
|
|
||||||
|
|
||||||
// 将KB转换为MB
|
|
||||||
const totalMemInMB = Math.round((totalMemInKB / 1024) * 100) / 100;
|
|
||||||
const nfUsedMemInMB = Math.round((nfUsedMemInKB / 1024) * 100) / 100;
|
|
||||||
const sysMemUsageInMB =
|
|
||||||
Math.round((sysMemUsageInKB / 1024) * 100) / 100;
|
|
||||||
|
|
||||||
//渲染详细信息
|
|
||||||
pronInfo = {
|
|
||||||
hostName: pronData.hostName,
|
|
||||||
osInfo: pronData.osInfo,
|
|
||||||
dbInfo: pronData.dbInfo,
|
|
||||||
ipAddress: pronData.ipAddress,
|
|
||||||
port: pronData.port,
|
|
||||||
version: pronData.version,
|
|
||||||
cpuUse:
|
|
||||||
pronData.name +
|
|
||||||
':' +
|
|
||||||
pronData.cpuUsage?.nfCpuUsage / 100 +
|
|
||||||
'%; ' +
|
|
||||||
'SYS:' +
|
|
||||||
pronData.cpuUsage?.sysCpuUsage / 100 +
|
|
||||||
'%',
|
|
||||||
memoryUse:
|
|
||||||
'Total:' +
|
|
||||||
totalMemInMB +
|
|
||||||
'MB; ' +
|
|
||||||
pronData.name +
|
|
||||||
':' +
|
|
||||||
nfUsedMemInMB +
|
|
||||||
'MB; SYS:' +
|
|
||||||
sysMemUsageInMB +
|
|
||||||
'MB',
|
|
||||||
capability: pronData.capability,
|
|
||||||
serialNum: pronData.serialNum,
|
|
||||||
expiryDate: pronData.expiryDate,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
visible.value = true;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let timer: any;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 国际化翻译转换
|
* 查找页面模块
|
||||||
|
* @param dirName 组件路径
|
||||||
|
* @returns 路由懒加载函数
|
||||||
*/
|
*/
|
||||||
function fnLocale() {
|
function findView(dirName: string): () => Promise<Component> {
|
||||||
let title = route.meta.title as string;
|
for (const dir in views) {
|
||||||
if (title.indexOf('router.') !== -1) {
|
let viewDirName = '';
|
||||||
title = t(title);
|
const component = dir.match(/\/(.+)\.(vue|tsx)/);
|
||||||
|
if (component && component.length === 3) {
|
||||||
|
viewDirName = component[1];
|
||||||
}
|
}
|
||||||
appStore.setTitle(title);
|
if (viewDirName === dirName) {
|
||||||
|
return views[dir];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return () => import('@/views/configManage/neOverview/index.vue');
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDict('index_status')
|
//获取当前系统设置的首页路径
|
||||||
.then(res => {
|
getConfigKey('sys.homePage').then(res => {
|
||||||
if (res.length > 0) {
|
spinning.value = false;
|
||||||
indexColor.value = res;
|
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||||
|
console.log(spinning);
|
||||||
|
if (res.data) {
|
||||||
|
const asyncComponent = findView(`${res.data}`);
|
||||||
|
currentComponent.value = defineAsyncComponent(asyncComponent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentComponent.value = defineAsyncComponent(
|
||||||
|
() => import('@/views/configManage/neOverview/index.vue')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
fnLocale();
|
|
||||||
fnGetList(true);
|
|
||||||
timer = setInterval(() => fnGetList(false), 10000); // 每隔10秒执行一次
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 在组件卸载之前清除定时器
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
clearInterval(timer);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<PageContainer :breadcrumb="{}">
|
<a-spin
|
||||||
<div>
|
size="large"
|
||||||
<a-drawer :visible="visible" @close="closeDrawer" :width="700">
|
:spinning="spinning"
|
||||||
<a-descriptions bordered :column="1" :label-style="{ width: '160px' }">
|
style="
|
||||||
<a-descriptions-item :label="t('views.index.hostName')">{{
|
display: flex;
|
||||||
pronInfo.hostName
|
flex-direction: column;
|
||||||
}}</a-descriptions-item>
|
align-items: center;
|
||||||
<a-descriptions-item :label="t('views.index.osInfo')">{{
|
justify-content: center;
|
||||||
pronInfo.osInfo
|
height: 100%;
|
||||||
}}</a-descriptions-item>
|
min-height: 362px;
|
||||||
<a-descriptions-item :label="t('views.index.dbInfo')">{{
|
"
|
||||||
pronInfo.dbInfo
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.ipAddress')">{{
|
|
||||||
pronInfo.ipAddress
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.port')">{{
|
|
||||||
pronInfo.port
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.version')">{{
|
|
||||||
pronInfo.version
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.cpuUse')">{{
|
|
||||||
pronInfo.cpuUse
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.memoryUse')">{{
|
|
||||||
pronInfo.memoryUse
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.capability')">{{
|
|
||||||
pronInfo.capability
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.serialNum')">{{
|
|
||||||
pronInfo.serialNum
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.expiryDate')">{{
|
|
||||||
pronInfo.expiryDate
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
|
||||||
</a-drawer>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a-row :gutter="16">
|
|
||||||
<a-col :lg="14" :md="16" :xs="24">
|
|
||||||
<!-- 表格列表 -->
|
|
||||||
<a-table
|
|
||||||
class="table"
|
|
||||||
row-key="id"
|
|
||||||
:columns="tableColumns"
|
|
||||||
:loading="tableState.loading"
|
|
||||||
:data-source="tableState.data"
|
|
||||||
:pagination="false"
|
|
||||||
:scroll="{ x: true }"
|
|
||||||
:customRow="rowClick"
|
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record }">
|
<component :is="currentComponent" />
|
||||||
<template v-if="column.key === 'status'">
|
</a-spin>
|
||||||
<div v-if="record.status == '正常' || record.status == 'Normal'">
|
|
||||||
<a-tag color="blue">{{ record.name }}</a-tag>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<a-tag color="pink">{{ record.name }}</a-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</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>
|
|
||||||
</a-card>
|
|
||||||
<a-card :title="t('views.index.mark')" style="margin-top: 16px">
|
|
||||||
<a-descriptions
|
|
||||||
bordered
|
|
||||||
:column="1"
|
|
||||||
:label-style="{ width: '160px' }"
|
|
||||||
>
|
|
||||||
<a-descriptions-item :label="t('views.index.object')">{{
|
|
||||||
nfInfo.obj
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<template v-if="nfInfo.obj === 'OMC'">
|
|
||||||
<a-descriptions-item :label="t('views.index.versionNum')">{{
|
|
||||||
nfInfo.version
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.systemStatus')">{{
|
|
||||||
nfInfo.status
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<a-descriptions-item :label="t('views.index.serialNum')">{{
|
|
||||||
nfInfo.serialNum
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.expiryDate')">{{
|
|
||||||
nfInfo.outTimeDate
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
</template>
|
|
||||||
</a-descriptions>
|
|
||||||
</a-card>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</PageContainer>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
@@ -0,0 +1,362 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||||
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
|
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||||
|
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||||
|
import { Modal, message } from 'ant-design-vue/lib';
|
||||||
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
|
import {
|
||||||
|
getBakFile,
|
||||||
|
getBakFileList,
|
||||||
|
downFile,
|
||||||
|
delFile,
|
||||||
|
} from '@/api/logManage/exportFile';
|
||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
|
import useI18n from '@/hooks/useI18n';
|
||||||
|
import saveAs from 'file-saver';
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
/**网元参数 */
|
||||||
|
let logSelect = ref<string[]>([]);
|
||||||
|
|
||||||
|
/**文件列表 */
|
||||||
|
let fileList = ref<any>([]);
|
||||||
|
|
||||||
|
/**查询参数 */
|
||||||
|
let queryParams = reactive({
|
||||||
|
/**读取路径 */
|
||||||
|
path: '',
|
||||||
|
/**表名 */
|
||||||
|
tableName: '',
|
||||||
|
/**当前页数 */
|
||||||
|
pageNum: 1,
|
||||||
|
/**每页条数 */
|
||||||
|
pageSize: 20,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**表格状态类型 */
|
||||||
|
type TabeStateType = {
|
||||||
|
/**加载等待 */
|
||||||
|
loading: boolean;
|
||||||
|
/**紧凑型 */
|
||||||
|
size: SizeType;
|
||||||
|
/**记录数据 */
|
||||||
|
data: object[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**表格状态 */
|
||||||
|
let tableState: TabeStateType = reactive({
|
||||||
|
loading: false,
|
||||||
|
size: 'small',
|
||||||
|
data: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
/**表格字段列 */
|
||||||
|
let tableColumns: ColumnsType = [
|
||||||
|
{
|
||||||
|
title: t('views.logManage.neFile.fileMode'),
|
||||||
|
dataIndex: 'fileMode',
|
||||||
|
align: 'center',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.logManage.neFile.owner'),
|
||||||
|
dataIndex: 'owner',
|
||||||
|
align: 'left',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.logManage.neFile.group'),
|
||||||
|
dataIndex: 'group',
|
||||||
|
align: 'left',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.logManage.neFile.size'),
|
||||||
|
dataIndex: 'size',
|
||||||
|
align: 'left',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.logManage.neFile.modifiedTime'),
|
||||||
|
dataIndex: 'modifiedTime',
|
||||||
|
align: 'left',
|
||||||
|
customRender(opt) {
|
||||||
|
if (!opt.value) return '';
|
||||||
|
return parseDateToStr(opt.value * 1000);
|
||||||
|
},
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.logManage.neFile.fileName'),
|
||||||
|
dataIndex: 'fileName',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('common.operate'),
|
||||||
|
key: 'fileName',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/**表格分页器参数 */
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**下载触发等待 */
|
||||||
|
let downLoading = ref<boolean>(false);
|
||||||
|
|
||||||
|
/**删除触发等待 */
|
||||||
|
let delLoading = ref<boolean>(false);
|
||||||
|
|
||||||
|
/**信息文件下载 */
|
||||||
|
function fnDownloadFile(row: Record<string, any>) {
|
||||||
|
if (downLoading.value) return;
|
||||||
|
Modal.confirm({
|
||||||
|
title: t('common.tipTitle'),
|
||||||
|
content: t('views.logManage.exportFile.downTip', {
|
||||||
|
fileName: row.fileName,
|
||||||
|
}),
|
||||||
|
onOk() {
|
||||||
|
downLoading.value = true;
|
||||||
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
|
downFile({
|
||||||
|
path: queryParams.path,
|
||||||
|
fileName: row.fileName,
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('common.msgSuccess', {
|
||||||
|
msg: t('common.downloadText'),
|
||||||
|
}),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
saveAs(res.data, `${row.fileName}`);
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: t('views.logManage.exportFile.downTipErr'),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
hide();
|
||||||
|
downLoading.value = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fnRecordDelete(row: Record<string, any>) {
|
||||||
|
if (delLoading.value) return;
|
||||||
|
Modal.confirm({
|
||||||
|
title: t('common.tipTitle'),
|
||||||
|
content: t('views.logManage.exportFile.deleteTip', {
|
||||||
|
fileName: row.fileName,
|
||||||
|
}),
|
||||||
|
onOk() {
|
||||||
|
const key = 'delFile';
|
||||||
|
delLoading.value = true;
|
||||||
|
message.loading({ content: t('common.loading'), key });
|
||||||
|
delFile({
|
||||||
|
fileName: row.fileName,
|
||||||
|
path: queryParams.path,
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('views.system.user.delSuss'),
|
||||||
|
key,
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
fnGetList();
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
key: key,
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
delLoading.value = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**网元类型选择对应修改 */
|
||||||
|
function fnNeChange(keys: any, opt: any) {
|
||||||
|
queryParams.tableName = keys;
|
||||||
|
queryParams.path = opt.path;
|
||||||
|
fnGetList(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**查询备份信息列表, pageNum初始页数 */
|
||||||
|
function fnGetList(pageNum?: number) {
|
||||||
|
if (queryParams.tableName === '') {
|
||||||
|
message.warning({
|
||||||
|
content: t('views.logManage.exportFile.selectTip'),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tableState.loading) return;
|
||||||
|
tableState.loading = true;
|
||||||
|
if (pageNum) {
|
||||||
|
queryParams.pageNum = pageNum;
|
||||||
|
}
|
||||||
|
getBakFileList(toRaw(queryParams)).then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
|
tablePagination.total = res.total;
|
||||||
|
tableState.data = res.data;
|
||||||
|
if (
|
||||||
|
tablePagination.total <=
|
||||||
|
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||||
|
queryParams.pageNum !== 1
|
||||||
|
) {
|
||||||
|
tableState.loading = false;
|
||||||
|
fnGetList(queryParams.pageNum - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.error(res.msg, 3);
|
||||||
|
tablePagination.total = 0;
|
||||||
|
tableState.data = [];
|
||||||
|
}
|
||||||
|
tableState.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getBakFile().then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
|
res.data.forEach((item: any) => {
|
||||||
|
fileList.value.push({
|
||||||
|
value: item.tableName,
|
||||||
|
label: item.tableDisplay,
|
||||||
|
path: item.filePath,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// .finally(() => {
|
||||||
|
// fnGetList();
|
||||||
|
// });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<PageContainer>
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||||
|
<!-- 插槽-卡片左侧侧 -->
|
||||||
|
<template #title>
|
||||||
|
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :lg="8" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.logManage.exportFile.fileName')"
|
||||||
|
name="fileName"
|
||||||
|
style="margin-bottom: 0"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model:value="logSelect"
|
||||||
|
:options="fileList"
|
||||||
|
@change="fnNeChange"
|
||||||
|
:allow-clear="false"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :lg="16" :md="18" :xs="24" v-if="queryParams.path">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.logManage.neFile.nePath')"
|
||||||
|
name="configName"
|
||||||
|
style="margin-bottom: 0"
|
||||||
|
>
|
||||||
|
<a-breadcrumb>
|
||||||
|
<a-breadcrumb-item>
|
||||||
|
{{ queryParams.path }}
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
</a-breadcrumb>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 插槽-卡片右侧 -->
|
||||||
|
<template #extra>
|
||||||
|
<a-space :size="8" align="center">
|
||||||
|
<a-tooltip>
|
||||||
|
<template #title>{{ t('common.reloadText') }}</template>
|
||||||
|
<a-button type="text" @click.prevent="fnGetList()">
|
||||||
|
<template #icon><ReloadOutlined /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 表格列表 -->
|
||||||
|
<a-table
|
||||||
|
class="table"
|
||||||
|
row-key="fileName"
|
||||||
|
:columns="tableColumns"
|
||||||
|
:loading="tableState.loading"
|
||||||
|
:data-source="tableState.data"
|
||||||
|
:size="tableState.size"
|
||||||
|
:pagination="tablePagination"
|
||||||
|
:scroll="{ x: 800 }"
|
||||||
|
>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'fileName'">
|
||||||
|
<a-space :size="8" align="center">
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
:loading="downLoading"
|
||||||
|
@click.prevent="fnDownloadFile(record)"
|
||||||
|
v-if="record.fileType === 'file'"
|
||||||
|
>
|
||||||
|
<template #icon><DownloadOutlined /></template>
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
:loading="delLoading"
|
||||||
|
@click.prevent="fnRecordDelete(record)"
|
||||||
|
v-if="record.fileType === 'file'"
|
||||||
|
>
|
||||||
|
<template #icon><DeleteOutlined /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
</PageContainer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, watch, ref } from 'vue';
|
||||||
|
import { ProModal } from 'antdv-pro-modal';
|
||||||
|
import TerminalSSHView from '@/components/TerminalSSHView/index.vue';
|
||||||
|
import useI18n from '@/hooks/useI18n';
|
||||||
|
const { t } = useI18n();
|
||||||
|
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**文件地址 */
|
||||||
|
filePath: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**网元类型 */
|
||||||
|
neType: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**网元ID */
|
||||||
|
neId: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**对话框对象信息状态类型 */
|
||||||
|
type StateType = {
|
||||||
|
/**框是否显示 */
|
||||||
|
visible: boolean;
|
||||||
|
/**标题 */
|
||||||
|
title: string;
|
||||||
|
/**查看命令 */
|
||||||
|
form: Record<string, any>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**对话框对象信息状态 */
|
||||||
|
let state: StateType = reactive({
|
||||||
|
visible: false,
|
||||||
|
title: '文件查看',
|
||||||
|
form: {
|
||||||
|
follow: true,
|
||||||
|
showType: 'lines', // lines/char
|
||||||
|
lines: 10,
|
||||||
|
char: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function onClose() {
|
||||||
|
state.visible = false;
|
||||||
|
emit('cancel');
|
||||||
|
emit('update:visible', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**监听是否显示,初始数据 */
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
val => {
|
||||||
|
if (val) {
|
||||||
|
if (props.neType && props.neId) {
|
||||||
|
const filePath = props.filePath;
|
||||||
|
const fileName = filePath.substring(filePath.lastIndexOf('/') + 1);
|
||||||
|
state.title = fileName;
|
||||||
|
state.visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/**终端实例 */
|
||||||
|
const viewTerminal = ref();
|
||||||
|
|
||||||
|
/**终端初始连接 */
|
||||||
|
function fnInit() {
|
||||||
|
setTimeout(fnReload, 1_500);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**重载查看方式 */
|
||||||
|
function fnReload() {
|
||||||
|
if (!viewTerminal.value) return;
|
||||||
|
viewTerminal.value.ctrlC();
|
||||||
|
if (state.form.showType !== 'lines') {
|
||||||
|
state.form.lines = 10;
|
||||||
|
} else {
|
||||||
|
state.form.char = 0;
|
||||||
|
}
|
||||||
|
viewTerminal.value.clear();
|
||||||
|
setTimeout(() => {
|
||||||
|
viewTerminal.value.send('tail', {
|
||||||
|
filePath: props.filePath,
|
||||||
|
lines: state.form.lines,
|
||||||
|
char: state.form.char,
|
||||||
|
follow: state.form.follow,
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ProModal
|
||||||
|
:drag="true"
|
||||||
|
:fullscreen="true"
|
||||||
|
:borderDraw="true"
|
||||||
|
:min-width="800"
|
||||||
|
:min-height="500"
|
||||||
|
:center-y="true"
|
||||||
|
:destroyOnClose="true"
|
||||||
|
:keyboard="false"
|
||||||
|
:mask-closable="false"
|
||||||
|
:visible="state.visible"
|
||||||
|
:title="state.title"
|
||||||
|
:body-style="{ padding: '12px', overflow: 'hidden' }"
|
||||||
|
:footer="null"
|
||||||
|
@cancel="onClose"
|
||||||
|
>
|
||||||
|
<TerminalSSHView
|
||||||
|
ref="viewTerminal"
|
||||||
|
:id="`V${Date.now()}`"
|
||||||
|
prefix="tail"
|
||||||
|
url="/ws/view"
|
||||||
|
:ne-type="neType"
|
||||||
|
:ne-id="neId"
|
||||||
|
style="height: calc(100% - 36px)"
|
||||||
|
@connect="fnInit()"
|
||||||
|
></TerminalSSHView>
|
||||||
|
<!-- 命令控制属性 -->
|
||||||
|
<a-form name="form" layout="horizontal">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
|
<a-form-item :label="t('views.logManage.neFile.viewAs')">
|
||||||
|
<a-input-group compact>
|
||||||
|
<a-select v-model:value="state.form.showType" style="width: 50%">
|
||||||
|
<a-select-option value="lines">
|
||||||
|
{{ t('views.logManage.neFile.tailLines') }}
|
||||||
|
</a-select-option>
|
||||||
|
<a-select-option value="char">
|
||||||
|
{{ t('views.logManage.neFile.tailChar') }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-input-number
|
||||||
|
style="width: 25%"
|
||||||
|
v-model:value="state.form[state.form.showType]"
|
||||||
|
:min="0"
|
||||||
|
:max="1000"
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
></a-input-number>
|
||||||
|
<a-button type="primary" style="width: 25%" @click="fnReload()">
|
||||||
|
{{ t('views.logManage.neFile.reload') }}
|
||||||
|
</a-button>
|
||||||
|
</a-input-group>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.logManage.neFile.follow')"
|
||||||
|
name="follow"
|
||||||
|
>
|
||||||
|
<a-switch v-model:checked="state.form.follow" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
</ProModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.ant-form :deep(.ant-form-item) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -3,12 +3,13 @@ import { reactive, ref, onMounted, toRaw } from 'vue';
|
|||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||||
|
import { Modal, message } from 'ant-design-vue/lib';
|
||||||
import { parseDateToStr } from '@/utils/date-utils';
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
import { getNeFile, listNeFiles } from '@/api/tool/neFile';
|
import { getNeFile, listNeFiles } from '@/api/tool/neFile';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { Modal, message } from 'ant-design-vue/lib';
|
import ViewDrawer from './components/ViewDrawer.vue';
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
const neInfoStore = useNeInfoStore();
|
const neInfoStore = useNeInfoStore();
|
||||||
@@ -19,11 +20,7 @@ const route = useRoute();
|
|||||||
const routeParams = route.query as Record<string, any>;
|
const routeParams = route.query as Record<string, any>;
|
||||||
|
|
||||||
/**网元参数 */
|
/**网元参数 */
|
||||||
let neType = ref<string[]>([]);
|
let neTypeSelect = ref<string[]>([]);
|
||||||
/**下载触发等待 */
|
|
||||||
let loading = ref(false);
|
|
||||||
/**访问路径 */
|
|
||||||
let nePathArr = ref<string[]>([]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
/**查询参数 */
|
||||||
let queryParams = reactive({
|
let queryParams = reactive({
|
||||||
@@ -134,20 +131,24 @@ let tablePagination = reactive({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**下载触发等待 */
|
||||||
|
let downLoading = ref<boolean>(false);
|
||||||
|
|
||||||
/**信息文件下载 */
|
/**信息文件下载 */
|
||||||
function fnDownloadFile(row: Record<string, any>) {
|
function fnDownloadFile(row: Record<string, any>) {
|
||||||
if (loading.value) return;
|
if (downLoading.value) return;
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: t('common.tipTitle'),
|
title: t('common.tipTitle'),
|
||||||
content: t('views.logManage.neFile.downTip', { fileName: row.fileName }),
|
content: t('views.logManage.neFile.downTip', { fileName: row.fileName }),
|
||||||
onOk() {
|
onOk() {
|
||||||
loading.value = true;
|
downLoading.value = true;
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
getNeFile({
|
getNeFile({
|
||||||
neType: queryParams.neType,
|
neType: queryParams.neType,
|
||||||
neId: queryParams.neId,
|
neId: queryParams.neId,
|
||||||
path: queryParams.path,
|
path: queryParams.path,
|
||||||
fileName: row.fileName,
|
fileName: row.fileName,
|
||||||
|
delTemp: true,
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
@@ -167,12 +168,15 @@ function fnDownloadFile(row: Record<string, any>) {
|
|||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
hide();
|
hide();
|
||||||
loading.value = false;
|
downLoading.value = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**访问路径 */
|
||||||
|
let nePathArr = ref<string[]>([]);
|
||||||
|
|
||||||
/**进入目录 */
|
/**进入目录 */
|
||||||
function fnDirCD(dir: string, index?: number) {
|
function fnDirCD(dir: string, index?: number) {
|
||||||
if (index === undefined) {
|
if (index === undefined) {
|
||||||
@@ -200,11 +204,13 @@ function fnDirCD(dir: string, index?: number) {
|
|||||||
|
|
||||||
/**网元类型选择对应修改 */
|
/**网元类型选择对应修改 */
|
||||||
function fnNeChange(keys: any, _: any) {
|
function fnNeChange(keys: any, _: any) {
|
||||||
// 不是同类型时需要重新加载
|
if (!Array.isArray(keys)) return;
|
||||||
if (Array.isArray(keys) && queryParams.neType !== keys[0]) {
|
|
||||||
const neType = keys[0];
|
const neType = keys[0];
|
||||||
|
const neId = keys[1];
|
||||||
|
// 不是同类型时需要重新加载
|
||||||
|
if (queryParams.neType !== neType || queryParams.neId !== neId) {
|
||||||
queryParams.neType = neType;
|
queryParams.neType = neType;
|
||||||
queryParams.neId = keys[1];
|
queryParams.neId = neId;
|
||||||
if (neType === 'IMS') {
|
if (neType === 'IMS') {
|
||||||
nePathArr.value = ['/var/log/ims'];
|
nePathArr.value = ['/var/log/ims'];
|
||||||
queryParams.search = '';
|
queryParams.search = '';
|
||||||
@@ -235,15 +241,42 @@ function fnGetList(pageNum?: number) {
|
|||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||||
tablePagination.total = res.total;
|
tablePagination.total = res.total;
|
||||||
tableState.data = res.rows;
|
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;
|
tableState.loading = false;
|
||||||
fnGetList(queryParams.pageNum - 1);
|
fnGetList(queryParams.pageNum - 1);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
message.error(res.msg, 3);
|
||||||
|
tablePagination.total = 0;
|
||||||
|
tableState.data = [];
|
||||||
}
|
}
|
||||||
tableState.loading = false;
|
tableState.loading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**抽屉状态 */
|
||||||
|
const viewDrawerState = reactive({
|
||||||
|
visible: false,
|
||||||
|
/**文件路径 /var/log/amf.log */
|
||||||
|
filePath: '',
|
||||||
|
/**网元类型 */
|
||||||
|
neType: '',
|
||||||
|
/**网元ID */
|
||||||
|
neId: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
/**打开抽屉查看 */
|
||||||
|
function fnDrawerOpen(row: Record<string, any>) {
|
||||||
|
viewDrawerState.filePath = [...nePathArr.value, row.fileName].join('/');
|
||||||
|
viewDrawerState.neType = neTypeSelect.value[0];
|
||||||
|
viewDrawerState.neId = neTypeSelect.value[1];
|
||||||
|
viewDrawerState.visible = !viewDrawerState.visible;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 获取网元网元列表
|
// 获取网元网元列表
|
||||||
neInfoStore.fnNelist().then(res => {
|
neInfoStore.fnNelist().then(res => {
|
||||||
@@ -254,8 +287,8 @@ onMounted(() => {
|
|||||||
duration: 2,
|
duration: 2,
|
||||||
});
|
});
|
||||||
} else if (routeParams.neType) {
|
} else if (routeParams.neType) {
|
||||||
neType.value = [routeParams.neType, routeParams.neId]
|
neTypeSelect.value = [routeParams.neType, routeParams.neId];
|
||||||
fnNeChange(neType.value, undefined);
|
fnNeChange(neTypeSelect.value, undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -276,12 +309,12 @@ onMounted(() => {
|
|||||||
style="margin-bottom: 0"
|
style="margin-bottom: 0"
|
||||||
>
|
>
|
||||||
<a-cascader
|
<a-cascader
|
||||||
v-model:value="neType"
|
v-model:value="neTypeSelect"
|
||||||
:options="neInfoStore.getNeCascaderOptions"
|
:options="neInfoStore.getNeCascaderOptions"
|
||||||
@change="fnNeChange"
|
@change="fnNeChange"
|
||||||
:allow-clear="false"
|
:allow-clear="false"
|
||||||
:placeholder="t('views.logManage.neFile.neTypePlease')"
|
:placeholder="t('views.logManage.neFile.neTypePlease')"
|
||||||
:disabled="loading || tableState.loading"
|
:disabled="downLoading || tableState.loading"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -332,8 +365,15 @@ onMounted(() => {
|
|||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'fileName'">
|
<template v-if="column.key === 'fileName'">
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
|
<a-tooltip v-if="record.fileType === 'file'">
|
||||||
|
<template #title>{{ t('common.viewText') }}</template>
|
||||||
|
<a-button type="link" @click.prevent="fnDrawerOpen(record)">
|
||||||
|
<template #icon><ProfileOutlined /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
<a-button
|
<a-button
|
||||||
type="link"
|
type="link"
|
||||||
|
:loading="downLoading"
|
||||||
@click.prevent="fnDownloadFile(record)"
|
@click.prevent="fnDownloadFile(record)"
|
||||||
v-if="record.fileType === 'file'"
|
v-if="record.fileType === 'file'"
|
||||||
>
|
>
|
||||||
@@ -342,6 +382,7 @@ onMounted(() => {
|
|||||||
</a-button>
|
</a-button>
|
||||||
<a-button
|
<a-button
|
||||||
type="link"
|
type="link"
|
||||||
|
:loading="downLoading"
|
||||||
@click.prevent="fnDirCD(record.fileName)"
|
@click.prevent="fnDirCD(record.fileName)"
|
||||||
v-if="record.fileType === 'dir'"
|
v-if="record.fileType === 'dir'"
|
||||||
>
|
>
|
||||||
@@ -353,6 +394,14 @@ onMounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 文件内容查看抽屉 -->
|
||||||
|
<ViewDrawer
|
||||||
|
v-model:visible="viewDrawerState.visible"
|
||||||
|
:file-path="viewDrawerState.filePath"
|
||||||
|
:ne-type="viewDrawerState.neType"
|
||||||
|
:ne-id="viewDrawerState.neId"
|
||||||
|
></ViewDrawer>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -134,16 +134,6 @@ onMounted(() => {
|
|||||||
function fnChangeLocale(e: any) {
|
function fnChangeLocale(e: any) {
|
||||||
changeLocale(e.key);
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -166,23 +156,6 @@ function fnClickHelpDoc(language?: string) {
|
|||||||
<img :src="logoUrl" class="logo-brand" :alt="appStore.appName" />
|
<img :src="logoUrl" class="logo-brand" :alt="appStore.appName" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</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>
|
</header>
|
||||||
|
|
||||||
<a-card :bordered="false" class="login-card">
|
<a-card :bordered="false" class="login-card">
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const graphG6Dom = ref<HTMLElement | undefined>(undefined);
|
|||||||
/**图状态 */
|
/**图状态 */
|
||||||
const graphState = reactive<Record<string, any>>({
|
const graphState = reactive<Record<string, any>>({
|
||||||
/**当前图组名 */
|
/**当前图组名 */
|
||||||
group: '5GC System Architecture5',
|
group: '5GC System Architecture',
|
||||||
/**图数据 */
|
/**图数据 */
|
||||||
data: {
|
data: {
|
||||||
combos: [],
|
combos: [],
|
||||||
|
|||||||
@@ -1,296 +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); // 主动改OMC_IP
|
|
||||||
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>
|
|
||||||
<template #content>
|
|
||||||
{{ t('views.ne.neConfPara5G.headerTip') }}
|
|
||||||
<RouterLink :to="{ name: 'NeQuickSetup_2142' }">
|
|
||||||
{{ t('views.ne.neConfPara5G.headerTipToPage') }}
|
|
||||||
</RouterLink>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<!-- 保存选择同步网元 -->
|
|
||||||
<ProModal
|
|
||||||
:drag="true"
|
|
||||||
:minHeight="0"
|
|
||||||
: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>
|
|
||||||
</ProModal>
|
|
||||||
</PageContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
|
||||||
@@ -0,0 +1,412 @@
|
|||||||
|
import {
|
||||||
|
addNeConfigData,
|
||||||
|
delNeConfigData,
|
||||||
|
editNeConfigData,
|
||||||
|
} from '@/api/ne/neConfig';
|
||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
|
import { Modal } from 'ant-design-vue/lib';
|
||||||
|
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||||
|
import message from 'ant-design-vue/lib/message';
|
||||||
|
import { reactive, watch } from 'vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数配置array类型
|
||||||
|
* @param param 父级传入 { t, treeState, neTypeSelect, fnActiveConfigNode, ruleVerification, modalState, fnModalCancel}
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function useConfigArray({
|
||||||
|
t,
|
||||||
|
treeState,
|
||||||
|
neTypeSelect,
|
||||||
|
fnActiveConfigNode,
|
||||||
|
ruleVerification,
|
||||||
|
modalState,
|
||||||
|
fnModalCancel,
|
||||||
|
}: any) {
|
||||||
|
/**多列列表状态类型 */
|
||||||
|
type ArrayStateType = {
|
||||||
|
/**紧凑型 */
|
||||||
|
size: SizeType;
|
||||||
|
/**多列嵌套记录字段 */
|
||||||
|
columns: Record<string, any>[];
|
||||||
|
/**表格字段列排序 */
|
||||||
|
columnsDnd: Record<string, any>[];
|
||||||
|
/**多列记录数据 */
|
||||||
|
columnsData: Record<string, any>[];
|
||||||
|
/**多列嵌套展开key */
|
||||||
|
arrayChildExpandKeys: any[];
|
||||||
|
|
||||||
|
/**多列记录数据 */
|
||||||
|
data: Record<string, any>[];
|
||||||
|
/**多列记录规则 */
|
||||||
|
dataRule: Record<string, any>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**多列列表状态 */
|
||||||
|
let arrayState: ArrayStateType = reactive({
|
||||||
|
size: 'small',
|
||||||
|
columns: [],
|
||||||
|
columnsDnd: [],
|
||||||
|
columnsData: [],
|
||||||
|
arrayChildExpandKeys: [],
|
||||||
|
data: [],
|
||||||
|
dataRule: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**多列表编辑 */
|
||||||
|
function arrayEdit(rowIndex: Record<string, any>) {
|
||||||
|
const item = arrayState.data.find((s: any) => s.key === rowIndex.value);
|
||||||
|
if (!item) return;
|
||||||
|
const from = arrayInitEdit(item, arrayState.dataRule);
|
||||||
|
// 处理信息
|
||||||
|
const row: Record<string, any> = {};
|
||||||
|
for (const v of from.record) {
|
||||||
|
if (Array.isArray(v.array)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
row[v.name] = Object.assign({}, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊SMF-upfid选择
|
||||||
|
if (neTypeSelect.value[0] === 'SMF' && Reflect.has(row, 'upfId')) {
|
||||||
|
const v = row.upfId.value;
|
||||||
|
if (typeof v === 'string') {
|
||||||
|
if (v === '') {
|
||||||
|
row.upfId.value = [];
|
||||||
|
} else if (v.includes(';')) {
|
||||||
|
row.upfId.value = v.split(';');
|
||||||
|
} else if (v.includes(',')) {
|
||||||
|
row.upfId.value = v.split(',');
|
||||||
|
} else {
|
||||||
|
row.upfId.value = [v];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modalState.from = row;
|
||||||
|
modalState.type = 'arrayEdit';
|
||||||
|
modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`;
|
||||||
|
modalState.key = from.key;
|
||||||
|
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||||
|
modalState.visible = true;
|
||||||
|
|
||||||
|
// 关闭嵌套
|
||||||
|
arrayState.arrayChildExpandKeys = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表编辑关闭 */
|
||||||
|
function arrayEditClose() {
|
||||||
|
arrayState.arrayChildExpandKeys = [];
|
||||||
|
fnModalCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表编辑确认 */
|
||||||
|
function arrayEditOk(from: Record<string, any>) {
|
||||||
|
const loc = `${from['index']['value']}`;
|
||||||
|
|
||||||
|
// 特殊SMF-upfid选择
|
||||||
|
if (neTypeSelect.value[0] === 'SMF' && Reflect.has(from, 'upfId')) {
|
||||||
|
const v = from.upfId.value;
|
||||||
|
if (Array.isArray(v)) {
|
||||||
|
from.upfId.value = v.join(';');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历提取属性和值
|
||||||
|
let data: Record<string, any> = {};
|
||||||
|
for (const key in from) {
|
||||||
|
// 子嵌套的不插入
|
||||||
|
if (from[key]['array']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 检查规则
|
||||||
|
const [ok, msg] = ruleVerification(from[key]);
|
||||||
|
if (!ok) {
|
||||||
|
message.warning({
|
||||||
|
content: `${msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data[key] = from[key]['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送
|
||||||
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
|
editNeConfigData({
|
||||||
|
neType: neTypeSelect.value[0],
|
||||||
|
neId: neTypeSelect.value[1],
|
||||||
|
paramName: treeState.selectNode.paramName,
|
||||||
|
paramData: data,
|
||||||
|
loc: loc,
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('views.ne.neConfig.updateItem', {
|
||||||
|
num: modalState.title,
|
||||||
|
}),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
fnActiveConfigNode('#');
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('views.ne.neConfig.updateItemErr'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
hide();
|
||||||
|
arrayEditClose();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表删除单行 */
|
||||||
|
function arrayDelete(rowIndex: Record<string, any>) {
|
||||||
|
const loc = `${rowIndex.value}`;
|
||||||
|
const title = `${treeState.selectNode.paramDisplay} Index-${loc}`;
|
||||||
|
|
||||||
|
Modal.confirm({
|
||||||
|
title: t('common.tipTitle'),
|
||||||
|
content: t('views.ne.neConfig.delItemTip', {
|
||||||
|
num: title,
|
||||||
|
}),
|
||||||
|
onOk() {
|
||||||
|
delNeConfigData({
|
||||||
|
neType: neTypeSelect.value[0],
|
||||||
|
neId: neTypeSelect.value[1],
|
||||||
|
paramName: treeState.selectNode.paramName,
|
||||||
|
loc: loc,
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('views.ne.neConfig.delItemOk', {
|
||||||
|
num: title,
|
||||||
|
}),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
arrayEditClose();
|
||||||
|
fnActiveConfigNode('#');
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表新增单行 */
|
||||||
|
function arrayAdd() {
|
||||||
|
const from = arrayInitAdd(arrayState.data, arrayState.dataRule);
|
||||||
|
|
||||||
|
// 处理信息
|
||||||
|
const row: Record<string, any> = {};
|
||||||
|
for (const v of from.record) {
|
||||||
|
if (Array.isArray(v.array)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
row[v.name] = Object.assign({}, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊SMF-upfid选择
|
||||||
|
if (neTypeSelect.value[0] === 'SMF' && Reflect.has(row, 'upfId')) {
|
||||||
|
const v = row.upfId.value;
|
||||||
|
if (typeof v === 'string') {
|
||||||
|
if (v === '') {
|
||||||
|
row.upfId.value = [];
|
||||||
|
} else if (v.includes(';')) {
|
||||||
|
row.upfId.value = v.split(';');
|
||||||
|
} else if (v.includes(',')) {
|
||||||
|
row.upfId.value = v.split(',');
|
||||||
|
} else {
|
||||||
|
row.upfId.value = [v];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modalState.from = row;
|
||||||
|
modalState.type = 'arrayAdd';
|
||||||
|
modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`;
|
||||||
|
modalState.key = from.key;
|
||||||
|
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||||
|
modalState.visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表新增单行确认 */
|
||||||
|
function arrayAddOk(from: Record<string, any>) {
|
||||||
|
// 特殊SMF-upfid选择
|
||||||
|
if (neTypeSelect.value[0] === 'SMF' && Reflect.has(from, 'upfId')) {
|
||||||
|
const v = from.upfId.value;
|
||||||
|
if (Array.isArray(v)) {
|
||||||
|
from.upfId.value = v.join(';');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历提取属性和值
|
||||||
|
let data: Record<string, any> = {};
|
||||||
|
for (const key in from) {
|
||||||
|
// 子嵌套的不插入
|
||||||
|
if (from[key]['array']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 检查规则
|
||||||
|
const [ok, msg] = ruleVerification(from[key]);
|
||||||
|
if (!ok) {
|
||||||
|
message.warning({
|
||||||
|
content: `${msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data[key] = from[key]['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送
|
||||||
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
|
addNeConfigData({
|
||||||
|
neType: neTypeSelect.value[0],
|
||||||
|
neId: neTypeSelect.value[1],
|
||||||
|
paramName: treeState.selectNode.paramName,
|
||||||
|
paramData: data,
|
||||||
|
loc: `${from['index']['value']}`,
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('views.ne.neConfig.addItemOk', {
|
||||||
|
num: modalState.title,
|
||||||
|
}),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
fnActiveConfigNode('#');
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('views.ne.neConfig.addItemErr'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
hide();
|
||||||
|
arrayEditClose();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表编辑行数据初始化 */
|
||||||
|
function arrayInitEdit(data: Record<string, any>, dataRule: any) {
|
||||||
|
const dataFrom = data.record;
|
||||||
|
const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule)));
|
||||||
|
for (const row of ruleFrom.record) {
|
||||||
|
// 子嵌套的不初始
|
||||||
|
if (row.array) {
|
||||||
|
row.value = [];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 查找项的值
|
||||||
|
const item = dataFrom.find((s: any) => s.name === row.name);
|
||||||
|
if (!item) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 可选的
|
||||||
|
row.optional = 'true';
|
||||||
|
// 根据规则类型转值
|
||||||
|
if (['enum', 'int'].includes(row.type)) {
|
||||||
|
row.value = Number(item.value);
|
||||||
|
} else if ('bool' === row.type) {
|
||||||
|
row.value = Boolean(item.value);
|
||||||
|
} else {
|
||||||
|
row.value = item.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ruleFrom.key = data.key;
|
||||||
|
ruleFrom.title = data.title;
|
||||||
|
return ruleFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表新增行数据初始化 */
|
||||||
|
function arrayInitAdd(data: any[], dataRule: any) {
|
||||||
|
// 有数据时取得最后的index
|
||||||
|
let dataLastIndex = 0;
|
||||||
|
if (data.length !== 0) {
|
||||||
|
const lastFrom = Object.assign(
|
||||||
|
{},
|
||||||
|
JSON.parse(JSON.stringify(data.at(-1)))
|
||||||
|
);
|
||||||
|
if (lastFrom.record.length > 0) {
|
||||||
|
dataLastIndex = parseInt(lastFrom.key);
|
||||||
|
dataLastIndex += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule)));
|
||||||
|
for (const row of ruleFrom.record) {
|
||||||
|
// 子嵌套的不初始
|
||||||
|
if (row.array) {
|
||||||
|
row.value = [];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 可选的
|
||||||
|
row.optional = 'true';
|
||||||
|
// index值
|
||||||
|
if (row.name === 'index') {
|
||||||
|
let newIndex =
|
||||||
|
dataLastIndex !== 0 ? dataLastIndex : parseInt(row.value);
|
||||||
|
if (isNaN(newIndex)) {
|
||||||
|
newIndex = 0;
|
||||||
|
}
|
||||||
|
row.value = newIndex;
|
||||||
|
ruleFrom.key = newIndex;
|
||||||
|
ruleFrom.title = `Index-${newIndex}`;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 根据规则类型转值
|
||||||
|
if (['enum', 'int'].includes(row.type)) {
|
||||||
|
row.value = Number(row.value);
|
||||||
|
}
|
||||||
|
if ('bool' === row.type) {
|
||||||
|
row.value = Boolean(row.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊SMF-upfid选择
|
||||||
|
if (neTypeSelect.value[0] === 'SMF' && row.name === 'upfId') {
|
||||||
|
const v = row.value;
|
||||||
|
if (typeof v === 'string') {
|
||||||
|
if (v === '') {
|
||||||
|
row.value = [];
|
||||||
|
} else if (v.includes(';')) {
|
||||||
|
row.value = v.split(';');
|
||||||
|
} else if (v.includes(',')) {
|
||||||
|
row.value = v.split(',');
|
||||||
|
} else {
|
||||||
|
row.value = [v];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ruleFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听表格字段列排序变化关闭展开
|
||||||
|
watch(
|
||||||
|
() => arrayState.columnsDnd,
|
||||||
|
() => {
|
||||||
|
arrayEditClose();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
arrayState,
|
||||||
|
arrayEdit,
|
||||||
|
arrayEditClose,
|
||||||
|
arrayEditOk,
|
||||||
|
arrayDelete,
|
||||||
|
arrayAdd,
|
||||||
|
arrayAddOk,
|
||||||
|
arrayInitEdit,
|
||||||
|
arrayInitAdd,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,353 @@
|
|||||||
|
import {
|
||||||
|
addNeConfigData,
|
||||||
|
editNeConfigData,
|
||||||
|
delNeConfigData,
|
||||||
|
} from '@/api/ne/neConfig';
|
||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
|
import { Modal } from 'ant-design-vue/lib';
|
||||||
|
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||||
|
import message from 'ant-design-vue/lib/message';
|
||||||
|
import { nextTick, reactive } from 'vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数配置array类型的嵌套array
|
||||||
|
* @param param 父级传入 { t, treeState, neTypeSelect, fnActiveConfigNode, ruleVerification, modalState, arrayState, arrayInitEdit, arrayInitAdd, arrayEditClose}
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function useConfigArrayChild({
|
||||||
|
t,
|
||||||
|
treeState,
|
||||||
|
neTypeSelect,
|
||||||
|
fnActiveConfigNode,
|
||||||
|
ruleVerification,
|
||||||
|
modalState,
|
||||||
|
arrayState,
|
||||||
|
arrayInitEdit,
|
||||||
|
arrayInitAdd,
|
||||||
|
arrayEditClose,
|
||||||
|
}: any) {
|
||||||
|
/**多列嵌套列表状态类型 */
|
||||||
|
type ArrayChildStateType = {
|
||||||
|
/**标题 */
|
||||||
|
title: string;
|
||||||
|
/**层级index */
|
||||||
|
loc: string;
|
||||||
|
/**紧凑型 */
|
||||||
|
size: SizeType;
|
||||||
|
/**多列嵌套记录字段 */
|
||||||
|
columns: Record<string, any>[];
|
||||||
|
/**表格字段列排序 */
|
||||||
|
columnsDnd: Record<string, any>[];
|
||||||
|
/**多列记录数据 */
|
||||||
|
columnsData: Record<string, any>[];
|
||||||
|
|
||||||
|
/**多列嵌套记录数据 */
|
||||||
|
data: Record<string, any>[];
|
||||||
|
/**多列嵌套记录规则 */
|
||||||
|
dataRule: Record<string, any>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**多列嵌套表格状态 */
|
||||||
|
let arrayChildState: ArrayChildStateType = reactive({
|
||||||
|
title: '',
|
||||||
|
loc: '',
|
||||||
|
size: 'small',
|
||||||
|
columns: [],
|
||||||
|
columnsDnd: [],
|
||||||
|
columnsData: [],
|
||||||
|
data: [],
|
||||||
|
dataRule: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**多列表展开嵌套行 */
|
||||||
|
function arrayChildExpand(
|
||||||
|
indexRow: Record<string, any>,
|
||||||
|
row: Record<string, any>
|
||||||
|
) {
|
||||||
|
const loc = indexRow.value;
|
||||||
|
if (arrayChildState.loc === `${loc}/${row.name}`) {
|
||||||
|
arrayChildState.loc = '';
|
||||||
|
arrayState.arrayChildExpandKeys = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
arrayChildState.loc = '';
|
||||||
|
arrayState.arrayChildExpandKeys = [];
|
||||||
|
const from = Object.assign({}, JSON.parse(JSON.stringify(row)));
|
||||||
|
// 无数据时
|
||||||
|
if (!Array.isArray(from.value)) {
|
||||||
|
from.value = [];
|
||||||
|
}
|
||||||
|
const dataArr = Object.freeze(from.value);
|
||||||
|
const ruleArr = Object.freeze(from.array);
|
||||||
|
|
||||||
|
// 列表项数据
|
||||||
|
const dataArray: Record<string, any>[] = [];
|
||||||
|
for (const item of dataArr) {
|
||||||
|
const index = item['index'];
|
||||||
|
let record: Record<string, any>[] = [];
|
||||||
|
for (const key of Object.keys(item)) {
|
||||||
|
// 规则为准
|
||||||
|
for (const rule of ruleArr) {
|
||||||
|
if (rule['name'] === key) {
|
||||||
|
const ruleItem = Object.assign({ optional: 'true' }, rule, {
|
||||||
|
value: item[key],
|
||||||
|
});
|
||||||
|
record.push(ruleItem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// dataArray.push(record);
|
||||||
|
dataArray.push({ title: `Index-${index}`, key: index, record });
|
||||||
|
}
|
||||||
|
arrayChildState.data = dataArray;
|
||||||
|
|
||||||
|
// 无数据时,用于新增
|
||||||
|
arrayChildState.dataRule = {
|
||||||
|
title: `Index-0`,
|
||||||
|
key: 0,
|
||||||
|
record: ruleArr,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 列表数据
|
||||||
|
const columnsData: Record<string, any>[] = [];
|
||||||
|
for (const v of arrayChildState.data) {
|
||||||
|
const row: Record<string, any> = {};
|
||||||
|
for (const item of v.record) {
|
||||||
|
row[item.name] = item;
|
||||||
|
}
|
||||||
|
columnsData.push(row);
|
||||||
|
}
|
||||||
|
arrayChildState.columnsData = columnsData;
|
||||||
|
|
||||||
|
// 列表字段
|
||||||
|
const columns: Record<string, any>[] = [];
|
||||||
|
for (const rule of arrayChildState.dataRule.record) {
|
||||||
|
columns.push({
|
||||||
|
title: rule.display,
|
||||||
|
dataIndex: rule.name,
|
||||||
|
align: 'left',
|
||||||
|
resizable: true,
|
||||||
|
width: 50,
|
||||||
|
minWidth: 50,
|
||||||
|
maxWidth: 250,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
columns.push({
|
||||||
|
title: t('common.operate'),
|
||||||
|
dataIndex: 'index',
|
||||||
|
key: 'index',
|
||||||
|
align: 'center',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 100,
|
||||||
|
});
|
||||||
|
arrayChildState.columns = columns;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
// 设置展开key
|
||||||
|
arrayState.arrayChildExpandKeys = [indexRow];
|
||||||
|
// 层级标识
|
||||||
|
arrayChildState.loc = `${loc}/${from['name']}`;
|
||||||
|
// 设置展开列表标题
|
||||||
|
arrayChildState.title = `${from['display']}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表嵌套行编辑 */
|
||||||
|
function arrayChildEdit(rowIndex: Record<string, any>) {
|
||||||
|
const item = arrayChildState.data.find(
|
||||||
|
(s: any) => s.key === rowIndex.value
|
||||||
|
);
|
||||||
|
if (!item) return;
|
||||||
|
const from = arrayInitEdit(item, arrayChildState.dataRule);
|
||||||
|
// 处理信息
|
||||||
|
const row: Record<string, any> = {};
|
||||||
|
for (const v of from.record) {
|
||||||
|
if (Array.isArray(v.array)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
row[v.name] = Object.assign({}, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
modalState.from = row;
|
||||||
|
modalState.type = 'arrayChildEdit';
|
||||||
|
modalState.title = `${arrayChildState.title} ${from.title}`;
|
||||||
|
modalState.key = from.key;
|
||||||
|
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||||
|
modalState.visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表嵌套行编辑确认 */
|
||||||
|
function arrayChildEditOk(from: Record<string, any>) {
|
||||||
|
const loc = `${arrayChildState.loc}/${from['index']['value']}`;
|
||||||
|
|
||||||
|
let data: Record<string, any> = {};
|
||||||
|
for (const key in from) {
|
||||||
|
// 子嵌套的不插入
|
||||||
|
if (from[key]['array']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 检查规则
|
||||||
|
const [ok, msg] = ruleVerification(from[key]);
|
||||||
|
if (!ok) {
|
||||||
|
message.warning({
|
||||||
|
content: `${msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data[key] = from[key]['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送
|
||||||
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
|
editNeConfigData({
|
||||||
|
neType: neTypeSelect.value[0],
|
||||||
|
neId: neTypeSelect.value[1],
|
||||||
|
paramName: treeState.selectNode.paramName,
|
||||||
|
paramData: data,
|
||||||
|
loc,
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('views.ne.neConfig.updateItem', {
|
||||||
|
num: modalState.title,
|
||||||
|
}),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
fnActiveConfigNode('#');
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('views.ne.neConfig.updateItemErr'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
hide();
|
||||||
|
arrayEditClose();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表嵌套行删除单行 */
|
||||||
|
function arrayChildDelete(rowIndex: Record<string, any>) {
|
||||||
|
const index = rowIndex.value;
|
||||||
|
const loc = `${arrayChildState.loc}/${index}`;
|
||||||
|
const title = `${arrayChildState.title} Index-${index}`;
|
||||||
|
|
||||||
|
Modal.confirm({
|
||||||
|
title: t('common.tipTitle'),
|
||||||
|
content: t('views.ne.neConfig.delItemTip', {
|
||||||
|
num: title,
|
||||||
|
}),
|
||||||
|
onOk() {
|
||||||
|
delNeConfigData({
|
||||||
|
neType: neTypeSelect.value[0],
|
||||||
|
neId: neTypeSelect.value[1],
|
||||||
|
paramName: treeState.selectNode.paramName,
|
||||||
|
loc,
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('views.ne.neConfig.delItemOk', {
|
||||||
|
num: title,
|
||||||
|
}),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
arrayEditClose();
|
||||||
|
fnActiveConfigNode('#');
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表嵌套行新增单行 */
|
||||||
|
function arrayChildAdd() {
|
||||||
|
const from = arrayInitAdd(arrayChildState.data, arrayChildState.dataRule);
|
||||||
|
// 处理信息
|
||||||
|
const row: Record<string, any> = {};
|
||||||
|
for (const v of from.record) {
|
||||||
|
if (Array.isArray(v.array)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
row[v.name] = Object.assign({}, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
modalState.from = row;
|
||||||
|
modalState.type = 'arrayChildAdd';
|
||||||
|
modalState.title = `${arrayChildState.title} ${from.title}`;
|
||||||
|
modalState.key = from.key;
|
||||||
|
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||||
|
modalState.visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**多列表新增单行确认 */
|
||||||
|
function arrayChildAddOk(from: Record<string, any>) {
|
||||||
|
const loc = `${arrayChildState.loc}/${from['index']['value']}`;
|
||||||
|
|
||||||
|
let data: Record<string, any> = {};
|
||||||
|
for (const key in from) {
|
||||||
|
// 子嵌套的不插入
|
||||||
|
if (from[key]['array']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 检查规则
|
||||||
|
const [ok, msg] = ruleVerification(from[key]);
|
||||||
|
if (!ok) {
|
||||||
|
message.warning({
|
||||||
|
content: `${msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data[key] = from[key]['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送
|
||||||
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
|
addNeConfigData({
|
||||||
|
neType: neTypeSelect.value[0],
|
||||||
|
neId: neTypeSelect.value[1],
|
||||||
|
paramName: treeState.selectNode.paramName,
|
||||||
|
paramData: data,
|
||||||
|
loc,
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('views.ne.neConfig.addItemOk', {
|
||||||
|
num: modalState.title,
|
||||||
|
}),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
fnActiveConfigNode('#');
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('views.ne.neConfig.addItemErr'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
hide();
|
||||||
|
arrayEditClose();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
arrayChildState,
|
||||||
|
arrayChildExpand,
|
||||||
|
arrayChildEdit,
|
||||||
|
arrayChildEditOk,
|
||||||
|
arrayChildDelete,
|
||||||
|
arrayChildAdd,
|
||||||
|
arrayChildAddOk,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
import { editNeConfigData } from '@/api/ne/neConfig';
|
||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
|
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||||
|
import message from 'ant-design-vue/lib/message';
|
||||||
|
import { reactive, toRaw } from 'vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list类型参数处理
|
||||||
|
* @param param 父级传入 {t, treeState, neTypeSelect, ruleVerification}
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function useConfigList({
|
||||||
|
t,
|
||||||
|
treeState,
|
||||||
|
neTypeSelect,
|
||||||
|
ruleVerification,
|
||||||
|
}: any) {
|
||||||
|
/**单列表状态类型 */
|
||||||
|
type ListStateType = {
|
||||||
|
/**紧凑型 */
|
||||||
|
size: SizeType;
|
||||||
|
/**单列记录字段 */
|
||||||
|
columns: Record<string, any>[];
|
||||||
|
/**单列记录数据 */
|
||||||
|
data: Record<string, any>[];
|
||||||
|
/**编辑行记录 */
|
||||||
|
editRecord: Record<string, any>;
|
||||||
|
/**确认提交等待 */
|
||||||
|
confirmLoading: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**单列表状态 */
|
||||||
|
let listState: ListStateType = reactive({
|
||||||
|
size: 'small',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: 'Key',
|
||||||
|
dataIndex: 'display',
|
||||||
|
align: 'left',
|
||||||
|
width: '30%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Value',
|
||||||
|
dataIndex: 'value',
|
||||||
|
align: 'left',
|
||||||
|
width: '70%',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
data: [],
|
||||||
|
confirmLoading: false,
|
||||||
|
editRecord: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**单列表编辑 */
|
||||||
|
function listEdit(row: Record<string, any>) {
|
||||||
|
if (
|
||||||
|
listState.confirmLoading ||
|
||||||
|
['read-only', 'read', 'ro'].includes(row.access)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
listState.editRecord = Object.assign({}, row);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**单列表编辑关闭 */
|
||||||
|
function listEditClose() {
|
||||||
|
listState.confirmLoading = false;
|
||||||
|
listState.editRecord = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**单列表编辑确认 */
|
||||||
|
function listEditOk() {
|
||||||
|
if (listState.confirmLoading) return;
|
||||||
|
const from = toRaw(listState.editRecord);
|
||||||
|
// 检查规则
|
||||||
|
const [ok, msg] = ruleVerification(from);
|
||||||
|
if (!ok) {
|
||||||
|
message.warning({
|
||||||
|
content: `${msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送
|
||||||
|
listState.confirmLoading = true;
|
||||||
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
|
editNeConfigData({
|
||||||
|
neType: neTypeSelect.value[0],
|
||||||
|
neId: neTypeSelect.value[1],
|
||||||
|
paramName: treeState.selectNode.paramName,
|
||||||
|
paramData: {
|
||||||
|
[from['name']]: from['value'],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('views.ne.neConfig.updateValue', {
|
||||||
|
num: from['display'],
|
||||||
|
}),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
// 改变表格数据
|
||||||
|
const item = listState.data.find(
|
||||||
|
(item: Record<string, any>) => from['name'] === item['name']
|
||||||
|
);
|
||||||
|
if (item) {
|
||||||
|
Object.assign(item, listState.editRecord);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('views.ne.neConfig.updateValueErr'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
hide();
|
||||||
|
listState.confirmLoading = false;
|
||||||
|
listState.editRecord = {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**表格分页器参数 */
|
||||||
|
let tablePagination = reactive({
|
||||||
|
/**当前页数 */
|
||||||
|
current: 1,
|
||||||
|
/**每页条数 */
|
||||||
|
pageSize: 10,
|
||||||
|
/**默认的每页条数 */
|
||||||
|
defaultPageSize: 10,
|
||||||
|
/**指定每页可以显示多少条 */
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100'],
|
||||||
|
/**只有一页时是否隐藏分页器 */
|
||||||
|
hideOnSinglePage: true,
|
||||||
|
/**是否可以快速跳转至某页 */
|
||||||
|
showQuickJumper: true,
|
||||||
|
/**是否可以改变 pageSize */
|
||||||
|
showSizeChanger: true,
|
||||||
|
/**数据总数 */
|
||||||
|
total: 0,
|
||||||
|
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
||||||
|
onChange: (page: number, pageSize: number) => {
|
||||||
|
tablePagination.current = page;
|
||||||
|
tablePagination.pageSize = pageSize;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { tablePagination, listState, listEdit, listEditClose, listEditOk };
|
||||||
|
}
|
||||||
+41
-14
@@ -1,9 +1,13 @@
|
|||||||
import useI18n from '@/hooks/useI18n';
|
import { getNeConfigData } from '@/api/ne/neConfig';
|
||||||
import { regExpIPv4, regExpIPv6, validURL } from '@/utils/regular-utils';
|
import { regExpIPv4, regExpIPv6, validURL } from '@/utils/regular-utils';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
export default function useOptions() {
|
/**
|
||||||
const { t } = useI18n();
|
* 参数公共函数
|
||||||
|
* @param param 父级传入 {t}
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function useOptions({ t }: any) {
|
||||||
/**规则校验 */
|
/**规则校验 */
|
||||||
function ruleVerification(row: Record<string, any>): (string | boolean)[] {
|
function ruleVerification(row: Record<string, any>): (string | boolean)[] {
|
||||||
let result = [true, ''];
|
let result = [true, ''];
|
||||||
@@ -33,7 +37,7 @@ export default function useOptions() {
|
|||||||
if (valueInt < minInt || valueInt > maxInt) {
|
if (valueInt < minInt || valueInt > maxInt) {
|
||||||
return [
|
return [
|
||||||
false,
|
false,
|
||||||
t('views.configManage.configParamForm.requireInt', {
|
t('views.ne.neConfig.requireInt', {
|
||||||
display,
|
display,
|
||||||
filter,
|
filter,
|
||||||
}),
|
}),
|
||||||
@@ -45,7 +49,7 @@ export default function useOptions() {
|
|||||||
if (!regExpIPv4.test(value)) {
|
if (!regExpIPv4.test(value)) {
|
||||||
return [
|
return [
|
||||||
false,
|
false,
|
||||||
t('views.configManage.configParamForm.requireIpv4', { display }),
|
t('views.ne.neConfig.requireIpv4', { display }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -53,7 +57,7 @@ export default function useOptions() {
|
|||||||
if (!regExpIPv6.test(value)) {
|
if (!regExpIPv6.test(value)) {
|
||||||
return [
|
return [
|
||||||
false,
|
false,
|
||||||
t('views.configManage.configParamForm.requireIpv6', { display }),
|
t('views.ne.neConfig.requireIpv6', { display }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -69,7 +73,7 @@ export default function useOptions() {
|
|||||||
if (!Object.keys(filterJson).includes(`${value}`)) {
|
if (!Object.keys(filterJson).includes(`${value}`)) {
|
||||||
return [
|
return [
|
||||||
false,
|
false,
|
||||||
t('views.configManage.configParamForm.requireEnum', { display }),
|
t('views.ne.neConfig.requireEnum', { display }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,7 +92,7 @@ export default function useOptions() {
|
|||||||
if (!Object.values(filterJson).includes(`${value}`)) {
|
if (!Object.values(filterJson).includes(`${value}`)) {
|
||||||
return [
|
return [
|
||||||
false,
|
false,
|
||||||
t('views.configManage.configParamForm.requireBool', { display }),
|
t('views.ne.neConfig.requireBool', { display }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,7 +110,7 @@ export default function useOptions() {
|
|||||||
if (!rule.test(value)) {
|
if (!rule.test(value)) {
|
||||||
return [
|
return [
|
||||||
false,
|
false,
|
||||||
t('views.configManage.configParamForm.requireString', {
|
t('views.ne.neConfig.requireString', {
|
||||||
display,
|
display,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
@@ -121,7 +125,7 @@ export default function useOptions() {
|
|||||||
if (!validURL(value)) {
|
if (!validURL(value)) {
|
||||||
return [
|
return [
|
||||||
false,
|
false,
|
||||||
t('views.configManage.configParamForm.requireString', {
|
t('views.ne.neConfig.requireString', {
|
||||||
display,
|
display,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
@@ -141,7 +145,7 @@ export default function useOptions() {
|
|||||||
if (!regex.test(value)) {
|
if (!regex.test(value)) {
|
||||||
return [
|
return [
|
||||||
false,
|
false,
|
||||||
t('views.configManage.configParamForm.requireString', {
|
t('views.ne.neConfig.requireString', {
|
||||||
display,
|
display,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
@@ -155,11 +159,34 @@ export default function useOptions() {
|
|||||||
default:
|
default:
|
||||||
return [
|
return [
|
||||||
false,
|
false,
|
||||||
t('views.configManage.configParamForm.requireUn', { display }),
|
t('views.ne.neConfig.requireUn', { display }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ruleVerification };
|
/**upfId可选择 */
|
||||||
|
const smfByUPFIdOptions = ref<{ value: string; label: string }[]>([]);
|
||||||
|
/**加载smf配置的upfId */
|
||||||
|
function smfByUPFIdLoadData(neId: string) {
|
||||||
|
getNeConfigData({
|
||||||
|
neType: 'SMF',
|
||||||
|
neId: neId,
|
||||||
|
paramName: 'upfConfig',
|
||||||
|
}).then(res => {
|
||||||
|
smfByUPFIdOptions.value = [];
|
||||||
|
for (const s of res.data) {
|
||||||
|
smfByUPFIdOptions.value.push({
|
||||||
|
value: s.id,
|
||||||
|
label: s.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
ruleVerification,
|
||||||
|
smfByUPFIdLoadData,
|
||||||
|
smfByUPFIdOptions,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
+238
-870
File diff suppressed because it is too large.
Load diff
+263
-158
@@ -1,24 +1,37 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, onMounted, toRaw } from 'vue';
|
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { Form, message } from 'ant-design-vue/lib';
|
import { Form, Modal, TableColumnsType, message } from 'ant-design-vue/lib';
|
||||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
|
||||||
import { uploadLicense, listLicense } from '@/api/configManage/license';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
import { FileType } from 'ant-design-vue/lib/upload/interface';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
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 { parseDateToStr } from '@/utils/date-utils';
|
||||||
const neInfoStore = useNeInfoStore();
|
import {
|
||||||
|
delNeConfigBackup,
|
||||||
|
downNeConfigBackup,
|
||||||
|
listNeConfigBackup,
|
||||||
|
updateNeConfigBackup,
|
||||||
|
} from '@/api/ne/neConfigBackup';
|
||||||
|
import saveAs from 'file-saver';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const { getDict } = useDictStore();
|
||||||
|
|
||||||
|
/**字典数据-状态 */
|
||||||
|
let dictStatus = ref<DictType[]>([]);
|
||||||
|
|
||||||
|
/**网元参数 */
|
||||||
|
let neOtions = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
/**查询参数 */
|
/**查询参数 */
|
||||||
let queryParams = reactive({
|
let queryParams = reactive({
|
||||||
/**网元类型 */
|
/**网元类型 */
|
||||||
neType: '',
|
neType: undefined,
|
||||||
|
/**名称 */
|
||||||
|
name: '',
|
||||||
/**当前页数 */
|
/**当前页数 */
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
/**每页条数 */
|
/**每页条数 */
|
||||||
@@ -28,7 +41,8 @@ let queryParams = reactive({
|
|||||||
/**查询参数重置 */
|
/**查询参数重置 */
|
||||||
function fnQueryReset() {
|
function fnQueryReset() {
|
||||||
queryParams = Object.assign(queryParams, {
|
queryParams = Object.assign(queryParams, {
|
||||||
neType: '',
|
neType: undefined,
|
||||||
|
name: '',
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
});
|
});
|
||||||
@@ -46,7 +60,7 @@ type TabeStateType = {
|
|||||||
/**搜索栏 */
|
/**搜索栏 */
|
||||||
seached: boolean;
|
seached: boolean;
|
||||||
/**记录数据 */
|
/**记录数据 */
|
||||||
data: object[];
|
data: any[];
|
||||||
/**勾选记录 */
|
/**勾选记录 */
|
||||||
selectedRowKeys: (string | number)[];
|
selectedRowKeys: (string | number)[];
|
||||||
};
|
};
|
||||||
@@ -55,48 +69,68 @@ type TabeStateType = {
|
|||||||
let tableState: TabeStateType = reactive({
|
let tableState: TabeStateType = reactive({
|
||||||
loading: false,
|
loading: false,
|
||||||
size: 'middle',
|
size: 'middle',
|
||||||
seached: true,
|
seached: false,
|
||||||
data: [],
|
data: [],
|
||||||
selectedRowKeys: [],
|
selectedRowKeys: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
/**表格字段列 */
|
/**表格字段列 */
|
||||||
let tableColumns: ColumnsType = [
|
let tableColumns = ref<TableColumnsType>([
|
||||||
{
|
{
|
||||||
title: t('views.configManage.license.neType'),
|
title: t('common.rowId'),
|
||||||
|
dataIndex: 'id',
|
||||||
|
align: 'left',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.ne.common.neType'),
|
||||||
dataIndex: 'neType',
|
dataIndex: 'neType',
|
||||||
align: 'center',
|
align: 'left',
|
||||||
width: 2,
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.configManage.license.neId'),
|
title: t('views.ne.common.neId'),
|
||||||
dataIndex: 'neId',
|
dataIndex: 'neId',
|
||||||
align: 'center',
|
align: 'left',
|
||||||
width: 2,
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.configManage.license.serialNum'),
|
title: t('common.createTime'),
|
||||||
dataIndex: 'serialNum',
|
|
||||||
align: 'center',
|
|
||||||
width: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.configManage.license.comment'),
|
|
||||||
dataIndex: 'remark',
|
|
||||||
align: 'center',
|
|
||||||
width: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.configManage.license.createTime'),
|
|
||||||
dataIndex: 'createTime',
|
dataIndex: 'createTime',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
customRender(opt) {
|
customRender(opt) {
|
||||||
if (!opt.value) return '';
|
if (!opt.value) return '';
|
||||||
return parseDateToStr(opt.value);
|
return parseDateToStr(opt.value);
|
||||||
},
|
},
|
||||||
width: 2,
|
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({
|
let tablePagination = reactive({
|
||||||
@@ -131,19 +165,20 @@ function fnTableSize({ key }: MenuInfo) {
|
|||||||
tableState.size = key as SizeType;
|
tableState.size = key as SizeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**查询信息列表, pageNum初始页数 */
|
/**表格多选 */
|
||||||
|
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||||
|
tableState.selectedRowKeys = keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**查询列表, pageNum初始页数 */
|
||||||
function fnGetList(pageNum?: number) {
|
function fnGetList(pageNum?: number) {
|
||||||
if (tableState.loading) return;
|
if (tableState.loading) return;
|
||||||
tableState.loading = true;
|
tableState.loading = true;
|
||||||
if (pageNum) {
|
if (pageNum) {
|
||||||
queryParams.pageNum = pageNum;
|
queryParams.pageNum = pageNum;
|
||||||
}
|
}
|
||||||
listLicense(toRaw(queryParams)).then(res => {
|
listNeConfigBackup(toRaw(queryParams)).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||||
// 取消勾选
|
|
||||||
if (tableState.selectedRowKeys.length > 0) {
|
|
||||||
tableState.selectedRowKeys = [];
|
|
||||||
}
|
|
||||||
tablePagination.total = res.total;
|
tablePagination.total = res.total;
|
||||||
tableState.data = res.rows;
|
tableState.data = res.rows;
|
||||||
if (
|
if (
|
||||||
@@ -159,12 +194,80 @@ function fnGetList(pageNum?: number) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**信息文件下载 */
|
||||||
|
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 = {
|
type ModalStateType = {
|
||||||
/**新增框或修改框是否显示 */
|
/**新增框或修改框是否显示 */
|
||||||
visibleByEdit: boolean;
|
visibleByEdit: boolean;
|
||||||
/**网元版本历史框是否显示 */
|
|
||||||
visibleByHistory: boolean;
|
|
||||||
/**标题 */
|
/**标题 */
|
||||||
title: string;
|
title: string;
|
||||||
/**表单数据 */
|
/**表单数据 */
|
||||||
@@ -176,13 +279,11 @@ type ModalStateType = {
|
|||||||
/**对话框对象信息状态 */
|
/**对话框对象信息状态 */
|
||||||
let modalState: ModalStateType = reactive({
|
let modalState: ModalStateType = reactive({
|
||||||
visibleByEdit: false,
|
visibleByEdit: false,
|
||||||
visibleByHistory: false,
|
title: '备份记录',
|
||||||
title: '任务设置',
|
|
||||||
from: {
|
from: {
|
||||||
neType: undefined,
|
id: undefined,
|
||||||
comment: '',
|
name: '',
|
||||||
file: undefined,
|
remark: '',
|
||||||
fileList: [],
|
|
||||||
},
|
},
|
||||||
confirmLoading: false,
|
confirmLoading: false,
|
||||||
});
|
});
|
||||||
@@ -191,8 +292,12 @@ let modalState: ModalStateType = reactive({
|
|||||||
* 对话框弹出显示为 新增或者修改
|
* 对话框弹出显示为 新增或者修改
|
||||||
* @param noticeId 网元id, 不传为新增
|
* @param noticeId 网元id, 不传为新增
|
||||||
*/
|
*/
|
||||||
function fnModalVisibleByEdit() {
|
function fnModalVisibleByEdit(row: Record<string, any>) {
|
||||||
modalState.title = t('common.uploadText');
|
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;
|
modalState.visibleByEdit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,22 +305,10 @@ function fnModalVisibleByEdit() {
|
|||||||
const modalStateFrom = Form.useForm(
|
const modalStateFrom = Form.useForm(
|
||||||
modalState.from,
|
modalState.from,
|
||||||
reactive({
|
reactive({
|
||||||
neType: [
|
name: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t('views.configManage.license.neTypePlease'),
|
message: '请输入名称',
|
||||||
},
|
|
||||||
],
|
|
||||||
comment: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: t('views.configManage.license.updateCommentPlease'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
file: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: t('views.configManage.license.updateFilePlease'),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -231,13 +324,8 @@ function fnModalOk() {
|
|||||||
.then(e => {
|
.then(e => {
|
||||||
modalState.confirmLoading = true;
|
modalState.confirmLoading = true;
|
||||||
const from = toRaw(modalState.from);
|
const from = toRaw(modalState.from);
|
||||||
let formData = new FormData();
|
|
||||||
formData.append('nfType', from.neType[0]);
|
|
||||||
formData.append('nfId', from.neType[1]);
|
|
||||||
formData.append('comment', from.comment);
|
|
||||||
formData.append('file', from.file);
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
uploadLicense(formData)
|
updateNeConfigBackup(from)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
message.success({
|
message.success({
|
||||||
@@ -246,18 +334,18 @@ function fnModalOk() {
|
|||||||
});
|
});
|
||||||
modalState.visibleByEdit = false;
|
modalState.visibleByEdit = false;
|
||||||
modalStateFrom.resetFields();
|
modalStateFrom.resetFields();
|
||||||
|
fnGetList();
|
||||||
} else {
|
} else {
|
||||||
message.error({
|
message.error({
|
||||||
content: `${res.msg}`,
|
content: `${res.msg}`,
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
|
fnGetList();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
hide();
|
hide();
|
||||||
modalState.confirmLoading = false;
|
modalState.confirmLoading = false;
|
||||||
// 获取列表数据
|
|
||||||
fnGetList();
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
@@ -271,49 +359,30 @@ function fnModalOk() {
|
|||||||
*/
|
*/
|
||||||
function fnModalCancel() {
|
function fnModalCancel() {
|
||||||
modalState.visibleByEdit = false;
|
modalState.visibleByEdit = false;
|
||||||
modalState.visibleByHistory = false;
|
|
||||||
modalStateFrom.resetFields();
|
modalStateFrom.resetFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**上传前检查或转换压缩 */
|
|
||||||
function fnBeforeUploadFile(file: FileType) {
|
|
||||||
if (modalState.confirmLoading) return false;
|
|
||||||
const fileName = file.name;
|
|
||||||
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
|
||||||
if (!['.ini'].includes(suff)) {
|
|
||||||
message.error(
|
|
||||||
t('views.configManage.softwareManage.onlyAble', { fileText: '(.ini)' }),
|
|
||||||
3
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**上传文件 */
|
|
||||||
function fnUploadFile(up: UploadRequestOption) {
|
|
||||||
// 改为完成状态
|
|
||||||
const file = modalState.from.fileList[0];
|
|
||||||
file.percent = 100;
|
|
||||||
file.status = 'done';
|
|
||||||
// 预置到表单
|
|
||||||
modalState.from.file = up.file;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
// 初始字典数据
|
||||||
|
getDict('ne_license_status').then(res => {
|
||||||
|
dictStatus.value = res;
|
||||||
|
});
|
||||||
// 获取网元网元列表
|
// 获取网元网元列表
|
||||||
neInfoStore.fnNelist().then(res => {
|
useNeInfoStore()
|
||||||
|
.fnNelist()
|
||||||
|
.then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
// 获取列表数据
|
neOtions.value = useNeInfoStore().getNeSelectOtions;
|
||||||
fnGetList();
|
|
||||||
} else {
|
} else {
|
||||||
message.warning({
|
message.warning({
|
||||||
content: t('common.noData'),
|
content: t('common.noData'),
|
||||||
duration: 2,
|
duration: 2,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
// 获取列表数据
|
||||||
|
fnGetList();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -329,18 +398,24 @@ onMounted(() => {
|
|||||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item :label="t('views.ne.common.neType')" name="neType ">
|
||||||
:label="t('views.configManage.license.neType')"
|
|
||||||
name="neType "
|
|
||||||
>
|
|
||||||
<a-auto-complete
|
<a-auto-complete
|
||||||
v-model:value="queryParams.neType"
|
v-model:value="queryParams.neType"
|
||||||
:options="neInfoStore.getNeSelectOtions"
|
:options="NE_TYPE_LIST.map(v => ({ value: v }))"
|
||||||
allow-clear
|
:allow-clear="true"
|
||||||
:placeholder="t('views.configManage.license.neTypePlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</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-col :lg="6" :md="12" :xs="24">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-space :size="8">
|
<a-space :size="8">
|
||||||
@@ -363,9 +438,16 @@ onMounted(() => {
|
|||||||
<!-- 插槽-卡片左侧侧 -->
|
<!-- 插槽-卡片左侧侧 -->
|
||||||
<template #title>
|
<template #title>
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
<a-button
|
||||||
<template #icon><UploadOutlined /></template>
|
type="default"
|
||||||
{{ t('common.uploadText') }}
|
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-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
@@ -388,9 +470,9 @@ onMounted(() => {
|
|||||||
<template #icon><ReloadOutlined /></template>
|
<template #icon><ReloadOutlined /></template>
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip>
|
<a-tooltip placement="topRight">
|
||||||
<template #title>{{ t('common.sizeText') }}</template>
|
<template #title>{{ t('common.sizeText') }}</template>
|
||||||
<a-dropdown trigger="click" placement="bottomRight">
|
<a-dropdown placement="bottomRight" trigger="click">
|
||||||
<a-button type="text">
|
<a-button type="text">
|
||||||
<template #icon><ColumnHeightOutlined /></template>
|
<template #icon><ColumnHeightOutlined /></template>
|
||||||
</a-button>
|
</a-button>
|
||||||
@@ -424,15 +506,54 @@ onMounted(() => {
|
|||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: 1000 }"
|
: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-table>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
<!-- 上传框 -->
|
<!-- 新增框或修改框 -->
|
||||||
<ProModal
|
<ProModal
|
||||||
:drag="true"
|
:drag="true"
|
||||||
:width="800"
|
:width="512"
|
||||||
:destroyOnClose="true"
|
:destroyOnClose="true"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
@@ -442,52 +563,36 @@ onMounted(() => {
|
|||||||
@ok="fnModalOk"
|
@ok="fnModalOk"
|
||||||
@cancel="fnModalCancel"
|
@cancel="fnModalCancel"
|
||||||
>
|
>
|
||||||
<a-form name="modalStateFrom" layout="horizontal">
|
<a-form
|
||||||
<a-form-item
|
name="modalStateFrom"
|
||||||
:label="t('views.configManage.license.neType')"
|
layout="horizontal"
|
||||||
name="neType"
|
:wrapper-col="{ span: 18 }"
|
||||||
v-bind="modalStateFrom.validateInfos.neType"
|
:label-col="{ span: 6 }"
|
||||||
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-cascader
|
|
||||||
v-model:value="modalState.from.neType"
|
|
||||||
:options="useNeInfoStore().getNeCascaderOptions"
|
|
||||||
:allow-clear="false"
|
|
||||||
:placeholder="t('views.configManage.license.neTypePlease')"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.configManage.license.updateComment')"
|
:label="t('views.ne.neConfigBackup.name')"
|
||||||
name="comment"
|
name="name"
|
||||||
v-bind="modalStateFrom.validateInfos.comment"
|
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
|
<a-textarea
|
||||||
v-model:value="modalState.from.comment"
|
v-model:value="modalState.from.remark"
|
||||||
:maxlength="200"
|
:auto-size="{ minRows: 2, maxRows: 6 }"
|
||||||
|
:maxlength="400"
|
||||||
:show-count="true"
|
:show-count="true"
|
||||||
:placeholder="t('views.configManage.license.updateCommentPlease')"
|
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
|
||||||
:label="t('views.configManage.license.updateFile')"
|
|
||||||
name="file"
|
|
||||||
v-bind="modalStateFrom.validateInfos.file"
|
|
||||||
>
|
|
||||||
<a-upload
|
|
||||||
name="file"
|
|
||||||
v-model:file-list="modalState.from.fileList"
|
|
||||||
accept=".ini"
|
|
||||||
list-type="text"
|
|
||||||
:max-count="1"
|
|
||||||
:show-upload-list="true"
|
|
||||||
:before-upload="fnBeforeUploadFile"
|
|
||||||
:custom-request="fnUploadFile"
|
|
||||||
>
|
|
||||||
<a-button type="default" :loading="modalState.confirmLoading">
|
|
||||||
{{ t('views.configManage.license.selectFile') }}
|
|
||||||
</a-button>
|
|
||||||
</a-upload>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
</a-form>
|
||||||
</ProModal>
|
</ProModal>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, toRaw, watch } from 'vue';
|
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 useI18n from '@/hooks/useI18n';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
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 {
|
import {
|
||||||
exportSet,
|
exportNeConfigBackup,
|
||||||
importFile,
|
importNeConfigBackup,
|
||||||
listServerFile,
|
listNeConfigBackup,
|
||||||
} from '@/api/configManage/neManage';
|
} from '@/api/ne/neConfigBackup';
|
||||||
|
import saveAs from 'file-saver';
|
||||||
|
import { uploadFile } from '@/api/tool/file';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
|
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -28,32 +30,49 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/**表格所需option */
|
/**导入状态数据 */
|
||||||
const neManageOption = reactive({
|
const importState = reactive({
|
||||||
importType: [
|
typeOption: [
|
||||||
{ label: t('views.ne.neInfo.backConf.server'), value: 'server' },
|
{ label: t('views.ne.neInfo.backConf.server'), value: 'backup' },
|
||||||
{ label: t('views.ne.neInfo.backConf.local'), value: 'local' },
|
{ label: t('views.ne.neInfo.backConf.local'), value: 'upload' },
|
||||||
],
|
],
|
||||||
serverFileName: <any[]>[],
|
backupData: <any[]>[],
|
||||||
});
|
});
|
||||||
|
|
||||||
/**查询网元远程服务器备份文件 */
|
/**查询网元远程服务器备份文件 */
|
||||||
function typeChange(value: any) {
|
function backupSearch(name?: string) {
|
||||||
if (value === 'server') {
|
const { neType, neId } = modalState.from;
|
||||||
modalState.from.fileName = undefined;
|
listNeConfigBackup({
|
||||||
listServerFile(modalState.from).then(res => {
|
neType,
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
neId,
|
||||||
neManageOption.serverFileName = [];
|
name,
|
||||||
res.data.forEach((item: any) => {
|
pageNum: 1,
|
||||||
neManageOption.serverFileName.push({
|
pageSize: 20,
|
||||||
label: item.fileName,
|
}).then(res => {
|
||||||
value: item.fileName,
|
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: {
|
from: {
|
||||||
neType: string;
|
neType: string;
|
||||||
neId: string;
|
neId: string;
|
||||||
importType: 'local' | 'server';
|
type: 'upload' | 'backup';
|
||||||
file: File | null;
|
path: string | undefined;
|
||||||
fileName: string | undefined;
|
|
||||||
};
|
};
|
||||||
/**确定按钮 loading */
|
/**确定按钮 loading */
|
||||||
confirmLoading: boolean;
|
confirmLoading: boolean;
|
||||||
@@ -84,9 +102,8 @@ let modalState: ModalStateType = reactive({
|
|||||||
from: {
|
from: {
|
||||||
neType: '',
|
neType: '',
|
||||||
neId: '',
|
neId: '',
|
||||||
importType: 'local',
|
type: 'upload',
|
||||||
file: null,
|
path: undefined,
|
||||||
fileName: undefined,
|
|
||||||
},
|
},
|
||||||
confirmLoading: false,
|
confirmLoading: false,
|
||||||
uploadFiles: [],
|
uploadFiles: [],
|
||||||
@@ -96,16 +113,10 @@ let modalState: ModalStateType = reactive({
|
|||||||
const modalStateFrom = Form.useForm(
|
const modalStateFrom = Form.useForm(
|
||||||
modalState.from,
|
modalState.from,
|
||||||
reactive({
|
reactive({
|
||||||
file: [
|
path: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t('views.ne.neInfo.backConf.filePlease'),
|
message: t('views.ne.neInfo.backConf.pathPlease'),
|
||||||
},
|
|
||||||
],
|
|
||||||
fileName: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: t('views.ne.neInfo.backConf.fileNamePlease'),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -117,21 +128,13 @@ const modalStateFrom = Form.useForm(
|
|||||||
*/
|
*/
|
||||||
function fnModalOk() {
|
function fnModalOk() {
|
||||||
if (modalState.confirmLoading) return;
|
if (modalState.confirmLoading) return;
|
||||||
|
|
||||||
const from = toRaw(modalState.from);
|
const from = toRaw(modalState.from);
|
||||||
let validateName = ['importType'];
|
|
||||||
if (from.importType === 'local') {
|
|
||||||
validateName.push('file');
|
|
||||||
} else {
|
|
||||||
validateName.push('fileName');
|
|
||||||
}
|
|
||||||
|
|
||||||
modalStateFrom
|
modalStateFrom
|
||||||
.validate(validateName)
|
.validate()
|
||||||
.then(e => {
|
.then(e => {
|
||||||
modalState.confirmLoading = true;
|
modalState.confirmLoading = true;
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
importFile(from)
|
importNeConfigBackup(from)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
message.success(t('common.operateOk'), 3);
|
message.success(t('common.operateOk'), 3);
|
||||||
@@ -168,6 +171,12 @@ function fnModalCancel() {
|
|||||||
emit('update:visible', false);
|
emit('update:visible', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**表单上传前删除 */
|
||||||
|
function fnBeforeRemoveFile(file: UploadFile) {
|
||||||
|
modalState.from.path = undefined;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**表单上传前检查或转换压缩 */
|
/**表单上传前检查或转换压缩 */
|
||||||
function fnBeforeUploadFile(file: FileType) {
|
function fnBeforeUploadFile(file: FileType) {
|
||||||
if (modalState.confirmLoading) return false;
|
if (modalState.confirmLoading) return false;
|
||||||
@@ -187,12 +196,30 @@ function fnBeforeUploadFile(file: FileType) {
|
|||||||
|
|
||||||
/**表单上传文件 */
|
/**表单上传文件 */
|
||||||
function fnUploadFile(up: UploadRequestOption) {
|
function fnUploadFile(up: UploadRequestOption) {
|
||||||
|
// 发送请求
|
||||||
|
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];
|
const file = modalState.uploadFiles[0];
|
||||||
file.percent = 100;
|
file.percent = 100;
|
||||||
file.status = 'done';
|
file.status = 'done';
|
||||||
// 预置到表单
|
// 预置到表单
|
||||||
modalState.from.file = up.file as File;
|
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'),
|
content: t('views.ne.neInfo.backConf.exportTip'),
|
||||||
onOk() {
|
onOk() {
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
exportSet({ neType, neId })
|
exportNeConfigBackup({ neType, neId })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
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 {
|
} else {
|
||||||
message.error(`${res.msg}`, 3);
|
message.error(`${res.msg}`, 3);
|
||||||
}
|
}
|
||||||
@@ -258,44 +292,44 @@ defineExpose({
|
|||||||
<a-form name="modalStateFrom" layout="horizontal" :label-col="{ span: 6 }">
|
<a-form name="modalStateFrom" layout="horizontal" :label-col="{ span: 6 }">
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item :label="t('views.ne.common.neType')" name="neType">
|
||||||
:label="t('views.ne.common.neType')"
|
|
||||||
name="neType"
|
|
||||||
v-bind="modalStateFrom.validateInfos.neType"
|
|
||||||
>
|
|
||||||
{{ modalState.from.neType }}
|
{{ modalState.from.neType }}
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.ne.neInfo.backConf.importType')"
|
:label="t('views.ne.neInfo.backConf.importType')"
|
||||||
name="importType"
|
name="type"
|
||||||
>
|
>
|
||||||
<a-select
|
<a-select
|
||||||
v-model:value="modalState.from.importType"
|
v-model:value="modalState.from.type"
|
||||||
default-value="server"
|
default-value="server"
|
||||||
:options="neManageOption.importType"
|
:options="importState.typeOption"
|
||||||
@change="typeChange"
|
@change="typeChange"
|
||||||
>
|
>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item :label="t('views.ne.common.neId')" name="neId">
|
||||||
:label="t('views.ne.common.neId')"
|
|
||||||
name="neId"
|
|
||||||
v-bind="modalStateFrom.validateInfos.neId"
|
|
||||||
>
|
|
||||||
{{ modalState.from.neId }}
|
{{ modalState.from.neId }}
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.ne.neInfo.backConf.server')"
|
:label="t('views.ne.neInfo.backConf.server')"
|
||||||
name="fileName"
|
name="fileName"
|
||||||
v-bind="modalStateFrom.validateInfos.fileName"
|
v-bind="modalStateFrom.validateInfos.path"
|
||||||
v-if="modalState.from.importType === 'server'"
|
v-if="modalState.from.type === 'backup'"
|
||||||
>
|
>
|
||||||
<a-select
|
<a-select
|
||||||
v-model:value="modalState.from.fileName"
|
v-model:value="modalState.from.path"
|
||||||
:options="neManageOption.serverFileName"
|
:options="importState.backupData"
|
||||||
:placeholder="t('common.selectPlease')"
|
: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-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -303,8 +337,8 @@ defineExpose({
|
|||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.ne.neInfo.backConf.local')"
|
:label="t('views.ne.neInfo.backConf.local')"
|
||||||
name="file"
|
name="file"
|
||||||
v-bind="modalStateFrom.validateInfos.file"
|
v-bind="modalStateFrom.validateInfos.path"
|
||||||
v-if="modalState.from.importType === 'local'"
|
v-if="modalState.from.type === 'upload'"
|
||||||
>
|
>
|
||||||
<a-upload
|
<a-upload
|
||||||
name="file"
|
name="file"
|
||||||
@@ -314,9 +348,10 @@ defineExpose({
|
|||||||
:max-count="1"
|
:max-count="1"
|
||||||
:show-upload-list="{
|
:show-upload-list="{
|
||||||
showPreviewIcon: false,
|
showPreviewIcon: false,
|
||||||
showRemoveIcon: false,
|
showRemoveIcon: true,
|
||||||
showDownloadIcon: false,
|
showDownloadIcon: false,
|
||||||
}"
|
}"
|
||||||
|
:remove="fnBeforeRemoveFile"
|
||||||
:before-upload="fnBeforeUploadFile"
|
:before-upload="fnBeforeUploadFile"
|
||||||
:custom-request="fnUploadFile"
|
:custom-request="fnUploadFile"
|
||||||
:disabled="modalState.confirmLoading"
|
:disabled="modalState.confirmLoading"
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ let dict: {
|
|||||||
* 测试主机连接
|
* 测试主机连接
|
||||||
*/
|
*/
|
||||||
function fnHostTest(row: Record<string, any>) {
|
function fnHostTest(row: Record<string, any>) {
|
||||||
if (modalState.confirmLoading || !row.addr) return;
|
if (modalState.confirmLoading || !row.addr || !row.port) return;
|
||||||
modalState.confirmLoading = true;
|
modalState.confirmLoading = true;
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
testNeHost(row)
|
testNeHost(row)
|
||||||
@@ -281,15 +281,13 @@ function fnModalCancel() {
|
|||||||
emit('update:visible', false);
|
emit('update:visible', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**表单修改网元类型 */
|
||||||
* 表单修改网元类型
|
|
||||||
*/
|
|
||||||
function fnNeTypeChange(v: any) {
|
function fnNeTypeChange(v: any) {
|
||||||
const hostsLen = modalState.from.hosts.length;
|
|
||||||
// 网元默认只含22和4100
|
// 网元默认只含22和4100
|
||||||
if (hostsLen === 3 && v !== 'UPF') {
|
if (modalState.from.hosts.length === 3) {
|
||||||
modalState.from.hosts.pop();
|
modalState.from.hosts.pop();
|
||||||
}
|
}
|
||||||
|
const hostsLen = modalState.from.hosts.length;
|
||||||
// UPF标准版本可支持5002
|
// UPF标准版本可支持5002
|
||||||
if (hostsLen === 2 && v === 'UPF') {
|
if (hostsLen === 2 && v === 'UPF') {
|
||||||
modalState.from.hosts.push({
|
modalState.from.hosts.push({
|
||||||
@@ -297,19 +295,42 @@ function fnNeTypeChange(v: any) {
|
|||||||
hostType: 'telnet',
|
hostType: 'telnet',
|
||||||
groupId: '1',
|
groupId: '1',
|
||||||
title: 'Telnet_NE_5002',
|
title: 'Telnet_NE_5002',
|
||||||
addr: '',
|
addr: modalState.from.ip,
|
||||||
port: 5002,
|
port: 5002,
|
||||||
user: 'user',
|
user: 'admin',
|
||||||
authMode: '0',
|
authMode: '0',
|
||||||
password: 'user',
|
password: 'admin',
|
||||||
remark: '',
|
remark: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// UDM可支持6379
|
||||||
|
if (hostsLen === 2 && v === 'UDM') {
|
||||||
|
modalState.from.hosts.push({
|
||||||
|
hostId: undefined,
|
||||||
|
hostType: 'redis',
|
||||||
|
groupId: '1',
|
||||||
|
title: 'REDIS_NE_6379',
|
||||||
|
addr: modalState.from.ip,
|
||||||
|
port: 6379,
|
||||||
|
user: 'udmdb',
|
||||||
|
authMode: '0',
|
||||||
|
password: 'helloearth',
|
||||||
|
dbName: '0',
|
||||||
|
remark: '',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
modalState.from.rmUid = `4400HX${v}${modalState.from.neId}`; // 4400HX1AMF001
|
||||||
* 表单修改网元IP
|
}
|
||||||
*/
|
|
||||||
|
/**表单修改网元neId */
|
||||||
|
function fnNeIdChange(e: any) {
|
||||||
|
const v = e.target.value;
|
||||||
|
if (v.length < 1) return;
|
||||||
|
modalState.from.rmUid = `4400HX${modalState.from.neType}${v}`; // 4400HX1AMF001
|
||||||
|
}
|
||||||
|
|
||||||
|
/**表单修改网元IP */
|
||||||
function fnNeIPChange(e: any) {
|
function fnNeIPChange(e: any) {
|
||||||
const v = e.target.value;
|
const v = e.target.value;
|
||||||
if (v.length < 7) return;
|
if (v.length < 7) return;
|
||||||
@@ -428,6 +449,7 @@ onMounted(() => {
|
|||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="32"
|
:maxlength="32"
|
||||||
|
@change="fnNeIdChange"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<a-tooltip placement="topLeft">
|
<a-tooltip placement="topLeft">
|
||||||
@@ -620,8 +642,13 @@ onMounted(() => {
|
|||||||
(s:any) => !(s.hostType === 'telnet' && modalState.from.neType === 'OMC')
|
(s:any) => !(s.hostType === 'telnet' && modalState.from.neType === 'OMC')
|
||||||
)"
|
)"
|
||||||
:key="host.title"
|
:key="host.title"
|
||||||
:header="`${host.hostType.toUpperCase()} ${host.port}`"
|
|
||||||
>
|
>
|
||||||
|
<template #header>
|
||||||
|
<span v-if="host.hostType === 'redis'"> DB {{ host.port }} </span>
|
||||||
|
<span v-else>
|
||||||
|
{{ `${host.hostType.toUpperCase()} ${host.port}` }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item :label="t('views.ne.neHost.addr')">
|
<a-form-item :label="t('views.ne.neHost.addr')">
|
||||||
@@ -648,7 +675,22 @@ onMounted(() => {
|
|||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|
||||||
<a-row :gutter="16">
|
<a-form-item
|
||||||
|
v-if="host.hostType === 'telnet'"
|
||||||
|
:label="t('views.ne.neHost.user')"
|
||||||
|
:label-col="{ span: 3 }"
|
||||||
|
:label-wrap="true"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:value="host.user"
|
||||||
|
allow-clear
|
||||||
|
:maxlength="32"
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-row :gutter="16" v-if="host.hostType === 'ssh'">
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item :label="t('views.ne.neHost.user')">
|
<a-form-item :label="t('views.ne.neHost.user')">
|
||||||
<a-input
|
<a-input
|
||||||
@@ -666,7 +708,6 @@ onMounted(() => {
|
|||||||
v-model:value="host.authMode"
|
v-model:value="host.authMode"
|
||||||
default-value="0"
|
default-value="0"
|
||||||
:options="dict.neHostAuthMode"
|
:options="dict.neHostAuthMode"
|
||||||
:disabled="host.hostType === 'telnet'"
|
|
||||||
>
|
>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -686,7 +727,6 @@ onMounted(() => {
|
|||||||
>
|
>
|
||||||
</a-input-password>
|
</a-input-password>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<template v-if="host.authMode === '1'">
|
<template v-if="host.authMode === '1'">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.ne.neHost.privateKey')"
|
:label="t('views.ne.neHost.privateKey')"
|
||||||
@@ -716,6 +756,21 @@ onMounted(() => {
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
v-if="host.hostType === 'mysql'"
|
||||||
|
:label="t('views.ne.neHost.database')"
|
||||||
|
:label-col="{ span: 3 }"
|
||||||
|
:label-wrap="true"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:value="host.dbName"
|
||||||
|
allow-clear
|
||||||
|
:maxlength="32"
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('common.remark')"
|
:label="t('common.remark')"
|
||||||
:label-col="{ span: 3 }"
|
:label-col="{ span: 3 }"
|
||||||
@@ -730,6 +785,7 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
<!-- 测试 -->
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.ne.neHost.test')"
|
:label="t('views.ne.neHost.test')"
|
||||||
name="test"
|
name="test"
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ let modalState: ModalStateType = reactive({
|
|||||||
title: 'OAM Configuration',
|
title: 'OAM Configuration',
|
||||||
sync: true,
|
sync: true,
|
||||||
from: {
|
from: {
|
||||||
|
omcIP: '',
|
||||||
oamEnable: true,
|
oamEnable: true,
|
||||||
oamPort: 33030,
|
oamPort: 33030,
|
||||||
snmpEnable: true,
|
snmpEnable: true,
|
||||||
@@ -77,6 +78,7 @@ function fnModalVisibleByTypeAndId(neType: string, neId: string) {
|
|||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
Object.assign(modalState.from, {
|
Object.assign(modalState.from, {
|
||||||
|
omcIP: data.oamConfig[data.oamConfig.ipType],
|
||||||
oamEnable: data.oamConfig.enable,
|
oamEnable: data.oamConfig.enable,
|
||||||
oamPort: data.oamConfig.port,
|
oamPort: data.oamConfig.port,
|
||||||
snmpEnable: data.snmpConfig.enable,
|
snmpEnable: data.snmpConfig.enable,
|
||||||
@@ -224,6 +226,17 @@ watch(
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.ne.neInfo.oam.omcIP')"
|
||||||
|
name="omcIP"
|
||||||
|
:label-col="{ span: 6 }"
|
||||||
|
:labelWrap="true"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:value="modalState.from.omcIP"
|
||||||
|
:maxlength="128"
|
||||||
|
></a-input>
|
||||||
|
</a-form-item>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
<a-collapse-panel header="SNMP">
|
<a-collapse-panel header="SNMP">
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
|
|||||||
@@ -233,9 +233,13 @@ function fnModalEditOk(from: Record<string, any>) {
|
|||||||
if (item && res.code === RESULT_CODE_SUCCESS) {
|
if (item && res.code === RESULT_CODE_SUCCESS) {
|
||||||
item.neType = from.neType;
|
item.neType = from.neType;
|
||||||
item.neId = from.neId;
|
item.neId = from.neId;
|
||||||
item.ip = from.ip;
|
item.rmUid = from.rmUid;
|
||||||
item.neName = from.neName;
|
item.neName = from.neName;
|
||||||
|
item.ip = from.ip;
|
||||||
|
item.port = from.port;
|
||||||
|
if (item.status !== '2') {
|
||||||
item.status = res.data.online ? '1' : '0';
|
item.status = res.data.online ? '1' : '0';
|
||||||
|
}
|
||||||
Object.assign(item.serverState, res.data);
|
Object.assign(item.serverState, res.data);
|
||||||
const resouresUsage = parseResouresUsage(item.serverState);
|
const resouresUsage = parseResouresUsage(item.serverState);
|
||||||
Reflect.set(item, 'resoures', resouresUsage);
|
Reflect.set(item, 'resoures', resouresUsage);
|
||||||
@@ -281,10 +285,10 @@ function fnRecordDelete(id: string) {
|
|||||||
message.success(t('common.operateOk'), 3);
|
message.success(t('common.operateOk'), 3);
|
||||||
// 过滤掉删除的id
|
// 过滤掉删除的id
|
||||||
tableState.data = tableState.data.filter(item => {
|
tableState.data = tableState.data.filter(item => {
|
||||||
if (id.indexOf(',')) {
|
if (id.indexOf(',') > -1) {
|
||||||
return !tableState.selectedRowKeys.includes(item.id);
|
return !tableState.selectedRowKeys.includes(item.id);
|
||||||
} else {
|
} else {
|
||||||
return item.id != id;
|
return item.id !== id;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 刷新缓存
|
// 刷新缓存
|
||||||
@@ -362,8 +366,18 @@ function fnGetList(pageNum?: number) {
|
|||||||
tablePagination.total = res.total;
|
tablePagination.total = res.total;
|
||||||
// 遍历处理资源情况数值
|
// 遍历处理资源情况数值
|
||||||
tableState.data = res.rows.map(item => {
|
tableState.data = res.rows.map(item => {
|
||||||
|
let resouresUsage = {
|
||||||
|
sysDiskUsage: 0,
|
||||||
|
sysMemUsage: 0,
|
||||||
|
sysCpuUsage: 0,
|
||||||
|
nfCpuUsage: 0,
|
||||||
|
};
|
||||||
const neState = item.serverState;
|
const neState = item.serverState;
|
||||||
const resouresUsage = parseResouresUsage(neState);
|
if (neState) {
|
||||||
|
resouresUsage = parseResouresUsage(neState);
|
||||||
|
} else {
|
||||||
|
item.serverState = { online: false };
|
||||||
|
}
|
||||||
Reflect.set(item, 'resoures', resouresUsage);
|
Reflect.set(item, 'resoures', resouresUsage);
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
@@ -378,33 +392,27 @@ function parseResouresUsage(neState: Record<string, any>) {
|
|||||||
let nfCpuUsage = 0;
|
let nfCpuUsage = 0;
|
||||||
if (neState.cpu) {
|
if (neState.cpu) {
|
||||||
nfCpuUsage = neState.cpu.nfCpuUsage;
|
nfCpuUsage = neState.cpu.nfCpuUsage;
|
||||||
if (nfCpuUsage > 100) {
|
const nfCpu = +(nfCpuUsage / 100);
|
||||||
const nfCpu = +(neState.cpu.nfCpuUsage / 100);
|
|
||||||
if (nfCpu > 100) {
|
|
||||||
nfCpuUsage = 100;
|
|
||||||
} else {
|
|
||||||
nfCpuUsage = +nfCpu.toFixed(2);
|
nfCpuUsage = +nfCpu.toFixed(2);
|
||||||
}
|
if (nfCpuUsage > 100) {
|
||||||
|
nfCpuUsage = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
sysCpuUsage = neState.cpu.sysCpuUsage;
|
sysCpuUsage = neState.cpu.sysCpuUsage;
|
||||||
if (sysCpuUsage > 100) {
|
const sysCpu = +(sysCpuUsage / 100);
|
||||||
const sysCpu = +(neState.cpu.sysCpuUsage / 100);
|
|
||||||
if (sysCpu > 100) {
|
|
||||||
sysCpuUsage = 100;
|
|
||||||
} else {
|
|
||||||
sysCpuUsage = +sysCpu.toFixed(2);
|
sysCpuUsage = +sysCpu.toFixed(2);
|
||||||
}
|
if (sysCpuUsage > 100) {
|
||||||
|
sysCpuUsage = 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sysMemUsage = 0;
|
let sysMemUsage = 0;
|
||||||
if (neState.mem) {
|
if (neState.mem) {
|
||||||
let men = neState.mem.sysMemUsage;
|
const men = neState.mem.sysMemUsage;
|
||||||
if (men > 100) {
|
sysMemUsage = +(men / 100).toFixed(2);
|
||||||
men = +(men / 100).toFixed(2);
|
if (sysMemUsage > 100) {
|
||||||
|
sysMemUsage = 100;
|
||||||
}
|
}
|
||||||
sysMemUsage = men;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sysDiskUsage = 0;
|
let sysDiskUsage = 0;
|
||||||
@@ -556,7 +564,7 @@ onMounted(() => {
|
|||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: tableColumns.length * 150 }"
|
:scroll="{ x: tableColumns.length * 120 }"
|
||||||
:row-selection="{
|
:row-selection="{
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
columnWidth: '48px',
|
columnWidth: '48px',
|
||||||
@@ -623,7 +631,10 @@ onMounted(() => {
|
|||||||
<DeleteOutlined />
|
<DeleteOutlined />
|
||||||
{{ t('common.deleteText') }}
|
{{ t('common.deleteText') }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="oam">
|
<a-menu-item
|
||||||
|
key="oam"
|
||||||
|
v-if="!['OMC'].includes(record.neType)"
|
||||||
|
>
|
||||||
<FileTextOutlined />
|
<FileTextOutlined />
|
||||||
{{ t('views.ne.common.oam') }}
|
{{ t('views.ne.common.oam') }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
|
|||||||
@@ -229,11 +229,11 @@ function fnModalOk() {
|
|||||||
* 表单修改网元类型
|
* 表单修改网元类型
|
||||||
*/
|
*/
|
||||||
function fnNeTypeChange(v: any) {
|
function fnNeTypeChange(v: any) {
|
||||||
const hostsLen = modalState.from.hosts.length;
|
|
||||||
// 网元默认只含22和4100
|
// 网元默认只含22和4100
|
||||||
if (hostsLen === 3 && v !== 'UPF') {
|
if (modalState.from.hosts.length === 3) {
|
||||||
modalState.from.hosts.pop();
|
modalState.from.hosts.pop();
|
||||||
}
|
}
|
||||||
|
const hostsLen = modalState.from.hosts.length;
|
||||||
// UPF标准版本可支持5002
|
// UPF标准版本可支持5002
|
||||||
if (hostsLen === 2 && v === 'UPF') {
|
if (hostsLen === 2 && v === 'UPF') {
|
||||||
modalState.from.hosts.push({
|
modalState.from.hosts.push({
|
||||||
@@ -249,6 +249,22 @@ function fnNeTypeChange(v: any) {
|
|||||||
remark: '',
|
remark: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// UDM可支持6379
|
||||||
|
if (hostsLen === 2 && v === 'UDM') {
|
||||||
|
modalState.from.hosts.push({
|
||||||
|
hostId: undefined,
|
||||||
|
hostType: 'redis',
|
||||||
|
groupId: '1',
|
||||||
|
title: 'REDIS_NE_6379',
|
||||||
|
addr: modalState.from.ip,
|
||||||
|
port: 6379,
|
||||||
|
user: 'udmdb',
|
||||||
|
authMode: '0',
|
||||||
|
password: 'helloearth',
|
||||||
|
dbName: '0',
|
||||||
|
remark: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -268,7 +284,7 @@ function fnStepPrev() {
|
|||||||
title: t('common.tipTitle'),
|
title: t('common.tipTitle'),
|
||||||
content: t('views.ne.neQuickSetup.stepPrevTip'),
|
content: t('views.ne.neQuickSetup.stepPrevTip'),
|
||||||
onOk() {
|
onOk() {
|
||||||
fnRestStepState();
|
fnRestStepState(t);
|
||||||
fnToStepName('Start');
|
fnToStepName('Start');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Modal, TableColumnsType, message } from 'ant-design-vue/lib';
|
import { Modal, message } from 'ant-design-vue/lib';
|
||||||
import { defineAsyncComponent, onMounted, reactive, ref, toRaw } from 'vue';
|
import { defineAsyncComponent, onMounted, reactive, toRaw } from 'vue';
|
||||||
import { fnToStepName, stepState } from '../hooks/useStep';
|
import { fnToStepName, stepState } from '../hooks/useStep';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { listNeVersion, operateNeVersion } from '@/api/ne/neVersion';
|
import { operateNeVersion } from '@/api/ne/neVersion';
|
||||||
import {
|
import {
|
||||||
RESULT_CODE_ERROR,
|
RESULT_CODE_ERROR,
|
||||||
RESULT_CODE_SUCCESS,
|
RESULT_CODE_SUCCESS,
|
||||||
} from '@/constants/result-constants';
|
} from '@/constants/result-constants';
|
||||||
import {
|
import { listNeSoftware, newNeVersion } from '@/api/ne/neSoftware';
|
||||||
addNeSoftware,
|
|
||||||
listNeSoftware,
|
|
||||||
newNeVersion,
|
|
||||||
} from '@/api/ne/neSoftware';
|
|
||||||
import { parseDateToStr } from '@/utils/date-utils';
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -157,11 +153,7 @@ type StateType = {
|
|||||||
optionType: 'upload' | 'option';
|
optionType: 'upload' | 'option';
|
||||||
/**文件上传 */
|
/**文件上传 */
|
||||||
visibleByFile: boolean;
|
visibleByFile: boolean;
|
||||||
/**
|
/**网元拓展包列表类型 */
|
||||||
* 依赖包类型
|
|
||||||
* IMS-rtproxy/mf/adb
|
|
||||||
* UDM-adb
|
|
||||||
*/
|
|
||||||
depType: string[];
|
depType: string[];
|
||||||
/**软件包信息数据 */
|
/**软件包信息数据 */
|
||||||
from: {
|
from: {
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ function fnStepEnd() {
|
|||||||
title: t('common.tipTitle'),
|
title: t('common.tipTitle'),
|
||||||
content: t('views.ne.neQuickSetup.licenseEndTip'),
|
content: t('views.ne.neQuickSetup.licenseEndTip'),
|
||||||
onOk() {
|
onOk() {
|
||||||
fnRestStepState();
|
fnRestStepState(t);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-78
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, onMounted, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const emit = defineEmits(['update:data']);
|
const emit = defineEmits(['update:data']);
|
||||||
@@ -21,22 +21,8 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/**对话框对象信息状态类型 */
|
/**表单信息状态 */
|
||||||
type StateType = {
|
let fromState = ref({
|
||||||
/**表单数据 */
|
|
||||||
from: Record<string, any>;
|
|
||||||
/**根据网元显示配置项 */
|
|
||||||
hasNE: {
|
|
||||||
amf: boolean;
|
|
||||||
upf: boolean;
|
|
||||||
ims: boolean;
|
|
||||||
mme: boolean;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**对话框对象信息状态 */
|
|
||||||
let state: StateType = reactive({
|
|
||||||
from: {
|
|
||||||
basic: {
|
basic: {
|
||||||
plmnId: {
|
plmnId: {
|
||||||
mcc: '001',
|
mcc: '001',
|
||||||
@@ -74,7 +60,7 @@ let state: StateType = reactive({
|
|||||||
amf_ip: '172.16.5.120',
|
amf_ip: '172.16.5.120',
|
||||||
ausf_ip: '172.16.5.130',
|
ausf_ip: '172.16.5.130',
|
||||||
udm_ip: '172.16.5.140',
|
udm_ip: '172.16.5.140',
|
||||||
adb_ip: '0.0.0.0',
|
db_ip: '0.0.0.0',
|
||||||
smf_ip: '172.16.5.150',
|
smf_ip: '172.16.5.150',
|
||||||
pcf_ip: '172.16.5.160',
|
pcf_ip: '172.16.5.160',
|
||||||
nssf_ip: '172.16.5.170',
|
nssf_ip: '172.16.5.170',
|
||||||
@@ -84,46 +70,18 @@ let state: StateType = reactive({
|
|||||||
nef_ip: '172.16.5.210',
|
nef_ip: '172.16.5.210',
|
||||||
mme_ip: '172.16.5.220',
|
mme_ip: '172.16.5.220',
|
||||||
n3iwf_ip: '172.16.5.230',
|
n3iwf_ip: '172.16.5.230',
|
||||||
},
|
smsc_ip: '172.16.5.240',
|
||||||
},
|
|
||||||
hasNE: {
|
|
||||||
amf: false,
|
|
||||||
upf: false,
|
|
||||||
ims: false,
|
|
||||||
mme: false,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/**监听数据 */
|
/**监听数据 */
|
||||||
watch(
|
watch(
|
||||||
() => props.data,
|
() => fromState,
|
||||||
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,
|
|
||||||
val => {
|
val => {
|
||||||
if (val) emit('update:data', val);
|
if (val) emit('update:data', val);
|
||||||
},
|
},
|
||||||
{ deep: true, immediate: true }
|
{ deep: true, immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
onMounted(() => {});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -140,7 +98,7 @@ onMounted(() => {});
|
|||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item label="DNN_DATA" name="basic.dnn_data">
|
<a-form-item label="DNN_DATA" name="basic.dnn_data">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.basic.dnn_data"
|
v-model:value="fromState.basic.dnn_data"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -155,13 +113,13 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="MCC" name="basic.plmnId.mcc">
|
<a-form-item label="MCC" name="basic.plmnId.mcc">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.basic.plmnId.mcc"
|
v-model:value="fromState.basic.plmnId.mcc"
|
||||||
placeholder="1-65535"
|
placeholder="1-65535"
|
||||||
></a-input>
|
></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="SST" name="basic.snssai.sst">
|
<a-form-item label="SST" name="basic.snssai.sst">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-model:value="state.from.basic.snssai.sst"
|
v-model:value="fromState.basic.snssai.sst"
|
||||||
:min="1"
|
:min="1"
|
||||||
:max="3"
|
:max="3"
|
||||||
placeholder="1-3"
|
placeholder="1-3"
|
||||||
@@ -177,7 +135,7 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="TAC" name="basic.tac">
|
<a-form-item label="TAC" name="basic.tac">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.basic.tac"
|
v-model:value="fromState.basic.tac"
|
||||||
placeholder="1-65535"
|
placeholder="1-65535"
|
||||||
></a-input>
|
></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -185,7 +143,7 @@ onMounted(() => {});
|
|||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item label="DNN_IMS" name="basic.dnn_ims">
|
<a-form-item label="DNN_IMS" name="basic.dnn_ims">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.basic.dnn_ims"
|
v-model:value="fromState.basic.dnn_ims"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -194,13 +152,13 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="MNC" name="basic.plmnId.mnc">
|
<a-form-item label="MNC" name="basic.plmnId.mnc">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.basic.plmnId.mnc"
|
v-model:value="fromState.basic.plmnId.mnc"
|
||||||
placeholder="1-65535"
|
placeholder="1-65535"
|
||||||
></a-input>
|
></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="SD" name="basic.snssai.sd">
|
<a-form-item label="SD" name="basic.snssai.sd">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.basic.snssai.sd"
|
v-model:value="fromState.basic.snssai.sd"
|
||||||
placeholder="1-65535"
|
placeholder="1-65535"
|
||||||
></a-input>
|
></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -220,7 +178,7 @@ onMounted(() => {});
|
|||||||
:validateTrigger="[]"
|
:validateTrigger="[]"
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.sbi.omc_ip"
|
v-model:value="fromState.sbi.omc_ip"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -237,14 +195,13 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
<template v-if="props.ne.amf">
|
||||||
<template v-if="state.hasNE.amf">
|
|
||||||
<a-divider orientation="left">AMF</a-divider>
|
<a-divider orientation="left">AMF</a-divider>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="24" :md="24" :xs="24">
|
<a-col :lg="24" :md="24" :xs="24">
|
||||||
<a-form-item label="N2_IP" name="external.amfn2_ip">
|
<a-form-item label="N2_IP" name="external.amfn2_ip">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.amfn2_ip"
|
v-model:value="fromState.external.amfn2_ip"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -262,7 +219,7 @@ onMounted(() => {});
|
|||||||
</template>
|
</template>
|
||||||
</a-col>
|
</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-divider orientation="left">UPF</a-divider>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
@@ -272,7 +229,7 @@ onMounted(() => {});
|
|||||||
help="Install of Standard or Light"
|
help="Install of Standard or Light"
|
||||||
>
|
>
|
||||||
<a-select
|
<a-select
|
||||||
v-model:value="state.from.external.upf_type"
|
v-model:value="fromState.external.upf_type"
|
||||||
:placeholder="t('common.selectPlease')"
|
:placeholder="t('common.selectPlease')"
|
||||||
>
|
>
|
||||||
<a-select-option value="StandardUPF">
|
<a-select-option value="StandardUPF">
|
||||||
@@ -285,7 +242,7 @@ onMounted(() => {});
|
|||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item label="UE_POOL" name="external.ue_pool">
|
<a-form-item label="UE_POOL" name="external.ue_pool">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.ue_pool"
|
v-model:value="fromState.external.ue_pool"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -305,7 +262,7 @@ onMounted(() => {});
|
|||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item label="N3_IP" name="external.upfn3_ip">
|
<a-form-item label="N3_IP" name="external.upfn3_ip">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.upfn3_ip"
|
v-model:value="fromState.external.upfn3_ip"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -320,7 +277,7 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="N3_GW" name="external.upfn3_gw">
|
<a-form-item label="N3_GW" name="external.upfn3_gw">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.upfn3_gw"
|
v-model:value="fromState.external.upfn3_gw"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -338,11 +295,11 @@ onMounted(() => {});
|
|||||||
:lg="12"
|
:lg="12"
|
||||||
:md="12"
|
:md="12"
|
||||||
:xs="24"
|
:xs="24"
|
||||||
v-if="state.from.external.upf_type === 'StandardUPF'"
|
v-if="fromState.external.upf_type === 'StandardUPF'"
|
||||||
>
|
>
|
||||||
<a-form-item label="N3_PCI" name="external.upfn3_pci">
|
<a-form-item label="N3_PCI" name="external.upfn3_pci">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.upfn3_pci"
|
v-model:value="fromState.external.upfn3_pci"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -359,7 +316,7 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="N3_MAC" name="external.upfn3_mac">
|
<a-form-item label="N3_MAC" name="external.upfn3_mac">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.upfn3_mac"
|
v-model:value="fromState.external.upfn3_mac"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -376,12 +333,12 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<template v-if="state.from.external.upf_type === 'StandardUPF'">
|
<template v-if="fromState.external.upf_type === 'StandardUPF'">
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item label="N6_IP" name="external.upfn6_ip">
|
<a-form-item label="N6_IP" name="external.upfn6_ip">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.upfn6_ip"
|
v-model:value="fromState.external.upfn6_ip"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -390,7 +347,7 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="N6_GW" name="external.upfn6_gw">
|
<a-form-item label="N6_GW" name="external.upfn6_gw">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.upfn6_gw"
|
v-model:value="fromState.external.upfn6_gw"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -401,7 +358,7 @@ onMounted(() => {});
|
|||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item label="N6_PCI" name="external.upfn6_pci">
|
<a-form-item label="N6_PCI" name="external.upfn6_pci">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.upfn6_pci"
|
v-model:value="fromState.external.upfn6_pci"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -410,7 +367,7 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="N6_MAC" name="external.upfn6_mac">
|
<a-form-item label="N6_MAC" name="external.upfn6_mac">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.upfn6_mac"
|
v-model:value="fromState.external.upfn6_mac"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -423,13 +380,13 @@ onMounted(() => {});
|
|||||||
</a-col>
|
</a-col>
|
||||||
|
|
||||||
<a-col :lg="8" :md="8" :xs="24">
|
<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-divider orientation="left">IMS</a-divider>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="24" :md="24" :xs="24">
|
<a-col :lg="24" :md="24" :xs="24">
|
||||||
<a-form-item label="SIP_IP" name="external.ims_sip_ip">
|
<a-form-item label="SIP_IP" name="external.ims_sip_ip">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.ims_sip_ip"
|
v-model:value="fromState.external.ims_sip_ip"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -446,13 +403,13 @@ onMounted(() => {});
|
|||||||
</a-row>
|
</a-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="state.hasNE.mme">
|
<template v-if="props.ne.mme">
|
||||||
<a-divider orientation="left">MME</a-divider>
|
<a-divider orientation="left">MME</a-divider>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="24" :md="24" :xs="24">
|
<a-col :lg="24" :md="24" :xs="24">
|
||||||
<a-form-item label="S1_IP" name="external.mmes1_ip">
|
<a-form-item label="S1_IP" name="external.mmes1_ip">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.mmes1_ip"
|
v-model:value="fromState.external.mmes1_ip"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -471,7 +428,7 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="S10_IP" name="external.mmes10_ip">
|
<a-form-item label="S10_IP" name="external.mmes10_ip">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.mmes10_ip"
|
v-model:value="fromState.external.mmes10_ip"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -486,7 +443,7 @@ onMounted(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="S11_IP" name="external.mmes11_ip">
|
<a-form-item label="S11_IP" name="external.mmes11_ip">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="state.from.external.mmes11_ip"
|
v-model:value="fromState.external.mmes11_ip"
|
||||||
allow-clear
|
allow-clear
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
:maxlength="50"
|
:maxlength="50"
|
||||||
@@ -231,6 +231,17 @@ function fnHostAuthorized() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**返回上一步 */
|
||||||
|
function fnStepPrev() {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t('common.tipTitle'),
|
||||||
|
content: t('views.ne.neQuickSetup.stepPrevTip'),
|
||||||
|
onOk() {
|
||||||
|
fnToStepName('Para5G');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**下一步操作 */
|
/**下一步操作 */
|
||||||
function fnStepNext() {
|
function fnStepNext() {
|
||||||
if (!state.stepNext) return;
|
if (!state.stepNext) return;
|
||||||
@@ -254,6 +265,7 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div class="ne">
|
||||||
<a-descriptions :column="{ lg: 3, md: 2, sm: 2, xs: 1 }" bordered>
|
<a-descriptions :column="{ lg: 3, md: 2, sm: 2, xs: 1 }" bordered>
|
||||||
<a-descriptions-item :label="t('views.ne.neQuickSetup.addr')" :span="3">
|
<a-descriptions-item :label="t('views.ne.neQuickSetup.addr')" :span="3">
|
||||||
{{ state.info.addr }}
|
{{ state.info.addr }}
|
||||||
@@ -299,14 +311,16 @@ onMounted(() => {
|
|||||||
{{ t('views.ne.neQuickSetup.sshLink') }}
|
{{ t('views.ne.neQuickSetup.sshLink') }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
<a-descriptions-item :span="2">
|
</a-descriptions>
|
||||||
|
|
||||||
<a-form
|
<a-form
|
||||||
name="checkStateFrom"
|
name="checkStateFrom"
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
:label-col="{ span: 6 }"
|
:label-col="{ span: 6 }"
|
||||||
:label-wrap="false"
|
:label-wrap="true"
|
||||||
|
style="margin-top: 20px; width: 68%"
|
||||||
>
|
>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="8">
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.ne.neHost.addr')"
|
:label="t('views.ne.neHost.addr')"
|
||||||
@@ -415,7 +429,7 @@ onMounted(() => {
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<a-form-item :wrapper-col="{ span: 10, offset: 3 }">
|
<a-form-item :wrapper-col="{ span: 8, offset: 3 }">
|
||||||
<a-space direction="horizontal" :size="18">
|
<a-space direction="horizontal" :size="18">
|
||||||
<a-button
|
<a-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -426,13 +440,6 @@ onMounted(() => {
|
|||||||
>
|
>
|
||||||
{{ t('views.ne.neHost.test') }}
|
{{ t('views.ne.neHost.test') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
@click="fnStepNext()"
|
|
||||||
:disabled="!state.stepNext"
|
|
||||||
>
|
|
||||||
{{ t('views.ne.neQuickSetup.stepNext') }}
|
|
||||||
</a-button>
|
|
||||||
|
|
||||||
<a-button
|
<a-button
|
||||||
type="dashed"
|
type="dashed"
|
||||||
@@ -453,8 +460,37 @@ onMounted(() => {
|
|||||||
</a-space>
|
</a-space>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
<div class="ne-oper">
|
||||||
|
<a-space direction="horizontal" :size="18">
|
||||||
|
<a-button @click="fnStepPrev()">
|
||||||
|
{{ t('views.ne.neQuickSetup.stepPrev') }}
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="fnStepNext()"
|
||||||
|
:disabled="!state.stepNext"
|
||||||
|
>
|
||||||
|
{{ t('views.ne.neQuickSetup.stepNext') }}
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped>
|
||||||
|
.ne {
|
||||||
|
min-height: 400px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
& .ant-form {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-oper {
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
import { reactive, toRaw } from 'vue';
|
||||||
|
import { getPara5GFilee, savePara5GFile, updateNeInfo } from '@/api/ne/neInfo';
|
||||||
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
|
|
||||||
|
/**对象信息信息状态类型 */
|
||||||
|
type StateType = {
|
||||||
|
/**表单数据 */
|
||||||
|
from: Record<string, any>;
|
||||||
|
/**OMC信息,需修改当前的IP */
|
||||||
|
omcInfo: Record<string, any>;
|
||||||
|
/**根据网元显示配置项 */
|
||||||
|
hasNE: {
|
||||||
|
amf: boolean;
|
||||||
|
upf: boolean;
|
||||||
|
ims: boolean;
|
||||||
|
mme: boolean;
|
||||||
|
};
|
||||||
|
/**确定按钮 loading */
|
||||||
|
confirmLoading: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function usePara5G() {
|
||||||
|
/**对象信息状态 */
|
||||||
|
let state: StateType = reactive({
|
||||||
|
from: {},
|
||||||
|
omcInfo: {},
|
||||||
|
hasNE: {
|
||||||
|
amf: false,
|
||||||
|
upf: false,
|
||||||
|
ims: false,
|
||||||
|
mme: false,
|
||||||
|
},
|
||||||
|
confirmLoading: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**载入数据*/
|
||||||
|
function fnReloadData() {
|
||||||
|
state.confirmLoading = true;
|
||||||
|
Promise.all([getPara5GFilee(), useNeInfoStore().fnRefreshNelist()]).then(
|
||||||
|
resArr => {
|
||||||
|
// 已保存的配置
|
||||||
|
if (resArr[0].code === RESULT_CODE_SUCCESS) {
|
||||||
|
Object.assign(state.from, resArr[0].data);
|
||||||
|
}
|
||||||
|
// 填充固定网元类型的ip
|
||||||
|
if (
|
||||||
|
resArr[1].code === RESULT_CODE_SUCCESS &&
|
||||||
|
Array.isArray(resArr[1].data)
|
||||||
|
) {
|
||||||
|
for (const item of resArr[1].data) {
|
||||||
|
// 公共配置文件sbi的各网元IP
|
||||||
|
switch (item.neType) {
|
||||||
|
case 'OMC':
|
||||||
|
state.from.sbi.omc_ip = item.ip;
|
||||||
|
Object.assign(state.omcInfo, item); // 主动改OMC_IP
|
||||||
|
break;
|
||||||
|
case 'IMS':
|
||||||
|
state.from.sbi.ims_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.db_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;
|
||||||
|
case 'SMSC':
|
||||||
|
state.from.sbi.smsc_ip = item.ip;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.confirmLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**保存数据 */
|
||||||
|
async function fnSaveData() {
|
||||||
|
if (state.confirmLoading) return;
|
||||||
|
state.confirmLoading = true;
|
||||||
|
const res = await savePara5GFile({
|
||||||
|
content: toRaw(state.from),
|
||||||
|
syncNe: [],
|
||||||
|
});
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
// 更新omc_ip
|
||||||
|
if (state.omcInfo.id) {
|
||||||
|
state.omcInfo.ip = state.from.sbi.omc_ip;
|
||||||
|
await updateNeInfo(toRaw(state.omcInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.confirmLoading = false;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
fnReloadData,
|
||||||
|
fnSaveData,
|
||||||
|
};
|
||||||
|
}
|
||||||
Loaded 100 of 149 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user