Compare commits
307 Commits
r2.2405.4-
...
2.2410.3-2
| 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 | ||
|
|
6102972373 | ||
|
|
d095531952 | ||
|
|
d49dc9ebfd | ||
|
|
43a99e9328 | ||
|
|
d333221620 | ||
|
|
481734cfe1 | ||
|
|
1fa8601675 | ||
|
|
c1aabdbe42 | ||
|
|
953a36f142 | ||
|
|
c5f62e8d76 | ||
|
|
946139facb | ||
|
|
95931b2b6e | ||
|
|
e31c85835d | ||
|
|
847bae4c77 | ||
|
|
e69f43a0c2 | ||
|
|
d96e1ad259 | ||
|
|
3829d339e7 | ||
|
|
cd4073bec3 | ||
|
|
e67126c57a | ||
|
|
2f651b5d1f | ||
|
|
525854604f | ||
|
|
d42a8701da | ||
|
|
2b680d6d20 | ||
|
|
de79760a0e | ||
|
|
a5b5269b91 | ||
|
|
8a2d0ccfa1 | ||
|
|
650b02dc30 | ||
|
|
b42d8cb370 | ||
|
|
a213be0d64 | ||
|
|
2a2b441e09 | ||
|
|
84bdb44286 | ||
|
|
06b6175a76 | ||
|
|
11b790e140 | ||
|
|
296a9ba02b | ||
|
|
1801a46396 | ||
|
|
f6644a0d97 | ||
|
|
57f575aa84 | ||
|
|
68cbbe7133 | ||
|
|
c11d814312 | ||
|
|
e1548d2c98 | ||
|
|
1ec374eb26 | ||
|
|
0955a79965 | ||
|
|
374a9bde7e | ||
|
|
639a4f0b1f | ||
|
|
d1b9d7b9ba | ||
|
|
3298203f60 | ||
|
|
8f3cce52c0 | ||
|
|
ce06a88e89 | ||
|
|
749a04972d | ||
|
|
a311f0a09b | ||
|
|
c74d311537 | ||
|
|
1492f18791 | ||
|
|
cbc81643a5 | ||
|
|
c18b557c97 | ||
|
|
b6bd9bc3d5 | ||
|
|
199607e322 | ||
|
|
ee10119d77 | ||
|
|
1b1a56e49b | ||
|
|
afdc188e17 | ||
|
|
5de7d0a73f | ||
|
|
8f73d80a42 | ||
|
|
5a85f245b0 | ||
|
|
ff600c49f6 | ||
|
|
4c7e99fdd7 | ||
|
|
a6037a9737 | ||
|
|
1d55c092b1 | ||
|
|
8bdfd7ea28 | ||
|
|
39ad75fbd3 | ||
|
|
7ef775209d | ||
|
|
a8e0f36562 | ||
|
|
be50fc9c5c | ||
|
|
375f236e32 | ||
|
|
c9eb0240d8 | ||
|
|
b67d591d0a | ||
|
|
7275a87fba | ||
|
|
c103222b65 | ||
|
|
5133d09ec2 | ||
|
|
d88cec34df | ||
|
|
eadd4709ee | ||
|
|
04cbdc6b11 | ||
|
|
233496e184 | ||
|
|
919f8ef2a5 | ||
|
|
8f8d056f45 | ||
|
|
8fcd7974e4 | ||
|
|
cb7fc418a5 | ||
|
|
e6d4a898a8 | ||
|
|
be4fc896d7 | ||
|
|
e5a5ef6f96 | ||
|
|
530662bf5d | ||
|
|
2e7514d3ca | ||
|
|
1db61a5d4e |
@@ -5,13 +5,13 @@ VITE_HISTORY_HASH = false
|
||||
VITE_HISTORY_BASE_URL = "/"
|
||||
|
||||
# 应用名称
|
||||
VITE_APP_NAME = "Core Network EMS"
|
||||
VITE_APP_NAME = "Core Network OMC"
|
||||
|
||||
# 应用标识
|
||||
VITE_APP_CODE = "CN EMS"
|
||||
VITE_APP_CODE = "OMC"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.240530.1"
|
||||
VITE_APP_VERSION = "2.241018"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
@@ -5,13 +5,13 @@ VITE_HISTORY_HASH = true
|
||||
VITE_HISTORY_BASE_URL = "/"
|
||||
|
||||
# 应用名称
|
||||
VITE_APP_NAME = "Core Network EMS"
|
||||
VITE_APP_NAME = "Core Network OMC"
|
||||
|
||||
# 应用标识
|
||||
VITE_APP_CODE = "CN EMS"
|
||||
VITE_APP_CODE = "OMC"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.240530.1"
|
||||
VITE_APP_VERSION = "2.241018"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
29
README.md
29
README.md
@@ -2,21 +2,14 @@
|
||||
|
||||
## 简介
|
||||
|
||||
- 系统布局使用 [@ant-design-vue/pro-layout](https://github.com/vueComponent/pro-components)
|
||||
- 图标来源 [@ant-design/icons-vue](https://ant.design/components/icon)
|
||||
- 菜单图标使用自定义 iconfont `font_8d5l8fzk5b87iudi.js`图标文件
|
||||
|
||||
## 测试环境
|
||||
|
||||
```text
|
||||
Jenkins: http://192.168.2.166:3185/
|
||||
Nginx: http://192.168.2.166:3188/#/index
|
||||
后端暴露端口: http://192.168.2.166:3186 \ http://192.168.2.166:3187
|
||||
|
||||
|
||||
新网管:192.168.5.13
|
||||
旧网管:192.168.5.14
|
||||
登录账户:manager/manager
|
||||
后端暴露端口: http://192.168.2.166:33030
|
||||
```
|
||||
|
||||
## 程序命令
|
||||
@@ -60,23 +53,5 @@ export NODE_OPTIONS=--max-old-space-size=50000
|
||||
|
||||
```text
|
||||
https://192.168.5.23/
|
||||
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
|
||||
```
|
||||
|
||||
```ssh
|
||||
# https://blog.csdn.net/m0_54706625/article/details/129721121
|
||||
sudo chmod 700 -/.ssh/
|
||||
sudo chmod 700 /home/mask/.ssh #这个尤其容易忽视掉,我就是从这个坑里爬出来。有木有很高兴呀!
|
||||
sudo chmod 600 ~/.ssh/authorized_keys
|
||||
admin / admin
|
||||
```
|
||||
|
||||
28
package.json
28
package.json
@@ -14,44 +14,48 @@
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@antv/g6": "~4.8.24",
|
||||
"@codemirror/lang-javascript": "^6.2.1",
|
||||
"@codemirror/lang-javascript": "^6.2.2",
|
||||
"@codemirror/lang-yaml": "^6.1.1",
|
||||
"@codemirror/merge": "^6.6.1",
|
||||
"@codemirror/merge": "^6.6.3",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@tato30/vue-pdf": "^1.9.6",
|
||||
"@vueuse/core": "~10.9.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"@tato30/vue-pdf": "^1.10.0",
|
||||
"@vueuse/core": "~10.10.1",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"ant-design-vue": "^3.2.20",
|
||||
"antdv-pro-layout": "^3.2.6",
|
||||
"antdv-pro-layout": "~3.3.5",
|
||||
"antdv-pro-modal": "^3.1.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.11",
|
||||
"echarts": "~5.5.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"intl-tel-input": "~22.0.2",
|
||||
"grid-layout-plus": "^1.0.5",
|
||||
"intl-tel-input": "^23.8.1",
|
||||
"js-base64": "^3.7.7",
|
||||
"js-cookie": "^3.0.5",
|
||||
"localforage": "^1.10.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"p-queue": "^8.0.1",
|
||||
"p-queue": "~8.0.1",
|
||||
"pinia": "^2.1.7",
|
||||
"vue": "~3.3.13",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-router": "^4.3.2",
|
||||
"vue-router": "^4.4.0",
|
||||
"vue3-smooth-dnd": "^0.0.6",
|
||||
"xlsx": "~0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"less": "^4.2.0",
|
||||
"typescript": "~5.4.5",
|
||||
"unplugin-vue-components": "~0.26.0",
|
||||
"vite": "~5.2.10",
|
||||
"vite": "~5.3.1",
|
||||
"vite-plugin-compression": "~0.5.1",
|
||||
"vue-tsc": "~1.8.27"
|
||||
"vue-tsc": "~2.0.22"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
*/
|
||||
(function () {
|
||||
// host = ip:port
|
||||
const host = '192.168.8.100:33030';
|
||||
|
||||
// const host = '192.168.8.100:33030';
|
||||
const host = `${window.location.hostname}:33030`;
|
||||
|
||||
// Service Address
|
||||
sessionStorage.setItem('baseUrl', `http://${host}`);
|
||||
// websocket Address
|
||||
|
||||
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
BIN
public/wiregasm/test_ethernet.pcap
Normal file
BIN
public/wiregasm/test_ethernet.pcap
Normal file
Binary file not shown.
178925
public/wiregasm/wiregasm.data
Normal file
178925
public/wiregasm/wiregasm.data
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/wiregasm/wiregasm.wasm
Normal file
BIN
public/wiregasm/wiregasm.wasm
Normal file
Binary file not shown.
9768
public/wiregasm/wiregasm_load.js
Normal file
9768
public/wiregasm/wiregasm_load.js
Normal file
File diff suppressed because one or more lines are too long
166
public/wiregasm/wiregasm_new.js
Normal file
166
public/wiregasm/wiregasm_new.js
Normal file
@@ -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;
|
||||
}
|
||||
162
public/wiregasm/worker.js
Normal file
162
public/wiregasm/worker.js
Normal file
@@ -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' });
|
||||
}
|
||||
};
|
||||
11
src/App.vue
11
src/App.vue
@@ -11,8 +11,8 @@ import useAppStore from '@/store/modules/app';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { t, currentLocale } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
dayjs.extend(advancedFormat)
|
||||
|
||||
dayjs.extend(advancedFormat);
|
||||
dayjs.locale('zh-cn'); // 默认中文
|
||||
usePrimaryColor(); // 载入用户自定义主题色
|
||||
|
||||
@@ -52,10 +52,11 @@ console.info(
|
||||
</ConfigProvider>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
<style lang="css">
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body .ant-pro-basicLayout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -63,10 +64,6 @@ body .ant-pro-basicLayout {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.ant-pro-sider {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.slide-left-enter-active,
|
||||
.slide-left-leave-active,
|
||||
.slide-right-enter-active,
|
||||
|
||||
@@ -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_SUCCESS,
|
||||
RESULT_MSG_ERROR,
|
||||
RESULT_MSG_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
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 top_display,top_tag,method FROM param_config WHERE ne_type = '${neType}'`,
|
||||
},
|
||||
});
|
||||
// 解析数据
|
||||
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用户策略输入框
|
||||
* @param neType 网元类型
|
||||
* @param topTag
|
||||
* @param neId
|
||||
* @returns object { wrRule, dataArr }
|
||||
* @returns object {pccRules,sessionRules,qosTemplate,headerEnrichTemplate,serviceAreaRestriction}
|
||||
*/
|
||||
export async function getPCCRule(neId: any) {
|
||||
return await Promise.allSettled([
|
||||
// 获取参数规则
|
||||
request({
|
||||
url: `/api/rest/systemManagement/v1/elementType/pcf/objectType/config/pccRules`,
|
||||
method: 'get',
|
||||
params: {
|
||||
ne_id: neId,
|
||||
},
|
||||
timeout: 1_000,
|
||||
}),
|
||||
// 获取对应信息
|
||||
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();
|
||||
const paramNameArr = [
|
||||
'pccRules',
|
||||
'sessionRules',
|
||||
'qosTemplate',
|
||||
'headerEnrichTemplate',
|
||||
'serviceAreaRestriction',
|
||||
];
|
||||
const reqArr = [];
|
||||
for (const paramName of paramNameArr) {
|
||||
reqArr.push(
|
||||
request({
|
||||
url: `/ne/config/data`,
|
||||
params: { neType: 'PCF', neId, paramName },
|
||||
method: 'get',
|
||||
})
|
||||
);
|
||||
}
|
||||
return await Promise.allSettled(reqArr).then(resArr => {
|
||||
// 规则数据
|
||||
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;
|
||||
itemData.forEach((item: any) => {
|
||||
pccJson.set(item.ruleId, { 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 });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
const obj: any = {};
|
||||
resArr.forEach((item, i: number) => {
|
||||
if (item.status === 'fulfilled') {
|
||||
const res = item.value;
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
const key = paramNameArr[i];
|
||||
obj[key] = res.data.map((item: any) => {
|
||||
if ('qosTemplate' === key) {
|
||||
return { value: item.qosId, label: item.qosId };
|
||||
}
|
||||
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[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 };
|
||||
});
|
||||
return obj;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
url: `/api/rest/faultManagement/v1/elementType/all/objectType/alarms`,
|
||||
method: 'get',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
* @param query 查询参数
|
||||
@@ -28,8 +26,6 @@ export async function listAct(query: Record<string, any>) {
|
||||
querySQL += ` and pv_flag = '${query.pvFlag}' `;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (query.neId) {
|
||||
querySQL += ` and ne_id like '%${query.neId}%' `;
|
||||
}
|
||||
@@ -69,7 +65,6 @@ export async function listAct(query: Record<string, any>) {
|
||||
msg: result.msg,
|
||||
};
|
||||
result.data.data.forEach((item: any) => {
|
||||
console.log(item)
|
||||
const itemData = item['alarm_event'];
|
||||
if (Array.isArray(itemData)) {
|
||||
if (itemData.length === 1 && itemData[0]['total'] >= 0) {
|
||||
@@ -84,12 +79,6 @@ export async function listAct(query: Record<string, any>) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 事件告警导出
|
||||
* @param query 查询参数
|
||||
@@ -133,7 +122,3 @@ export async function exportAll(query: Record<string, any>) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
53
src/api/logManage/exportFile.ts
Normal file
53
src/api/logManage/exportFile.ts
Normal file
@@ -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',
|
||||
data: data,
|
||||
whithToken: false,
|
||||
crypto: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,6 +22,7 @@ export function register(data: Record<string, any>) {
|
||||
method: 'post',
|
||||
data: data,
|
||||
whithToken: false,
|
||||
crypto: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,5 +6,6 @@ export function getLoad(query: Record<string, any>) {
|
||||
url: '/monitor/load',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ export function getSystemInfo() {
|
||||
return request({
|
||||
url: '/monitor/system-info',
|
||||
method: 'get',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
66
src/api/ne/neConfig.ts
Normal file
66
src/api/ne/neConfig.ts
Normal file
@@ -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,
|
||||
});
|
||||
}
|
||||
83
src/api/ne/neConfigBackup.ts
Normal file
83
src/api/ne/neConfigBackup.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 网元配置文件备份记录列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listNeConfigBackup(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/config/backup/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元配置文件备份记录修改
|
||||
* @param data 数据 { id, name, remark }
|
||||
* @returns object
|
||||
*/
|
||||
export function updateNeConfigBackup(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/config/backup',
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元配置文件备份记录下载
|
||||
* @param id 记录ID
|
||||
* @returns object
|
||||
*/
|
||||
export async function downNeConfigBackup(id: string) {
|
||||
return await request({
|
||||
url: '/ne/config/backup/download',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元配置文件备份记录删除
|
||||
* @param id 记录ID
|
||||
* @returns object
|
||||
*/
|
||||
export async function delNeConfigBackup(id: string) {
|
||||
return request({
|
||||
url: '/ne/config/backup',
|
||||
method: 'delete',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元配置文件备份导出
|
||||
* @param data 数据 { neType, neId }
|
||||
* @returns object
|
||||
*/
|
||||
export function exportNeConfigBackup(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/config/backup/export',
|
||||
method: 'post',
|
||||
data: data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元配置文件备份导入
|
||||
* @param data 数据 { neType, neId, type, path }
|
||||
* @returns object
|
||||
*/
|
||||
export function importNeConfigBackup(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/config/backup/import',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
@@ -36,6 +36,8 @@ export function addNeInfo(data: Record<string, any>) {
|
||||
url: `/ne/info`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
crypto: true,
|
||||
timeout: 30_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -49,6 +51,8 @@ export function updateNeInfo(data: Record<string, any>) {
|
||||
url: `/ne/info`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
crypto: true,
|
||||
timeout: 30_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -134,6 +138,7 @@ export function saveOAMFile(data: Record<string, any>) {
|
||||
url: `/ne/info/oamFile`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,5 +178,6 @@ export function serviceNeAction(data: Record<string, any>) {
|
||||
url: `/ne/action/service`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,10 +19,24 @@ export function listAMFDataUE(query: Record<string, any>) {
|
||||
* @returns object
|
||||
*/
|
||||
export function delAMFDataUE(ueIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/amf/ue/${ueIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
return request({
|
||||
url: `/neData/amf/ue/${ueIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* AMF-UE会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportAMFDataUE(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/amf/ue/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,10 +19,24 @@ export function listIMSDataCDR(query: Record<string, any>) {
|
||||
* @returns object
|
||||
*/
|
||||
export function delIMSDataCDR(cdrIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/ims/cdr/${cdrIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
return request({
|
||||
url: `/neData/ims/cdr/${cdrIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* IMS-CDR会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportIMSDataCDR(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/ims/cdr/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
42
src/api/neData/mme.ts
Normal file
42
src/api/neData/mme.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询MME-UE会话事件列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listMMEDataUE(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/mme/ue/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* MME-UE会话删除
|
||||
* @param id 信息ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delMMEDataUE(ueIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/mme/ue/${ueIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* MME-UE会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportMMEDataUE(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/mme/ue/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
55
src/api/neData/smf.ts
Normal file
55
src/api/neData/smf.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询SMF-CDR会话事件
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listSMFDataCDR(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/smf/cdr/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SMF-CDR会话删除
|
||||
* @param id 信息ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delSMFDataCDR(cdrIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/smf/cdr/${cdrIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SMF-CDR会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportSMFDataCDR(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/smf/cdr/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SMF-在线订阅用户列表信息
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listSMFSubscribers(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/smf/subscribers',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
42
src/api/neData/smsc.ts
Normal file
42
src/api/neData/smsc.ts
Normal file
@@ -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,
|
||||
});
|
||||
}
|
||||
141
src/api/neData/udm_auth.ts
Normal file
141
src/api/neData/udm_auth.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* UDM鉴权用户重载数据
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function resetUDMAuth(neId: string) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listUDMAuth(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/udm/auth/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户信息
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @returns object
|
||||
*/
|
||||
export function getUDMAuth(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${neId}/${imsi}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户新增
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${data.neId}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户批量新增
|
||||
* @param data 鉴权对象
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchAddUDMAuth(data: Record<string, any>, num: number) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${data.neId}/${num}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户修改
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${data.neId}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户删除
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @returns object
|
||||
*/
|
||||
export function delUDMAuth(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${neId}/${imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户批量删除
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchDelUDMAuth(neId: string, imsi: string, num: number) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/${neId}/${imsi}/${num}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户导入
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户导出
|
||||
* @param data 数据参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/udm/auth/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
140
src/api/neData/udm_sub.ts
Normal file
140
src/api/neData/udm_sub.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* UDM签约用户重载数据
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function resetUDMSub(neId: string) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listUDMSub(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/udm/sub/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户信息
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @returns object
|
||||
*/
|
||||
export function getUDMSub(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${neId}/${imsi}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户新增
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addUDMSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${data.neId}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户批量新增
|
||||
* @param data 签约对象
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchAddUDMSub(data: Record<string, any>, num: number) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${data.neId}/${num}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户修改
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateUDMSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${data.neId}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户删除
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function delUDMSub(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${neId}/${imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户批量删除
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchDelUDMSub(neId: string, imsi: string, num: number) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/${neId}/${imsi}/${num}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户导出
|
||||
* @param data 数据参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportUDMSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/udm/sub/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户导入
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importUDMSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/neData/udm/sub/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 签约鉴权导出
|
||||
* @param query 查询参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportAuth(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/udm/auth/export',
|
||||
method: 'post',
|
||||
data: query,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入鉴权数据
|
||||
* @param neId 网元ID
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importAuthData(data: FormData) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询鉴权列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listAuth(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/udm/auth/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询重新更新加载全部
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function loadAuth(neId: string) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询鉴权详细
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function getAuth(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${neId}/${imsi}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${data.neId}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${data.neId}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function batchAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${data.neID}/${data.num}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function delAuth(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${neId}/${imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除鉴权
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function batchDelAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${data.neID}/${data.imsi}/${data.num}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -25,8 +25,10 @@ export async function listBase5G(query: Record<string, any>) {
|
||||
data.total = rows.length;
|
||||
data.rows = rows;
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
// data.rows =[{"address":"192.168.1.137:38412","id":"217","name":"attach-enb-100000-20","ueNum":0}]
|
||||
// data.rows = [{"address":"192.168.1.137:38412","id":"217","name":"attach-enb-100000-20","ueNum":0}]
|
||||
// data.rows = [{address: "192.168.8.223", id: 257, name: "SmallCell", ueNum: 0}]
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -52,9 +52,11 @@ export async function listUENumByIMS(neId: String) {
|
||||
method: 'get',
|
||||
});
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
return Object.assign(result, {
|
||||
data: result.data['ueNum'],
|
||||
});
|
||||
let num = result.data['ueNum'] || 0;
|
||||
if (num === 0) {
|
||||
num = result.data.data['ueNum'] || 0;
|
||||
}
|
||||
return Object.assign(result, { data: num });
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
@@ -21,46 +20,70 @@ export async function listUEInfoBySMF(query: Record<string, any>) {
|
||||
msg: result.msg,
|
||||
};
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
||||
const rows = parseObjLineToHump(result.data.data);
|
||||
data.total = rows.length;
|
||||
data.rows = rows;
|
||||
if (result.code === RESULT_CODE_SUCCESS && result.data) {
|
||||
if (Array.isArray(result.data.data)) {
|
||||
const rows = result.data.data;
|
||||
data.total = rows.length;
|
||||
data.rows = rows;
|
||||
} else {
|
||||
Object.assign(data, result.data);
|
||||
}
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
// data.code = RESULT_CODE_SUCCESS;
|
||||
// data.total = 2;
|
||||
// data.rows = [
|
||||
// {
|
||||
// imsi: 'imsi-460002082101038',
|
||||
// msisdn: 'msisdn-12307550000',
|
||||
// imsi: 'imsi-460000100000090',
|
||||
// msisdn: 'msisdn-12307550090',
|
||||
// pduSessionInfo: [
|
||||
// {
|
||||
// activeTime: '2024-05-08 11:08:22',
|
||||
// activeTime: '2024-06-19 14:35:26',
|
||||
// dnn: 'ims',
|
||||
// ipv4: '10.10.86.2',
|
||||
// ipv6: '',
|
||||
// pduSessionID: 5,
|
||||
// ranN3IP: '192.168.5.100',
|
||||
// sstSD: '1-000001',
|
||||
// tai: '46000-001124',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.14.201',
|
||||
// },
|
||||
// {
|
||||
// activeTime: '2024-05-08 11:08:23',
|
||||
// dnn: 'cmnet',
|
||||
// ipv4: '10.10.86.201',
|
||||
// ipv4: '10.10.48.8',
|
||||
// ipv6: '',
|
||||
// pduSessionID: 6,
|
||||
// ranN3IP: '192.168.5.100',
|
||||
// ranN3IP: '192.168.1.137',
|
||||
// sstSD: '1-000001',
|
||||
// tai: '46000-001124',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.14.201',
|
||||
// upfN3IP: '192.168.1.161',
|
||||
// },
|
||||
// {
|
||||
// activeTime: '2024-06-19 14:35:26',
|
||||
// dnn: 'cmnet',
|
||||
// ipv4: '10.10.48.9',
|
||||
// ipv6: '2001:4860:4860::/64',
|
||||
// pduSessionID: 7,
|
||||
// ranN3IP: '192.168.1.137',
|
||||
// sstSD: '1-000001',
|
||||
// tai: '46000-001124',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.1.161',
|
||||
// },
|
||||
// ],
|
||||
// ratType: 'NR',
|
||||
// },
|
||||
// {
|
||||
// imsi: 'imsi-460602072701180',
|
||||
// msisdn: 'msisdn-123460600080',
|
||||
// pduSessionInfo: [
|
||||
// {
|
||||
// activeTime: '2024-06-19 14:31:09',
|
||||
// dnn: 'cmnet',
|
||||
// ipv4: '10.10.48.4',
|
||||
// ipv6: '',
|
||||
// pduSessionID: 5,
|
||||
// ranN3IP: '192.168.8.223',
|
||||
// sstSD: '1-000001',
|
||||
// tai: '46060-0001',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.1.161',
|
||||
// },
|
||||
// ],
|
||||
// ratType: 'EUTRAN',
|
||||
// },
|
||||
// ];
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 签约列表导出
|
||||
* @param query 查询参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportSub(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/udm/sub/export',
|
||||
method: 'post',
|
||||
data: query,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入签约数据
|
||||
* @param neId 网元ID
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importSubData(data: FormData) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询重新更新加载全部
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function loadSub(neId: string) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询签约列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listSub(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/udm/sub/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询签约详细
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function getSub(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${neId}/${imsi}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改签约
|
||||
* @param data 签约对象
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function updateSub(neId: string, data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${neId}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增签约
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addSub(neID: string, data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${neID}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增新增签约
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function batchAddSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${data.neID}/${data.num}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除签约
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function delSub(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${neId}/${imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除签约
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function batchDelSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/udm/sub/${data.neID}/${data.imsi}/${data.num}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
19
src/api/perfManage/customData.ts
Normal file
19
src/api/perfManage/customData.ts
Normal file
@@ -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 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export async function listCustom(query: Record<string, any>) {
|
||||
let totalSQL = 'select count(*) as total from pm_custom_title where 1=1 ';
|
||||
let rowsSQL = 'select * from pm_custom_title where 1=1 ';
|
||||
// export async function listCustom(query: Record<string, any>) {
|
||||
// let totalSQL = 'select count(*) as total from pm_custom_title where 1=1 ';
|
||||
// let rowsSQL = 'select * from pm_custom_title where 1=1 ';
|
||||
|
||||
// 查询
|
||||
let querySQL = '';
|
||||
if (query.neType) {
|
||||
querySQL += ` and ne_type like '%${query.neType}%' `;
|
||||
}
|
||||
// // 查询
|
||||
// let querySQL = '';
|
||||
// if (query.neType) {
|
||||
// querySQL += ` and ne_type like '%${query.neType}%' `;
|
||||
// }
|
||||
|
||||
// 排序
|
||||
let sortSql = ' order by update_time ';
|
||||
if (query.sortOrder === 'asc') {
|
||||
sortSql += ' asc ';
|
||||
} else {
|
||||
sortSql += ' desc ';
|
||||
}
|
||||
// 分页
|
||||
const pageNum = (query.pageNum - 1) * query.pageSize;
|
||||
const limtSql = ` limit ${pageNum},${query.pageSize} `;
|
||||
// // 排序
|
||||
// let sortSql = ' order by update_time ';
|
||||
// if (query.sortOrder === 'asc') {
|
||||
// sortSql += ' asc ';
|
||||
// } else {
|
||||
// sortSql += ' desc ';
|
||||
// }
|
||||
// // 分页
|
||||
// const pageNum = (query.pageNum - 1) * 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({
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/pm_custom_title`,
|
||||
url: `/pm/kpiC/title/totalList`,
|
||||
method: 'get',
|
||||
params: {
|
||||
totalSQL: totalSQL + querySQL,
|
||||
rowsSQL: rowsSQL + querySQL + sortSql + limtSql,
|
||||
},
|
||||
params: query,
|
||||
});
|
||||
|
||||
// 解析数据
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -68,22 +83,10 @@ export async function listCustom(query: Record<string, any>) {
|
||||
* @returns object
|
||||
*/
|
||||
export async function getCustom(id: string | number) {
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/pm_custom_title`,
|
||||
return request({
|
||||
url: `/pm/kpiC/title/${id}`,
|
||||
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
|
||||
*/
|
||||
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({
|
||||
url: `/api/rest/databaseManagement/v1/omc_db/pm_custom_title`,
|
||||
url: `/pm/kpiC/title`,
|
||||
method: 'post',
|
||||
data: { 'data': [obj] },
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -116,20 +108,10 @@ export function addCustom(data: Record<string, any>) {
|
||||
* @returns object
|
||||
*/
|
||||
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({
|
||||
url: `/api/rest/databaseManagement/v1/omc_db/pm_custom_title?WHERE=id=${data.id}`,
|
||||
url: `/pm/kpiC/title/${data.id}`,
|
||||
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>) {
|
||||
return request({
|
||||
url: `/api/rest/databaseManagement/v1/omc_db/pm_custom_title?WHERE=id=${data.id}`,
|
||||
url: `/pm/kpiC/title/${data.id}`,
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
20
src/api/tool/iperf.ts
Normal file
20
src/api/tool/iperf.ts
Normal file
@@ -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,
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询文件列表列表
|
||||
* 查询网元端文件列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
@@ -14,7 +14,7 @@ export function listNeFiles(query: Record<string, any>) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 从网元端获取文件
|
||||
* 从网元到本地获取文件
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
@@ -27,3 +27,24 @@ export function getNeFile(query: Record<string, any>) {
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
10
src/api/tool/ping.ts
Normal file
10
src/api/tool/ping.ts
Normal file
@@ -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,
|
||||
});
|
||||
}
|
||||
64
src/api/trace/packet.ts
Normal file
64
src/api/trace/packet.ts
Normal file
@@ -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 },
|
||||
});
|
||||
}
|
||||
@@ -3,26 +3,29 @@ import { request } from '@/plugins/http-fetch';
|
||||
// 网元抓包PACP 开始
|
||||
export function dumpStart(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tcpdump/start',
|
||||
url: '/trace/tcpdump/start',
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
// 网元抓包PACP 结束
|
||||
export function dumpStop(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tcpdump/stop',
|
||||
url: '/trace/tcpdump/stop',
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
// UPF标准版内部抓包
|
||||
export function traceUPF(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tcpdump/traceUPF',
|
||||
url: '/trace/tcpdump/upf',
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
104
src/api/trace/task.ts
Normal file
104
src/api/trace/task.ts
Normal file
@@ -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;
|
||||
}
|
||||
83
src/api/trace/taskHLR.ts
Normal file
83
src/api/trace/taskHLR.ts
Normal file
@@ -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;
|
||||
}
|
||||
11
src/assets/js/wiregasm_worker.ts
Normal file
11
src/assets/js/wiregasm_worker.ts
Normal file
@@ -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`;
|
||||
@@ -1,9 +1,10 @@
|
||||
<template>
|
||||
<a-modal
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:title="t('components.CronModal.title')"
|
||||
:visible="props.visible"
|
||||
:body-style="{ padding: '0 24px' }"
|
||||
:destroy-on-close="true"
|
||||
@cancel="fnCronModal(false)"
|
||||
@ok="fnCronModal(true)"
|
||||
>
|
||||
@@ -31,7 +32,7 @@
|
||||
v-model:value="cronStr"
|
||||
disabled
|
||||
/>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import CronSecond from './components/Second.vue';
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, PropType } from 'vue';
|
||||
const props = defineProps({
|
||||
/**数据 */
|
||||
options: {
|
||||
type: Array,
|
||||
type: Array as PropType<DictType[]>,
|
||||
},
|
||||
/**当前的值对应数据中的项字段 */
|
||||
valueField: {
|
||||
type: String,
|
||||
type: String as PropType<keyof DictType>,
|
||||
default: 'value',
|
||||
},
|
||||
/**当前的值 */
|
||||
@@ -16,7 +16,7 @@ const props = defineProps({
|
||||
default: '',
|
||||
},
|
||||
/**数据默认值,当前值不存在时 */
|
||||
valueOption: {
|
||||
valueDefault: {
|
||||
type: [Number, String],
|
||||
},
|
||||
});
|
||||
@@ -24,13 +24,13 @@ const props = defineProps({
|
||||
/**遍历找到对应值数据项 */
|
||||
const item = computed(() => {
|
||||
if (Array.isArray(props.options) && props.options.length > 0) {
|
||||
let option = (props.options as any[]).find(
|
||||
let option = props.options.find(
|
||||
item => `${item[props.valueField]}` === `${props.value}`
|
||||
);
|
||||
// 数据默认值
|
||||
if (props.valueOption != undefined && !option) {
|
||||
option = (props.options as any[]).find(
|
||||
item => `${item[props.valueField]}` === `${props.valueOption }`
|
||||
if (!option && props.valueDefault != undefined) {
|
||||
option = props.options.find(
|
||||
item => `${item[props.valueField]}` === `${props.valueDefault}`
|
||||
);
|
||||
}
|
||||
return option;
|
||||
@@ -41,14 +41,10 @@ const item = computed(() => {
|
||||
|
||||
<template>
|
||||
<template v-if="item">
|
||||
<a-tag
|
||||
v-if="item.elTagType"
|
||||
:class="item.elTagClass"
|
||||
:color="item.elTagType"
|
||||
>
|
||||
<a-tag v-if="item.tagType" :class="item.tagClass" :color="item.tagType">
|
||||
{{ item.label }}
|
||||
</a-tag>
|
||||
<span v-else :class="item.elTagClass">
|
||||
<span v-else :class="item.tagClass">
|
||||
{{ item.label }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, watchEffect, CSSProperties, computed } from 'vue';
|
||||
import { useDraggable } from '@vueuse/core';
|
||||
const emit = defineEmits(['update:visible', 'ok', 'cancel']);
|
||||
/**于a-modal保持一致 */
|
||||
const props = defineProps({
|
||||
/**是否弹出显示,必传 */
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
/**窗口标题 */
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**窗口宽度 */
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: '520px',
|
||||
},
|
||||
bodyStyle: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
keyboard: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
mask: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
maskClosable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
maskStyle: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
destroyOnClose: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
confirmLoading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
footer: {
|
||||
type: Object as any,
|
||||
},
|
||||
});
|
||||
|
||||
// 对标题进行监听
|
||||
const modalTitleRef = ref<HTMLElement | null>(null);
|
||||
const { x, y, isDragging } = useDraggable(modalTitleRef);
|
||||
|
||||
const startX = ref<number>(0);
|
||||
const startY = ref<number>(0);
|
||||
const startedDrag = ref(false);
|
||||
const transformX = ref(0);
|
||||
const transformY = ref(0);
|
||||
const preTransformX = ref(0);
|
||||
const preTransformY = ref(0);
|
||||
const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 });
|
||||
|
||||
watch([x, y], () => {
|
||||
if (!startedDrag.value) {
|
||||
startX.value = x.value;
|
||||
startY.value = y.value;
|
||||
const bodyRect = document.body.getBoundingClientRect();
|
||||
const titleRectEl = modalTitleRef.value;
|
||||
if (titleRectEl) {
|
||||
const titleRect = titleRectEl.getBoundingClientRect();
|
||||
dragRect.value.right = bodyRect.width - (titleRect.width + 24);
|
||||
dragRect.value.bottom = bodyRect.height - (titleRect.height + 16);
|
||||
}
|
||||
preTransformX.value = transformX.value;
|
||||
preTransformY.value = transformY.value;
|
||||
}
|
||||
startedDrag.value = true;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (!isDragging.value) {
|
||||
startedDrag.value = false;
|
||||
}
|
||||
if (startedDrag.value) {
|
||||
const dragRectX = Math.min(
|
||||
Math.max(dragRect.value.left + 24, x.value),
|
||||
dragRect.value.right
|
||||
);
|
||||
transformX.value = preTransformX.value + dragRectX - startX.value;
|
||||
|
||||
const dragRectY = Math.min(
|
||||
Math.max(dragRect.value.top + 16, y.value),
|
||||
dragRect.value.bottom
|
||||
);
|
||||
transformY.value = preTransformY.value + dragRectY - startY.value;
|
||||
}
|
||||
});
|
||||
|
||||
// 位移
|
||||
const transformStyle = computed<CSSProperties>(() => {
|
||||
return {
|
||||
transform: `translate(${transformX.value}px, ${transformY.value}px)`,
|
||||
};
|
||||
});
|
||||
|
||||
/**监听是否显示,位置还原 */
|
||||
watch(
|
||||
() => props.visible,
|
||||
val => {
|
||||
if (val) {
|
||||
transformX.value = 0;
|
||||
transformY.value = 0;
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
wrapClassName="draggable-modal"
|
||||
:width="props.width"
|
||||
:keyboard="props.keyboard"
|
||||
:mask="props.mask"
|
||||
:mask-closable="props.maskClosable"
|
||||
:visible="props.visible"
|
||||
:confirm-loading="props.confirmLoading"
|
||||
:body-style="props.bodyStyle"
|
||||
:mask-style="props.maskStyle"
|
||||
:destroy-on-close="props.destroyOnClose"
|
||||
:footer="props.footer"
|
||||
@ok="(e:any) => emit('ok', e)"
|
||||
@cancel="(e:any) => emit('cancel', e)"
|
||||
>
|
||||
<template #title>
|
||||
<div
|
||||
ref="modalTitleRef"
|
||||
class="draggable-modal-title"
|
||||
v-text="title"
|
||||
></div>
|
||||
</template>
|
||||
<template #modalRender="{ originVNode }">
|
||||
<div :style="transformStyle">
|
||||
<component :is="originVNode" />
|
||||
</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.draggable-modal {
|
||||
// 穿透选择文字
|
||||
// 给a-modal设置 get-container=".ant-pro-page-container"
|
||||
// 防止跳转显示
|
||||
// &.ant-modal-wrap {
|
||||
// pointer-events: none;
|
||||
// }
|
||||
&-title {
|
||||
width: 100%;
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
141
src/components/GlobalMask/index.vue
Normal file
141
src/components/GlobalMask/index.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, computed } from 'vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useThrottleFn } from '@vueuse/core';
|
||||
import { getConfigKey } from '@/api/system/config';
|
||||
const maskStore = useMaskStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**显示遮罩 */
|
||||
const isVisible = computed(() => !['none', 'lock'].includes(maskStore.type));
|
||||
|
||||
// 用户无操作一段时间后进行锁屏
|
||||
function idleTimeout(time: number, callback: Function) {
|
||||
if (time === 0) return;
|
||||
let timeoutId: any;
|
||||
let idleTime = 0;
|
||||
function resetIdleTime() {
|
||||
idleTime = 0;
|
||||
}
|
||||
// 监听用户活动事件
|
||||
document.addEventListener('mousemove', useThrottleFn(resetIdleTime, 1000));
|
||||
document.addEventListener('keydown', useThrottleFn(resetIdleTime, 1000));
|
||||
document.addEventListener('click', useThrottleFn(resetIdleTime, 1000));
|
||||
// 定时检查用户是否长时间无操作
|
||||
timeoutId = setInterval(() => {
|
||||
idleTime += 1000;
|
||||
if (idleTime >= time) {
|
||||
clearTimeout(timeoutId);
|
||||
callback();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/**组件实例挂载之后调用 */
|
||||
onMounted(() => {
|
||||
// 本地锁定类型设置;
|
||||
maskStore.handleMaskType(maskStore.type);
|
||||
getConfigKey('sys.lockTime')
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
maskStore.lockTimeout = +res.data;
|
||||
}
|
||||
maskStore.handleMaskType(maskStore.type);
|
||||
// 是锁屏的调整到页面
|
||||
if (maskStore.type === 'lock') {
|
||||
maskStore.handleMaskType('lock');
|
||||
router.push({ name: 'LockScreen', query: { redirect: route.path } });
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// 无操作x秒后跳转锁屏
|
||||
idleTimeout(maskStore.lockTimeout * 1000, () => {
|
||||
if (route.name === 'LockScreen') return;
|
||||
maskStore.handleMaskType('lock');
|
||||
router.push({ name: 'LockScreen', query: { redirect: route.path } });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**组件实例被卸载之后调用 */
|
||||
onUnmounted(() => {});
|
||||
</script>
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="isVisible"
|
||||
get-container="#app"
|
||||
:footer="null"
|
||||
:zIndex="1008"
|
||||
:closable="false"
|
||||
:keyboard="false"
|
||||
:centered="true"
|
||||
:maskClosable="false"
|
||||
:maskStyle="{
|
||||
backdropFilter: 'blur(10px)',
|
||||
WebkitBackdropFilter: 'blur(10px)',
|
||||
}"
|
||||
wrapClassName="lock-screen"
|
||||
:wrap-style="{
|
||||
background: 'rgba(0, 0, 0, 0.85)',
|
||||
}"
|
||||
>
|
||||
<!-- 锁屏-OMC重启升级 -->
|
||||
<div class="lock-screen_reload" v-if="maskStore.type === 'reload'">
|
||||
<LoadingOutlined style="font-size: 56px" />
|
||||
<div class="text">
|
||||
{{ t('components.LockScreen.backReload') }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{ t('components.LockScreen.backReload2') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 锁屏-OMC系统重置 -->
|
||||
<div class="lock-screen_reload" v-if="maskStore.type === 'reset'">
|
||||
<LoadingOutlined style="font-size: 56px" />
|
||||
<div class="text">
|
||||
{{ t('components.LockScreen.systemReset') }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{ t('components.LockScreen.systemReset2') }}
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.lock-screen_reload {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
|
||||
color: #fff;
|
||||
|
||||
& .text {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
& .desc {
|
||||
margin-top: 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.lock-screen {
|
||||
.ant-modal-content {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,230 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, toRaw, onMounted, onUnmounted } from 'vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { message } from 'ant-design-vue/lib';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
import { getConfigKey } from '@/api/system/config';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { computed } from 'vue';
|
||||
const lockedStore = useLockedStore();
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
|
||||
const password = ref('');
|
||||
/**设置定时器ID */
|
||||
let timeoutDuration = 10 * 60 * 1000; // 设置超时时间为10分钟,单位为毫秒
|
||||
let timeoutId: any = null;
|
||||
|
||||
// 超时锁屏
|
||||
function resetTimeout() {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
timeoutId = setTimeout(() => {
|
||||
lockedStore.fnLock('lock');
|
||||
}, timeoutDuration);
|
||||
}
|
||||
|
||||
/**解锁 */
|
||||
function handleUnlock() {
|
||||
let lockFrom: any = {};
|
||||
lockFrom.username = userStore.userName;
|
||||
lockFrom.password = password.value;
|
||||
userStore.fnLogin(toRaw(lockFrom)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('components.LockScreen.validSucc'), 3);
|
||||
password.value = '';
|
||||
lockedStore.fnLock('none');
|
||||
} else {
|
||||
message.error(t('components.LockScreen.validError'), 3);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**返回登录界面 */
|
||||
function backLogin() {
|
||||
lockedStore.fnLock('none');
|
||||
userStore.fnLogOut().finally(() => router.push({ name: 'Login' }));
|
||||
}
|
||||
|
||||
const isLocked = computed(() => lockedStore.type !== 'none');
|
||||
|
||||
onMounted(() => {
|
||||
// 本地锁定类型设置;
|
||||
lockedStore.fnLock(lockedStore.type);
|
||||
// getConfigKey('sys.lockTime')
|
||||
// .then(res => {
|
||||
// if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
// lockedStore.lockTimeout = res.data;
|
||||
// timeoutDuration = res.data * 1000;
|
||||
// }
|
||||
// // 本地锁定类型设置
|
||||
// lockedStore.fnLock(lockedStore.type);
|
||||
// })
|
||||
// .finally(() => {
|
||||
// if (timeoutDuration !== 0) {
|
||||
// resetTimeout();
|
||||
// // 监听用户的操作,重置超时时间
|
||||
// window.addEventListener('mousemove', resetTimeout);
|
||||
// window.addEventListener('keydown', resetTimeout);
|
||||
// }
|
||||
// });
|
||||
});
|
||||
|
||||
/**组件实例被卸载之后调用 */
|
||||
onUnmounted(() => {
|
||||
// if (timeoutId) {
|
||||
// clearTimeout(timeoutId);
|
||||
// }
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="isLocked"
|
||||
get-container="#app"
|
||||
:footer="null"
|
||||
:zIndex="1008"
|
||||
:closable="false"
|
||||
:keyboard="false"
|
||||
:centered="true"
|
||||
:maskClosable="false"
|
||||
:maskStyle="{
|
||||
backdropFilter: 'blur(10px)',
|
||||
WebkitBackdropFilter: 'blur(10px)',
|
||||
}"
|
||||
wrapClassName="lock-screen"
|
||||
:wrap-style="{
|
||||
background: 'rgba(0, 0, 0, 0.85)',
|
||||
}"
|
||||
>
|
||||
<!-- 锁屏-登录 -->
|
||||
<div class="lock-screen_login" v-if="lockedStore.type === 'lock'">
|
||||
<div class="lock-screen_login-user">
|
||||
<a-avatar
|
||||
shape="circle"
|
||||
:size="100"
|
||||
:src="userStore.getAvatar"
|
||||
:alt="userStore.userName"
|
||||
></a-avatar>
|
||||
<span class="nick">
|
||||
{{ userStore.nickName }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="lock-screen_login-from">
|
||||
<a-input-group compact>
|
||||
<a-input
|
||||
type="password"
|
||||
v-model:value="password"
|
||||
:placeholder="t('components.LockScreen.inputPlacePwd')"
|
||||
:maxlength="32"
|
||||
style="width: calc(100% - 50px)"
|
||||
@keyup.enter="handleUnlock"
|
||||
/>
|
||||
<a-button type="primary" @click="handleUnlock">
|
||||
<LoginOutlined />
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
<a-button type="text" class="logout" @click="backLogin">
|
||||
{{ t('components.LockScreen.backLogin') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 锁屏-OMC重启升级 -->
|
||||
<div class="lock-screen_reload" v-if="lockedStore.type === 'reload'">
|
||||
<LoadingOutlined style="font-size: 56px" />
|
||||
<div class="text">
|
||||
{{ t('components.LockScreen.backReload') }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{ t('components.LockScreen.backReload2') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 锁屏-OMC系统重置 -->
|
||||
<div class="lock-screen_reload" v-if="lockedStore.type === 'reset'">
|
||||
<LoadingOutlined style="font-size: 56px" />
|
||||
<div class="text">
|
||||
{{ t('components.LockScreen.systemReset') }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{ t('components.LockScreen.systemReset2') }}
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.lock-screen_login {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
|
||||
&-user {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.nick {
|
||||
font-size: 28px;
|
||||
max-width: 164px;
|
||||
white-space: nowrap;
|
||||
text-align: start;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&-from {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
width: 256px;
|
||||
margin-top: 30px;
|
||||
|
||||
.logout {
|
||||
margin-top: 8px;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
|
||||
&:hover {
|
||||
color: var(--ant-primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lock-screen_reload {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
|
||||
color: #fff;
|
||||
|
||||
& .text {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
& .desc {
|
||||
margin-top: 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.lock-screen {
|
||||
.ant-modal-content {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
242
src/components/TerminalSSHView/index.vue
Normal file
242
src/components/TerminalSSHView/index.vue
Normal file
@@ -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>
|
||||
@@ -22,7 +22,7 @@ const props = defineProps({
|
||||
/**窗口单行字符数 */
|
||||
cols: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
default: 120,
|
||||
},
|
||||
/**窗口行数 */
|
||||
rows: {
|
||||
@@ -119,7 +119,7 @@ function fnAutoCompleteKeydown(evt: any) {
|
||||
ws.send({
|
||||
requestId: `telnet_${props.hostId}`,
|
||||
type: 'telnet',
|
||||
data: `${cmdStr}\r\n'`,
|
||||
data: `${cmdStr}\r\n`,
|
||||
});
|
||||
terminalState.text = ' ';
|
||||
|
||||
@@ -155,6 +155,15 @@ function handleRanderXterm(container: HTMLElement | undefined) {
|
||||
// 自适应尺寸
|
||||
const fitAddon = new 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 实例
|
||||
var observer = new ResizeObserver(entries => {
|
||||
@@ -280,7 +289,7 @@ defineExpose({
|
||||
|
||||
<template>
|
||||
<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
|
||||
v-model:value="terminalState.text"
|
||||
:dropdown-match-select-width="500"
|
||||
|
||||
@@ -35,19 +35,22 @@ const props = defineProps({
|
||||
|
||||
/**弹框关闭事件 */
|
||||
function fnModalClose() {
|
||||
if(props.loading) return
|
||||
if (props.loading) return;
|
||||
emit('close');
|
||||
}
|
||||
|
||||
/**上传前检查或转换压缩 */
|
||||
function fnBeforeUpload(file: FileType) {
|
||||
if (props.loading) return false;
|
||||
// 检查文件大小
|
||||
if (props.size > 0) {
|
||||
// 检查文件大小
|
||||
if (props.size > 0) {
|
||||
const fileSize = file.size;
|
||||
const isLtM = fileSize / 1024 / 1024 < props.size;
|
||||
if (!isLtM) {
|
||||
message.error(`${t('components.UploadModal.allowFilter')} ${props.size}MB`, 3);
|
||||
message.error(
|
||||
`${t('components.UploadModal.allowFilter')} ${props.size}MB`,
|
||||
3
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -56,7 +59,10 @@ function fnBeforeUpload(file: FileType) {
|
||||
const fileName = file.name;
|
||||
const isAllowType = props.ext.some(v => fileName.endsWith(v));
|
||||
if (!isAllowType) {
|
||||
message.error(`${t('components.UploadModal.onlyAllow')} ${props.ext.join('、')}`, 3);
|
||||
message.error(
|
||||
`${t('components.UploadModal.onlyAllow')} ${props.ext.join('、')}`,
|
||||
3
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -65,19 +71,20 @@ function fnBeforeUpload(file: FileType) {
|
||||
|
||||
/**上传请求发出 */
|
||||
function fnUpload(up: UploadRequestOption) {
|
||||
emit('upload', up.file)
|
||||
emit('upload', up.file);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="500px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:confirm-loading="props.loading"
|
||||
:footer="null"
|
||||
:footer="false"
|
||||
@cancel="fnModalClose"
|
||||
>
|
||||
<a-space :size="8" direction="vertical" style="width: 100%">
|
||||
@@ -93,20 +100,26 @@ function fnUpload(up: UploadRequestOption) {
|
||||
<p class="ant-upload-drag-icon">
|
||||
<inbox-outlined></inbox-outlined>
|
||||
</p>
|
||||
<p class="ant-upload-text">{{t('components.UploadModal.uploadTip')}}</p>
|
||||
<p class="ant-upload-text">
|
||||
{{ t('components.UploadModal.uploadTip') }}
|
||||
</p>
|
||||
<p class="ant-upload-hint">
|
||||
<div v-if="props.size > 0">
|
||||
{{t('components.UploadModal.allowSize')}} {{ props.size }} MB
|
||||
</div>
|
||||
<div v-if="props.ext.length > 0">
|
||||
{{t('components.UploadModal.allowFormat')}} {{ props.ext.join('、') }}
|
||||
|
||||
</div>
|
||||
<template v-if="props.size > 0">
|
||||
<div>
|
||||
{{ t('components.UploadModal.allowSize') }} {{ props.size }} MB
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="props.ext.length > 0">
|
||||
<div>
|
||||
{{ t('components.UploadModal.allowFormat') }}
|
||||
{{ props.ext.join('、') }}
|
||||
</div>
|
||||
</template>
|
||||
</p>
|
||||
</a-upload-dragger>
|
||||
<slot></slot>
|
||||
</a-space>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
204
src/components/VirtualList/index.vue
Normal file
204
src/components/VirtualList/index.vue
Normal file
@@ -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>
|
||||
@@ -1,5 +1,5 @@
|
||||
/**管理员-系统指定角色KEY */
|
||||
export const ADMIN_ROLE_KEY = 'admin';
|
||||
/**系统管理员-系统指定角色KEY */
|
||||
export const ADMIN_ROLE_KEY = 'system';
|
||||
|
||||
/**管理员-系统指定权限 */
|
||||
/**系统管理员-系统指定权限 */
|
||||
export const ADMIN_PERMISSION = '*:*:*';
|
||||
|
||||
@@ -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_DATA_API_KEY = 'T9ox2DCzpLfJIPzkH9pKhsOTMOEMJcFv';
|
||||
|
||||
@@ -10,8 +10,11 @@ export const CACHE_LOCAL_PRIMARY_COLOR = 'cache:local:primaryColor';
|
||||
/**本地缓存-多语言 */
|
||||
export const CACHE_LOCAL_I18N = 'cache:local:i18n';
|
||||
|
||||
/**本地缓存-锁屏设置 */
|
||||
export const CACHE_LOCAL_LOCK = 'cache:local:Lock';
|
||||
/**本地缓存-遮罩设置 */
|
||||
export const CACHE_LOCAL_MASK = 'cache:local:mask';
|
||||
|
||||
/**本地缓存-锁屏密码 */
|
||||
export const CACHE_LOCAL_LOCK_PASSWD = 'cache:local:lock:passwd';
|
||||
|
||||
/**数据缓存表-表格排序 */
|
||||
export const CACHE_DB_TABLE_DND = 'tbl_dnd';
|
||||
|
||||
@@ -16,11 +16,12 @@ export const NE_TYPE_LIST = [
|
||||
'N3IWF',
|
||||
'MOCNGW',
|
||||
'SMSC',
|
||||
'CBC',
|
||||
];
|
||||
|
||||
/**
|
||||
* 网元拓展包列表,默认顺序
|
||||
* IMS-adb/rtproxy/mf
|
||||
* UDM-adb
|
||||
* IMS-adb/kvdb/rtproxy/mf
|
||||
* UDM-adb/kvdb
|
||||
*/
|
||||
export const NE_EXPAND_LIST = ['ADB', 'RTPROXY', 'MF'];
|
||||
export const NE_EXPAND_LIST = ['ADB', 'KVDB', 'RTPROXY', 'MF'];
|
||||
|
||||
@@ -1,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正常成功 */
|
||||
export const RESULT_CODE_SUCCESS = 1;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { onBeforeMount } from 'vue';
|
||||
import { ConfigProvider } from 'ant-design-vue/lib';
|
||||
import { ConfigProvider, message } from 'ant-design-vue/lib';
|
||||
import { CACHE_LOCAL_PRIMARY_COLOR } from '@/constants/cache-keys-constants';
|
||||
import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||
|
||||
@@ -8,6 +8,7 @@ import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||
*/
|
||||
export const usePrimaryColor = () => {
|
||||
onBeforeMount(() => {
|
||||
message.config({ top: '100px' }); // 全局配置消息距离顶部的位置
|
||||
changePrimaryColor(getLocalColor());
|
||||
});
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ export default {
|
||||
updateTime: 'Update Time',
|
||||
remark: 'Remark',
|
||||
description: 'Description',
|
||||
operate: 'Operation',
|
||||
operate: 'More Action',
|
||||
operateOk: 'Operation Successful!',
|
||||
operateErr: 'Operation Failed!',
|
||||
copyText: "Copy",
|
||||
@@ -88,7 +88,7 @@ export default {
|
||||
day33: "days",
|
||||
day4: "Designated day (optional)",
|
||||
day5: "Last day of the month",
|
||||
hour1: "Hourly",
|
||||
hour1: "Hourly",
|
||||
hour21: "Execute every",
|
||||
hour22: "hours, starting from the",
|
||||
hour23: "hour",
|
||||
@@ -130,7 +130,7 @@ export default {
|
||||
onlyAllow:'Only supports upload file formats',
|
||||
},
|
||||
LockScreen: {
|
||||
inputPlacePwd:'Please enter login password',
|
||||
inputPlacePwd:'Lock Screen Password',
|
||||
validSucc:'Validation Passed',
|
||||
validError:'Validation Failure',
|
||||
backLogin:'Logout to Relogin',
|
||||
@@ -149,6 +149,8 @@ export default {
|
||||
page403: 'No Access',
|
||||
page404: 'Match Page Not Found',
|
||||
helpDoc: 'System User Documentation',
|
||||
traceTaskHLR: 'Tracking Tasks HLR',
|
||||
lockScreen: 'Lock Screen',
|
||||
account: {
|
||||
index: "Personal Center",
|
||||
profile: "Personal Info",
|
||||
@@ -184,9 +186,11 @@ export default {
|
||||
helpDoc: 'Doc',
|
||||
},
|
||||
rightContent: {
|
||||
alarm: "Active Alarms",
|
||||
lock: "Lock Screen",
|
||||
lockTip: "Confirmed to perform a lock screen?",
|
||||
helpDoc: "System User Documentation",
|
||||
lockTip: "Confirmation of the lock screen?",
|
||||
lockPasswd: "Unlock Password",
|
||||
lockPasswdTip: "No password can be set",
|
||||
fullscreen: "Full Screen",
|
||||
logout: "Logout",
|
||||
profile: "Profile",
|
||||
@@ -236,7 +240,7 @@ export default {
|
||||
ttile: 'No access',
|
||||
subTitle:'Please do not perform illegal operations, you can go back to the main page or return to the',
|
||||
backHome: 'Back to Home',
|
||||
back: 'Back',
|
||||
back: 'Back',
|
||||
},
|
||||
err404: {
|
||||
ttile: 'Match page not found',
|
||||
@@ -293,10 +297,10 @@ export default {
|
||||
newPassword: "New Password",
|
||||
newPasswordTip: "Password contains at least upper and lower case letters, numbers, special symbols, and not less than 6 digits",
|
||||
newPassworddPleace: "Please enter a new password",
|
||||
confirmPassword: "Confirm new password",
|
||||
confirmPassword: "Confirm new password",
|
||||
confirmPasswordPleace: "Please confirm the new password",
|
||||
submit: "Submit changes",
|
||||
reset: "Reset",
|
||||
reset: "Reset",
|
||||
submitTip: "Are you sure you want to submit a password change?",
|
||||
submitOkTip: "Congratulations, {num} account password changed successfully!",
|
||||
submitOk: "Sign in again",
|
||||
@@ -522,7 +526,7 @@ export default {
|
||||
up:'Uplink',
|
||||
down:'Downlink'
|
||||
},
|
||||
upfFlowTotal:{
|
||||
upfFlowTotal:{
|
||||
title:'Traffic Summary',
|
||||
up:'Uplink',
|
||||
down:'Downlink'
|
||||
@@ -559,8 +563,6 @@ export default {
|
||||
realTimeDataStart: "Turn on real-time data",
|
||||
realTimeDataStop: "Turn off real-time data",
|
||||
cdrInfo: "CDR Info",
|
||||
neName: "NE name",
|
||||
rmUID: "UID",
|
||||
time: "Time",
|
||||
rowInfo: "Info",
|
||||
type: "Type",
|
||||
@@ -568,20 +570,30 @@ export default {
|
||||
caller: "Caller",
|
||||
called: "Called",
|
||||
result: "Result",
|
||||
resultOk: "Success",
|
||||
resultFail: "Fail",
|
||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||
exportTip: "Do you confirm to export the current query conditions of the CDR data? (Maximum 10,000 items can be exported.)",
|
||||
smfChargingID: 'Charging ID',
|
||||
smfSubscriptionIDData: 'Subscription ID Data',
|
||||
smfSubscriptionIDType: 'Subscription ID Type',
|
||||
smfDataVolumeUplink: 'Data Volume Uplink',
|
||||
smfDataVolumeDownlink: 'Data Volume Downlink',
|
||||
smfDataTotalVolume: 'Data Total Volume',
|
||||
smfDuration: 'Duration',
|
||||
smfInvocationTime: 'Invocation Time',
|
||||
},
|
||||
ue: {
|
||||
eventType: "Event Type",
|
||||
realTimeDataStart: "Turn on real-time data",
|
||||
realTimeDataStop: "Turn off real-time data",
|
||||
ueInfo: "UE Info",
|
||||
neName: "NE name",
|
||||
rmUID: "UID",
|
||||
time: "Time",
|
||||
rowInfo: "Info",
|
||||
result: "Result",
|
||||
resultOk: "Successes",
|
||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||
exportTip: "Do you confirm to export the event data of the current query condition? (Maximum 10,000 items can be exported.)",
|
||||
},
|
||||
},
|
||||
ne: {
|
||||
@@ -594,7 +606,7 @@ export default {
|
||||
neIdTip: 'Fill in the unique identifier of the network element binding',
|
||||
rmUid: 'Resource Unique ID',
|
||||
rmUidPlease: 'Please enter a resource unique ID',
|
||||
rmUidTip: "Tagging for data reporting of network element logs, alarms, metrics, etc.",
|
||||
rmUidTip: "Tagging for data reporting of network element logs, alarms, metrics, etc.",
|
||||
neName: 'NE Name',
|
||||
neNamePlease: 'Please enter the name of the network element',
|
||||
ipAddr: 'IP Addr',
|
||||
@@ -618,9 +630,9 @@ export default {
|
||||
log: 'Logs',
|
||||
},
|
||||
neInfo: {
|
||||
version: "Version",
|
||||
version: "Version",
|
||||
state: "State",
|
||||
serviceState: "Service Status",
|
||||
serviceState: "Service Status",
|
||||
info: 'Status Message',
|
||||
resourceInfo: 'Resource Situation',
|
||||
sysMem: "SYS Mem",
|
||||
@@ -649,19 +661,19 @@ export default {
|
||||
kpiEnable: 'Report',
|
||||
kpiTimer: 'Reporting Cycle',
|
||||
kpiTimerPlease: 'Please enter the reporting period (in seconds)',
|
||||
omcIP: 'OMC IP',
|
||||
},
|
||||
backConf: {
|
||||
export: 'Config Export',
|
||||
import: 'Config Import',
|
||||
title: 'Configuration File Import',
|
||||
importType: 'Source of File',
|
||||
title: 'Configuration File Import',
|
||||
importType: 'Source of File',
|
||||
server:'Server File',
|
||||
local:'Local File',
|
||||
localUpload:'Local Upload',
|
||||
exportTip:'Confirm that you want to export the network element configuration file?',
|
||||
exportMsg:'Exported successfully, please download from [Backup Management].',
|
||||
filePlease: "Please upload a file",
|
||||
fileNamePlease: 'Please select the server file',
|
||||
exportMsg:'Exporting Network Element Configuration Information to a File Succeeded',
|
||||
pathPlease: 'No Backup File Found',
|
||||
},
|
||||
},
|
||||
neHost: {
|
||||
@@ -673,11 +685,12 @@ export default {
|
||||
addrPlease: "Please fill in the host IP address correctly",
|
||||
port: "Port",
|
||||
portPlease: "Please fill in the host port number correctly",
|
||||
user: "Login User",
|
||||
userPlease: "Please fill in the host login user correctly",
|
||||
user: "User",
|
||||
userPlease: "Please fill in the host user correctly",
|
||||
database: "DataBase",
|
||||
authMode: "Auth Mode",
|
||||
password: "Password",
|
||||
passwordPlease: "Please fill in the host login password correctly",
|
||||
passwordPlease: "Please fill in the host password correctly",
|
||||
privateKey: "Private Key",
|
||||
privateKeyPlease: "Please fill in the private key characters correctly ~/.ssh/id_rsa",
|
||||
passPhrase: "Private Key Cipher",
|
||||
@@ -704,7 +717,7 @@ export default {
|
||||
uploadTitle: "Update Software",
|
||||
upload: "Upload",
|
||||
uploadNotFile: "No software files uploaded",
|
||||
uploadBatch: "Update Softwares",
|
||||
uploadBatch: "Batch Upload",
|
||||
uploadBatchMax: "Multiple packages can be uploaded, with up to {txt} selected at the same time.",
|
||||
uploadFileName: "Parses file names in the format of: amf-r2.240x.xx-xxx",
|
||||
name: "File Name",
|
||||
@@ -727,20 +740,21 @@ export default {
|
||||
upgrade: "Upgrade To New Version",
|
||||
upgradeTip: "Confirmed to upgrade to the new version?",
|
||||
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',
|
||||
rollbackTip: "Confirm switching to the previous version?",
|
||||
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",
|
||||
preVersion: "Previous Version",
|
||||
newVersion: "New Version",
|
||||
status: "Revision Status",
|
||||
upgradeBatch: "Batch Upgrade",
|
||||
upgradeBatchTip: "Do you perform new version upgrades on checked records?",
|
||||
upgradeNotNewVer: 'No new version found',
|
||||
upgradeDone: 'Update complete, service being reloaded',
|
||||
upgradeFail: 'The update failed, check if the service terminal environment is available!',
|
||||
upgradeNotNewVer: 'No new version found',
|
||||
upgradeOMCVer: 'Rejection of batch operation upgrades OMC',
|
||||
upgradeDone: 'Update complete, service being reloaded',
|
||||
upgradeFail: 'The update fails, please check whether the software file exists and whether the service terminal environment is available!',
|
||||
upgradeModal: 'Network Element Version Updates',
|
||||
},
|
||||
neLicense: {
|
||||
@@ -756,19 +770,42 @@ export default {
|
||||
licensePath: "License File",
|
||||
licensePathTip: "Please upload license file",
|
||||
upload: 'Upload',
|
||||
uploadBatch: "Upload License",
|
||||
uploadFile: "Upload License",
|
||||
uploadChangeOk: 'Network Element renewed license successfully and is being calibrated in the background!',
|
||||
uploadChangeFail: "Some network elements failed to update the license, please check whether the service terminal environment is available!",
|
||||
},
|
||||
neConfPara5G: {
|
||||
save: 'Save',
|
||||
reload: 'Reload',
|
||||
title: 'Save Info',
|
||||
sync: 'Sync to NE',
|
||||
syncNe: 'Select NE',
|
||||
syncNeDone: 'Synchronization to network element terminals complete',
|
||||
saveOk: 'Save Success!',
|
||||
neConfig: {
|
||||
treeTitle: "Navigation Configuration",
|
||||
treeSelectTip: "Select configuration item information in the left configuration navigation!",
|
||||
neType: 'NE Type',
|
||||
neTypePleace: "Please select the network element type",
|
||||
noConfigData: "No data on configuration items",
|
||||
updateValue: "[ {num} ] parameter value modified successfully.",
|
||||
updateValueErr: "Attribute value modification failure",
|
||||
updateItem: "Modify Index to {num}.",
|
||||
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: {
|
||||
reloadPara5G: 'Reload',
|
||||
stepPrev: 'Previous',
|
||||
stepPrevTip: 'Confirm that you want to abandon the current change and return to the previous step?',
|
||||
stepNext: 'Next',
|
||||
@@ -818,7 +855,7 @@ export default {
|
||||
},
|
||||
neUser: {
|
||||
auth: {
|
||||
authInfo:'Authentication Info',
|
||||
authInfo:' Authentication Info',
|
||||
neTypePlease: 'Query network element Object',
|
||||
neType: 'UDM Object',
|
||||
export: 'Export',
|
||||
@@ -841,12 +878,13 @@ export default {
|
||||
imsiTip3: 'MSIN = Mobile Subscriber Identification Number, consisting of 10 equal digits.',
|
||||
amfTip: 'Authentication management field, maximum parameter length is 4',
|
||||
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.',
|
||||
delSure:'Are you sure you want to delete the user with IMSI number: {imsi} ?',
|
||||
imsiConfirm:'The length of the IMSI must be 15',
|
||||
},
|
||||
sub: {
|
||||
subInfo:' Subscription Info',
|
||||
subInfo:' Subscription Info',
|
||||
neType: 'UDM Object',
|
||||
export: 'Export',
|
||||
exportConfirm: 'Are you sure to export all signed user data?',
|
||||
@@ -861,8 +899,8 @@ export default {
|
||||
checkDel: 'Check Delete',
|
||||
batchAddText: 'Batch Add',
|
||||
batchDelText: 'Batch Delete',
|
||||
enable:'Enable',
|
||||
disable:'Disable',
|
||||
enable:'Enabled',
|
||||
disable:'Disabled',
|
||||
startIMSI: 'Start IMSI',
|
||||
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
||||
imsiTip1: 'MCC=Mobile Country Code, consisting of three digits.',
|
||||
@@ -875,7 +913,8 @@ export default {
|
||||
micoTip: 'Signed MICO business flag bits',
|
||||
rfspTip:'RFSP index, in NG-RAN, the index of a specific RRM configuration, parameter between 0 and 127',
|
||||
ueTypeTip: 'Operator-defined subscriber UE Usage Type, integer, parameter between 0 and 127',
|
||||
epsFlagTip: 'Enable or disable 4G EPS service',
|
||||
cnFlag: 'Whether to enable 5G Core Network service',
|
||||
epsFlagTip: 'Whether to enable 4G EPS service',
|
||||
contextIdTip: 'To sign up for an APN Context ID, you must select it from the APN Context list.',
|
||||
apnContextTip: 'The list of APNs available to the phone, up to six, is defined in the HSS.',
|
||||
staticIpTip: 'Specify the static IP address to be used by the cell phone user to access the Internet, and "-" means dynamic IP address is used.',
|
||||
@@ -897,7 +936,7 @@ export default {
|
||||
batchAddText: 'Batch Add',
|
||||
batchDelText: 'Batch Delete',
|
||||
batchUpdateText: 'Batch Modify',
|
||||
batchNum: 'Number of batches',
|
||||
batchNum: 'Number of batches',
|
||||
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
||||
imsiTip1: 'MCC=Mobile Country Code, consisting of three digits.',
|
||||
imsiTip2: 'MNC = Mobile Network Number, consisting of two digits',
|
||||
@@ -916,16 +955,16 @@ export default {
|
||||
sarTip2:'(corresponding parameter setting -Service Area Restriction)',
|
||||
rfsfTip:'RAT Frequency Selection Priority',
|
||||
},
|
||||
base5G: {
|
||||
base5G: {
|
||||
neType: 'NE Object',
|
||||
},
|
||||
n3iwf: {
|
||||
neType: 'N3IWF Object',
|
||||
},
|
||||
ue: {
|
||||
ue: {
|
||||
neType: 'SMF Object',
|
||||
},
|
||||
ims: {
|
||||
ims: {
|
||||
neType: 'IMS Object',
|
||||
},
|
||||
nssf:{
|
||||
@@ -1014,6 +1053,7 @@ export default {
|
||||
},
|
||||
customTarget:{
|
||||
kpiId:' Custom Indicator',
|
||||
kpiIdTip:'This Ne has no custom indicators',
|
||||
period:' Granularity',
|
||||
title:' Custom Indicator Title',
|
||||
objectType:' Object type',
|
||||
@@ -1025,7 +1065,26 @@ export default {
|
||||
addCustom:' Add custom indicator',
|
||||
editCustom:' Edit Custom indicator',
|
||||
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: {
|
||||
analysis: {
|
||||
@@ -1050,18 +1109,23 @@ export default {
|
||||
pcap: {
|
||||
capArgPlease: 'Please enter tcpdump -i any support parameter',
|
||||
cmd: 'Command',
|
||||
execCmd: "Generic tcpdump packet capture command",
|
||||
execCmdsSctp: "Generic tcpdump filter sctp and port commands",
|
||||
execUPFCmdA: 'Suitable for anomalous packet capture of other NE',
|
||||
execUPFCmdB: 'Suitable for UPF anomaly packet capture analysis',
|
||||
execCmd: "Common Command Options",
|
||||
execCmd2: "Filter Protocol Port Command",
|
||||
execCmd3: "File Split By Time units of seconds (-G 10), Generated Max File Number (-W 7)",
|
||||
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",
|
||||
textStartBatch: "Batch Start",
|
||||
textStop: "Stop",
|
||||
textStopBatch: "Batch Stop",
|
||||
textLog: "Log",
|
||||
textLogMsg: "Log Info",
|
||||
textLog: "LogFile",
|
||||
textLogMsg: "LogFile Info",
|
||||
textDown: "Download",
|
||||
textDownBatch: "Batch Download",
|
||||
downTip: "Are you sure you want to download the {title} capture data file?",
|
||||
downOk: "{title} file download complete",
|
||||
downErr: "{title} file download exception",
|
||||
@@ -1075,12 +1139,13 @@ export default {
|
||||
stopNotRun: "{title} not running",
|
||||
},
|
||||
task: {
|
||||
neTypePlease: 'Query network element type',
|
||||
neType: 'NE Type',
|
||||
neID: 'NE ID',
|
||||
traceId: 'Tracing No',
|
||||
trackType: 'Tracing Type',
|
||||
trackTypePlease: 'Please select a tracing type',
|
||||
creater: 'Created by',
|
||||
textStop: "Stop",
|
||||
status: 'Status',
|
||||
time: 'Time',
|
||||
startTime: 'Start Time',
|
||||
endTime: 'End Time',
|
||||
msisdn: 'MSISDN',
|
||||
@@ -1090,26 +1155,31 @@ export default {
|
||||
imsiPlease: 'Please enter IMSI',
|
||||
imsiTip: 'Mobile communication IMSI number',
|
||||
srcIp: 'Source IP Address',
|
||||
srcIpPlease: 'Please enter the source IP address',
|
||||
srcIpPlease: 'Please enter the IP address',
|
||||
srcIpTip: 'Current sender IPv4 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',
|
||||
interfaces: 'Signaling Interface',
|
||||
interfacesPlease: 'Please enter the signaling interface',
|
||||
signalPort: 'Signal 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',
|
||||
rangePickerPlease: 'Please select the start and end time of the task',
|
||||
comment: 'Task Description',
|
||||
commentPlease: 'Task description can be entered',
|
||||
remark: 'Remark',
|
||||
remarkPlease: 'Task description can be entered',
|
||||
addTask: 'Add Task',
|
||||
editTask: 'Modify Task',
|
||||
viewTask: 'View Task',
|
||||
errorTaskInfo: 'Failed to obtain task information',
|
||||
delTask: 'Successfully deleted task {num}',
|
||||
delTaskTip: 'Are you sure to delete the data item with record number {num}?',
|
||||
delTaskTip: 'Are you sure to delete the data item with record ID {id} ?',
|
||||
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: {
|
||||
@@ -1222,7 +1292,20 @@ export default {
|
||||
downTip: "Confirm the download file name is [{fileName}] File?",
|
||||
downTipErr: "Failed to get file",
|
||||
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: {
|
||||
session: {
|
||||
@@ -1357,7 +1440,7 @@ export default {
|
||||
status0: "Failures",
|
||||
status1: "Active",
|
||||
createTime: "Time",
|
||||
costTime: "Time Consumption",
|
||||
costTime: "Time Lap",
|
||||
viewLog: "Scheduling log Info",
|
||||
delTip: "Are you sure you want to delete the scheduling log entry with the number [{num}]?",
|
||||
delOk: "Deleted Successfully",
|
||||
@@ -1540,7 +1623,7 @@ export default {
|
||||
edgeTypeLineAnimateState: "Straight line with state animations",
|
||||
edgeLabelPositionStart: "Start",
|
||||
edgeLabelPositionMiddle: "Middle",
|
||||
edgeLabelPositionEnd: "End",
|
||||
edgeLabelPositionEnd: "End",
|
||||
nodeTypeCircle: "Circle",
|
||||
nodeTypeRect: "Rect",
|
||||
nodeTypeEllipse: "Ellipse",
|
||||
@@ -1598,7 +1681,7 @@ export default {
|
||||
loginIp: 'Login Address',
|
||||
loginTime: 'Login Time',
|
||||
status: 'Status',
|
||||
userNameTip:'The account cannot start with a number and can contain uppercase and lowercase letters, numbers, and no less than 5 digits',
|
||||
userNameTip:'The account number can only contain strings of uppercase letters, lowercase letters and numbers with a minimum length of 6 digits',
|
||||
passwdTip:'The password should contain at least uppercase and lowercase letters, numbers, special symbols, and no less than 6 digits',
|
||||
nickNameTip:'Nicknames no less than 2 digits',
|
||||
emailTip:'Please enter the correct email address',
|
||||
@@ -1712,6 +1795,10 @@ export default {
|
||||
reset: "System Reset",
|
||||
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?',
|
||||
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:{
|
||||
allScopeOptions:'All data permissions',
|
||||
@@ -1762,7 +1849,7 @@ export default {
|
||||
className:'Department Name',
|
||||
classId:'Department Number',
|
||||
classSort:'Department Sorting',
|
||||
status:'Position Status',
|
||||
status:'Department Status',
|
||||
createTime:'Creation Time',
|
||||
highClass:'Higher Office',
|
||||
emailTip:'Please input the correct email address',
|
||||
@@ -1793,13 +1880,13 @@ export default {
|
||||
operate:{
|
||||
operId:'Log ID',
|
||||
moduleName:'Module Name',
|
||||
workType:'Business Type',
|
||||
workType:'Operation',
|
||||
operUser:'Operator',
|
||||
requestMe:'Request Method',
|
||||
host:'Request Host',
|
||||
operStatus:'Status',
|
||||
operDate:'Time',
|
||||
useTime:'Time Consumption',
|
||||
useTime:'Time Lap',
|
||||
logInfo:'Operation Log Information',
|
||||
delSure:'Are you sure to delete the data item with access number [{ids}]?',
|
||||
delAllSure:'Confirm to clear all login log data items?',
|
||||
@@ -1865,7 +1952,7 @@ export default {
|
||||
componentTip:' The component path accessed by views in the page component directory, such as: system/user/index Note: The routing address without the .vue file suffix is the network address and can be filled in as a link',
|
||||
perms:`Permission identification example: monitor:server:query Permission identification is used in the back-end controller, such as:['monitor:server:query'] Permission identification is used in the front-end Vue page, such as: v-perms:has="['monitor:server:query']"`
|
||||
},
|
||||
dict:{
|
||||
dict:{
|
||||
dictInfo:'Dictionary Type Information',
|
||||
dictId:'Dictionary Number',
|
||||
dictName:'Dictionary Name',
|
||||
@@ -1934,6 +2021,7 @@ export default {
|
||||
stepNeInfoStepNext: 'Confirm that you want to proceed to the next step to configure the parameters of the network element?',
|
||||
stepPara5GTitle: "Configuration Parameter",
|
||||
stepPara5GDesc: "Setting network element global parameter information",
|
||||
savePara5GOk: 'Save Success!',
|
||||
stepPara5GStepPrev: 'Confirm that you want to abandon the current change and return to the previous step?',
|
||||
stepPara5GStepNext: 'Confirm that you want to proceed to the next step for the network element service installation?',
|
||||
stepInstallTitle: "Service Install",
|
||||
@@ -1943,9 +2031,9 @@ export default {
|
||||
stepInstallText: 'Select Install',
|
||||
stepInstallTip: 'Confirm the installation of the new version of the chosen Net Meta?',
|
||||
stepInstallModal: 'Network Element For Install',
|
||||
stepInstallNotNewVer: 'No new version found',
|
||||
stepInstallDone: 'Installation complete, service initialized',
|
||||
stepInstallFail: 'Installation fails, check if the service terminal environment is available!',
|
||||
stepInstallNotNewVer: 'No new version found',
|
||||
stepInstallDone: 'Installation complete, service initialized',
|
||||
stepInstallFail: 'Installation fails, check if the service terminal environment is available!',
|
||||
stepLicenseTitle: "Service License",
|
||||
stepLicenseDesc: "Obtaining a license activation code for authorization authentication",
|
||||
stepLicenseReload: 'Select Refresh',
|
||||
@@ -2034,6 +2122,28 @@ export default {
|
||||
hostSelectMore: "Load More {num}",
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ export default {
|
||||
updateTime: '更新时间',
|
||||
remark: '备注',
|
||||
description: '说明',
|
||||
operate: '操作',
|
||||
operate: '更多操作',
|
||||
operateOk: '操作成功!',
|
||||
operateErr: '操作失败!',
|
||||
copyText: "复制",
|
||||
@@ -130,7 +130,7 @@ export default {
|
||||
onlyAllow:'只支持上传文件格式',
|
||||
},
|
||||
LockScreen: {
|
||||
inputPlacePwd:'请输入登录密码',
|
||||
inputPlacePwd:'请输入锁屏密码',
|
||||
validSucc:'校验通过',
|
||||
validError:'校验失败',
|
||||
backLogin:'退出并重新登录',
|
||||
@@ -149,6 +149,8 @@ export default {
|
||||
page403: '没有访问权限',
|
||||
page404: '找不到匹配页面',
|
||||
helpDoc: '系统使用文档',
|
||||
traceTaskHLR: '跟踪任务 HLR',
|
||||
lockScreen: '锁屏',
|
||||
account: {
|
||||
index: "个人中心",
|
||||
profile: "个人信息",
|
||||
@@ -184,9 +186,11 @@ export default {
|
||||
helpDoc: '使用手册',
|
||||
},
|
||||
rightContent: {
|
||||
alarm: "活动告警",
|
||||
lock: "锁屏",
|
||||
lockTip: "确认要进行锁屏吗?",
|
||||
helpDoc: "系统使用文档",
|
||||
lockPasswd: "解锁密码",
|
||||
lockPasswdTip: "可不设置密码",
|
||||
fullscreen: "全屏显示",
|
||||
logout: "退出登录",
|
||||
profile: "个人中心",
|
||||
@@ -293,10 +297,10 @@ export default {
|
||||
newPassword: "新密码",
|
||||
newPasswordTip: "密码至少包含大小写字母、数字、特殊符号,且不少于6位",
|
||||
newPassworddPleace: "请输入新密码",
|
||||
confirmPassword: "确认新密码",
|
||||
confirmPassword: "确认新密码",
|
||||
confirmPasswordPleace: "请确认新密码",
|
||||
submit: "提交修改",
|
||||
reset: "重置",
|
||||
reset: "重置",
|
||||
submitTip: "确认要提交修改密码吗?",
|
||||
submitOkTip: "恭喜您,{num} 账号密码修改成功!",
|
||||
submitOk: "重新登录",
|
||||
@@ -559,8 +563,6 @@ export default {
|
||||
realTimeDataStart: "开启实时数据",
|
||||
realTimeDataStop: "关闭实时数据",
|
||||
cdrInfo: "CDR信息",
|
||||
neName: "网元名称",
|
||||
rmUID: "资源标识",
|
||||
time: "记录时间",
|
||||
rowInfo: "记录信息",
|
||||
type: "记录类型",
|
||||
@@ -568,20 +570,30 @@ export default {
|
||||
caller: "主叫",
|
||||
called: "被叫",
|
||||
result: "结果",
|
||||
resultOk: "成功",
|
||||
resultFail: "失败",
|
||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||
exportTip: "确认导出当前查询条件的话单数据吗?(导出最大支持一万条)",
|
||||
smfChargingID: '计费ID',
|
||||
smfSubscriptionIDData: '订阅 ID 数据',
|
||||
smfSubscriptionIDType: '订阅 ID 类型',
|
||||
smfDataVolumeUplink: '数据量上行链路',
|
||||
smfDataVolumeDownlink: '数据量下行链路',
|
||||
smfDataTotalVolume: '数据总量',
|
||||
smfDuration: '持续时间',
|
||||
smfInvocationTime: '调用时间',
|
||||
},
|
||||
ue: {
|
||||
eventType: "事件类型",
|
||||
realTimeDataStart: "开启实时数据",
|
||||
realTimeDataStop: "关闭实时数据",
|
||||
ueInfo: "UE信息",
|
||||
neName: "网元名称",
|
||||
rmUID: "资源标识",
|
||||
rowInfo: "记录信息",
|
||||
time: "记录时间",
|
||||
result: "结果",
|
||||
resultOk: "成功",
|
||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||
exportTip: "确认导出当前查询条件的事件数据吗?(导出最大支持一万条)",
|
||||
},
|
||||
},
|
||||
ne: {
|
||||
@@ -594,7 +606,7 @@ export default {
|
||||
neIdTip: '填写网元绑定的唯一标识',
|
||||
rmUid: '资源唯一标识',
|
||||
rmUidPlease: '请输入资源唯一标识',
|
||||
rmUidTip: "用于网元日志、告警、指标等数据上报的标记",
|
||||
rmUidTip: "用于网元日志、告警、指标等数据上报的标记",
|
||||
neName: '网元名称',
|
||||
neNamePlease: '请输入网元名称',
|
||||
ipAddr: '服务IP',
|
||||
@@ -618,9 +630,9 @@ export default {
|
||||
log: '日志',
|
||||
},
|
||||
neInfo: {
|
||||
version: "网元版本",
|
||||
version: "网元版本",
|
||||
state: "网元状态",
|
||||
serviceState: "服务状态",
|
||||
serviceState: "服务状态",
|
||||
info: '状态信息',
|
||||
resourceInfo: '资源情况',
|
||||
sysMem: "系统内存",
|
||||
@@ -649,19 +661,19 @@ export default {
|
||||
kpiEnable: '上报',
|
||||
kpiTimer: '上报周期',
|
||||
kpiTimerPlease: '请输入上报周期(单位秒)',
|
||||
omcIP: 'OMC IP',
|
||||
},
|
||||
backConf: {
|
||||
export: '配置导出',
|
||||
import: '配置导入',
|
||||
title: '配置文件导入',
|
||||
importType: '文件来源',
|
||||
title: '配置文件导入',
|
||||
importType: '文件来源',
|
||||
server:'服务器文件',
|
||||
local:'本地文件',
|
||||
localUpload:'本地上传',
|
||||
exportTip:'确认要导出网元配置信息到文件?',
|
||||
exportMsg:'导出成功,请到【备份管理】进行下载',
|
||||
filePlease: "请上传文件",
|
||||
fileNamePlease: '请选择服务器文件',
|
||||
exportMsg:'导出网元配置信息到文件成功',
|
||||
pathPlease: '未发现文件',
|
||||
},
|
||||
},
|
||||
neHost: {
|
||||
@@ -674,10 +686,11 @@ export default {
|
||||
port: "端口",
|
||||
portPlease: "请正确填写主机端口号",
|
||||
user: "用户名",
|
||||
userPlease: "请正确填写主机登录用户",
|
||||
userPlease: "请正确填写主机用户",
|
||||
database: "数据库",
|
||||
authMode: "认证模式",
|
||||
password: "密码",
|
||||
passwordPlease: "请正确填写主机登录密码",
|
||||
passwordPlease: "请正确填写主机密码",
|
||||
privateKey: "私钥",
|
||||
privateKeyPlease: "请正确填写私钥字符内容 ~/.ssh/id_rsa",
|
||||
passPhrase: "私钥密码",
|
||||
@@ -704,7 +717,7 @@ export default {
|
||||
uploadTitle: "上传软件",
|
||||
upload: "上传",
|
||||
uploadNotFile: "未上传软件文件",
|
||||
uploadBatch: "上传软件包",
|
||||
uploadBatch: "批量上传",
|
||||
uploadBatchMax: "可上传多个软件包,最多同时选择{txt}个。",
|
||||
uploadFileName: "解析文件名称格式如: amf-r2.240x.xx-xxx",
|
||||
name: "文件名",
|
||||
@@ -727,21 +740,22 @@ export default {
|
||||
upgrade: "升级到新版本",
|
||||
upgradeTip: "确认要升级到新版本吗?",
|
||||
upgradeTipEmpty: "当前没有可用的新版本",
|
||||
upgradeTipEqual: "当前版本与新版本相同",
|
||||
upgradeTipEqual: "当前版本与新版本相同,确认要进行更新吗?",
|
||||
rollback: '切换到上一个版本',
|
||||
rollbackTip: "确认切换到上一个版本吗?",
|
||||
rollbackTipEmpty: "目前没有可用的上一个版本",
|
||||
rollbackTipEqual: '当前版本与之前版本相同',
|
||||
rollbackTipEqual: '当前版本与之前版本相同,确认要进行切换吗?',
|
||||
version: "当前版本",
|
||||
preVersion: "上一个版本",
|
||||
newVersion: "新版本",
|
||||
status: "版本状态",
|
||||
upgradeBatch: "批量更新",
|
||||
upgradeBatchTip: "对勾选的记录进行新版本升级吗?",
|
||||
upgradeNotNewVer: '没有发现新版本',
|
||||
upgradeDone: '更新完成,服务正在重载',
|
||||
upgradeFail: '更新失败,请检查服务终端环境是否可用!',
|
||||
upgradeModal: '网元版本更新',
|
||||
upgradeNotNewVer: '没有发现新版本',
|
||||
upgradeOMCVer: '拒绝批量操作升级OMC',
|
||||
upgradeDone: '更新完成,服务正在重载',
|
||||
upgradeFail: '更新失败,请检查软件文件是否存在且服务终端环境是否可用!',
|
||||
upgradeModal: '网元版本更新',
|
||||
},
|
||||
neLicense: {
|
||||
status: "许可证状态",
|
||||
@@ -756,19 +770,42 @@ export default {
|
||||
licensePath: "许可证文件",
|
||||
licensePathTip: "请上传许可证文件",
|
||||
upload: '上传',
|
||||
uploadBatch: "上传许可证",
|
||||
uploadFile: "上传许可证",
|
||||
uploadChangeOk: '网元更新许可证成功,正在后台校验!',
|
||||
uploadChangeFail: "部分网元更新许可证失败,请检查服务终端环境是否可用!",
|
||||
},
|
||||
neConfPara5G: {
|
||||
save: '保存',
|
||||
reload: '刷新',
|
||||
title: '保存信息',
|
||||
sync: '同步到网元',
|
||||
syncNe: '选择网元',
|
||||
syncNeDone: '同步到网元终端完成',
|
||||
saveOk: '保存成功!',
|
||||
neConfig: {
|
||||
treeTitle: "配置导航",
|
||||
treeSelectTip: "左侧配置导航中选择配置项信息!",
|
||||
neType: "网元类型",
|
||||
neTypePleace: "请选择网元类型",
|
||||
noConfigData: "暂无配置项数据",
|
||||
updateValue: "【 {num} 】 属性值修改成功",
|
||||
updateValueErr: "属性值修改失败",
|
||||
updateItem: "修改 Index 为 {num} 记录成功",
|
||||
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: {
|
||||
reloadPara5G: '刷新',
|
||||
stepPrev: '上一步',
|
||||
stepPrevTip: '确认要放弃当前变更返回上一步吗?',
|
||||
stepNext: '下一步',
|
||||
@@ -841,9 +878,10 @@ export default {
|
||||
imsiTip3: 'MSIN=移动客户识别码,采用等长10位数字构成',
|
||||
amfTip: '鉴权管理域,参数最大长度为 4',
|
||||
algoIndexTip: '算法索引,介于0到15之间',
|
||||
kiTip: '用户签权密钥信息,最大长度为32',
|
||||
kiTip: '用户签权密钥信息,长度只能是32',
|
||||
opcTip: '鉴权秘钥,OPC是由Ki和OP经过计算得来的,OP为运营商的根秘钥,ki是鉴权秘钥,最大长度为32',
|
||||
delSure:'确认删除IMSI编号为: {imsi} 的用户吗?',
|
||||
imsiConfirm:'IMSI的长度必须为15',
|
||||
},
|
||||
sub: {
|
||||
subInfo:'签约信息',
|
||||
@@ -875,7 +913,8 @@ export default {
|
||||
micoTip: '签约的 MICO 业务标志位',
|
||||
rfspTip:'RFSP 索引,在 NG-RAN 中,特定 RRM 配置的索引,参数介于0到127之间',
|
||||
ueTypeTip: '运营商定义的用户 UE Usage Type,整型,参数介于0到127之间',
|
||||
epsFlagTip: '是否开启4G EPS 服务',
|
||||
cnFlag: '是否开启 5G Core Network 服务',
|
||||
epsFlagTip: '是否开启 4G EPS 服务',
|
||||
contextIdTip: '签约APN 上下文ID,必须从APN Context list 中选择。',
|
||||
apnContextTip: '手机可用的APN列表,最多六个,在HSS中定义。',
|
||||
staticIpTip: '指定手机用户上网时使用的静态IP地址,为"-"时表示使用动态IP地址',
|
||||
@@ -897,7 +936,7 @@ export default {
|
||||
batchAddText: '批量新增',
|
||||
batchDelText: '批量删除',
|
||||
batchUpdateText: '批量更新',
|
||||
batchNum: '批量个数',
|
||||
batchNum: '批量个数',
|
||||
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
||||
imsiTip1: 'MCC=移动国家号码, 由三位数字组成',
|
||||
imsiTip2: 'MNC=移动网络号,由两位数字组成',
|
||||
@@ -1014,6 +1053,7 @@ export default {
|
||||
},
|
||||
customTarget:{
|
||||
kpiId:'自定义指标项',
|
||||
kpiIdTip:'该网元没有自定义指标',
|
||||
period:'颗粒度',
|
||||
title:'自定义指标项标题',
|
||||
objectType:'对象类型',
|
||||
@@ -1024,8 +1064,27 @@ export default {
|
||||
delCustom:'成功删除记录编号为 {num} 自定义指标',
|
||||
addCustom:'添加自定义指标',
|
||||
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: {
|
||||
analysis: {
|
||||
@@ -1050,18 +1109,23 @@ export default {
|
||||
pcap: {
|
||||
capArgPlease: '请输入tcpdump -i any支持参数',
|
||||
cmd: '命令',
|
||||
execCmd: "通用tcpdump抓包命令",
|
||||
execCmdsSctp: "过滤sctp和port命令",
|
||||
execUPFCmdA: '适合其他网元异常,UPF配合抓包的情况',
|
||||
execUPFCmdB: '适合UPF异常需要抓包分析的情况',
|
||||
execCmd: "通用命令选项",
|
||||
execCmd2: "过滤协议端口命令",
|
||||
execCmd3: "分割文件按时间单位秒 (-G 10 ),最多生成文件数量 (-W 7)",
|
||||
execUPFCmdA: '标准版-UPF配合其他网元异常抓包分析',
|
||||
execUPFCmdB: '标准版-UPF异常需要抓包分析',
|
||||
batchOper: '批量操作',
|
||||
batchStartText: '批量开始',
|
||||
batchStopText: '批量停止',
|
||||
batchDownText: '批量下载',
|
||||
fileView: '历史抓包文件',
|
||||
fileUPF: '标准版',
|
||||
fileUPFTip: 'UPF内部抓包分析包',
|
||||
textStart: "开始",
|
||||
textStartBatch: "批量开始",
|
||||
textStop: "停止",
|
||||
textStopBatch: "批量停止",
|
||||
textLog: "日志",
|
||||
textLogMsg: "日志信息",
|
||||
textLog: "日志文件",
|
||||
textLogMsg: "日志文件信息",
|
||||
textDown: "下载",
|
||||
textDownBatch: "批量下载",
|
||||
downTip: "确认要下载 {title} 抓包数据文件吗?",
|
||||
downOk: "{title} 文件下载完成",
|
||||
downErr: "{title} 文件下载异常",
|
||||
@@ -1075,12 +1139,13 @@ export default {
|
||||
stopNotRun: "{title} 任务未运行",
|
||||
},
|
||||
task: {
|
||||
neTypePlease: '请选择网元类型',
|
||||
neType: '网元类型',
|
||||
neID: '网元内部标识',
|
||||
traceId: '跟踪编号',
|
||||
trackType: '跟踪类型',
|
||||
trackTypePlease: '请选择跟踪类型',
|
||||
creater: '创建人',
|
||||
textStop: "停止",
|
||||
status: '状态',
|
||||
time: '时间',
|
||||
startTime: '开始时间',
|
||||
endTime: '结束时间',
|
||||
msisdn: 'MSISDN',
|
||||
@@ -1099,17 +1164,22 @@ export default {
|
||||
interfacesPlease: '请输入信令接口',
|
||||
signalPort: '信令端口',
|
||||
signalPortPlease: '请输入信令端口',
|
||||
signalPortTip: '接口对应的端口',
|
||||
signalPortTip: '目标IP地址或源IP地址对应一方的端口',
|
||||
rangePicker: '开始结束时间',
|
||||
rangePickerPlease: '请选择任务时间开始结束时间',
|
||||
comment: '任务说明',
|
||||
commentPlease: '可输入任务说明',
|
||||
remark: '说明',
|
||||
remarkPlease: '可输入任务说明',
|
||||
addTask: '添加任务',
|
||||
editTask: '修改任务',
|
||||
viewTask: '查看任务',
|
||||
errorTaskInfo: '获取任务信息失败',
|
||||
delTask: '成功删除任务 {num}',
|
||||
delTaskTip: '确认删除记录编号为 {num} 的数据项?',
|
||||
delTaskTip: '确认删除记录编号为 {id} 的数据项?',
|
||||
stopTask: '成功停止任务 {id}',
|
||||
stopTaskTip: '确认停止记录编号为 {id} 的任务?',
|
||||
pcapView: "跟踪数据分析",
|
||||
traceFile: "跟踪文件",
|
||||
errMsg: "错误信息",
|
||||
imsiORmsisdn: "imsi 或 msisdn 是空值,不能开始任务",
|
||||
},
|
||||
},
|
||||
faultManage: {
|
||||
@@ -1222,8 +1292,21 @@ export default {
|
||||
downTip: "确认下载文件名为 【{fileName}】 文件?",
|
||||
downTipErr: "文件获取失败",
|
||||
dirCd: "进入目录",
|
||||
viewAs: '查看操作',
|
||||
reload: "重载",
|
||||
follow: '监视内容变化',
|
||||
tailChar: '末尾字数',
|
||||
tailLines: '末尾行数',
|
||||
},
|
||||
},
|
||||
exportFile:{
|
||||
fileName:'文件来源',
|
||||
downTip: "确认下载文件名为 【{fileName}】 文件?",
|
||||
downTipErr: "文件获取失败",
|
||||
deleteTip: "确认删除文件名为 【{fileName}】 文件?",
|
||||
deleteTipErr: "文件删除失败",
|
||||
selectTip:"请选择文件名",
|
||||
}
|
||||
},
|
||||
monitor: {
|
||||
session: {
|
||||
userName: "登录账号",
|
||||
@@ -1540,7 +1623,7 @@ export default {
|
||||
edgeTypeLineAnimateState: "直线,含有状态动画",
|
||||
edgeLabelPositionStart: "开头",
|
||||
edgeLabelPositionMiddle: "中间",
|
||||
edgeLabelPositionEnd: "末尾",
|
||||
edgeLabelPositionEnd: "末尾",
|
||||
nodeTypeCircle: "圆形",
|
||||
nodeTypeRect: "矩形",
|
||||
nodeTypeEllipse: "椭圆",
|
||||
@@ -1598,7 +1681,7 @@ export default {
|
||||
loginIp: '登录地址',
|
||||
loginTime: '登录时间',
|
||||
status: '用户状态',
|
||||
userNameTip:'账号不能以数字开头,可包含大写小写字母,数字,且不少于5位',
|
||||
userNameTip:'账号只能包含大写字母、小写字母和数字的字符串,长度至少为6位',
|
||||
passwdTip:'密码至少包含大小写字母、数字、特殊符号,且不少于6位',
|
||||
nickNameTip:'昵称不少于2位',
|
||||
emailTip:'请输入正确的邮箱地址',
|
||||
@@ -1712,6 +1795,10 @@ export default {
|
||||
reset: "系统重置",
|
||||
resetInstruction: "系统重置将会清除当前系统内所有数据,请谨慎操作!!!",
|
||||
resetTipContent: '确认要清除当前系统内所有数据并坚持继续吗?',
|
||||
homeInstruction:'设置系统首页界面',
|
||||
home: '系统首页',
|
||||
homeTip:'确认要提交当前界面为系统界面吗?',
|
||||
homeSet:'系统首页设置',
|
||||
},
|
||||
role:{
|
||||
allScopeOptions:'全部数据权限',
|
||||
@@ -1762,7 +1849,7 @@ export default {
|
||||
className:'部门名称',
|
||||
classId:'部门编号',
|
||||
classSort:'部门排序',
|
||||
status:'岗位状态',
|
||||
status:'部门状态',
|
||||
createTime:'创建时间',
|
||||
highClass:'上级部门',
|
||||
emailTip:'请输入正确的邮箱地址',
|
||||
@@ -1793,7 +1880,7 @@ export default {
|
||||
operate:{
|
||||
operId:'日志编号',
|
||||
moduleName:'模块名称',
|
||||
workType:'业务类型',
|
||||
workType:'操作类型',
|
||||
operUser:'操作人员',
|
||||
requestMe:'请求方式',
|
||||
host:'请求主机',
|
||||
@@ -1832,8 +1919,8 @@ export default {
|
||||
unlockSure:'确认解锁用户 【{username}】 数据项?',
|
||||
},
|
||||
},
|
||||
menu:{
|
||||
menuInfo:'菜单信息',
|
||||
menu:{
|
||||
menuInfo:'菜单信息',
|
||||
menuName:'菜单名称',
|
||||
menuId:'菜单编号',
|
||||
menuSort:'菜单排序',
|
||||
@@ -1865,7 +1952,7 @@ export default {
|
||||
componentTip:' 页面组件目录 views 访问的组件路径,如:system/user/index 注意:不带 .vue 文件后缀路由地址是网络地址可填入链接',
|
||||
perms:`权限标识示例:monitor:server:query 后端控制器中使用权限标识,如:['monitor:server:query'] 前端vue页面中使用权限标识,如:v-perms:has="['monitor:server:query']"`
|
||||
},
|
||||
dict:{
|
||||
dict:{
|
||||
dictInfo:'字典类型信息',
|
||||
dictId:'字典编号',
|
||||
dictName:'字典名称',
|
||||
@@ -1934,6 +2021,7 @@ export default {
|
||||
stepNeInfoStepNext: '确认要下一步进行网元配置参数?',
|
||||
stepPara5GTitle: "网元配置参数",
|
||||
stepPara5GDesc: "设置网元全局参数信息",
|
||||
savePara5GOk: '保存成功!',
|
||||
stepPara5GStepPrev: '确认要放弃当前变更返回上一步吗?',
|
||||
stepPara5GStepNext: '确认要下一步进行网元服务安装吗?',
|
||||
stepInstallTitle: "网元服务安装",
|
||||
@@ -1943,9 +2031,9 @@ export default {
|
||||
stepInstallText: '选择安装',
|
||||
stepInstallTip: '确认安装选择的网元新版本吗?',
|
||||
stepInstallModal: '网元进行安装',
|
||||
stepInstallNotNewVer: '没有发现新版本',
|
||||
stepInstallDone: '安装完成,服务进入初始化',
|
||||
stepInstallFail: '安装失败,请检查服务终端环境是否可用!',
|
||||
stepInstallNotNewVer: '没有发现新版本',
|
||||
stepInstallDone: '安装完成,服务进入初始化',
|
||||
stepInstallFail: '安装失败,请检查服务终端环境是否可用!',
|
||||
stepLicenseTitle: "网元许可授权",
|
||||
stepLicenseDesc: "获取网元许可激活码进行授权认证",
|
||||
stepLicenseReload: '选择刷新许可证',
|
||||
@@ -2034,6 +2122,28 @@ export default {
|
||||
hostSelectMore: "加载更多 {num}",
|
||||
hostSelectHeader: "主机列表",
|
||||
},
|
||||
ps:{
|
||||
realTimeHigh:"高",
|
||||
realTimeLow:"低",
|
||||
realTimeRegular:"常规",
|
||||
realTimeStop:"已暂停",
|
||||
realTime:"实时更新速度",
|
||||
pid:"PID",
|
||||
name:"应用名称",
|
||||
username:"用户名",
|
||||
runTime:"运行时间",
|
||||
numThreads:"线程数",
|
||||
cpuPercent:"CPU使用率",
|
||||
diskRead:"磁盘读取",
|
||||
diskWrite:"磁盘写入",
|
||||
},
|
||||
net:{
|
||||
localAddr:"本地地址",
|
||||
remoteAddr:"远程地址",
|
||||
status:"状态",
|
||||
proto:"协议",
|
||||
port:"端口",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,12 +4,20 @@ import {
|
||||
WaterMark,
|
||||
getMenuData,
|
||||
clearMenuItem,
|
||||
MenuDataItem,
|
||||
type MenuDataItem,
|
||||
} from 'antdv-pro-layout';
|
||||
import RightContent from './components/RightContent.vue';
|
||||
import Tabs from './components/Tabs.vue';
|
||||
import GlobalMask from '@/components/GlobalMask/index.vue';
|
||||
import { scriptUrl } from '@/assets/js/icon_font_8d5l8fzk5b87iudi';
|
||||
import { computed, reactive, watch, onMounted, onUnmounted } from 'vue';
|
||||
import {
|
||||
computed,
|
||||
reactive,
|
||||
watch,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
nextTick,
|
||||
} from 'vue';
|
||||
import useLayoutStore from '@/store/modules/layout';
|
||||
import useRouterStore from '@/store/modules/router';
|
||||
import useTabsStore from '@/store/modules/tabs';
|
||||
@@ -21,6 +29,7 @@ const { proConfig, waterMarkContent } = useLayoutStore();
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { getServerTime } from '@/api';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { parseUrlPath } from '@/plugins/file-static-url';
|
||||
const { t, currentLocale } = useI18n();
|
||||
@@ -50,7 +59,7 @@ watch(
|
||||
// 路由地址含有内嵌地址标识又是隐藏菜单需要处理打开高亮菜单栏
|
||||
if (v.path.includes(MENU_PATH_INLINE) && v.meta.hideInMenu) {
|
||||
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);
|
||||
}
|
||||
},
|
||||
@@ -159,8 +168,28 @@ function fnLocale(m: MenuDataItem) {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**检查系统名称是否超出范围进行滚动 */
|
||||
function fnCheckAppNameOverflow() {
|
||||
const container: HTMLDivElement | null = document.querySelector('.app-name');
|
||||
if (!container) return;
|
||||
const text: HTMLDivElement | null = container.querySelector('.marquee');
|
||||
if (!text) return;
|
||||
if (text.offsetWidth > container.offsetWidth) {
|
||||
text.classList.add('app-name_scrollable');
|
||||
text.setAttribute('data-content', text.innerText);
|
||||
} else {
|
||||
text.classList.remove('app-name_scrollable');
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => appStore.appName,
|
||||
() => nextTick(fnCheckAppNameOverflow)
|
||||
);
|
||||
|
||||
//
|
||||
onMounted(() => {
|
||||
fnCheckAppNameOverflow();
|
||||
fnGetServerTime();
|
||||
useAlarmStore().fnGetActiveAlarmInfo();
|
||||
});
|
||||
@@ -224,12 +253,10 @@ onUnmounted(() => {
|
||||
v-model:selectedKeys="layoutState.selectedKeys"
|
||||
v-model:openKeys="layoutState.openKeys"
|
||||
:menu-data="menuData"
|
||||
:breadcrumb="{ routes: breadcrumb } as any"
|
||||
disable-content-margin
|
||||
:breadcrumb="{ routes: breadcrumb }"
|
||||
v-bind="proConfig"
|
||||
:iconfont-url="scriptUrl"
|
||||
:sider-width="208"
|
||||
:locale="(fnLocale as any)"
|
||||
:locale="fnLocale"
|
||||
>
|
||||
<!--插槽-菜单头-->
|
||||
<template #menuHeaderRender>
|
||||
@@ -246,8 +273,10 @@ onUnmounted(() => {
|
||||
:alt="appStore.appName"
|
||||
:title="appStore.appName"
|
||||
/>
|
||||
<h1 class="title" :title="appStore.appName">
|
||||
{{ appStore.appName }}
|
||||
<h1 class="app-name" :title="appStore.appName">
|
||||
<span class="marquee app-name_scrollable">
|
||||
{{ appStore.appName }}
|
||||
</span>
|
||||
</h1>
|
||||
</template>
|
||||
<template v-if="appStore.logoType === 'brand'">
|
||||
@@ -265,7 +294,7 @@ onUnmounted(() => {
|
||||
<template #headerContentRender></template>
|
||||
|
||||
<!--插槽-顶部右侧-->
|
||||
<template #rightContentRender>
|
||||
<template #headerContentRightRender>
|
||||
<RightContent />
|
||||
</template>
|
||||
|
||||
@@ -300,9 +329,6 @@ onUnmounted(() => {
|
||||
</transition>
|
||||
</RouterView>
|
||||
|
||||
<!-- 锁屏遮罩 -->
|
||||
<LockScreen />
|
||||
|
||||
<!--插槽-内容底部-->
|
||||
<template #footerRender="{ width }">
|
||||
<footer class="footer">
|
||||
@@ -317,11 +343,17 @@ onUnmounted(() => {
|
||||
:href="appStore.officialUrl"
|
||||
target="_blank"
|
||||
size="small"
|
||||
v-perms:has="['system:setting:official']"
|
||||
v-if="appStore.officialUrl !== '#'"
|
||||
>
|
||||
{{ t('loayouts.basic.officialUrl') }}
|
||||
</a-button>
|
||||
<a-button type="link" size="small" @click="fnClickHelpDoc()">
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
v-perms:has="['system:setting:doc']"
|
||||
@click="fnClickHelpDoc()"
|
||||
>
|
||||
{{ t('loayouts.basic.helpDoc') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
@@ -329,6 +361,9 @@ onUnmounted(() => {
|
||||
</footer>
|
||||
</template>
|
||||
</ProLayout>
|
||||
|
||||
<!-- 全局遮罩 -->
|
||||
<GlobalMask />
|
||||
</WaterMark>
|
||||
</template>
|
||||
|
||||
@@ -349,18 +384,40 @@ onUnmounted(() => {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
.app-name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
// text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 130px;
|
||||
width: 148px;
|
||||
> .app-name_scrollable {
|
||||
padding-right: 12px;
|
||||
display: inline-block;
|
||||
animation: scrollable-animation linear 6s infinite both;
|
||||
&::after {
|
||||
content: attr(data-content);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -100%;
|
||||
transition: right 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes scrollable-animation {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(calc(-100% - 12px));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
z-index: 16;
|
||||
margin: 0px;
|
||||
width: auto;
|
||||
margin-top: 52px;
|
||||
margin-top: 32px;
|
||||
&-fixed {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
@@ -378,7 +435,8 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
& #serverTimeDom {
|
||||
color: #00000085;
|
||||
color: inherit;
|
||||
opacity: 0.85;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import Modal from 'ant-design-vue/lib/modal/Modal';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import useAlarmStore from '@/store/modules/alarm';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
import { hasPermissions } from '@/plugins/auth-user';
|
||||
import { ref } from 'vue';
|
||||
const { isFullscreen, toggle } = useFullscreen();
|
||||
const { t, changeLocale, optionsLocale } = useI18n();
|
||||
const lockedStore = useLockedStore();
|
||||
const maskStore = useMaskStore();
|
||||
const userStore = useUserStore();
|
||||
const appStore = useAppStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
/**头像展开项点击 */
|
||||
@@ -31,15 +32,24 @@ function fnClick({ key }: MenuInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
/**锁屏确认 */
|
||||
const lockConfirm = ref<boolean>(false);
|
||||
/**锁屏密码 */
|
||||
const lockPasswd = ref<string>('');
|
||||
|
||||
/**锁屏按钮提示 */
|
||||
function fnClickLock() {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('loayouts.rightContent.lockTip'),
|
||||
onOk() {
|
||||
lockedStore.fnLock('lock');
|
||||
},
|
||||
});
|
||||
lockConfirm.value = true;
|
||||
lockPasswd.value = '';
|
||||
maskStore.lockPasswd = '';
|
||||
}
|
||||
|
||||
/**锁屏确认跳转锁屏页面 */
|
||||
function fnClickLockToPage() {
|
||||
lockConfirm.value = false;
|
||||
maskStore.lockPasswd = lockPasswd.value;
|
||||
maskStore.handleMaskType('lock');
|
||||
router.push({ name: 'LockScreen', query: { redirect: route.path } });
|
||||
}
|
||||
|
||||
/**告警数按钮提示跳转 */
|
||||
@@ -47,16 +57,6 @@ function fnClickAlarm() {
|
||||
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) {
|
||||
changeLocale(e.key);
|
||||
@@ -65,39 +65,63 @@ function fnChangeLocale(e: any) {
|
||||
|
||||
<template>
|
||||
<a-space :size="12" align="center">
|
||||
<a-button type="text" @click="fnClickAlarm">
|
||||
<template #icon>
|
||||
<a-badge
|
||||
:count="useAlarmStore().activeAlarmTotal"
|
||||
:overflow-count="99"
|
||||
status="warning"
|
||||
>
|
||||
<BellOutlined />
|
||||
</a-badge>
|
||||
</template>
|
||||
</a-button>
|
||||
|
||||
<a-tooltip placement="bottom" v-if="false">
|
||||
<template #title>{{ t('loayouts.rightContent.lock') }}</template>
|
||||
<a-button type="text" @click="fnClickLock">
|
||||
<template #icon>
|
||||
<LockOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ t('loayouts.rightContent.helpDoc') }}</template>
|
||||
<a-button type="text" @click="fnClickHelpDoc()">
|
||||
<template #title>{{ t('loayouts.rightContent.alarm') }}</template>
|
||||
<a-button type="text" style="color: inherit" @click="fnClickAlarm">
|
||||
<template #icon>
|
||||
<QuestionCircleOutlined />
|
||||
<a-badge
|
||||
:count="useAlarmStore().activeAlarmTotal"
|
||||
:overflow-count="99"
|
||||
status="warning"
|
||||
style="color: inherit"
|
||||
>
|
||||
<BellOutlined />
|
||||
</a-badge>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
<!-- 锁屏操作 -->
|
||||
<span v-perms:has="['system:setting:lock']">
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ t('loayouts.rightContent.lock') }}</template>
|
||||
<a-button type="text" style="color: inherit" @click="fnClickLock()">
|
||||
<template #icon>
|
||||
<LockOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="400"
|
||||
:minHeight="200"
|
||||
:mask-closable="false"
|
||||
v-model:visible="lockConfirm"
|
||||
:title="t('loayouts.rightContent.lockTip')"
|
||||
@ok="fnClickLockToPage()"
|
||||
>
|
||||
<a-space>
|
||||
{{ t('loayouts.rightContent.lockPasswd') }}:
|
||||
<a-input-password
|
||||
v-model:value="lockPasswd"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip
|
||||
:title="t('loayouts.rightContent.lockPasswdTip')"
|
||||
placement="topLeft"
|
||||
>
|
||||
<UnlockOutlined />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input-password>
|
||||
</a-space>
|
||||
</ProModal>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ t('loayouts.rightContent.fullscreen') }}</template>
|
||||
<a-button type="text" @click="toggle">
|
||||
<a-button type="text" style="color: inherit" @click="toggle">
|
||||
<template #icon>
|
||||
<FullscreenExitOutlined v-if="isFullscreen" />
|
||||
<FullscreenOutlined v-else />
|
||||
|
||||
@@ -4,7 +4,9 @@ import App from './App.vue';
|
||||
import router from './router';
|
||||
import directive from './directive';
|
||||
import i18n from './i18n';
|
||||
import ProModal from "antdv-pro-modal";
|
||||
import 'antdv-pro-layout/dist/style.css';
|
||||
import 'antdv-pro-modal/dist/style.css';
|
||||
import 'ant-design-vue/dist/antd.variable.min.css';
|
||||
|
||||
const app = createApp(App);
|
||||
@@ -12,5 +14,6 @@ app.use(store);
|
||||
app.use(router);
|
||||
app.use(directive);
|
||||
app.use(i18n);
|
||||
app.use(ProModal);
|
||||
|
||||
app.mount('#app');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Cookies from 'js-cookie';
|
||||
import { TOKEN_COOKIE } from '@/constants/token-constants';
|
||||
import { localRemove, localSet } from '@/utils/cache-local-utils';
|
||||
import { CACHE_LOCAL_LOCK } from '@/constants/cache-keys-constants';
|
||||
import { CACHE_LOCAL_LOCK_PASSWD, CACHE_LOCAL_MASK } from '@/constants/cache-keys-constants';
|
||||
|
||||
/**获取cookis中Token字符串 */
|
||||
export function getToken(): string {
|
||||
@@ -11,11 +11,12 @@ export function getToken(): string {
|
||||
/**设置cookis中Token字符串 */
|
||||
export function setToken(token: string): void {
|
||||
Cookies.set(TOKEN_COOKIE, token);
|
||||
localSet(CACHE_LOCAL_LOCK, 'none');
|
||||
localSet(CACHE_LOCAL_MASK, 'none');
|
||||
}
|
||||
|
||||
/**移除cookis中Token字符串,localStorage中锁屏字符串 */
|
||||
export function removeToken(): void {
|
||||
Cookies.remove(TOKEN_COOKIE);
|
||||
localRemove(CACHE_LOCAL_LOCK);
|
||||
localRemove(CACHE_LOCAL_MASK);
|
||||
localRemove(CACHE_LOCAL_LOCK_PASSWD);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,13 @@ import {
|
||||
import {
|
||||
APP_REQUEST_HEADER_CODE,
|
||||
APP_REQUEST_HEADER_VERSION,
|
||||
APP_DATA_API_KEY,
|
||||
} from '@/constants/app-constants';
|
||||
import {
|
||||
RESULT_CODE_ENCRYPT,
|
||||
RESULT_CODE_ERROR,
|
||||
RESULT_CODE_SUCCESS,
|
||||
RESULT_MSG_ENCRYPT,
|
||||
RESULT_MSG_ERROR,
|
||||
RESULT_MSG_NOT_TYPE,
|
||||
RESULT_MSG_SERVER_ERROR,
|
||||
@@ -25,11 +28,12 @@ import {
|
||||
RESULT_MSG_URL_NOTFOUND,
|
||||
RESULT_MSG_URL_RESUBMIT,
|
||||
} from '@/constants/result-constants';
|
||||
import { decryptAES, encryptAES } from '@/utils/encrypt-utils';
|
||||
|
||||
/**响应结果类型 */
|
||||
export type ResultType = {
|
||||
/**响应码 */
|
||||
code: number | 1 | 0;
|
||||
code: number;
|
||||
/**信息 */
|
||||
msg: string;
|
||||
/**数据 */
|
||||
@@ -76,6 +80,8 @@ type OptionsType = {
|
||||
body?: BodyInit;
|
||||
/**防止数据重复提交 */
|
||||
repeatSubmit?: boolean;
|
||||
/**接口数据加密 */
|
||||
crypto?: boolean;
|
||||
/**携带授权Token请求头 */
|
||||
whithToken?: boolean;
|
||||
/**中断控制信号,timeout不会生效 */
|
||||
@@ -165,26 +171,43 @@ function beforeRequest(options: OptionsType): OptionsType | Promise<any> {
|
||||
}
|
||||
}
|
||||
|
||||
// get请求拼接地址栏参数
|
||||
if (options.method === 'get' && options.params) {
|
||||
let paramStr = '';
|
||||
// 请求拼接地址栏参数
|
||||
if (options.params) {
|
||||
const params = options.params;
|
||||
const queryParams: string[] = [];
|
||||
for (const key in params) {
|
||||
const value = params[key];
|
||||
// 空字符或未定义的值不作为参数发送
|
||||
if (value === '' || value === undefined) continue;
|
||||
paramStr += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
||||
const str = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
||||
queryParams.push(str);
|
||||
}
|
||||
if (paramStr && paramStr.startsWith('&')) {
|
||||
options.url = `${options.url}?${paramStr.substring(1)}`;
|
||||
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 (options.method === 'get') return options;
|
||||
|
||||
// 非get参数提交
|
||||
if (options.data instanceof FormData) {
|
||||
options.body = options.data;
|
||||
} else {
|
||||
options.body = JSON.stringify(options.data);
|
||||
let body = options.data
|
||||
if (body instanceof FormData) {
|
||||
options.body = body;
|
||||
} 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;
|
||||
}
|
||||
@@ -199,6 +222,28 @@ function interceptorResponse(res: ResultType): ResultType | Promise<any> {
|
||||
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')) {
|
||||
return Promise.resolve({
|
||||
@@ -266,7 +311,7 @@ export async function request(options: OptionsType): Promise<ResultType> {
|
||||
case 'text': // 文本数据
|
||||
const str = await res.text();
|
||||
return {
|
||||
code: 1,
|
||||
code: RESULT_CODE_SUCCESS,
|
||||
msg: str,
|
||||
};
|
||||
case 'json': // json格式数据
|
||||
|
||||
124
src/plugins/wk-worker.ts
Normal file
124
src/plugins/wk-worker.ts
Normal file
@@ -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 使用方法
|
||||
*
|
||||
* import WS from '@/plugins/ws-websocket.ts';
|
||||
* import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
*
|
||||
* const ws = new WS();
|
||||
*
|
||||
|
||||
@@ -87,12 +87,24 @@ const constantRoutes: RouteRecordRaw[] = [
|
||||
meta: { title: 'router.helpDoc' },
|
||||
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',
|
||||
name: 'QuickStart',
|
||||
meta: { title: 'router.quickStart' },
|
||||
component: () => import('@/views/system/quick-start/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/lock-screen',
|
||||
name: 'LockScreen',
|
||||
meta: { title: 'router.lockScreen' },
|
||||
component: () => import('@/views/tool/lockScreen/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/redirect',
|
||||
name: 'Redirect',
|
||||
@@ -148,6 +160,7 @@ const WHITE_LIST: string[] = [
|
||||
'/help',
|
||||
'/register',
|
||||
'/quick-start',
|
||||
'/trace-task-hlr',
|
||||
];
|
||||
|
||||
/**全局路由-前置守卫 */
|
||||
@@ -159,11 +172,15 @@ router.beforeEach(async (to, from, next) => {
|
||||
if (!appStore.loginBackground) {
|
||||
await appStore.fnSysConf();
|
||||
}
|
||||
|
||||
|
||||
// 需要系统引导跳转
|
||||
if (appStore.bootloader && to.path !== '/quick-start') {
|
||||
next({ name: 'QuickStart' });
|
||||
}
|
||||
// 不重复引导
|
||||
if (!appStore.bootloader && to.path === '/quick-start') {
|
||||
next({ name: 'Index' });
|
||||
}
|
||||
|
||||
const token = getToken();
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ const useDictStore = defineStore('dict', {
|
||||
{
|
||||
label: data.dictLabel,
|
||||
value: data.dictValue,
|
||||
elTagType: data.tagType,
|
||||
elTagClass: data.tagClass,
|
||||
tagType: data.tagType,
|
||||
tagClass: data.tagClass,
|
||||
},
|
||||
];
|
||||
},
|
||||
@@ -47,8 +47,8 @@ const useDictStore = defineStore('dict', {
|
||||
const dictData: DictType[] = res.data.map(d => ({
|
||||
label: d.dictLabel,
|
||||
value: d.dictValue,
|
||||
elTagType: d.tagType,
|
||||
elTagClass: d.tagClass,
|
||||
tagType: d.tagType,
|
||||
tagClass: d.tagClass,
|
||||
}));
|
||||
this.dicts.set(key, dictData);
|
||||
disct = dictData;
|
||||
|
||||
@@ -10,10 +10,10 @@ type LayoutStore = {
|
||||
proConfig: {
|
||||
/**导航布局 */
|
||||
layout: 'side' | 'top' | 'mix';
|
||||
/**导航菜单主题色 */
|
||||
navTheme: 'dark' | 'light';
|
||||
/**顶部导航主题,仅导航布局为mix时生效 */
|
||||
headerTheme: 'dark' | 'light';
|
||||
/**全局主题色,需要导入样式文件 */
|
||||
theme: 'dark' | 'light';
|
||||
/**菜单导航主题色 */
|
||||
menuTheme: 'dark' | 'light';
|
||||
/**固定顶部栏 */
|
||||
fixedHeader: boolean;
|
||||
/**固定菜单栏 */
|
||||
@@ -41,8 +41,8 @@ const proConfigLocal: LayoutStore['proConfig'] = localGetJSON(
|
||||
CACHE_LOCAL_PROCONFIG
|
||||
) || {
|
||||
layout: 'mix',
|
||||
headerTheme: 'light',
|
||||
navTheme: 'light',
|
||||
theme: 'light',
|
||||
menuTheme: 'light',
|
||||
fixSiderbar: true,
|
||||
fixedHeader: true,
|
||||
splitMenus: true,
|
||||
@@ -53,8 +53,8 @@ const useLayoutStore = defineStore('layout', {
|
||||
visible: false,
|
||||
proConfig: {
|
||||
layout: proConfigLocal.layout,
|
||||
navTheme: proConfigLocal.navTheme,
|
||||
headerTheme: proConfigLocal.headerTheme,
|
||||
theme: proConfigLocal.theme,
|
||||
menuTheme: proConfigLocal.menuTheme,
|
||||
fixedHeader: Boolean(proConfigLocal.fixedHeader),
|
||||
fixSiderbar: Boolean(proConfigLocal.fixSiderbar),
|
||||
splitMenus: Boolean(proConfigLocal.splitMenus),
|
||||
@@ -77,10 +77,6 @@ const useLayoutStore = defineStore('layout', {
|
||||
/**修改布局设置 */
|
||||
changeConf(key: string, value: boolean | string | number | undefined) {
|
||||
if (Reflect.has(this.proConfig, key)) {
|
||||
// 同时修改mix混合菜单的导航主题
|
||||
if (key === 'navTheme') {
|
||||
Reflect.set(this.proConfig, 'headerTheme', value);
|
||||
}
|
||||
Reflect.set(this.proConfig, key, value);
|
||||
localSetJSON(CACHE_LOCAL_PROCONFIG, this.proConfig);
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
import { getSysConf } from '@/api';
|
||||
import { CACHE_LOCAL_LOCK } from '@/constants/cache-keys-constants';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
/**锁屏信息类型 */
|
||||
type Locked = {
|
||||
/**锁屏类型 */
|
||||
type: 'none' | 'lock' | 'reload' | 'reset';
|
||||
/**lock 超时锁屏时间,秒*/
|
||||
lockTimeout: number;
|
||||
};
|
||||
|
||||
const useLockedStore = defineStore('locked', {
|
||||
state: (): Locked => ({
|
||||
type: (localGet(CACHE_LOCAL_LOCK) || 'none') as Locked['type'],
|
||||
lockTimeout: 0,
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// 重启等待-轮询
|
||||
async relaodWait() {
|
||||
try {
|
||||
const res = await getSysConf();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.fnLock('none');
|
||||
window.location.reload();
|
||||
}, 2_000);
|
||||
} else {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.relaodWait();
|
||||
}, 5_000);
|
||||
}
|
||||
} catch (error) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.relaodWait();
|
||||
}, 5_000);
|
||||
}
|
||||
},
|
||||
// 设置锁定
|
||||
async fnLock(type: Locked['type']) {
|
||||
this.type = type;
|
||||
localSet(CACHE_LOCAL_LOCK, type);
|
||||
if (type === 'reload') {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.relaodWait();
|
||||
}, 2_000);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default useLockedStore;
|
||||
70
src/store/modules/mask.ts
Normal file
70
src/store/modules/mask.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { getSysConf } from '@/api';
|
||||
import {
|
||||
CACHE_LOCAL_LOCK_PASSWD,
|
||||
CACHE_LOCAL_MASK,
|
||||
} from '@/constants/cache-keys-constants';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { localGet, localRemove, localSet } from '@/utils/cache-local-utils';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
/**全局遮罩信息类型 */
|
||||
type MaskStateType = {
|
||||
/**锁屏类型 */
|
||||
type: 'none' | 'lock' | 'reload' | 'reset';
|
||||
/**lock 锁屏密码*/
|
||||
lockPasswd: string;
|
||||
/**lock 超时锁屏时间,秒*/
|
||||
lockTimeout: number;
|
||||
};
|
||||
|
||||
const useMaskStore = defineStore('mask', {
|
||||
state: (): MaskStateType => ({
|
||||
type: (localGet(CACHE_LOCAL_MASK) || 'none') as MaskStateType['type'],
|
||||
lockPasswd: localGet(CACHE_LOCAL_LOCK_PASSWD) || '',
|
||||
lockTimeout: 0,
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// 检查服务等待-轮询
|
||||
async checkServiceWait() {
|
||||
try {
|
||||
const res = await getSysConf();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.handleMaskType('none');
|
||||
window.location.reload();
|
||||
}, 2_000);
|
||||
} else {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.checkServiceWait();
|
||||
}, 5_000);
|
||||
}
|
||||
} catch (error) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.checkServiceWait();
|
||||
}, 5_000);
|
||||
}
|
||||
},
|
||||
// 设置遮罩类型
|
||||
async handleMaskType(type: MaskStateType['type']) {
|
||||
this.type = type;
|
||||
localSet(CACHE_LOCAL_MASK, type);
|
||||
if (type === 'reload') {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.checkServiceWait();
|
||||
}, 5_000);
|
||||
}
|
||||
if (type === 'lock') {
|
||||
localSet(CACHE_LOCAL_LOCK_PASSWD, this.lockPasswd);
|
||||
} else {
|
||||
localRemove(CACHE_LOCAL_LOCK_PASSWD);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default useMaskStore;
|
||||
@@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { listAllNeInfo } from '@/api/ne/neInfo';
|
||||
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';
|
||||
|
||||
/**网元信息类型 */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import {
|
||||
import type {
|
||||
RouteComponent,
|
||||
RouteLocationRaw,
|
||||
RouteMeta,
|
||||
|
||||
@@ -9,6 +9,8 @@ import { parseUrlPath } from '@/plugins/file-static-url';
|
||||
|
||||
/**用户信息类型 */
|
||||
type UserInfo = {
|
||||
/**用户ID */
|
||||
userId: string;
|
||||
/**登录账号 */
|
||||
userName: string;
|
||||
/**用户角色 字符串数组 */
|
||||
@@ -31,6 +33,7 @@ type UserInfo = {
|
||||
|
||||
const useUserStore = defineStore('user', {
|
||||
state: (): UserInfo => ({
|
||||
userId: '',
|
||||
userName: '',
|
||||
roles: [],
|
||||
permissions: [],
|
||||
@@ -109,6 +112,7 @@ const useUserStore = defineStore('user', {
|
||||
const res = await getInfo();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
const { user, roles, permissions } = res.data;
|
||||
this.userId = user.userId;
|
||||
// 登录账号
|
||||
this.userName = user.userName;
|
||||
// 用户头像
|
||||
|
||||
4
src/typings/dict.d.ts
vendored
4
src/typings/dict.d.ts
vendored
@@ -2,6 +2,6 @@
|
||||
type DictType = {
|
||||
label: string;
|
||||
value: string;
|
||||
elTagType: string;
|
||||
elTagClass: string;
|
||||
tagType?: string;
|
||||
tagClass?: string;
|
||||
};
|
||||
|
||||
50
src/utils/encrypt-utils.ts
Normal file
50
src/utils/encrypt-utils.ts
Normal file
@@ -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 {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文件大小
|
||||
* @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 数值大小
|
||||
@@ -153,15 +172,16 @@ export function parseSizeFromKbs(sizeByte: number, timeInterval: number): any {
|
||||
|
||||
/**
|
||||
* 字节数转换单位
|
||||
* @param bits 字节Bit大小
|
||||
* @returns MB
|
||||
* @param bits 字节Bit大小 64009540 = 512.08 MB
|
||||
* @returns xx B / KB / MB / GB / TB / PB / EB / ZB / YB
|
||||
*/
|
||||
export function parseSizeFromBits(bits: number | string): string {
|
||||
bits = Number(bits) || 0;
|
||||
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 value = (bits / Math.pow(1024, unitIndex)).toFixed(2);
|
||||
const value = (bits / Math.pow(1000, unitIndex)).toFixed(2);
|
||||
const unti = units[unitIndex];
|
||||
return `${value} ${unti}`;
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ export const regExpPort =
|
||||
/**
|
||||
* 有效账号格式
|
||||
*
|
||||
* 账号不能以数字开头,可包含大写小写字母,数字,且不少于5位
|
||||
* 账号只能包含大写字母、小写字母和数字的字符串,长度至少为6位
|
||||
*/
|
||||
export const regExpUserName = /^[a-zA-Z][a-z0-9A-Z]{4,}$/;
|
||||
export const regExpUserName = /^[A-Za-z0-9]{6,}$/;
|
||||
|
||||
/**
|
||||
* 有效密码格式
|
||||
@@ -91,7 +91,7 @@ export function validURL(str: string) {
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (u.host.startsWith('.')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ const { getDict } = useDictStore();
|
||||
|
||||
/**用户性别字典 */
|
||||
let sysUserSex = ref<DictType[]>([
|
||||
{ label: '未知', value: '0', elTagType: '', elTagClass: '' },
|
||||
{ label: '男', value: '1', elTagType: '', elTagClass: '' },
|
||||
{ label: '女', value: '2', elTagType: '', elTagClass: '' },
|
||||
{ label: '未知', value: '0', tagType: '', tagClass: '' },
|
||||
{ label: '男', value: '1', tagType: '', tagClass: '' },
|
||||
{ label: '女', value: '2', tagType: '', tagClass: '' },
|
||||
]);
|
||||
|
||||
/**表单数据状态 */
|
||||
|
||||
@@ -72,9 +72,9 @@ function fnColorChange(e: Event) {
|
||||
<a-switch
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
:checked="proConfig.navTheme === 'dark'"
|
||||
:checked="proConfig.menuTheme === 'dark'"
|
||||
@change="
|
||||
(checked:any) => changeConf('navTheme', checked ? 'dark' : 'light')
|
||||
(checked:any) => changeConf('menuTheme', checked ? 'dark' : 'light')
|
||||
"
|
||||
></a-switch>
|
||||
</template>
|
||||
|
||||
@@ -481,8 +481,10 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -505,7 +507,7 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
@@ -26,8 +26,8 @@ import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
const lockedStore = useLockedStore();
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
const maskStore = useMaskStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**表格所需option */
|
||||
@@ -550,7 +550,7 @@ function fnRecordRestart(row: Record<string, any>) {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// OMC自升级
|
||||
if (row.neType.toLowerCase() === 'omc') {
|
||||
lockedStore.fnLock('reload');
|
||||
maskStore.handleMaskType('reload');
|
||||
return;
|
||||
}
|
||||
message.success({
|
||||
@@ -972,8 +972,10 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -1168,11 +1170,13 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 导入框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByImport"
|
||||
@@ -1259,7 +1263,7 @@ onMounted(() => {
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
437
src/views/configManage/neOverview/index.vue
Normal file
437
src/views/configManage/neOverview/index.vue
Normal file
@@ -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>
|
||||
@@ -167,7 +167,11 @@ function fnGetList(pageNum?: number) {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
if (tablePagination.total <=(queryParams.pageNum - 1) * tablePagination.pageSize &&queryParams.pageNum !== 1) {
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
@@ -197,15 +201,16 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="100%"
|
||||
wrap-class-name="full-modal"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:forceFullscreen="true"
|
||||
:destroyOnClose="true"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@cancel="fnModalCancel"
|
||||
:footer="null"
|
||||
:footer="false"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
@@ -265,7 +270,7 @@ watch(
|
||||
:pagination="tablePagination"
|
||||
>
|
||||
</a-table>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -273,22 +278,3 @@ watch(
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.full-modal {
|
||||
.ant-modal {
|
||||
max-width: 100%;
|
||||
top: 0;
|
||||
padding-bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.ant-modal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh);
|
||||
}
|
||||
.ant-modal-body {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -23,8 +23,8 @@ import useI18n from '@/hooks/useI18n';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { FileType } from 'ant-design-vue/lib/upload/interface';
|
||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
const lockedStore = useLockedStore();
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
const maskStore = useMaskStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**查询参数 */
|
||||
@@ -299,7 +299,7 @@ function fnFileModalOk() {
|
||||
if (type === 'run' && from.neType.toLowerCase() === 'omc') {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
fnFileModalCancel();
|
||||
lockedStore.fnLock('reload');
|
||||
maskStore.handleMaskType('reload');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${fileModalState.title} ${res.msg}`,
|
||||
@@ -425,8 +425,6 @@ function fnGetList(pageNum?: number) {
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
debugger;
|
||||
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
@@ -919,8 +917,9 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 上传框 -->
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -1012,7 +1011,7 @@ onMounted(() => {
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 上传激活历史 -->
|
||||
<SoftwareHistory
|
||||
@@ -1022,8 +1021,8 @@ onMounted(() => {
|
||||
/>
|
||||
|
||||
<!-- 文件框 下发激活 -->
|
||||
<a-modal
|
||||
width="600px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="fileModalState.visible"
|
||||
@@ -1051,11 +1050,11 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 回退框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="fileModalState.visibleByBack"
|
||||
@@ -1086,7 +1085,7 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -11,8 +11,9 @@ import {
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { listAMFDataUE, delAMFDataUE } from '@/api/neData/amf';
|
||||
import { listAMFDataUE, delAMFDataUE, exportAMFDataUE } from '@/api/neData/amf';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import saveAs from 'file-saver';
|
||||
import PQueue from 'p-queue';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
@@ -33,15 +34,22 @@ let dict: {
|
||||
ueEventCmState: [],
|
||||
});
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'AMF',
|
||||
neId: '001',
|
||||
eventType: 'auth-result',
|
||||
eventType: '',
|
||||
imsi: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
@@ -50,20 +58,23 @@ let queryParams = reactive({
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
eventTypes.value = ['auth-result'];
|
||||
eventTypes.value = [];
|
||||
queryParams = Object.assign(queryParams, {
|
||||
eventType: 'auth-result',
|
||||
eventType: '',
|
||||
imsi: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**记录类型 */
|
||||
const eventTypes = ref<string[]>(['auth-result']);
|
||||
const eventTypes = ref<string[]>([]);
|
||||
|
||||
/**查询记录类型变更 */
|
||||
function fnQueryEventTypeChange(value: any) {
|
||||
@@ -241,6 +252,11 @@ function fnGetList(pageNum?: number) {
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listAMFDataUE(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
@@ -275,6 +291,39 @@ function fnGetList(pageNum?: number) {
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportAMFDataUE(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `amf_ue_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
@@ -290,7 +339,7 @@ function fnRealTime() {
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* UE会话事件-AMF (GroupID:1010)
|
||||
* AMF_UE会话事件(GroupID:1010)
|
||||
*/
|
||||
subGroupID: '1010',
|
||||
},
|
||||
@@ -321,7 +370,7 @@ function wsMessage(res: Record<string, any>) {
|
||||
if (!data?.groupId) {
|
||||
return;
|
||||
}
|
||||
// ueEvent CDR会话事件
|
||||
// ueEvent AMF_UE会话事件
|
||||
if (data.groupId === '1010') {
|
||||
const ueEvent = data.data;
|
||||
queue.add(async () => {
|
||||
@@ -399,7 +448,7 @@ onBeforeUnmount(() => {
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item label="IMSI" name="imsi ">
|
||||
<a-input
|
||||
v-model:value="queryParams.imsi"
|
||||
@@ -408,6 +457,22 @@ onBeforeUnmount(() => {
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
@@ -461,6 +526,11 @@ onBeforeUnmount(() => {
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
@@ -537,10 +607,7 @@ onBeforeUnmount(() => {
|
||||
:value="record.eventJSON.authCode"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
v-if="record.eventType === 'detach'"
|
||||
:title="record.eventJSON.detachTime"
|
||||
>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
<span>{{ t('views.dashboard.ue.resultOk') }}</span>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
@@ -592,11 +659,11 @@ onBeforeUnmount(() => {
|
||||
{{ t('views.dashboard.ue.ueInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.neName') }}: </span>
|
||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||
<span>{{ record.neName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.rmUID') }}: </span>
|
||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||
<span>{{ record.rmUID }}</span>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
@@ -636,7 +703,7 @@ onBeforeUnmount(() => {
|
||||
/>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
{{ t('views.dashboard.ue.resultOK') }}
|
||||
{{ t('views.dashboard.ue.resultOk') }}
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
<DictTag
|
||||
|
||||
@@ -11,9 +11,15 @@ import {
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { delIMSDataCDR, listIMSDataCDR } from '@/api/neData/ims';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import {
|
||||
delIMSDataCDR,
|
||||
exportIMSDataCDR,
|
||||
listIMSDataCDR,
|
||||
} from '@/api/neData/ims';
|
||||
import { parseDateToStr, parseDuration } from '@/utils/date-utils';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import saveAs from 'file-saver';
|
||||
import PQueue from 'p-queue';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
@@ -31,16 +37,26 @@ let dict: {
|
||||
cdrCallType: [],
|
||||
});
|
||||
|
||||
/**网元可选 */
|
||||
let neOtions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'IMS',
|
||||
neId: '001',
|
||||
recordType: 'MOC',
|
||||
recordType: '',
|
||||
callerParty: '',
|
||||
calledParty: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
@@ -49,21 +65,24 @@ let queryParams = reactive({
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
recordTypes.value = ['MOC'];
|
||||
recordTypes.value = [];
|
||||
queryParams = Object.assign(queryParams, {
|
||||
recordType: 'MOC',
|
||||
recordType: '',
|
||||
callerParty: '',
|
||||
calledParty: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**记录类型 */
|
||||
const recordTypes = ref<string[]>(['MOC']);
|
||||
const recordTypes = ref<string[]>([]);
|
||||
|
||||
/**查询记录类型变更 */
|
||||
function fnQueryRecordTypeChange(value: any) {
|
||||
@@ -120,17 +139,6 @@ let tableColumns: ColumnsType = [
|
||||
align: 'left',
|
||||
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'),
|
||||
dataIndex: 'cdrJSON',
|
||||
@@ -142,6 +150,17 @@ let tableColumns: ColumnsType = [
|
||||
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'),
|
||||
dataIndex: 'cdrJSON',
|
||||
@@ -279,6 +298,11 @@ function fnGetList(pageNum?: number) {
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listIMSDataCDR(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
@@ -313,6 +337,39 @@ function fnGetList(pageNum?: number) {
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportIMSDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `ims_cdr_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
@@ -322,15 +379,16 @@ const realTimeData = ref<boolean>(false);
|
||||
function fnRealTime() {
|
||||
realTimeData.value = !realTimeData.value;
|
||||
if (realTimeData.value) {
|
||||
tableState.seached = false;
|
||||
// 建立链接
|
||||
const options: OptionsType = {
|
||||
url: '/ws',
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* CDR会话事件-IMS (GroupID:1005)
|
||||
* IMS_CDR会话事件(GroupID:1005)
|
||||
*/
|
||||
subGroupID: '1005',
|
||||
subGroupID: `1005_${queryParams.neId}`,
|
||||
},
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
@@ -338,6 +396,8 @@ function fnRealTime() {
|
||||
ws.connect(options);
|
||||
} else {
|
||||
ws.close();
|
||||
tableState.seached = true;
|
||||
fnGetList(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +420,7 @@ function wsMessage(res: Record<string, any>) {
|
||||
return;
|
||||
}
|
||||
// cdrEvent CDR会话事件
|
||||
if (data.groupId === '1005') {
|
||||
if (data.groupId === `1005_${queryParams.neId}`) {
|
||||
const cdrEvent = data.data;
|
||||
queue.add(async () => {
|
||||
modalState.maxId += 1;
|
||||
@@ -383,14 +443,39 @@ function wsMessage(res: Record<string, any>) {
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([getDict('cdr_sip_code'), getDict('cdr_call_type')])
|
||||
.then(resArr => {
|
||||
Promise.allSettled([getDict('cdr_sip_code'), getDict('cdr_call_type')]).then(
|
||||
resArr => {
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
dict.cdrSipCode = resArr[0].value;
|
||||
}
|
||||
if (resArr[1].status === 'fulfilled') {
|
||||
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(() => {
|
||||
// 获取列表数据
|
||||
@@ -415,26 +500,19 @@ onBeforeUnmount(() => {
|
||||
<!-- 表格搜索栏 -->
|
||||
<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.dashboard.cdr.recordType')"
|
||||
name="recordType "
|
||||
>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item label="IMS" name="neId ">
|
||||
<a-select
|
||||
v-model:value="recordTypes"
|
||||
mode="multiple"
|
||||
:options="
|
||||
['MOC', 'MTC', 'MOSM', 'MTSM'].map(v => ({ value: v }))
|
||||
"
|
||||
v-model:value="queryParams.neId"
|
||||
:options="neOtions"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
@change="fnQueryRecordTypeChange"
|
||||
></a-select>
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.called')"
|
||||
name="calledParty "
|
||||
name="calledParty"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="queryParams.calledParty"
|
||||
@@ -443,7 +521,7 @@ onBeforeUnmount(() => {
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.caller')"
|
||||
name="callerParty "
|
||||
@@ -469,6 +547,38 @@ onBeforeUnmount(() => {
|
||||
</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="
|
||||
['MOC', 'MTC', '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>
|
||||
@@ -508,6 +618,11 @@ onBeforeUnmount(() => {
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
@@ -521,6 +636,7 @@ onBeforeUnmount(() => {
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
:disabled="realTimeData"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
@@ -565,7 +681,7 @@ onBeforeUnmount(() => {
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
||||
:scroll="{ x: tableColumns.length * 150, y: 'calc(100vh - 480px)' }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
columnWidth: '48px',
|
||||
@@ -585,11 +701,11 @@ onBeforeUnmount(() => {
|
||||
<DictTag
|
||||
:options="dict.cdrSipCode"
|
||||
:value="record.cdrJSON.cause"
|
||||
value-option="0"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ t('views.dashboard.overview.userActivity.resultOK') }}
|
||||
{{ t('views.dashboard.cdr.resultOk') }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'id'">
|
||||
@@ -614,11 +730,11 @@ onBeforeUnmount(() => {
|
||||
{{ t('views.dashboard.cdr.cdrInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.cdr.neName') }}: </span>
|
||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||
<span>{{ record.neName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.cdr.rmUID') }}: </span>
|
||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||
<span>{{ record.rmUID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -656,11 +772,11 @@ onBeforeUnmount(() => {
|
||||
<DictTag
|
||||
:options="dict.cdrSipCode"
|
||||
:value="record.cdrJSON.cause"
|
||||
value-option="0"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ t('views.dashboard.overview.userActivity.resultOK') }}
|
||||
{{ t('views.dashboard.cdr.resultOk') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
744
src/views/dashboard/mmeUE/index.vue
Normal file
744
src/views/dashboard/mmeUE/index.vue
Normal file
@@ -0,0 +1,744 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, ref, onBeforeUnmount } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { message, Modal } from 'ant-design-vue/lib';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import {
|
||||
RESULT_CODE_ERROR,
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { listMMEDataUE, delMMEDataUE, exportMMEDataUE } from '@/api/neData/mme';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import saveAs from 'file-saver';
|
||||
import PQueue from 'p-queue';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
const ws = new WS();
|
||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||
|
||||
/**网元可选 */
|
||||
let neOtions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**event Type */
|
||||
let mmeEventType = ref<DictType[]>([]);
|
||||
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
/**UE 事件认证代码类型 */
|
||||
ueAauthCode: DictType[];
|
||||
/**UE 事件类型 */
|
||||
ueEventType: DictType[];
|
||||
/**UE 事件CM状态 */
|
||||
ueEventCmState: DictType[];
|
||||
} = reactive({
|
||||
ueAauthCode: [],
|
||||
ueEventType: [],
|
||||
ueEventCmState: [],
|
||||
});
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'MME',
|
||||
neId: '001',
|
||||
eventType: '',
|
||||
imsi: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
eventTypes.value = [];
|
||||
queryParams = Object.assign(queryParams, {
|
||||
eventType: '',
|
||||
imsi: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**记录类型 */
|
||||
const eventTypes = ref<string[]>([]);
|
||||
|
||||
/**查询记录类型变更 */
|
||||
function fnQueryEventTypeChange(value: any) {
|
||||
if (Array.isArray(value)) {
|
||||
queryParams.eventType = value.join(',');
|
||||
}
|
||||
}
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: 'IMSI',
|
||||
dataIndex: 'eventJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const eventJSON = opt.value;
|
||||
return eventJSON.imsi;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.eventType'),
|
||||
dataIndex: 'eventType',
|
||||
key: 'eventType',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.result'),
|
||||
dataIndex: 'eventJSON',
|
||||
key: 'result',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.time'),
|
||||
dataIndex: 'eventJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return parseDateToStr(+cdrJSON.timestamp * 1000);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'id',
|
||||
align: 'left',
|
||||
},
|
||||
];
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
current: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
/**默认的每页条数 */
|
||||
defaultPageSize: 20,
|
||||
/**指定每页可以显示多少条 */
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
/**只有一页时是否隐藏分页器 */
|
||||
hideOnSinglePage: false,
|
||||
/**是否可以快速跳转至某页 */
|
||||
showQuickJumper: true,
|
||||
/**是否可以改变 pageSize */
|
||||
showSizeChanger: true,
|
||||
/**数据总数 */
|
||||
total: 0,
|
||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
||||
onChange: (page: number, pageSize: number) => {
|
||||
tablePagination.current = page;
|
||||
tablePagination.pageSize = pageSize;
|
||||
queryParams.pageNum = page;
|
||||
queryParams.pageSize = pageSize;
|
||||
fnGetList();
|
||||
},
|
||||
});
|
||||
|
||||
/**表格紧凑型变更操作 */
|
||||
function fnTableSize({ key }: MenuInfo) {
|
||||
tableState.size = key as SizeType;
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
/**最大ID值 */
|
||||
maxId: number;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
confirmLoading: false,
|
||||
maxId: 0,
|
||||
});
|
||||
|
||||
/**
|
||||
* 记录删除
|
||||
* @param id 编号
|
||||
*/
|
||||
function fnRecordDelete(id: string) {
|
||||
if (!id || modalState.confirmLoading) return;
|
||||
let msg = id;
|
||||
if (id === '0') {
|
||||
msg = `${id}... ${tableState.selectedRowKeys.length}`;
|
||||
id = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.delTip', { msg }),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
delMMEDataUE(id)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
fnGetList(1);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**查询列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listMMEDataUE(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
if (tableState.selectedRowKeys.length > 0) {
|
||||
tableState.selectedRowKeys = [];
|
||||
}
|
||||
tablePagination.total = res.total;
|
||||
// 遍历处理cdr字符串数据
|
||||
tableState.data = res.rows.map(item => {
|
||||
let eventJSON = item.eventJSON;
|
||||
if (!eventJSON) {
|
||||
Reflect.set(item, 'eventJSON', {});
|
||||
}
|
||||
|
||||
try {
|
||||
eventJSON = JSON.parse(eventJSON);
|
||||
Reflect.set(item, 'eventJSON', eventJSON);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Reflect.set(item, 'eventJSON', {});
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
// 取最大值ID用作实时累加
|
||||
if (res.total > 0) {
|
||||
modalState.maxId = Number(res.rows[0].id);
|
||||
}
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportMMEDataUE(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `mme_ue_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
/**
|
||||
* 实时数据
|
||||
*/
|
||||
function fnRealTime() {
|
||||
realTimeData.value = !realTimeData.value;
|
||||
if (realTimeData.value) {
|
||||
tableState.seached = false;
|
||||
// 建立链接
|
||||
const options: OptionsType = {
|
||||
url: '/ws',
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* MME_UE会话事件(GroupID:1011)
|
||||
*/
|
||||
subGroupID: `1011_${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;
|
||||
}
|
||||
// ueEvent MME_UE会话事件
|
||||
if (data.groupId === `1011_${queryParams.neId}`) {
|
||||
const ueEvent = data.data;
|
||||
queue.add(async () => {
|
||||
modalState.maxId += 1;
|
||||
tableState.data.unshift({
|
||||
id: modalState.maxId,
|
||||
neType: ueEvent.neType,
|
||||
neName: ueEvent.neName, // 空
|
||||
rmUID: ueEvent.rmUID, // 空
|
||||
timestamp: ueEvent.timestamp,
|
||||
eventType: ueEvent.eventType,
|
||||
eventJSON: ueEvent.eventJSON,
|
||||
});
|
||||
tablePagination.total += 1;
|
||||
if (tableState.data.length > 100) {
|
||||
tableState.data.pop();
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([
|
||||
getDict('ue_auth_code'),
|
||||
getDict('ue_event_type'),
|
||||
getDict('ue_event_cm_state'),
|
||||
]).then(resArr => {
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
dict.ueAauthCode = resArr[0].value;
|
||||
}
|
||||
if (resArr[1].status === 'fulfilled') {
|
||||
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') {
|
||||
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(() => {
|
||||
// 获取列表数据
|
||||
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="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-form-item
|
||||
:label="t('views.dashboard.ue.eventType')"
|
||||
name="eventType "
|
||||
>
|
||||
<a-select
|
||||
v-model:value="eventTypes"
|
||||
mode="multiple"
|
||||
:options="mmeEventType"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
@change="fnQueryEventTypeChange"
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item label="IMSI" name="imsi ">
|
||||
<a-input
|
||||
v-model:value="queryParams.imsi"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-popconfirm
|
||||
placement="bottomLeft"
|
||||
:title="
|
||||
!realTimeData
|
||||
? t('views.dashboard.ue.realTimeDataStart')
|
||||
: t('views.dashboard.ue.realTimeDataStop')
|
||||
"
|
||||
ok-text="Yes"
|
||||
cancel-text="No"
|
||||
@confirm="fnRealTime()"
|
||||
>
|
||||
<a-button type="primary" :danger="realTimeData">
|
||||
<template #icon><FundOutlined /> </template>
|
||||
{{
|
||||
!realTimeData
|
||||
? t('views.dashboard.ue.realTimeDataStart')
|
||||
: t('views.dashboard.ue.realTimeDataStop')
|
||||
}}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
: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 * 120, y: 'calc(100vh - 480px)' }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
columnWidth: '48px',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'eventType'">
|
||||
<DictTag :options="mmeEventType" :value="record.eventType" />
|
||||
</template>
|
||||
<template v-if="column.key === 'result'">
|
||||
<span v-if="record.eventType === 'auth-result'">
|
||||
<DictTag
|
||||
:options="dict.ueAauthCode"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
<span>{{ t('views.dashboard.ue.resultOk') }}</span>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
<DictTag
|
||||
:options="dict.ueEventCmState"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'id'">
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.deleteText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.id)"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
<template #expandedRowRender="{ record }">
|
||||
<div style="width: 46%; padding-left: 32px; padding-bottom: 16px">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.ue.ueInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||
<span>{{ record.neName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||
<span>{{ record.rmUID }}</span>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.ue.rowInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.time') }}: </span>
|
||||
{{ parseDateToStr(record.eventJSON.timestamp * 1000) }}
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
|
||||
<DictTag :options="mmeEventType" :value="record.eventType" />
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.result') }}: </span>
|
||||
<span v-if="record.eventType === 'auth-result'">
|
||||
<DictTag
|
||||
:options="dict.ueAauthCode"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
{{ t('views.dashboard.ue.resultOk') }}
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
<DictTag
|
||||
:options="dict.ueEventCmState"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -56,8 +56,9 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
@@ -82,7 +83,7 @@ watch(
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@@ -10,7 +10,7 @@ import UserActivity from '../overview/components/UserActivity/index.vue';
|
||||
import AlarnTypeBar from './components/AlarnTypeBar/index.vue';
|
||||
import setting from './components/setting.vue';
|
||||
import UPFFlow from '../overview/components/UPFFlow/index.vue';
|
||||
import { listSub } from '@/api/neUser/sub';
|
||||
import { listUDMSub } from '@/api/neData/udm_sub';
|
||||
import { listUENumBySMF } from '@/api/neUser/smf';
|
||||
import { listUENumByIMS } from '@/api/neUser/ims';
|
||||
import { listBase5G } from '@/api/neUser/base5G';
|
||||
@@ -31,7 +31,7 @@ import { dbGetJSON } from '@/utils/cache-db-utils';
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const { t } = useI18n();
|
||||
const { wsSend, cdrEventSend, ueEventSend, upfTFSend } = useWS();
|
||||
const { wsSend, userActivitySend, upfTFSend } = useWS();
|
||||
|
||||
/**概览状态类型 */
|
||||
type SkimStateType = {
|
||||
@@ -97,7 +97,7 @@ function fnGetNeState() {
|
||||
/**获取概览信息 */
|
||||
async function fnGetSkim() {
|
||||
const resArr = await Promise.allSettled([
|
||||
listSub({
|
||||
listUDMSub({
|
||||
neid: '001',
|
||||
pageNum: 1,
|
||||
pageSize: 1,
|
||||
@@ -157,23 +157,26 @@ async function fnGetSkim() {
|
||||
/**初始数据函数 */
|
||||
function loadData() {
|
||||
fnGetNeState(); // 获取网元状态
|
||||
cdrEventSend();
|
||||
ueEventSend();
|
||||
upfTFSend(0);
|
||||
upfTFSend(7);
|
||||
upfTFSend(30);
|
||||
userActivitySend();
|
||||
upfTFSend('0');
|
||||
upfTFSend('7');
|
||||
upfTFSend('30');
|
||||
|
||||
clearInterval(interval10s.value);
|
||||
interval10s.value = setInterval(() => {
|
||||
upfTFActive.value = upfTFActive.value >= 2 ? 0 : upfTFActive.value + 1;
|
||||
if (upfTFActive.value === 0) {
|
||||
upfTFSend(7);
|
||||
} else if (upfTFActive.value === 1) {
|
||||
upfTFSend(30);
|
||||
} else if (upfTFActive.value === 2) {
|
||||
upfTFSend(0);
|
||||
if (upfTFActive.value === '0') {
|
||||
upfTFSend('7');
|
||||
upfTFActive.value = '7';
|
||||
} else if (upfTFActive.value === '7') {
|
||||
upfTFSend('30');
|
||||
upfTFActive.value = '30';
|
||||
} else if (upfTFActive.value === '30') {
|
||||
upfTFSend('0');
|
||||
upfTFActive.value = '0';
|
||||
}
|
||||
}, 10_000);
|
||||
|
||||
clearInterval(interval5s.value);
|
||||
interval5s.value = setInterval(() => {
|
||||
fnGetSkim(); // 获取概览信息
|
||||
fnGetNeState(); // 获取网元状态
|
||||
@@ -426,12 +429,12 @@ function fnRightClick() {
|
||||
<div class="filter">
|
||||
<span
|
||||
:data-key="v"
|
||||
:class="{ active: upfTFActive === i }"
|
||||
v-for="(v, i) in ['0', '7', '30']"
|
||||
:class="{ active: upfTFActive === v }"
|
||||
v-for="v in ['0', '7', '30']"
|
||||
:key="v"
|
||||
@click="
|
||||
() => {
|
||||
upfTFActive = i;
|
||||
upfTFActive = v;
|
||||
}
|
||||
"
|
||||
>
|
||||
@@ -451,14 +454,14 @@ function fnRightClick() {
|
||||
<ArrowUpOutlined style="color: #597ef7" />
|
||||
{{ t('views.dashboard.overview.upfFlowTotal.up') }}
|
||||
</span>
|
||||
<h4>{{ upfTotalFlow[upfTFActive].up }}</h4>
|
||||
<h4>{{ upfTotalFlow[upfTFActive].upFrom }}</h4>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span>
|
||||
<ArrowDownOutlined style="color: #52c41a" />
|
||||
{{ t('views.dashboard.overview.upfFlowTotal.down') }}
|
||||
</span>
|
||||
<h4>{{ upfTotalFlow[upfTFActive].down }}</h4>
|
||||
<h4>{{ upfTotalFlow[upfTFActive].downFrom }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -237,7 +237,7 @@ function handleRanderChart(
|
||||
|
||||
function fnChangeData(data: any[], itemID: string) {
|
||||
let info = data.find((item: any) => item.id === itemID);
|
||||
if (!info.neState.online) return;
|
||||
if (!info || !info.neState.online) return;
|
||||
// if (!info.neState.online) {
|
||||
// info = data.find((item: any) => item.id === itemID);
|
||||
// graphNodeClickID.value = itemID;
|
||||
@@ -251,33 +251,27 @@ function fnChangeData(data: any[], itemID: string) {
|
||||
let nfCpuUsage = 0;
|
||||
if (info.neState.cpu) {
|
||||
nfCpuUsage = info.neState.cpu.nfCpuUsage;
|
||||
const nfCpu = +(info.neState.cpu.nfCpuUsage / 100);
|
||||
nfCpuUsage = +nfCpu.toFixed(2);
|
||||
if (nfCpuUsage > 100) {
|
||||
const nfCpu = +(info.neState.cpu.nfCpuUsage / 100);
|
||||
if (nfCpu > 100) {
|
||||
nfCpuUsage = 100;
|
||||
} else {
|
||||
nfCpuUsage = +nfCpu.toFixed(2);
|
||||
}
|
||||
nfCpuUsage = 100;
|
||||
}
|
||||
|
||||
sysCpuUsage = info.neState.cpu.sysCpuUsage;
|
||||
let sysCpu = +(info.neState.cpu.sysCpuUsage / 100);
|
||||
sysCpuUsage = +sysCpu.toFixed(2);
|
||||
if (sysCpuUsage > 100) {
|
||||
const sysCpu = +(info.neState.cpu.sysCpuUsage / 100);
|
||||
if (sysCpu > 100) {
|
||||
sysCpuUsage = 100;
|
||||
} else {
|
||||
sysCpuUsage = +sysCpu.toFixed(2);
|
||||
}
|
||||
sysCpuUsage = 100;
|
||||
}
|
||||
}
|
||||
|
||||
let sysMemUsage = 0;
|
||||
if (info.neState.mem) {
|
||||
let men = info.neState.mem.sysMemUsage;
|
||||
if (men > 100) {
|
||||
men = +(men / 100).toFixed(2);
|
||||
const men = info.neState.mem.sysMemUsage;
|
||||
sysMemUsage = +(men / 100).toFixed(2);
|
||||
if (sysMemUsage > 100) {
|
||||
sysMemUsage = 100;
|
||||
}
|
||||
sysMemUsage = men;
|
||||
}
|
||||
|
||||
let sysDiskUsage = 0;
|
||||
|
||||
@@ -203,17 +203,14 @@ function handleRanderChart() {
|
||||
|
||||
/**查询初始UPF数据 */
|
||||
function fnGetInitData() {
|
||||
// 查询10分钟前的
|
||||
const nowDate: Date = new Date();
|
||||
const tenMinutesAgo = new Date(nowDate.getTime() - 5 * 60 * 1000);
|
||||
// 查询5分钟前的
|
||||
const nowDate = new Date().getTime();
|
||||
|
||||
listKPIData({
|
||||
neType: 'UPF',
|
||||
neId: '001',
|
||||
startTime: parseDateToStr(tenMinutesAgo),
|
||||
endTime: parseDateToStr(nowDate),
|
||||
// startTime: '2024-03-20 19:50:00',
|
||||
// endTime: '2024-03-20 19:55:00',
|
||||
startTime: nowDate - 5 * 60 * 1000,
|
||||
endTime: nowDate,
|
||||
interval: 5, // 5秒
|
||||
sortField: 'timeGroup',
|
||||
sortOrder: 'asc',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user