Compare commits
354
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
618499e777 | ||
|
|
71c0306587 | ||
|
|
a3cd8f05fb | ||
|
|
d8ca0ca5ef | ||
|
|
da08e1cc5b | ||
|
|
8e4c5d0b90 | ||
|
|
467c93f710 | ||
|
|
22ced8bdb2 | ||
|
|
2ee26a6958 | ||
|
|
c63e892544 | ||
|
|
cce3088f73 | ||
|
|
2211896768 | ||
|
|
5bb3cd814c | ||
|
|
266d816a21 | ||
|
|
90c64c029a | ||
|
|
d06e2da72e | ||
|
|
7714d506c4 | ||
|
|
0b7a198235 | ||
|
|
68362ba3e3 | ||
|
|
a9633e652f | ||
|
|
6592561bca | ||
|
|
09e0353053 | ||
|
|
c1e95fd1e9 | ||
|
|
89857e0c1b | ||
|
|
7aa37ee330 | ||
|
|
4c16888184 | ||
|
|
a61716d40d | ||
|
|
3f02cb628b | ||
|
|
22805924fb | ||
|
|
e00229e5ff | ||
|
|
939a235a87 | ||
|
|
cd49162dfc | ||
|
|
b7f2df5d1c | ||
|
|
8b24bc55b9 | ||
|
|
9f2b80718e | ||
|
|
38cb406687 | ||
|
|
c25fe63a26 | ||
|
|
b84d6bb9fc | ||
|
|
b325cde5c0 | ||
|
|
34266da44e | ||
|
|
d82d6b7b47 | ||
|
|
b1c7a068cf | ||
|
|
c155160cf7 | ||
|
|
2ae4559958 | ||
|
|
782283bba6 | ||
|
|
1b50708786 | ||
|
|
206d3755a0 | ||
|
|
6470effbda | ||
|
|
f94b1ef44a | ||
|
|
7c78eab431 | ||
|
|
814b7b0058 | ||
|
|
624f67ecca | ||
|
|
c1a9497b77 | ||
|
|
1ad2ed2d26 | ||
|
|
48f278997f | ||
|
|
9b9d6222e1 | ||
|
|
2e8a878365 | ||
|
|
bc59dc67e6 | ||
|
|
df6022b4a8 | ||
|
|
f2c67d087b | ||
|
|
7a0298a419 | ||
|
|
b40e798090 | ||
|
|
d48d5d6c95 | ||
|
|
69f3347a4d | ||
|
|
85ae7dc5ea | ||
|
|
531cd6d03d | ||
|
|
9fd8c4597a | ||
|
|
7060a3d887 | ||
|
|
c12ffa583c | ||
|
|
05aabb8c61 | ||
|
|
6b461ead7c | ||
|
|
7c54e372e5 | ||
|
|
5be95a7af6 | ||
|
|
08515541b4 | ||
|
|
3948924f61 | ||
|
|
ce1944881a | ||
|
|
f6122c0758 | ||
|
|
3d3f4c2cc6 | ||
|
|
e8e5b92a57 | ||
|
|
4ad704398d | ||
|
|
26289b7787 | ||
|
|
7ad8c1706e | ||
|
|
424a596613 | ||
|
|
6d5b9f417c | ||
|
|
7278e24dce | ||
|
|
76839ae18a | ||
|
|
c8a6aa3210 | ||
|
|
9b4bbcedc5 | ||
|
|
3b793c107c | ||
|
|
a076e6d079 | ||
|
|
fb2a7c51f9 | ||
|
|
1e2c2b5170 | ||
|
|
56833b654e | ||
|
|
f50e02e6e7 | ||
|
|
52cc24813f | ||
|
|
c8a0d4c3f7 | ||
|
|
7560f21f11 | ||
|
|
8a5f80fe47 | ||
|
|
29eb1f08b1 | ||
|
|
9981de2271 | ||
|
|
207acb3f3d | ||
|
|
873a76f48f | ||
|
|
4ca700092a | ||
|
|
ad9f8574bd | ||
|
|
75faae6d7c | ||
|
|
c88c146a5e | ||
|
|
c65cda1468 | ||
|
|
d8059341fe | ||
|
|
ad86bee5f9 | ||
|
|
f44cc44a1b | ||
|
|
ad93588796 | ||
|
|
b5f6a5d24a | ||
|
|
fa4be253f7 | ||
|
|
2db0220c98 | ||
|
|
05fd678ce2 | ||
|
|
165b28bab1 | ||
|
|
dc67cdc262 | ||
|
|
c97394a0ed | ||
|
|
6b9297d30e | ||
|
|
ace7f26b53 | ||
|
|
976f72f79a | ||
|
|
530e7fd43f | ||
|
|
b76fed7dcf | ||
|
|
60a26dd015 | ||
|
|
7bdfc257c1 | ||
|
|
e3395b47cf | ||
|
|
4c9b4de12f | ||
|
|
1cfe5e2777 | ||
|
|
0cae26a1ee | ||
|
|
ed4d556384 | ||
|
|
6d9d7362a4 | ||
|
|
5a40733f20 | ||
|
|
45ee884529 | ||
|
|
7de3f7f05d | ||
|
|
97bb4db1eb | ||
|
|
fc6dfe9894 | ||
|
|
607660124a | ||
|
|
c50b3add95 | ||
|
|
2f7f0e9e20 | ||
|
|
6875ffd113 | ||
|
|
44844bfa7f | ||
|
|
21ab066761 | ||
|
|
83bdf289fa | ||
|
|
d7aa0fc91a | ||
|
|
a6be5190ec | ||
|
|
03cd06e835 | ||
|
|
2d7fe5a73b | ||
|
|
dd5604c8b7 | ||
|
|
7bf2672981 | ||
|
|
6e616c63f0 | ||
|
|
3ded481cce | ||
|
|
1baff582d8 | ||
|
|
957868cc27 | ||
|
|
efb98ac577 | ||
|
|
ff228daae7 | ||
|
|
c93e693517 | ||
|
|
55863c1c58 | ||
|
|
8a2d6c91ba | ||
|
|
86a939f206 | ||
|
|
2b86f724b1 | ||
|
|
68fbc45b7c | ||
|
|
4629ef28ff | ||
|
|
e3a11b0ede | ||
|
|
3df9ee4f3a | ||
|
|
e64d558c27 | ||
|
|
5a2aa383fe | ||
|
|
fe9f458465 | ||
|
|
8e2e9aec67 | ||
|
|
ad48e8e2e1 | ||
|
|
6f8b1000ba | ||
|
|
f5549992c2 | ||
|
|
19771ea6dc | ||
|
|
5965737384 | ||
|
|
b3cb40fd8c | ||
|
|
0ab5141369 | ||
|
|
a23284da4c | ||
|
|
1c8cc13436 | ||
|
|
e6a439faea | ||
|
|
f8b1b1f6c3 | ||
|
|
3844e07258 | ||
|
|
1fab9b3d97 | ||
|
|
1bfacbf2e0 | ||
|
|
c01f9f3830 | ||
|
|
28f9d365fd | ||
|
|
1085fa16aa | ||
|
|
e351960229 | ||
|
|
03caa354da | ||
|
|
34754ea0b6 | ||
|
|
86e1f07f08 | ||
|
|
2add7547d6 | ||
|
|
ecb89e9f26 | ||
|
|
7a9b38dc66 | ||
|
|
979b18092d | ||
|
|
ba43a647dd | ||
|
|
3be14590c6 | ||
|
|
857f8c4313 | ||
|
|
c9c39d2d4a | ||
|
|
845084f77f | ||
|
|
becba4919e | ||
|
|
b797055df9 | ||
|
|
8101c852c8 | ||
|
|
9bbeb9fc9a | ||
|
|
19a9bd3f5c | ||
|
|
399bddc635 | ||
|
|
5a67a1a51c | ||
|
|
9a168d2ba0 | ||
|
|
e42a620aed | ||
|
|
eb902594b8 | ||
|
|
817fd97496 | ||
|
|
96aab47003 | ||
|
|
432666b1ab | ||
|
|
662583c73b | ||
|
|
f73c21e6e6 | ||
|
|
17e72f1db1 | ||
|
|
55d4a36efb | ||
|
|
d3794ba904 | ||
|
|
832f18e2ee | ||
|
|
cd2e282624 | ||
|
|
3db88f1d3a | ||
|
|
f291bb0907 | ||
|
|
69c32b2593 | ||
|
|
1a2939ab01 | ||
|
|
8bf4a2a9ce | ||
|
|
efd389f98a | ||
|
|
f1125cc042 | ||
|
|
f1a0e200dc | ||
|
|
70c025f0f5 | ||
|
|
b9f0a3923d | ||
|
|
5c942c9ef7 | ||
|
|
4294fe82c5 | ||
|
|
4e7fb90544 | ||
|
|
f050e500e9 | ||
|
|
6bc10babba | ||
|
|
4d36f9952a | ||
|
|
b03f4bb1d6 | ||
|
|
4aaedf0f77 | ||
|
|
c1ea851705 | ||
|
|
47103249ef | ||
|
|
2642f18204 | ||
|
|
e2e22eabf5 | ||
|
|
325ecc8029 | ||
|
|
dc6f4560d5 | ||
|
|
3970797d5b | ||
|
|
73776ed0f9 | ||
|
|
aca842f8c2 | ||
|
|
612fb77861 | ||
|
|
6ba695ceaf | ||
|
|
070f77d3b8 | ||
|
|
15de63212f | ||
|
|
2202540763 | ||
|
|
c674b9b3f9 | ||
|
|
43d30e7bfa | ||
|
|
cd0633d519 | ||
|
|
b8bff2a159 | ||
|
|
638f890228 | ||
|
|
4460f7201c | ||
|
|
d0bbfafedc | ||
|
|
16dc1c2e20 | ||
|
|
73ed5f5285 | ||
|
|
50cb92a95b | ||
|
|
3888fd2bca | ||
|
|
4194d8cca6 | ||
|
|
ac84a0ca0a |
No files matched your search
+1
-1
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network EMS"
|
||||
VITE_APP_CODE = "CN EMS"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.240330.1"
|
||||
VITE_APP_VERSION = "2.240704"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
+1
-1
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network EMS"
|
||||
VITE_APP_CODE = "CN EMS"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.240330.1"
|
||||
VITE_APP_VERSION = "2.240704"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
## 简介
|
||||
|
||||
- 系统布局使用 [@ant-design-vue/pro-layout](https://github.com/vueComponent/pro-components)
|
||||
- 图标来源 [@ant-design/icons-vue](https://ant.design/components/icon)
|
||||
- 菜单图标使用自定义 iconfont `font_8d5l8fzk5b87iudi.js`图标文件
|
||||
|
||||
@@ -11,7 +10,7 @@
|
||||
```text
|
||||
Jenkins: http://192.168.2.166:3185/
|
||||
Nginx: http://192.168.2.166:3188/#/index
|
||||
后端暴露端口: http://192.168.2.166:3186 \ http://192.168.2.166:3187
|
||||
后端暴露端口: http://192.168.2.166:33030
|
||||
|
||||
|
||||
新网管:192.168.5.13
|
||||
@@ -73,10 +72,3 @@ https://192.168.5.27:31325/#/workloads?namespace=default
|
||||
```text
|
||||
eyJhbGciOiJSUzI1NiIsImtpZCI6ImZFVUhIb1puLW04M1dfSUYyRU8zWlZueXBpNUh4T0hTRVlzU19jNlVGQ0kifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLW44ZzRtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI2M2NmYjAyNS01ZmQ0LTQ0ZTgtOTdiNC0yYWRiYWIxNzc5M2MiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.R3GRygFOjngTj-mEMBAHDeBxm3lpsXZYvC6cdTxByONtLrcMXDebwNVeKtAZ1V9qh2OrjD8n9CIygjULGPdfV6S520vjMh7Oa2q68nOyW49DNWQyYD8xLo-dQ6sX07fI7X_I3H35YUWW80jJAXjJawqIGXBSMG5intlo4tLTUSXmjCfhoQvFsgeRWu0j76pDvhMAvLPcgEXfTCi9tyL3yqJBIKONcKwmMlJeaKSR3pQk3KiibqrBO0MZclRozpke6J0ulfzTemwDDyCqBZmLsRPZ2yDd5hVBIJ9bHEcK0a25NmSFFzmd8XWQPZwg3Y4IbbY-8UhByGq0p9xS-7pGCQ
|
||||
```
|
||||
|
||||
```ssh
|
||||
# https://blog.csdn.net/m0_54706625/article/details/129721121
|
||||
sudo chmod 700 -/.ssh/
|
||||
sudo chmod 700 /home/mask/.ssh #这个尤其容易忽视掉,我就是从这个坑里爬出来。有木有很高兴呀!
|
||||
sudo chmod 600 ~/.ssh/authorized_keys
|
||||
```
|
||||
+22
-20
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ems_frontend_vue3",
|
||||
"type": "module",
|
||||
"description": "核心网管理平台",
|
||||
"description": "Core Network EMS",
|
||||
"author": "TsMask",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -14,43 +14,45 @@
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@antv/g6": "~4.8.24",
|
||||
"@codemirror/lang-javascript": "^6.2.1",
|
||||
"@codemirror/lang-yaml": "^6.0.0",
|
||||
"@codemirror/merge": "^6.6.1",
|
||||
"@codemirror/lang-javascript": "^6.2.2",
|
||||
"@codemirror/lang-yaml": "^6.1.1",
|
||||
"@codemirror/merge": "^6.6.3",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@tato30/vue-pdf": "^1.9.6",
|
||||
"@vueuse/core": "~10.9.0",
|
||||
"@tato30/vue-pdf": "~1.9.7",
|
||||
"@vueuse/core": "~10.10.1",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"ant-design-vue": "^3.2.20",
|
||||
"antdv-pro-layout": "^3.2.6",
|
||||
"antdv-pro-layout": "~3.3.5",
|
||||
"antdv-pro-modal": "^3.1.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"dayjs": "^1.11.10",
|
||||
"dayjs": "^1.11.11",
|
||||
"echarts": "~5.5.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"intl-tel-input": "~23.0.12",
|
||||
"js-base64": "^3.7.7",
|
||||
"js-cookie": "^3.0.5",
|
||||
"localforage": "^1.10.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"p-queue": "^8.0.1",
|
||||
"p-queue": "~8.0.1",
|
||||
"pinia": "^2.1.7",
|
||||
"vue": "~3.3.13",
|
||||
"vue-i18n": "~9.10.0",
|
||||
"vue-router": "^4.2.5",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-router": "^4.4.0",
|
||||
"vue3-smooth-dnd": "^0.0.6",
|
||||
"xlsx": "^0.18.5",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0"
|
||||
"xlsx": "~0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@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.3",
|
||||
"unplugin-vue-components": "^0.26.0",
|
||||
"vite": "^5.2.6",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vue-tsc": "^1.8.27"
|
||||
"typescript": "~5.4.5",
|
||||
"unplugin-vue-components": "~0.26.0",
|
||||
"vite": "~5.3.1",
|
||||
"vite-plugin-compression": "~0.5.1",
|
||||
"vue-tsc": "~2.0.22"
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -4,6 +4,7 @@ import { usePrimaryColor } from '@/hooks/useTheme';
|
||||
import zhCN from 'ant-design-vue/lib/locale/zh_CN';
|
||||
import enUS from 'ant-design-vue/lib/locale/en_US';
|
||||
import dayjs from 'dayjs';
|
||||
import advancedFormat from 'dayjs/plugin/advancedFormat';
|
||||
import 'dayjs/locale/zh-cn';
|
||||
import { ref, watch } from 'vue';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
@@ -11,6 +12,7 @@ import useI18n from '@/hooks/useI18n';
|
||||
const { t, currentLocale } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
dayjs.extend(advancedFormat);
|
||||
dayjs.locale('zh-cn'); // 默认中文
|
||||
usePrimaryColor(); // 载入用户自定义主题色
|
||||
|
||||
@@ -50,10 +52,11 @@ console.info(
|
||||
</ConfigProvider>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
<style lang="css">
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body .ant-pro-basicLayout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -61,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,
|
||||
|
||||
+178
-159
@@ -18,7 +18,7 @@ export async function getParamConfigTopTab(neType: string) {
|
||||
url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/param_config`,
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: `SELECT top_display,top_tag,method FROM param_config WHERE ne_type = '${neType}'`,
|
||||
SQL: `SELECT id,top_display,top_tag,method FROM param_config WHERE ne_type = '${neType}' ORDER BY id ASC`,
|
||||
},
|
||||
});
|
||||
// 解析数据
|
||||
@@ -38,13 +38,13 @@ export async function getParamConfigTopTab(neType: string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询配置参数标签栏对应信息
|
||||
* 查询配置参数标签栏对应信息和规则
|
||||
* @param neType 网元类型
|
||||
* @param topTag
|
||||
* @param neId
|
||||
* @returns object { wrRule, dataArr }
|
||||
*/
|
||||
async function getParamConfigInfo(
|
||||
async function getParamConfigInfoAndRule(
|
||||
neType: string,
|
||||
topTag: string,
|
||||
neId: string
|
||||
@@ -57,7 +57,6 @@ async function getParamConfigInfo(
|
||||
params: {
|
||||
SQL: `SELECT param_json FROM param_config WHERE ne_type = '${neType}' AND top_tag='${topTag}'`,
|
||||
},
|
||||
timeout: 1_000,
|
||||
}),
|
||||
// 获取对应信息
|
||||
request({
|
||||
@@ -66,7 +65,6 @@ async function getParamConfigInfo(
|
||||
params: {
|
||||
ne_id: neId,
|
||||
},
|
||||
timeout: 1_000,
|
||||
}),
|
||||
]).then(resArr => {
|
||||
let wrRule: Record<string, any> = {};
|
||||
@@ -108,159 +106,6 @@ async function getParamConfigInfo(
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询配置参数标签栏对应信息-表格处理
|
||||
* @param neType 网元类型
|
||||
* @param topTag
|
||||
* @param neId
|
||||
* @returns object
|
||||
*/
|
||||
export async function getParamConfigInfoTable(
|
||||
neType: string,
|
||||
topTag: string,
|
||||
neId: string
|
||||
) {
|
||||
const { wrRule, dataArr } = await getParamConfigInfo(neType, topTag, neId);
|
||||
|
||||
// UPF参数不统一
|
||||
// if (neType === 'UPF') {
|
||||
// if (Reflect.has(wrRule, 'list')) {
|
||||
// for (const arr of wrRule['list']) {
|
||||
// arr['name'] = parseFirstLower(arr['name']);
|
||||
// }
|
||||
// for (const item of dataArr) {
|
||||
// for (const k in item) {
|
||||
// item[parseFirstLower(k)] = item[k];
|
||||
// Reflect.deleteProperty(item, k);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (Reflect.has(wrRule, 'array')) {
|
||||
// for (const arr of wrRule['array']) {
|
||||
// if (Array.isArray(arr['array'])) {
|
||||
// for (const child of arr['array']) {
|
||||
// child['name'] = parseFirstLower(child['name']);
|
||||
// }
|
||||
// }
|
||||
// arr['name'] = parseFirstLower(arr['name']);
|
||||
// }
|
||||
// for (const item of dataArr) {
|
||||
// for (const k in item) {
|
||||
// // 处理子列表
|
||||
// if (Array.isArray(item[k])) {
|
||||
// for (const child of item[k]) {
|
||||
// for (const childKey in child) {
|
||||
// child[parseFirstLower(childKey)] = child[childKey];
|
||||
// Reflect.deleteProperty(child, childKey);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// item[parseFirstLower(k)] = item[k];
|
||||
// Reflect.deleteProperty(item, k);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// 拼装数据
|
||||
const result = {
|
||||
code: RESULT_CODE_SUCCESS,
|
||||
msg: RESULT_MSG_SUCCESS,
|
||||
data: {
|
||||
type: 'list' as 'list' | 'array',
|
||||
data: [] as any[],
|
||||
dataRule: {},
|
||||
columns: [] as any[],
|
||||
},
|
||||
};
|
||||
|
||||
// kv单列表
|
||||
if (Reflect.has(wrRule, 'list')) {
|
||||
result.data.type = 'list';
|
||||
const ruleArr = Object.freeze(wrRule['list']);
|
||||
|
||||
// 列表项数据
|
||||
let dataList = [];
|
||||
for (const item of dataArr) {
|
||||
for (const key of Object.keys(item)) {
|
||||
// 规则为准
|
||||
for (const rule of ruleArr) {
|
||||
if (rule['name'] === key) {
|
||||
const ruleItem = Object.assign({ optional: 'true' }, rule, {
|
||||
value: item[key],
|
||||
});
|
||||
dataList.push(ruleItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.data.data = dataList;
|
||||
|
||||
// 列表字段
|
||||
result.data.columns = [
|
||||
{
|
||||
title: 'Key',
|
||||
dataIndex: 'display',
|
||||
align: 'left',
|
||||
width: '30%',
|
||||
},
|
||||
{
|
||||
title: 'Value',
|
||||
dataIndex: 'value',
|
||||
align: 'left',
|
||||
width: '70%',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// 多列表
|
||||
if (Reflect.has(wrRule, 'array')) {
|
||||
result.data.type = 'array';
|
||||
const ruleArr = Object.freeze(wrRule['array']);
|
||||
|
||||
// 列表项数据
|
||||
const dataArray = [];
|
||||
for (const item of dataArr) {
|
||||
let record: Record<string, any> = {};
|
||||
for (const key of Object.keys(item)) {
|
||||
// 规则为准
|
||||
for (const rule of ruleArr) {
|
||||
if (rule['name'] === key) {
|
||||
const ruleItem = Object.assign({ optional: 'true' }, rule, {
|
||||
value: item[key],
|
||||
});
|
||||
record[ruleItem.name] = ruleItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dataArray.push(record);
|
||||
}
|
||||
result.data.data = dataArray;
|
||||
|
||||
// 无数据时,用于新增
|
||||
let dataRule: Record<string, any> = {};
|
||||
for (const rule of ruleArr) {
|
||||
dataRule[rule.name] = rule;
|
||||
}
|
||||
result.data.dataRule = dataRule;
|
||||
|
||||
// 列表字段
|
||||
const columns: Record<string, any>[] = [];
|
||||
for (const rule of ruleArr) {
|
||||
columns.push({
|
||||
title: rule.display,
|
||||
dataIndex: rule.name,
|
||||
align: 'left',
|
||||
width: 5,
|
||||
});
|
||||
}
|
||||
result.data.columns = columns;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询配置参数标签栏对应信息-表单结构处理
|
||||
* @param neType 网元类型
|
||||
@@ -273,7 +118,11 @@ export async function getParamConfigInfoForm(
|
||||
topTag: string,
|
||||
neId: string
|
||||
) {
|
||||
const { wrRule, dataArr } = await getParamConfigInfo(neType, topTag, neId);
|
||||
const { wrRule, dataArr } = await getParamConfigInfoAndRule(
|
||||
neType,
|
||||
topTag,
|
||||
neId
|
||||
);
|
||||
|
||||
// 拼装数据
|
||||
const result = {
|
||||
@@ -340,6 +189,35 @@ export async function getParamConfigInfoForm(
|
||||
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 网元类型
|
||||
@@ -462,3 +340,144 @@ export async function updateNeConfigReload(neType: string, neId: string) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从参数配置PCF中获取对应信息提供给PCC用户策略输入框
|
||||
* @param neType 网元类型
|
||||
* @param topTag
|
||||
* @param neId
|
||||
* @returns object { wrRule, dataArr }
|
||||
*/
|
||||
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();
|
||||
// 规则数据
|
||||
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,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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 };
|
||||
});
|
||||
}
|
||||
@@ -19,7 +19,7 @@ export async function listLicense(query: Record<string, any>) {
|
||||
|
||||
// 分页
|
||||
const pageNum = (query.pageNum - 1) * query.pageSize;
|
||||
const limtSql = ` order by created_at desc limit ${pageNum},${query.pageSize} `;
|
||||
const limtSql = ` order by create_time desc limit ${pageNum},${query.pageSize} `;
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
} from '@/constants/result-constants';
|
||||
import { language, request } from '@/plugins/http-fetch';
|
||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||
|
||||
/**
|
||||
* 查询网元列表
|
||||
@@ -15,24 +16,6 @@ export async function listNeInfo(query: Record<string, any>) {
|
||||
let totalSQL = 'select count(*) as total from ne_info where 1=1 ';
|
||||
let rowsSQL = 'select * from ne_info where 1=1 ';
|
||||
|
||||
// 系统特定顺序
|
||||
const specificOrder = [
|
||||
'OMC',
|
||||
'MME',
|
||||
'AMF',
|
||||
'AUSF',
|
||||
'UDM',
|
||||
'SMF',
|
||||
'PCF',
|
||||
'UPF',
|
||||
'NRF',
|
||||
'NSSF',
|
||||
'IMS',
|
||||
'N3IWF',
|
||||
'NEF',
|
||||
'LMF',
|
||||
];
|
||||
|
||||
// 查询
|
||||
let querySQL = '';
|
||||
if (query.neType) {
|
||||
@@ -70,8 +53,8 @@ export async function listNeInfo(query: Record<string, any>) {
|
||||
data.rows = itemData.map(v => parseObjLineToHump(v));
|
||||
//通过sort进行冒泡排序
|
||||
data.rows.sort((a: any, b: any) => {
|
||||
const typeA = specificOrder.indexOf(a.neType);
|
||||
const typeB = specificOrder.indexOf(b.neType);
|
||||
const typeA = NE_TYPE_LIST.indexOf(a.neType);
|
||||
const typeB = NE_TYPE_LIST.indexOf(b.neType);
|
||||
if (typeA === -1) return 1; // 如果不在特定顺序中,排到后面
|
||||
if (typeB === -1) return -1; // 如果不在特定顺序中,排到后面
|
||||
return typeA - typeB;
|
||||
@@ -156,7 +139,7 @@ export async function delNeInfo(data: Record<string, any>) {
|
||||
|
||||
/**
|
||||
* 导出网元配置文件
|
||||
* @param
|
||||
* @param data data {neType neId}
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportSet(data: Record<string, any>) {
|
||||
|
||||
@@ -111,6 +111,7 @@ export async function sendNeSoftware(data: Record<string, any>) {
|
||||
url: `/api/rest/systemManagement/v1/${data.neType}/software/${data.version}/${data.neId}`,
|
||||
method: 'post',
|
||||
timeout: 180_000,
|
||||
repeatSubmit: false,
|
||||
});
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -130,6 +131,7 @@ export async function runNeSoftware(data: Record<string, any>) {
|
||||
url: `/api/rest/systemManagement/v1/${data.neType}/software/${data.version}/${data.neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
repeatSubmit: false,
|
||||
});
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -149,6 +151,7 @@ export async function backNeSoftware(data: Record<string, any>) {
|
||||
url: `/api/rest/systemManagement/v1/${data.neType}/software/${data.version}/${data.neId}`,
|
||||
method: 'PATCH',
|
||||
timeout: 180_000,
|
||||
repeatSubmit: false,
|
||||
});
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
|
||||
@@ -294,7 +294,7 @@ export async function exportAll(query: Record<string, any>) {
|
||||
* @returns bolb
|
||||
*/
|
||||
export async function origGet() {
|
||||
let totalSQL = `select count(*) as value,orig_severity as name from alarm group by orig_severity`;
|
||||
let totalSQL = `select count(*) as value,orig_severity as name from alarm WHERE alarm_status='1' and orig_severity!='Event' group by orig_severity`;
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
@@ -329,10 +329,10 @@ export async function origGet() {
|
||||
* @returns object
|
||||
*/
|
||||
export async function top3Sel(filterFlag?: string) {
|
||||
let filter = ` WHERE orig_severity='${filterFlag}'`;
|
||||
if (!filterFlag) filter = '';
|
||||
let filter = ` WHERE alarm_status='1'and orig_severity='${filterFlag}'`;
|
||||
if (!filterFlag) filter = "WHERE alarm_status='1'";
|
||||
|
||||
let top3SQL = `select count(*) as value,ne_type as name from alarm ${filter} group by ne_type ORDER BY value desc limit 0,3 `;
|
||||
let top3SQL = `select count(*) as value,ne_type as name from alarm ${filter} and orig_severity!='Event' group by ne_type ORDER BY value desc limit 0,3 `;
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
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';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export async function listAct(query: Record<string, any>) {
|
||||
let totalSQL = `select count(*) as total from alarm_event where 1=1 `;
|
||||
let rowsSQL = `select * from alarm_event where 1=1 `;
|
||||
// 查询
|
||||
let querySQL = '';
|
||||
if (query.alarmCode) {
|
||||
querySQL += ` and alarm_code = '${query.alarmCode}' `;
|
||||
}
|
||||
|
||||
if (query.alarmType) {
|
||||
querySQL += ` and alarm_type = '${query.alarmType}' `;
|
||||
}
|
||||
|
||||
if (query.pvFlag) {
|
||||
querySQL += ` and pv_flag = '${query.pvFlag}' `;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (query.neId) {
|
||||
querySQL += ` and ne_id like '%${query.neId}%' `;
|
||||
}
|
||||
|
||||
if (query.neName) {
|
||||
querySQL += ` and ne_name like '%${query.neName}%' `;
|
||||
}
|
||||
|
||||
if (query.neType) {
|
||||
querySQL += ` and ne_type like '%${query.neType}%' `;
|
||||
}
|
||||
|
||||
if (query.beginTime && query.endTime) {
|
||||
querySQL += ` and event_time BETWEEN '${query.beginTime}' and ' ${query.endTime}'`;
|
||||
}
|
||||
|
||||
// 分页
|
||||
const pageNum = (query.pageNum - 1) * query.pageSize;
|
||||
const limtSql = ` order by event_time desc limit ${pageNum},${query.pageSize} `;
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/alarm_event`,
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: 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) => {
|
||||
console.log(item)
|
||||
const itemData = item['alarm_event'];
|
||||
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 bolb
|
||||
*/
|
||||
export async function exportAll(query: Record<string, any>) {
|
||||
let rowsSQL = `select * from alarm_event where 1=1`;
|
||||
// 查询
|
||||
let querySQL = '';
|
||||
querySQL += query.alarm_code
|
||||
? ` and alarm_code = '${query.alarm_code}' `
|
||||
: '';
|
||||
querySQL += query.alarm_type
|
||||
? ` and alarm_type = '${query.alarm_type}' `
|
||||
: '';
|
||||
querySQL += query.pv_flag ? ` and pv_flag = '${query.pv_flag}' ` : '';
|
||||
querySQL += query.orig_severity
|
||||
? ` and orig_severity in('${query.orig_severity}' )`
|
||||
: '';
|
||||
querySQL += query.ne_id ? ` and ne_id like '%${query.ne_id}%' ` : '';
|
||||
querySQL += query.ne_name ? ` and ne_name like '%${query.ne_name}%' ` : '';
|
||||
querySQL += query.ne_type ? ` and ne_type like '%${query.ne_type}%' ` : '';
|
||||
querySQL +=
|
||||
query.beginTime && query.endTime
|
||||
? ` and event_time BETWEEN '${query.beginTime}' and ' ${query.endTime}'`
|
||||
: '';
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/alarm_event`,
|
||||
method: 'get',
|
||||
params: {
|
||||
rowsSQL: rowsSQL + querySQL,
|
||||
},
|
||||
});
|
||||
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
let v = result.data.data[0];
|
||||
const vArr = parseObjLineToHump(v['alarm_event']);
|
||||
result.data = vArr == null ? [] : vArr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+6
-21
@@ -1,29 +1,14 @@
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||
|
||||
/**
|
||||
* 查询公告列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export async function listMain() {
|
||||
// 系统特定顺序
|
||||
const specificOrder = [
|
||||
'OMC',
|
||||
'MME',
|
||||
'AMF',
|
||||
'AUSF',
|
||||
'UDM',
|
||||
'SMF',
|
||||
'PCF',
|
||||
'UPF',
|
||||
'NRF',
|
||||
'NSSF',
|
||||
'IMS',
|
||||
'N3IWF',
|
||||
'NEF',
|
||||
'LMF',
|
||||
];
|
||||
const result = await request({
|
||||
url: '/api/rest/systemManagement/v1/elementType/all/objectType/systemState',
|
||||
method: 'get',
|
||||
@@ -39,7 +24,6 @@ export async function listMain() {
|
||||
const serialNum = (value as any).serialNum;
|
||||
const version = (value as any).version;
|
||||
|
||||
|
||||
const errCode = systemState && systemState['errorCode'];
|
||||
var time = new Date();
|
||||
// console.log(key, value);
|
||||
@@ -59,7 +43,7 @@ export async function listMain() {
|
||||
ipAddress,
|
||||
serialNum,
|
||||
name: key.split('/').join('_'),
|
||||
expiryDate:'-',
|
||||
expiryDate: '-',
|
||||
status: 'Abnormal',
|
||||
};
|
||||
}
|
||||
@@ -67,8 +51,8 @@ export async function listMain() {
|
||||
});
|
||||
//通过sort进行冒泡排序
|
||||
mergedData.sort((a: any, b: any) => {
|
||||
const typeA = specificOrder.indexOf(a.name.split('_')[0]);
|
||||
const typeB = specificOrder.indexOf(b.name.split('_')[0]);
|
||||
const typeA = NE_TYPE_LIST.indexOf(a.name.split('_')[0]);
|
||||
const typeB = NE_TYPE_LIST.indexOf(b.name.split('_')[0]);
|
||||
if (typeA === -1) return 1; // 如果不在特定顺序中,排到后面
|
||||
if (typeB === -1) return -1; // 如果不在特定顺序中,排到后面
|
||||
return typeA - typeB;
|
||||
@@ -104,5 +88,6 @@ export function getSysConf() {
|
||||
return request({
|
||||
url: `/sys-conf`,
|
||||
method: 'get',
|
||||
whithToken: false,
|
||||
});
|
||||
}
|
||||
@@ -1,93 +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 query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export async function listSession(query: Record<string, any>) {
|
||||
let totalSQL = 'select count(*) as total from session where 1=1 ';
|
||||
let rowsSQL = 'select * from session where 1=1 ';
|
||||
|
||||
// 查询
|
||||
let querySQL = '';
|
||||
if (query.accountId) {
|
||||
querySQL += ` and account_id like '%${query.accountId}%' `;
|
||||
}
|
||||
if (query.ip) {
|
||||
querySQL += ` and host like '%${query.ip}%' `;
|
||||
}
|
||||
|
||||
// 分页
|
||||
const pageNum = (query.pageNum - 1) * query.pageSize;
|
||||
const limtSql = ` limit ${pageNum},${query.pageSize} `;
|
||||
|
||||
// 排序
|
||||
let sortSql = ' order by login_time ';
|
||||
if (query.sortOrder === 'desc') {
|
||||
sortSql += ' desc ';
|
||||
} else {
|
||||
sortSql += ' asc ';
|
||||
}
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/omc_db/session`,
|
||||
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['session'];
|
||||
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 tokenId 授权标识
|
||||
* @returns object
|
||||
*/
|
||||
export async function logoutSession(id: string) {
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/omc_db/session?WHERE=id='${id}'`,
|
||||
method: 'delete',
|
||||
});
|
||||
// 解析数据
|
||||
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;
|
||||
}
|
||||
+53
-10
@@ -67,7 +67,7 @@ export function delNeInfo(infoIds: string | number) {
|
||||
|
||||
/**
|
||||
* 查询网元列表全部无分页
|
||||
* @param query 查询参数 neType neId bandStatus
|
||||
* @param query 查询参数 neType neId bandStatus bandHost
|
||||
* @returns object
|
||||
*/
|
||||
export function listAllNeInfo(query: Record<string, any>) {
|
||||
@@ -99,7 +99,7 @@ export function stateNeInfo(neType: string, neId: string) {
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function getTypeAndIDNeInfo(neType: string, neId: string) {
|
||||
export function getNeInfoByTypeAndID(neType: string, neId: string) {
|
||||
return request({
|
||||
url: '/ne/info/byTypeAndID',
|
||||
method: 'get',
|
||||
@@ -108,29 +108,72 @@ export function getTypeAndIDNeInfo(neType: string, neId: string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元端配置文件读取
|
||||
* 网元端OAM配置文件读取
|
||||
* @param neType 网元类型
|
||||
* @param neId 网元ID
|
||||
* @param filePath 不带文件时重新覆盖返回目录列表
|
||||
* @returns object
|
||||
*/
|
||||
export function getConfigFile(neType: string, neId: string, filePath: string) {
|
||||
export function getOAMFile(neType: string, neId: string) {
|
||||
return request({
|
||||
url: '/ne/info/configFile',
|
||||
url: '/ne/info/oamFile',
|
||||
method: 'get',
|
||||
params: { neType, neId, filePath },
|
||||
params: { neType, neId },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元端配置文件写入
|
||||
* @param data neType网元类型 neId网元ID filePath文件 content内容 sync同步到网元
|
||||
* @param neType 网元类型
|
||||
* @param neId 网元ID
|
||||
* @param content 用json对象
|
||||
* @param sync 同步到网元
|
||||
* @returns object
|
||||
*/
|
||||
export function saveConfigFile(data: Record<string, any>) {
|
||||
export function saveOAMFile(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/info/configFile`,
|
||||
url: `/ne/info/oamFile`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元端公共配置文件读取
|
||||
* @returns object
|
||||
*/
|
||||
export function getPara5GFilee() {
|
||||
return request({
|
||||
url: '/ne/info/para5GFile',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元端公共配置文件写入
|
||||
* @param content txt内容为字符串 其他文件格式都用json对象
|
||||
* @param syncNe 同步到网元端 NeType@ NeId
|
||||
* @returns object
|
||||
*/
|
||||
export function savePara5GFile(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/info/para5GFile`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元服务操作
|
||||
* @param data 对象 {neType,neId,action}
|
||||
* @returns object
|
||||
*/
|
||||
export function serviceNeAction(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/action/service`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
+8
-33
@@ -27,41 +27,16 @@ export function getNeLicense(licenseId: string | number) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元授权新增
|
||||
* @param data 网元对象
|
||||
* 网元neType和neID查询
|
||||
* @param neType 网元类型
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function addNeLicense(data: Record<string, any>) {
|
||||
export function getNeLicenseByTypeAndID(neType: string, neId: string) {
|
||||
return request({
|
||||
url: `/ne/license`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元授权修改
|
||||
* @param data 网元对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateNeLicense(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/license`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元授权删除
|
||||
* @param id 信息ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delNeLicense(licenseIds: string | number) {
|
||||
return request({
|
||||
url: `/ne/license/${licenseIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
url: `/ne/license/byTypeAndID`,
|
||||
method: 'get',
|
||||
params: { neType, neId },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -81,7 +56,7 @@ export function codeNeLicense(neType: string, neId: string) {
|
||||
|
||||
/**
|
||||
* 网元授权激活授权文件替换
|
||||
* @param data 网元对象
|
||||
* @param data 网元对象 {"neType": "", "neId": "", "licensePath": "", "reload": true}
|
||||
* @returns object
|
||||
*/
|
||||
export function changeNeLicense(data: Record<string, any>) {
|
||||
|
||||
@@ -36,6 +36,7 @@ export function addNeSoftware(data: Record<string, any>) {
|
||||
url: `/ne/software`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
repeatSubmit: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -66,15 +67,14 @@ export function delNeSoftware(softwareIds: string | number) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元软件包安装检查
|
||||
* @param data 网元对象
|
||||
* 网元软件包设为网元新版本
|
||||
* @param data data { "version": "2.2404.18", "neType": "SMF", "name": "smf-r2.2404.18-ub22.deb"}
|
||||
* @returns object
|
||||
*/
|
||||
export function checkInstallNeSoftware(data: Record<string, any>) {
|
||||
export function newNeVersion(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/software/checkInstall`,
|
||||
url: `/ne/software/newNeVersion`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
}
|
||||
+5
-30
@@ -27,40 +27,15 @@ export function getNeVersion(versionId: string | number) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元版本新增
|
||||
* @param data 网元对象
|
||||
* 网元版本操作
|
||||
* @param data {neType,neId,preinput:{参数},action:"upgrade"}
|
||||
* @returns object
|
||||
*/
|
||||
export function addNeVersion(data: Record<string, any>) {
|
||||
export function operateNeVersion(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/version`,
|
||||
url: `/ne/version/operate`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元版本修改
|
||||
* @param data 网元对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateNeVersion(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/version`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元版本删除
|
||||
* @param id 信息ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delNeVersion(versionIds: string | number) {
|
||||
return request({
|
||||
url: `/ne/version/${versionIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
+21
-7
@@ -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,
|
||||
});
|
||||
}
|
||||
+21
-7
@@ -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,
|
||||
});
|
||||
}
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询SMF-CDR会话事件
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listSMFDataCDR(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/smf/cdr/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SMF-CDR会话删除
|
||||
* @param id 信息ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delSMFDataCDR(cdrIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/smf/cdr/${cdrIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SMF-CDR会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportSMFDataCDR(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/smf/cdr/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
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 neId 网元ID
|
||||
* @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,
|
||||
});
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -136,6 +136,7 @@ export async function batchUpdateRule(data: Record<string, any>) {
|
||||
url: `/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo/batch/${data.num}?neId=${data.neId}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -164,6 +165,7 @@ export async function addRule(data: Record<string, any>) {
|
||||
url: `/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo?neId=${data.neId}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS && result.data?.status) {
|
||||
@@ -186,6 +188,7 @@ export async function batchAddRule(data: Record<string, any>) {
|
||||
url: `/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo/batch/${data.num}?neId=${data.neId}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -209,10 +212,11 @@ export async function batchAddRule(data: Record<string, any>) {
|
||||
* @param data 规则对象
|
||||
* @returns object
|
||||
*/
|
||||
export function delRule(neId: string, data: Record<string, any>) {
|
||||
export function delRule(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo?neId=${neId}&imsi=${data.imsi}`,
|
||||
url: `/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo?neId=${neId}&imsi=${imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -225,5 +229,6 @@ export async function batchDelRule(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo/batch/${data.num}?neId=${data.neId}&imsi=${data.imsi}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
+41
-15
@@ -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,39 +20,66 @@ 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-460029004200044',
|
||||
// msisdn: 'msisdn-12346002044',
|
||||
// imsi: 'imsi-460000100000090',
|
||||
// msisdn: 'msisdn-12307550090',
|
||||
// pduSessionInfo: [
|
||||
// {
|
||||
// activeTime: '2023-11-29 18:39:06',
|
||||
// activeTime: '2024-06-19 14:35:26',
|
||||
// dnn: 'ims',
|
||||
// ipv4: '10.10.48.97',
|
||||
// ipv4: '10.10.48.8',
|
||||
// ipv6: '',
|
||||
// pduSessionID: 6,
|
||||
// ranN3IP: '192.168.8.223',
|
||||
// ranN3IP: '192.168.1.137',
|
||||
// sstSD: '1-000001',
|
||||
// tai: '46000-0001',
|
||||
// tai: '46000-001124',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.1.161',
|
||||
// },
|
||||
// {
|
||||
// activeTime: '2023-11-29 18:39:05',
|
||||
// activeTime: '2024-06-19 14:35:26',
|
||||
// dnn: 'cmnet',
|
||||
// ipv4: '10.10.48.62',
|
||||
// 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: '46000-0001',
|
||||
// upfN3IP: '192.168.1.163',
|
||||
// tai: '46060-0001',
|
||||
// upState: 'Active',
|
||||
// upfN3IP: '192.168.1.161',
|
||||
// },
|
||||
// ],
|
||||
// ratType: 'EUTRAN',
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 首次引导开始
|
||||
* @returns object
|
||||
*/
|
||||
export function bootloaderStart() {
|
||||
return request({
|
||||
url: `/bootloader`,
|
||||
method: 'post',
|
||||
whithToken: false,
|
||||
repeatSubmit: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 首次引导完成
|
||||
* @returns object
|
||||
*/
|
||||
export function bootloaderDone() {
|
||||
return request({
|
||||
url: `/bootloader`,
|
||||
method: 'put',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 引导系统数据重置
|
||||
* @returns object
|
||||
*/
|
||||
export function bootloaderReset() {
|
||||
return request({
|
||||
url: `/bootloader`,
|
||||
method: 'delete',
|
||||
timeout: 180_000
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员账号变更
|
||||
* @returns object
|
||||
*/
|
||||
export function bootloaderAccount(username: string, password: string) {
|
||||
return request({
|
||||
url: `/bootloader/account`,
|
||||
method: 'put',
|
||||
data: {
|
||||
username,
|
||||
password,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -18,6 +18,7 @@ export async function downloadFile(filePath: string, range?: string) {
|
||||
method: 'get',
|
||||
headers: range ? { range } : {},
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,6 +80,7 @@ export function uploadFile(data: FormData) {
|
||||
method: 'post',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -169,6 +171,7 @@ export function chunkCheck(identifier: string, fileName: string) {
|
||||
url: '/file/chunkCheck',
|
||||
method: 'post',
|
||||
data: { identifier, fileName },
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -188,6 +191,7 @@ export function chunkMerge(
|
||||
url: '/file/chunkMerge',
|
||||
method: 'post',
|
||||
data: { identifier, fileName, subPath },
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -202,6 +206,7 @@ export function chunkUpload(data: FormData) {
|
||||
method: 'post',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -214,6 +219,7 @@ export function transferStaticFile(data: Record<string, any>) {
|
||||
url: `/file/transferStaticFile`,
|
||||
method: 'post',
|
||||
data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -241,6 +247,7 @@ export async function uploadFileToNE(
|
||||
neType,
|
||||
neId,
|
||||
},
|
||||
timeout: 60_000,
|
||||
});
|
||||
return transferToNeFileRes;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { request } from '@/plugins/http-fetch';
|
||||
// 网元抓包PACP 开始
|
||||
export function dumpStart(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tcpdump/start',
|
||||
url: '/trace/tcpdump/start',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
@@ -12,7 +12,7 @@ export function dumpStart(data: Record<string, string>) {
|
||||
// 网元抓包PACP 结束
|
||||
export function dumpStop(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tcpdump/stop',
|
||||
url: '/trace/tcpdump/stop',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
@@ -21,7 +21,7 @@ export function dumpStop(data: Record<string, string>) {
|
||||
// UPF标准版内部抓包
|
||||
export function traceUPF(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tcpdump/traceUPF',
|
||||
url: '/trace/tcpdump/traceUPF',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<template>
|
||||
<a-modal
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:title="t('components.CronModal.title')"
|
||||
:visible="props.visible"
|
||||
:body-style="{ padding: '0 24px' }"
|
||||
:destroy-on-close="true"
|
||||
@cancel="fnCronModal(false)"
|
||||
@ok="fnCronModal(true)"
|
||||
>
|
||||
@@ -31,7 +32,7 @@
|
||||
v-model:value="cronStr"
|
||||
disabled
|
||||
/>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import CronSecond from './components/Second.vue';
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, PropType } from 'vue';
|
||||
const props = defineProps({
|
||||
/**数据 */
|
||||
options: {
|
||||
type: Array,
|
||||
type: Array as PropType<DictType[]>,
|
||||
},
|
||||
/**当前的值对应数据中的项字段 */
|
||||
valueField: {
|
||||
type: String,
|
||||
type: String as PropType<keyof DictType>,
|
||||
default: 'value',
|
||||
},
|
||||
/**当前的值 */
|
||||
@@ -16,7 +16,7 @@ const props = defineProps({
|
||||
default: '',
|
||||
},
|
||||
/**数据默认值,当前值不存在时 */
|
||||
valueOption: {
|
||||
valueDefault: {
|
||||
type: [Number, String],
|
||||
},
|
||||
});
|
||||
@@ -24,13 +24,13 @@ const props = defineProps({
|
||||
/**遍历找到对应值数据项 */
|
||||
const item = computed(() => {
|
||||
if (Array.isArray(props.options) && props.options.length > 0) {
|
||||
let option = (props.options as any[]).find(
|
||||
let option = props.options.find(
|
||||
item => `${item[props.valueField]}` === `${props.value}`
|
||||
);
|
||||
// 数据默认值
|
||||
if (props.valueOption != undefined && !option) {
|
||||
option = (props.options as any[]).find(
|
||||
item => `${item[props.valueField]}` === `${props.valueOption }`
|
||||
if (!option && props.valueDefault != undefined) {
|
||||
option = props.options.find(
|
||||
item => `${item[props.valueField]}` === `${props.valueDefault}`
|
||||
);
|
||||
}
|
||||
return option;
|
||||
@@ -41,14 +41,10 @@ const item = computed(() => {
|
||||
|
||||
<template>
|
||||
<template v-if="item">
|
||||
<a-tag
|
||||
v-if="item.elTagType"
|
||||
:class="item.elTagClass"
|
||||
:color="item.elTagType"
|
||||
>
|
||||
<a-tag v-if="item.tagType" :class="item.tagClass" :color="item.tagType">
|
||||
{{ item.label }}
|
||||
</a-tag>
|
||||
<span v-else :class="item.elTagClass">
|
||||
<span v-else :class="item.tagClass">
|
||||
{{ item.label }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, watchEffect, CSSProperties, computed } from 'vue';
|
||||
import { useDraggable } from '@vueuse/core';
|
||||
const emit = defineEmits(['update:visible', 'ok', 'cancel']);
|
||||
/**于a-modal保持一致 */
|
||||
const props = defineProps({
|
||||
/**是否弹出显示,必传 */
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
/**窗口标题 */
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**窗口宽度 */
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: '520px',
|
||||
},
|
||||
bodyStyle: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
keyboard: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
mask: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
maskClosable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
maskStyle: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
destroyOnClose: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
confirmLoading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
footer: {
|
||||
type: Object as any,
|
||||
},
|
||||
});
|
||||
|
||||
// 对标题进行监听
|
||||
const modalTitleRef = ref<HTMLElement | null>(null);
|
||||
const { x, y, isDragging } = useDraggable(modalTitleRef);
|
||||
|
||||
const startX = ref<number>(0);
|
||||
const startY = ref<number>(0);
|
||||
const startedDrag = ref(false);
|
||||
const transformX = ref(0);
|
||||
const transformY = ref(0);
|
||||
const preTransformX = ref(0);
|
||||
const preTransformY = ref(0);
|
||||
const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 });
|
||||
|
||||
watch([x, y], () => {
|
||||
if (!startedDrag.value) {
|
||||
startX.value = x.value;
|
||||
startY.value = y.value;
|
||||
const bodyRect = document.body.getBoundingClientRect();
|
||||
const titleRectEl = modalTitleRef.value;
|
||||
if (titleRectEl) {
|
||||
const titleRect = titleRectEl.getBoundingClientRect();
|
||||
dragRect.value.right = bodyRect.width - (titleRect.width + 24);
|
||||
dragRect.value.bottom = bodyRect.height - (titleRect.height + 16);
|
||||
}
|
||||
preTransformX.value = transformX.value;
|
||||
preTransformY.value = transformY.value;
|
||||
}
|
||||
startedDrag.value = true;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (!isDragging.value) {
|
||||
startedDrag.value = false;
|
||||
}
|
||||
if (startedDrag.value) {
|
||||
const dragRectX = Math.min(
|
||||
Math.max(dragRect.value.left + 24, x.value),
|
||||
dragRect.value.right
|
||||
);
|
||||
transformX.value = preTransformX.value + dragRectX - startX.value;
|
||||
|
||||
const dragRectY = Math.min(
|
||||
Math.max(dragRect.value.top + 16, y.value),
|
||||
dragRect.value.bottom
|
||||
);
|
||||
transformY.value = preTransformY.value + dragRectY - startY.value;
|
||||
}
|
||||
});
|
||||
|
||||
// 位移
|
||||
const transformStyle = computed<CSSProperties>(() => {
|
||||
return {
|
||||
transform: `translate(${transformX.value}px, ${transformY.value}px)`,
|
||||
};
|
||||
});
|
||||
|
||||
/**监听是否显示,位置还原 */
|
||||
watch(
|
||||
() => props.visible,
|
||||
val => {
|
||||
if (val) {
|
||||
transformX.value = 0;
|
||||
transformY.value = 0;
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
wrapClassName="draggable-modal"
|
||||
:width="props.width"
|
||||
:keyboard="props.keyboard"
|
||||
:mask="props.mask"
|
||||
:mask-closable="props.maskClosable"
|
||||
:visible="props.visible"
|
||||
:confirm-loading="props.confirmLoading"
|
||||
:body-style="props.bodyStyle"
|
||||
:mask-style="props.maskStyle"
|
||||
:destroy-on-close="props.destroyOnClose"
|
||||
:footer="props.footer"
|
||||
@ok="(e:any) => emit('ok', e)"
|
||||
@cancel="(e:any) => emit('cancel', e)"
|
||||
>
|
||||
<template #title>
|
||||
<div
|
||||
ref="modalTitleRef"
|
||||
class="draggable-modal-title"
|
||||
v-text="title"
|
||||
></div>
|
||||
</template>
|
||||
<template #modalRender="{ originVNode }">
|
||||
<div :style="transformStyle">
|
||||
<component :is="originVNode" />
|
||||
</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.draggable-modal {
|
||||
// 穿透选择文字
|
||||
// 给a-modal设置 get-container=".ant-pro-page-container"
|
||||
// 防止跳转显示
|
||||
// &.ant-modal-wrap {
|
||||
// pointer-events: none;
|
||||
// }
|
||||
&-title {
|
||||
width: 100%;
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,252 @@
|
||||
//* THIS FILE IS AUTO-GENERATED. DO NOT EDIT.
|
||||
export default {
|
||||
af: "Afghanistan",
|
||||
ax: "Åland Islands",
|
||||
al: "Albania",
|
||||
dz: "Algeria",
|
||||
as: "American Samoa",
|
||||
ad: "Andorra",
|
||||
ao: "Angola",
|
||||
ai: "Anguilla",
|
||||
aq: "Antarctica",
|
||||
ag: "Antigua & Barbuda",
|
||||
ar: "Argentina",
|
||||
am: "Armenia",
|
||||
aw: "Aruba",
|
||||
au: "Australia",
|
||||
at: "Austria",
|
||||
az: "Azerbaijan",
|
||||
bs: "Bahamas",
|
||||
bh: "Bahrain",
|
||||
bd: "Bangladesh",
|
||||
bb: "Barbados",
|
||||
by: "Belarus",
|
||||
be: "Belgium",
|
||||
bz: "Belize",
|
||||
bj: "Benin",
|
||||
bm: "Bermuda",
|
||||
bt: "Bhutan",
|
||||
bo: "Bolivia",
|
||||
ba: "Bosnia & Herzegovina",
|
||||
bw: "Botswana",
|
||||
bv: "Bouvet Island",
|
||||
br: "Brazil",
|
||||
io: "British Indian Ocean Territory",
|
||||
vg: "British Virgin Islands",
|
||||
bn: "Brunei",
|
||||
bg: "Bulgaria",
|
||||
bf: "Burkina Faso",
|
||||
bi: "Burundi",
|
||||
kh: "Cambodia",
|
||||
cm: "Cameroon",
|
||||
ca: "Canada",
|
||||
cv: "Cape Verde",
|
||||
bq: "Caribbean Netherlands",
|
||||
ky: "Cayman Islands",
|
||||
cf: "Central African Republic",
|
||||
td: "Chad",
|
||||
cl: "Chile",
|
||||
cn: "China",
|
||||
cx: "Christmas Island",
|
||||
cc: "Cocos (Keeling) Islands",
|
||||
co: "Colombia",
|
||||
km: "Comoros",
|
||||
cg: "Congo - Brazzaville",
|
||||
cd: "Congo - Kinshasa",
|
||||
ck: "Cook Islands",
|
||||
cr: "Costa Rica",
|
||||
ci: "Côte d’Ivoire",
|
||||
hr: "Croatia",
|
||||
cu: "Cuba",
|
||||
cw: "Curaçao",
|
||||
cy: "Cyprus",
|
||||
cz: "Czechia",
|
||||
dk: "Denmark",
|
||||
dj: "Djibouti",
|
||||
dm: "Dominica",
|
||||
do: "Dominican Republic",
|
||||
ec: "Ecuador",
|
||||
eg: "Egypt",
|
||||
sv: "El Salvador",
|
||||
gq: "Equatorial Guinea",
|
||||
er: "Eritrea",
|
||||
ee: "Estonia",
|
||||
sz: "Eswatini",
|
||||
et: "Ethiopia",
|
||||
fk: "Falkland Islands",
|
||||
fo: "Faroe Islands",
|
||||
fj: "Fiji",
|
||||
fi: "Finland",
|
||||
fr: "France",
|
||||
gf: "French Guiana",
|
||||
pf: "French Polynesia",
|
||||
tf: "French Southern Territories",
|
||||
ga: "Gabon",
|
||||
gm: "Gambia",
|
||||
ge: "Georgia",
|
||||
de: "Germany",
|
||||
gh: "Ghana",
|
||||
gi: "Gibraltar",
|
||||
gr: "Greece",
|
||||
gl: "Greenland",
|
||||
gd: "Grenada",
|
||||
gp: "Guadeloupe",
|
||||
gu: "Guam",
|
||||
gt: "Guatemala",
|
||||
gg: "Guernsey",
|
||||
gn: "Guinea",
|
||||
gw: "Guinea-Bissau",
|
||||
gy: "Guyana",
|
||||
ht: "Haiti",
|
||||
hm: "Heard & McDonald Islands",
|
||||
hn: "Honduras",
|
||||
hk: "Hong Kong SAR China",
|
||||
hu: "Hungary",
|
||||
is: "Iceland",
|
||||
in: "India",
|
||||
id: "Indonesia",
|
||||
ir: "Iran",
|
||||
iq: "Iraq",
|
||||
ie: "Ireland",
|
||||
im: "Isle of Man",
|
||||
il: "Israel",
|
||||
it: "Italy",
|
||||
jm: "Jamaica",
|
||||
jp: "Japan",
|
||||
je: "Jersey",
|
||||
jo: "Jordan",
|
||||
kz: "Kazakhstan",
|
||||
ke: "Kenya",
|
||||
ki: "Kiribati",
|
||||
kw: "Kuwait",
|
||||
kg: "Kyrgyzstan",
|
||||
la: "Laos",
|
||||
lv: "Latvia",
|
||||
lb: "Lebanon",
|
||||
ls: "Lesotho",
|
||||
lr: "Liberia",
|
||||
ly: "Libya",
|
||||
li: "Liechtenstein",
|
||||
lt: "Lithuania",
|
||||
lu: "Luxembourg",
|
||||
mo: "Macao SAR China",
|
||||
mg: "Madagascar",
|
||||
mw: "Malawi",
|
||||
my: "Malaysia",
|
||||
mv: "Maldives",
|
||||
ml: "Mali",
|
||||
mt: "Malta",
|
||||
mh: "Marshall Islands",
|
||||
mq: "Martinique",
|
||||
mr: "Mauritania",
|
||||
mu: "Mauritius",
|
||||
yt: "Mayotte",
|
||||
mx: "Mexico",
|
||||
fm: "Micronesia",
|
||||
md: "Moldova",
|
||||
mc: "Monaco",
|
||||
mn: "Mongolia",
|
||||
me: "Montenegro",
|
||||
ms: "Montserrat",
|
||||
ma: "Morocco",
|
||||
mz: "Mozambique",
|
||||
mm: "Myanmar (Burma)",
|
||||
na: "Namibia",
|
||||
nr: "Nauru",
|
||||
np: "Nepal",
|
||||
nl: "Netherlands",
|
||||
nc: "New Caledonia",
|
||||
nz: "New Zealand",
|
||||
ni: "Nicaragua",
|
||||
ne: "Niger",
|
||||
ng: "Nigeria",
|
||||
nu: "Niue",
|
||||
nf: "Norfolk Island",
|
||||
kp: "North Korea",
|
||||
mk: "North Macedonia",
|
||||
mp: "Northern Mariana Islands",
|
||||
no: "Norway",
|
||||
om: "Oman",
|
||||
pk: "Pakistan",
|
||||
pw: "Palau",
|
||||
ps: "Palestinian Territories",
|
||||
pa: "Panama",
|
||||
pg: "Papua New Guinea",
|
||||
py: "Paraguay",
|
||||
pe: "Peru",
|
||||
ph: "Philippines",
|
||||
pn: "Pitcairn Islands",
|
||||
pl: "Poland",
|
||||
pt: "Portugal",
|
||||
pr: "Puerto Rico",
|
||||
qa: "Qatar",
|
||||
re: "Réunion",
|
||||
ro: "Romania",
|
||||
ru: "Russia",
|
||||
rw: "Rwanda",
|
||||
ws: "Samoa",
|
||||
sm: "San Marino",
|
||||
st: "São Tomé & Príncipe",
|
||||
sa: "Saudi Arabia",
|
||||
sn: "Senegal",
|
||||
rs: "Serbia",
|
||||
sc: "Seychelles",
|
||||
sl: "Sierra Leone",
|
||||
sg: "Singapore",
|
||||
sx: "Sint Maarten",
|
||||
sk: "Slovakia",
|
||||
si: "Slovenia",
|
||||
sb: "Solomon Islands",
|
||||
so: "Somalia",
|
||||
za: "South Africa",
|
||||
gs: "South Georgia & South Sandwich Islands",
|
||||
kr: "South Korea",
|
||||
ss: "South Sudan",
|
||||
es: "Spain",
|
||||
lk: "Sri Lanka",
|
||||
bl: "St. Barthélemy",
|
||||
sh: "St. Helena",
|
||||
kn: "St. Kitts & Nevis",
|
||||
lc: "St. Lucia",
|
||||
mf: "St. Martin",
|
||||
pm: "St. Pierre & Miquelon",
|
||||
vc: "St. Vincent & Grenadines",
|
||||
sd: "Sudan",
|
||||
sr: "Suriname",
|
||||
sj: "Svalbard & Jan Mayen",
|
||||
se: "Sweden",
|
||||
ch: "Switzerland",
|
||||
sy: "Syria",
|
||||
tw: "Taiwan",
|
||||
tj: "Tajikistan",
|
||||
tz: "Tanzania",
|
||||
th: "Thailand",
|
||||
tl: "Timor-Leste",
|
||||
tg: "Togo",
|
||||
tk: "Tokelau",
|
||||
to: "Tonga",
|
||||
tt: "Trinidad & Tobago",
|
||||
tn: "Tunisia",
|
||||
tr: "Turkey",
|
||||
tm: "Turkmenistan",
|
||||
tc: "Turks & Caicos Islands",
|
||||
tv: "Tuvalu",
|
||||
um: "U.S. Outlying Islands",
|
||||
vi: "U.S. Virgin Islands",
|
||||
ug: "Uganda",
|
||||
ua: "Ukraine",
|
||||
ae: "United Arab Emirates",
|
||||
gb: "United Kingdom",
|
||||
us: "United States",
|
||||
uy: "Uruguay",
|
||||
uz: "Uzbekistan",
|
||||
vu: "Vanuatu",
|
||||
va: "Vatican City",
|
||||
ve: "Venezuela",
|
||||
vn: "Vietnam",
|
||||
wf: "Wallis & Futuna",
|
||||
eh: "Western Sahara",
|
||||
ye: "Yemen",
|
||||
zm: "Zambia",
|
||||
zw: "Zimbabwe",
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
import countryTranslations from './countries';
|
||||
import interfaceTranslations from './interface';
|
||||
|
||||
export default { ...countryTranslations, ...interfaceTranslations };
|
||||
@@ -0,0 +1,14 @@
|
||||
//* English. Translated by: Jack O'Connor (jackocnr).
|
||||
export default {
|
||||
selectedCountryAriaLabel: "Selected country",
|
||||
noCountrySelected: "No country selected",
|
||||
countryListAriaLabel: "List of countries",
|
||||
searchPlaceholder: "Search",
|
||||
zeroSearchResults: "No results found",
|
||||
oneSearchResult: "1 result found",
|
||||
multipleSearchResults: "${count} results found",
|
||||
|
||||
// additional countries (not supported by country-list library)
|
||||
ac: "Ascension Island",
|
||||
xk: "Kosovo",
|
||||
};
|
||||
@@ -0,0 +1,252 @@
|
||||
//* THIS FILE IS AUTO-GENERATED. DO NOT EDIT.
|
||||
export default {
|
||||
al: "阿尔巴尼亚",
|
||||
dz: "阿尔及利亚",
|
||||
af: "阿富汗",
|
||||
ar: "阿根廷",
|
||||
ae: "阿拉伯联合酋长国",
|
||||
aw: "阿鲁巴",
|
||||
om: "阿曼",
|
||||
az: "阿塞拜疆",
|
||||
eg: "埃及",
|
||||
et: "埃塞俄比亚",
|
||||
ie: "爱尔兰",
|
||||
ee: "爱沙尼亚",
|
||||
ad: "安道尔",
|
||||
ao: "安哥拉",
|
||||
ai: "安圭拉",
|
||||
ag: "安提瓜和巴布达",
|
||||
at: "奥地利",
|
||||
ax: "奥兰群岛",
|
||||
au: "澳大利亚",
|
||||
bb: "巴巴多斯",
|
||||
pg: "巴布亚新几内亚",
|
||||
bs: "巴哈马",
|
||||
pk: "巴基斯坦",
|
||||
py: "巴拉圭",
|
||||
ps: "巴勒斯坦领土",
|
||||
bh: "巴林",
|
||||
pa: "巴拿马",
|
||||
br: "巴西",
|
||||
by: "白俄罗斯",
|
||||
bm: "百慕大",
|
||||
bg: "保加利亚",
|
||||
mp: "北马里亚纳群岛",
|
||||
mk: "北马其顿",
|
||||
bj: "贝宁",
|
||||
be: "比利时",
|
||||
is: "冰岛",
|
||||
pr: "波多黎各",
|
||||
pl: "波兰",
|
||||
ba: "波斯尼亚和黑塞哥维那",
|
||||
bo: "玻利维亚",
|
||||
bz: "伯利兹",
|
||||
bw: "博茨瓦纳",
|
||||
bt: "不丹",
|
||||
bf: "布基纳法索",
|
||||
bi: "布隆迪",
|
||||
bv: "布韦岛",
|
||||
kp: "朝鲜",
|
||||
gq: "赤道几内亚",
|
||||
dk: "丹麦",
|
||||
de: "德国",
|
||||
tl: "东帝汶",
|
||||
tg: "多哥",
|
||||
do: "多米尼加共和国",
|
||||
dm: "多米尼克",
|
||||
ru: "俄罗斯",
|
||||
ec: "厄瓜多尔",
|
||||
er: "厄立特里亚",
|
||||
fr: "法国",
|
||||
fo: "法罗群岛",
|
||||
pf: "法属波利尼西亚",
|
||||
gf: "法属圭亚那",
|
||||
tf: "法属南部领地",
|
||||
mf: "法属圣马丁",
|
||||
va: "梵蒂冈",
|
||||
ph: "菲律宾",
|
||||
fj: "斐济",
|
||||
fi: "芬兰",
|
||||
cv: "佛得角",
|
||||
fk: "福克兰群岛",
|
||||
gm: "冈比亚",
|
||||
cg: "刚果(布)",
|
||||
cd: "刚果(金)",
|
||||
co: "哥伦比亚",
|
||||
cr: "哥斯达黎加",
|
||||
gd: "格林纳达",
|
||||
gl: "格陵兰",
|
||||
ge: "格鲁吉亚",
|
||||
gg: "根西岛",
|
||||
cu: "古巴",
|
||||
gp: "瓜德罗普",
|
||||
gu: "关岛",
|
||||
gy: "圭亚那",
|
||||
kz: "哈萨克斯坦",
|
||||
ht: "海地",
|
||||
kr: "韩国",
|
||||
nl: "荷兰",
|
||||
bq: "荷属加勒比区",
|
||||
sx: "荷属圣马丁",
|
||||
hm: "赫德岛和麦克唐纳群岛",
|
||||
me: "黑山",
|
||||
hn: "洪都拉斯",
|
||||
ki: "基里巴斯",
|
||||
dj: "吉布提",
|
||||
kg: "吉尔吉斯斯坦",
|
||||
gn: "几内亚",
|
||||
gw: "几内亚比绍",
|
||||
ca: "加拿大",
|
||||
gh: "加纳",
|
||||
ga: "加蓬",
|
||||
kh: "柬埔寨",
|
||||
cz: "捷克",
|
||||
zw: "津巴布韦",
|
||||
cm: "喀麦隆",
|
||||
qa: "卡塔尔",
|
||||
ky: "开曼群岛",
|
||||
cc: "科科斯(基林)群岛",
|
||||
km: "科摩罗",
|
||||
ci: "科特迪瓦",
|
||||
kw: "科威特",
|
||||
hr: "克罗地亚",
|
||||
ke: "肯尼亚",
|
||||
ck: "库克群岛",
|
||||
cw: "库拉索",
|
||||
lv: "拉脱维亚",
|
||||
ls: "莱索托",
|
||||
la: "老挝",
|
||||
lb: "黎巴嫩",
|
||||
lt: "立陶宛",
|
||||
lr: "利比里亚",
|
||||
ly: "利比亚",
|
||||
li: "列支敦士登",
|
||||
re: "留尼汪",
|
||||
lu: "卢森堡",
|
||||
rw: "卢旺达",
|
||||
ro: "罗马尼亚",
|
||||
mg: "马达加斯加",
|
||||
im: "马恩岛",
|
||||
mv: "马尔代夫",
|
||||
mt: "马耳他",
|
||||
mw: "马拉维",
|
||||
my: "马来西亚",
|
||||
ml: "马里",
|
||||
mh: "马绍尔群岛",
|
||||
mq: "马提尼克",
|
||||
yt: "马约特",
|
||||
mu: "毛里求斯",
|
||||
mr: "毛里塔尼亚",
|
||||
us: "美国",
|
||||
um: "美国本土外小岛屿",
|
||||
as: "美属萨摩亚",
|
||||
vi: "美属维尔京群岛",
|
||||
mn: "蒙古",
|
||||
ms: "蒙特塞拉特",
|
||||
bd: "孟加拉国",
|
||||
pe: "秘鲁",
|
||||
fm: "密克罗尼西亚",
|
||||
mm: "缅甸",
|
||||
md: "摩尔多瓦",
|
||||
ma: "摩洛哥",
|
||||
mc: "摩纳哥",
|
||||
mz: "莫桑比克",
|
||||
mx: "墨西哥",
|
||||
na: "纳米比亚",
|
||||
za: "南非",
|
||||
aq: "南极洲",
|
||||
gs: "南乔治亚和南桑威奇群岛",
|
||||
ss: "南苏丹",
|
||||
nr: "瑙鲁",
|
||||
ni: "尼加拉瓜",
|
||||
np: "尼泊尔",
|
||||
ne: "尼日尔",
|
||||
ng: "尼日利亚",
|
||||
nu: "纽埃",
|
||||
no: "挪威",
|
||||
nf: "诺福克岛",
|
||||
pw: "帕劳",
|
||||
pn: "皮特凯恩群岛",
|
||||
pt: "葡萄牙",
|
||||
jp: "日本",
|
||||
se: "瑞典",
|
||||
ch: "瑞士",
|
||||
sv: "萨尔瓦多",
|
||||
ws: "萨摩亚",
|
||||
rs: "塞尔维亚",
|
||||
sl: "塞拉利昂",
|
||||
sn: "塞内加尔",
|
||||
cy: "塞浦路斯",
|
||||
sc: "塞舌尔",
|
||||
sa: "沙特阿拉伯",
|
||||
bl: "圣巴泰勒米",
|
||||
cx: "圣诞岛",
|
||||
st: "圣多美和普林西比",
|
||||
sh: "圣赫勒拿",
|
||||
kn: "圣基茨和尼维斯",
|
||||
lc: "圣卢西亚",
|
||||
sm: "圣马力诺",
|
||||
pm: "圣皮埃尔和密克隆群岛",
|
||||
vc: "圣文森特和格林纳丁斯",
|
||||
lk: "斯里兰卡",
|
||||
sk: "斯洛伐克",
|
||||
si: "斯洛文尼亚",
|
||||
sj: "斯瓦尔巴和扬马延",
|
||||
sz: "斯威士兰",
|
||||
sd: "苏丹",
|
||||
sr: "苏里南",
|
||||
sb: "所罗门群岛",
|
||||
so: "索马里",
|
||||
tj: "塔吉克斯坦",
|
||||
tw: "台湾",
|
||||
th: "泰国",
|
||||
tz: "坦桑尼亚",
|
||||
to: "汤加",
|
||||
tc: "特克斯和凯科斯群岛",
|
||||
tt: "特立尼达和多巴哥",
|
||||
tn: "突尼斯",
|
||||
tv: "图瓦卢",
|
||||
tr: "土耳其",
|
||||
tm: "土库曼斯坦",
|
||||
tk: "托克劳",
|
||||
wf: "瓦利斯和富图纳",
|
||||
vu: "瓦努阿图",
|
||||
gt: "危地马拉",
|
||||
ve: "委内瑞拉",
|
||||
bn: "文莱",
|
||||
ug: "乌干达",
|
||||
ua: "乌克兰",
|
||||
uy: "乌拉圭",
|
||||
uz: "乌兹别克斯坦",
|
||||
es: "西班牙",
|
||||
eh: "西撒哈拉",
|
||||
gr: "希腊",
|
||||
sg: "新加坡",
|
||||
nc: "新喀里多尼亚",
|
||||
nz: "新西兰",
|
||||
hu: "匈牙利",
|
||||
sy: "叙利亚",
|
||||
jm: "牙买加",
|
||||
am: "亚美尼亚",
|
||||
ye: "也门",
|
||||
iq: "伊拉克",
|
||||
ir: "伊朗",
|
||||
il: "以色列",
|
||||
it: "意大利",
|
||||
in: "印度",
|
||||
id: "印度尼西亚",
|
||||
gb: "英国",
|
||||
vg: "英属维尔京群岛",
|
||||
io: "英属印度洋领地",
|
||||
jo: "约旦",
|
||||
vn: "越南",
|
||||
zm: "赞比亚",
|
||||
je: "泽西岛",
|
||||
td: "乍得",
|
||||
gi: "直布罗陀",
|
||||
cl: "智利",
|
||||
cf: "中非共和国",
|
||||
cn: "中国",
|
||||
mo: "中国澳门特别行政区",
|
||||
hk: "中国香港特别行政区",
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
import countryTranslations from './countries';
|
||||
import interfaceTranslations from './interface';
|
||||
|
||||
export default { ...countryTranslations, ...interfaceTranslations };
|
||||
@@ -0,0 +1,15 @@
|
||||
//* Chinese (Simplified). Translated by: Google Translate.
|
||||
export default {
|
||||
selectedCountryAriaLabel: "所选国家",
|
||||
noCountrySelected: "未选择国家/地区",
|
||||
countryListAriaLabel: "国家名单",
|
||||
searchPlaceholder: "搜索",
|
||||
zeroSearchResults: "未找到结果",
|
||||
oneSearchResult: "找到 1 个结果",
|
||||
multipleSearchResults: "找到 ${count} 个结果",
|
||||
|
||||
// additional countries (not supported by country-list library)
|
||||
ac: "阿森松岛",
|
||||
xk: "科索沃",
|
||||
};
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
<!-- https://github.com/jackocnr/intl-tel-input/blob/master/react/src/intl-tel-input/react.tsx -->
|
||||
<script lang="ts" setup>
|
||||
import intlTelInput, { Iti, SomeOptions } from 'intl-tel-input';
|
||||
import 'intl-tel-input/build/css/intlTelInput.min.css';
|
||||
import 'intl-tel-input/build/js/utils.js';
|
||||
import { ref, onMounted, onBeforeUnmount, nextTick, watch } from 'vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { currentLocale } = useI18n();
|
||||
const emit = defineEmits(['update:value', 'update:change']);
|
||||
const props = defineProps({
|
||||
/**有效检验 */
|
||||
preciseValidation: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**手机号 */
|
||||
value: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**禁用输入 */
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**手机号输入提示 */
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**手机号输入最大字符串长度 */
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: 255,
|
||||
},
|
||||
/**允许清空手机号输入框 */
|
||||
allowClear: {
|
||||
type: Boolean,
|
||||
},
|
||||
});
|
||||
|
||||
const inputRef = ref<HTMLInputElement | null>(null);
|
||||
const itiRef = ref<Iti | null>(null);
|
||||
|
||||
function fnChange() {
|
||||
if (!itiRef.value) return;
|
||||
|
||||
const num = itiRef.value?.getNumber() || '';
|
||||
const countryIso = itiRef.value?.getSelectedCountryData().iso2 || '';
|
||||
// note: this number will be in standard E164 format, but any container component can use
|
||||
// intlTelInputUtils.formatNumber() to convert this to another format
|
||||
// as well as intlTelInputUtils.getNumberType() etc. if need be
|
||||
let data = {
|
||||
num,
|
||||
countryIso,
|
||||
validity: false,
|
||||
errorCode: -1,
|
||||
};
|
||||
|
||||
const isValid = props.preciseValidation
|
||||
? itiRef.value.isValidNumberPrecise()
|
||||
: itiRef.value.isValidNumber();
|
||||
if (isValid) {
|
||||
data.validity = true;
|
||||
data.errorCode = 0;
|
||||
} else {
|
||||
const errorCode = itiRef.value.getValidationError();
|
||||
data.validity = false;
|
||||
data.errorCode = errorCode;
|
||||
}
|
||||
// console.log(data);
|
||||
emit('update:value', num);
|
||||
emit('update:change', data);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
v => {
|
||||
if (v) {
|
||||
itiRef.value?.setNumber(v);
|
||||
} else {
|
||||
itiRef.value?.setNumber('');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(async () => {
|
||||
if (inputRef.value) {
|
||||
let i18n = undefined;
|
||||
let initialCountry = 'us';
|
||||
// 语言文件导入问题只能复制到项目内处理
|
||||
// import fr from "intl-tel-input/i18n/fr";
|
||||
if (currentLocale.value.startsWith('zh')) {
|
||||
const { default: zh } = await import('./i18n/zh');
|
||||
i18n = zh;
|
||||
initialCountry = 'cn';
|
||||
} else {
|
||||
const { default: en } = await import('./i18n/en');
|
||||
i18n = en;
|
||||
initialCountry = 'us';
|
||||
}
|
||||
|
||||
itiRef.value = intlTelInput(inputRef.value, {
|
||||
initialCountry: initialCountry,
|
||||
formatOnDisplay: true,
|
||||
autoPlaceholder: 'polite',
|
||||
i18n: i18n,
|
||||
} as SomeOptions);
|
||||
inputRef.value.addEventListener('countrychange', fnChange);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (inputRef.value) {
|
||||
inputRef.value.removeEventListener('countrychange', fnChange);
|
||||
}
|
||||
itiRef.value?.destroy();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<input
|
||||
type="tel"
|
||||
class="ant-input"
|
||||
ref="inputRef"
|
||||
:value="value"
|
||||
:disabled="disabled"
|
||||
:placeholder="placeholder"
|
||||
:maxlength="maxlength"
|
||||
:allow-clear="allowClear"
|
||||
@input="fnChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style lang="css">
|
||||
.iti {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.iti .iti__country-container .iti__search-input {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,217 +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(() => {
|
||||
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>
|
||||
</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>
|
||||
@@ -62,7 +62,7 @@ function fnTableColumnsCheckAllChange(e: any) {
|
||||
/**表格字段列拖拽操作 */
|
||||
function fnTableColumnsDrop(dropResult: any) {
|
||||
const { removedIndex, addedIndex, payload } = dropResult;
|
||||
if (!removedIndex || !addedIndex) {
|
||||
if (removedIndex === null || addedIndex === null) {
|
||||
return;
|
||||
}
|
||||
let itemToAdd = payload;
|
||||
@@ -184,6 +184,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
v-if="c.fixed !== undefined"
|
||||
size="small"
|
||||
:title="c.fixed ? `Fixed ${c.fixed} side` : ''"
|
||||
:type="c.fixed ? 'primary' : 'dashed'"
|
||||
@click="fnTableColumnsFixed(c)"
|
||||
>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { Terminal } from 'xterm';
|
||||
import 'xterm/css/xterm.css';
|
||||
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();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { message } from 'ant-design-vue/lib';
|
||||
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { Terminal } from 'xterm';
|
||||
import 'xterm/css/xterm.css';
|
||||
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();
|
||||
@@ -19,6 +19,16 @@ const props = defineProps({
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
/**窗口单行字符数 */
|
||||
cols: {
|
||||
type: Number,
|
||||
default: 120,
|
||||
},
|
||||
/**窗口行数 */
|
||||
rows: {
|
||||
type: Number,
|
||||
default: 128,
|
||||
},
|
||||
/**禁止输入 */
|
||||
disable: {
|
||||
type: Boolean,
|
||||
@@ -238,6 +248,8 @@ onMounted(() => {
|
||||
url: '/ws/telnet',
|
||||
params: {
|
||||
hostId: props.hostId,
|
||||
cols: props.cols,
|
||||
rows: props.rows,
|
||||
},
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<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';
|
||||
const emit = defineEmits(['update:value']);
|
||||
const props = defineProps({
|
||||
/**终端ID,必传 */
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
/**窗口单行字符数 */
|
||||
cols: {
|
||||
type: Number,
|
||||
default: 80,
|
||||
},
|
||||
/**窗口行数 */
|
||||
rows: {
|
||||
type: Number,
|
||||
default: 40,
|
||||
},
|
||||
/**信息 */
|
||||
value: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
/**终端输入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: false, // 光标闪烁
|
||||
cursorStyle: 'block',
|
||||
scrollback: 1000,
|
||||
scrollSensitivity: 15,
|
||||
tabStopWidth: 4,
|
||||
disableStdin: true, // 禁止输入
|
||||
});
|
||||
// 挂载
|
||||
xterm.open(container);
|
||||
// 自适应尺寸
|
||||
const fitAddon = new FitAddon();
|
||||
xterm.loadAddon(fitAddon);
|
||||
|
||||
// 创建 ResizeObserver 实例
|
||||
var observer = new ResizeObserver(entries => {
|
||||
fitAddon.fit();
|
||||
});
|
||||
// 监听元素大小变化
|
||||
observer.observe(container);
|
||||
|
||||
terminal.value = xterm;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
handleRanderXterm(terminalDom.value);
|
||||
// 初始发送命令
|
||||
if (typeof props.value === 'string') {
|
||||
terminal.value.write(props.value);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (terminal.value != null) {
|
||||
terminal.value.dispose();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="terminalDom" :id="id" class="terminal"></div>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.terminal {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -35,19 +35,22 @@ const props = defineProps({
|
||||
|
||||
/**弹框关闭事件 */
|
||||
function fnModalClose() {
|
||||
if(props.loading) return
|
||||
if (props.loading) return;
|
||||
emit('close');
|
||||
}
|
||||
|
||||
/**上传前检查或转换压缩 */
|
||||
function fnBeforeUpload(file: FileType) {
|
||||
if (props.loading) return false;
|
||||
// 检查文件大小
|
||||
if (props.size > 0) {
|
||||
// 检查文件大小
|
||||
if (props.size > 0) {
|
||||
const fileSize = file.size;
|
||||
const isLtM = fileSize / 1024 / 1024 < props.size;
|
||||
if (!isLtM) {
|
||||
message.error(`${t('components.UploadModal.allowFilter')} ${props.size}MB`, 3);
|
||||
message.error(
|
||||
`${t('components.UploadModal.allowFilter')} ${props.size}MB`,
|
||||
3
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -56,7 +59,10 @@ function fnBeforeUpload(file: FileType) {
|
||||
const fileName = file.name;
|
||||
const isAllowType = props.ext.some(v => fileName.endsWith(v));
|
||||
if (!isAllowType) {
|
||||
message.error(`${t('components.UploadModal.onlyAllow')} ${props.ext.join('、')}`, 3);
|
||||
message.error(
|
||||
`${t('components.UploadModal.onlyAllow')} ${props.ext.join('、')}`,
|
||||
3
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -65,19 +71,20 @@ function fnBeforeUpload(file: FileType) {
|
||||
|
||||
/**上传请求发出 */
|
||||
function fnUpload(up: UploadRequestOption) {
|
||||
emit('upload', up.file)
|
||||
emit('upload', up.file);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="500px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:confirm-loading="props.loading"
|
||||
:footer="null"
|
||||
:footer="false"
|
||||
@cancel="fnModalClose"
|
||||
>
|
||||
<a-space :size="8" direction="vertical" style="width: 100%">
|
||||
@@ -93,20 +100,26 @@ function fnUpload(up: UploadRequestOption) {
|
||||
<p class="ant-upload-drag-icon">
|
||||
<inbox-outlined></inbox-outlined>
|
||||
</p>
|
||||
<p class="ant-upload-text">{{t('components.UploadModal.uploadTip')}}</p>
|
||||
<p class="ant-upload-text">
|
||||
{{ t('components.UploadModal.uploadTip') }}
|
||||
</p>
|
||||
<p class="ant-upload-hint">
|
||||
<div v-if="props.size > 0">
|
||||
{{t('components.UploadModal.allowSize')}} {{ props.size }} MB
|
||||
</div>
|
||||
<div v-if="props.ext.length > 0">
|
||||
{{t('components.UploadModal.allowFormat')}} {{ props.ext.join('、') }}
|
||||
|
||||
</div>
|
||||
<template v-if="props.size > 0">
|
||||
<div>
|
||||
{{ t('components.UploadModal.allowSize') }} {{ props.size }} MB
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="props.ext.length > 0">
|
||||
<div>
|
||||
{{ t('components.UploadModal.allowFormat') }}
|
||||
{{ props.ext.join('、') }}
|
||||
</div>
|
||||
</template>
|
||||
</p>
|
||||
</a-upload-dragger>
|
||||
<slot></slot>
|
||||
</a-space>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -1,5 +1,5 @@
|
||||
/**管理员-系统指定角色KEY */
|
||||
export const ADMIN_ROLE_KEY = 'admin';
|
||||
/**系统管理员-系统指定角色KEY */
|
||||
export const ADMIN_ROLE_KEY = 'system';
|
||||
|
||||
/**管理员-系统指定权限 */
|
||||
/**系统管理员-系统指定权限 */
|
||||
export const ADMIN_PERMISSION = '*:*:*';
|
||||
@@ -10,8 +10,11 @@ export const CACHE_LOCAL_PRIMARY_COLOR = 'cache:local:primaryColor';
|
||||
/**本地缓存-多语言 */
|
||||
export const CACHE_LOCAL_I18N = 'cache:local:i18n';
|
||||
|
||||
/**本地缓存-锁屏设置 */
|
||||
export const CACHE_LOCAL_LOCK = 'cache:local:Lock';
|
||||
/**本地缓存-遮罩设置 */
|
||||
export const CACHE_LOCAL_MASK = 'cache:local:mask';
|
||||
|
||||
/**本地缓存-锁屏密码 */
|
||||
export const CACHE_LOCAL_LOCK_PASSWD = 'cache:local:lock:passwd';
|
||||
|
||||
/**数据缓存表-表格排序 */
|
||||
export const CACHE_DB_TABLE_DND = 'tbl_dnd';
|
||||
@@ -1,18 +1,26 @@
|
||||
/**网元列表,默认顺序 */
|
||||
export const NE_TYPE_LIST = [
|
||||
'OMC',
|
||||
'MME',
|
||||
'IMS',
|
||||
'AMF',
|
||||
'AUSF',
|
||||
'UDM',
|
||||
'SMF',
|
||||
'PCF',
|
||||
'UPF',
|
||||
'NRF',
|
||||
'NSSF',
|
||||
'IMS',
|
||||
'N3IWF',
|
||||
'NEF',
|
||||
'NRF',
|
||||
'UPF',
|
||||
'LMF',
|
||||
'NEF',
|
||||
'MME',
|
||||
'N3IWF',
|
||||
'MOCNGW',
|
||||
'SMSC',
|
||||
];
|
||||
|
||||
/**
|
||||
* 网元拓展包列表,默认顺序
|
||||
* IMS-adb/rtproxy/mf
|
||||
* UDM-adb
|
||||
*/
|
||||
export const NE_EXPAND_LIST = ['ADB', 'RTPROXY', 'MF'];
|
||||
@@ -1,5 +1,5 @@
|
||||
import { onBeforeMount } from 'vue';
|
||||
import { ConfigProvider } from 'ant-design-vue/lib';
|
||||
import { ConfigProvider, message } from 'ant-design-vue/lib';
|
||||
import { CACHE_LOCAL_PRIMARY_COLOR } from '@/constants/cache-keys-constants';
|
||||
import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||
|
||||
@@ -8,6 +8,7 @@ import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||
*/
|
||||
export const usePrimaryColor = () => {
|
||||
onBeforeMount(() => {
|
||||
message.config({ top: '100px' }); // 全局配置消息距离顶部的位置
|
||||
changePrimaryColor(getLocalColor());
|
||||
});
|
||||
};
|
||||
|
||||
+350
-75
@@ -2,6 +2,7 @@ export default {
|
||||
// 语言
|
||||
i18n: 'English',
|
||||
hello: 'Hello',
|
||||
welcome: 'Welcome, Core Network Management Platform',
|
||||
|
||||
// 通用
|
||||
common: {
|
||||
@@ -34,7 +35,6 @@ export default {
|
||||
unableNull:' Cannot be empty',
|
||||
moreText: 'More',
|
||||
searchBarText: 'Search bar',
|
||||
tableStripedText: 'Form Zebra',
|
||||
reloadText: 'Refresh',
|
||||
columnSetText: 'Column Setting',
|
||||
columnSetTitle: 'Column Display / Sorting',
|
||||
@@ -53,9 +53,15 @@ export default {
|
||||
fold: 'Fold',
|
||||
},
|
||||
rowId: 'ID',
|
||||
operate: 'Operation',
|
||||
createTime: 'Create Time',
|
||||
updateTime: 'Update Time',
|
||||
remark: 'Remark',
|
||||
description: 'Description',
|
||||
operate: 'More Action',
|
||||
operateOk: 'Operation Successful!',
|
||||
operateErr: 'Operation Failed!',
|
||||
copyText: "Copy",
|
||||
copyOk: 'Copy Successful!',
|
||||
units: {
|
||||
second: 'Second',
|
||||
minute: 'Minute',
|
||||
@@ -124,12 +130,14 @@ 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',
|
||||
backReload:'Restarting now, please wait...',
|
||||
backReload2:'When ready, your browser will automatically refresh.',
|
||||
backReload2:'When ready, Your browser will automatically refresh.',
|
||||
systemReset:'Resetting now, please wait...',
|
||||
systemReset2:'Data information is being reset.',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -141,6 +149,7 @@ export default {
|
||||
page403: 'No Access',
|
||||
page404: 'Match Page Not Found',
|
||||
helpDoc: 'System User Documentation',
|
||||
lockScreen: 'Lock Screen',
|
||||
account: {
|
||||
index: "Personal Center",
|
||||
profile: "Personal Info",
|
||||
@@ -164,6 +173,9 @@ export default {
|
||||
codeHit: 'Verification code',
|
||||
codeText: 'Obtain verification code',
|
||||
codeSmsSend: 'Successfully sent, please pay attention to checking the SMS',
|
||||
ipPlease: 'Please enter a valid IP address',
|
||||
ipv4Reg: 'Not a valid IPv4 address',
|
||||
ipv6Reg: 'Not a valid IPv6 address',
|
||||
},
|
||||
|
||||
// 布局
|
||||
@@ -174,7 +186,9 @@ export default {
|
||||
},
|
||||
rightContent: {
|
||||
lock: "Lock Screen",
|
||||
lockTip: "Confirmed to perform a lock screen?",
|
||||
lockTip: "Confirmation of the lock screen?",
|
||||
lockPasswd: "Unlock Password",
|
||||
lockPasswdTip: "No password can be set",
|
||||
helpDoc: "System User Documentation",
|
||||
fullscreen: "Full Screen",
|
||||
logout: "Logout",
|
||||
@@ -356,7 +370,7 @@ export default {
|
||||
pvflag:'PV Flag',
|
||||
pnf:'Physical Network Element',
|
||||
vnf:'Virtual Network Element',
|
||||
province:'Province',
|
||||
province:'Region',
|
||||
vendorName:'Vendor Name',
|
||||
dn:'Network Identification',
|
||||
reload: 'Reload',
|
||||
@@ -424,15 +438,14 @@ export default {
|
||||
letUpTime:'Activation time',
|
||||
createTime:'Creation time',
|
||||
onlyAble:'Only upload file format {fileText} is supported',
|
||||
nullData:'No network element list data yet',
|
||||
nullVersion:'There is no rollback version for the current network element.',
|
||||
},
|
||||
license: {
|
||||
neTypePlease: 'Select network element type',
|
||||
neType: 'NE Type',
|
||||
fileName: 'File Name',
|
||||
createTime: 'Uploaded Time',
|
||||
comment: 'File Description',
|
||||
serialNum: 'Serial Num',
|
||||
createTime: 'Time',
|
||||
comment: 'Description',
|
||||
updateComment: 'License Description',
|
||||
updateCommentPlease: 'Please enter a license description',
|
||||
updateFile: 'License File',
|
||||
@@ -471,21 +484,21 @@ export default {
|
||||
neType: 'NE Type',
|
||||
neTypePleace: "Please select the network element type",
|
||||
noConfigData: "No data on configuration items",
|
||||
updateValue: "The value of the {num} attribute was modified successfully.",
|
||||
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: "The {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?",
|
||||
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",
|
||||
@@ -549,8 +562,6 @@ export default {
|
||||
realTimeDataStart: "Turn on real-time data",
|
||||
realTimeDataStop: "Turn off real-time data",
|
||||
cdrInfo: "CDR Info",
|
||||
neName: "NE name",
|
||||
rmUID: "UID",
|
||||
time: "Time",
|
||||
rowInfo: "Info",
|
||||
type: "Type",
|
||||
@@ -559,30 +570,66 @@ export default {
|
||||
called: "Called",
|
||||
result: "Result",
|
||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||
exportTip: "Do you confirm to export the current query conditions of the CDR data? (Maximum 10,000 items can be exported.)",
|
||||
smfChargingID: 'Charging ID',
|
||||
smfSubscriptionIDData: 'Subscription ID Data',
|
||||
smfSubscriptionIDType: 'Subscription ID Type',
|
||||
smfDataVolumeUplink: 'Data Volume Uplink',
|
||||
smfDataVolumeDownlink: 'Data Volume Downlink',
|
||||
smfDataTotalVolume: 'Data Total Volume',
|
||||
smfDuration: 'Duration',
|
||||
smfInvocationTime: 'Invocation Time',
|
||||
},
|
||||
ue: {
|
||||
eventType: "Event Type",
|
||||
realTimeDataStart: "Turn on real-time data",
|
||||
realTimeDataStop: "Turn off real-time data",
|
||||
ueInfo: "UE Info",
|
||||
neName: "NE name",
|
||||
rmUID: "UID",
|
||||
time: "Time",
|
||||
rowInfo: "Info",
|
||||
result: "Result",
|
||||
resultOk: "Successes",
|
||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||
exportTip: "Do you confirm to export the event data of the current query condition? (Maximum 10,000 items can be exported.)",
|
||||
},
|
||||
},
|
||||
ne: {
|
||||
neInfo: {
|
||||
version: "Version",
|
||||
common: {
|
||||
neType: 'NE Type',
|
||||
neTypePlease: "Please select network element type",
|
||||
neTypeTip: 'Fill in the type of network element to be created, e.g. SMF.',
|
||||
neId: 'NE ID',
|
||||
neIdPlease: 'Please enter the network element identification',
|
||||
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.",
|
||||
neName: 'NE Name',
|
||||
neNamePlease: 'Please enter the name of the network element',
|
||||
ipAddr: 'IP Addr',
|
||||
ipAddrPlease: 'Please enter the IP address of the network element',
|
||||
ipAddrTip: "Support IPV4/IPV6, synchronized change of configuration address",
|
||||
port: 'Port',
|
||||
portTip: "Network element port default:33030",
|
||||
serialNum: 'Serial Number',
|
||||
expiryDate: 'Expiry Date',
|
||||
normalcy: 'Normal',
|
||||
exceptions: 'Abnormal',
|
||||
restart: 'Restart',
|
||||
restartTip: 'Are you sure you want to restart the network element service?',
|
||||
start: 'Start',
|
||||
startTip: 'Are you sure you want to start the network element service?',
|
||||
stop: 'Stop',
|
||||
stopTip: 'Are you sure you want to stop the network element service?',
|
||||
reload: 'Reload',
|
||||
reloadTip: 'Confirm that you want to reload the network element configuration information?',
|
||||
oam: 'OAM',
|
||||
log: 'Logs',
|
||||
},
|
||||
neInfo: {
|
||||
version: "Version",
|
||||
state: "State",
|
||||
serviceState: "Service Status",
|
||||
normalcy: "Normal",
|
||||
exceptions: "Abnormal",
|
||||
serviceState: "Service Status",
|
||||
info: 'Status Message',
|
||||
resourceInfo: 'Resource Situation',
|
||||
sysMem: "SYS Mem",
|
||||
@@ -590,8 +637,41 @@ export default {
|
||||
sysDisk: "SYS Store",
|
||||
neCpu: "NE CPU",
|
||||
hostConfig: "Connection Configuration",
|
||||
rmUID: "Data resource location identifiers are used for data tagging such as logging, alarm reporting, etc.",
|
||||
ipAddr: "Support IPV4/IPV6, synchronize the change of the configuration address of the following configuration",
|
||||
pvflag: 'NE Virtualization',
|
||||
pnf: 'physical network element',
|
||||
vnf: 'virtual network element',
|
||||
neAddress: 'MAC',
|
||||
neAddressTip: 'Record the physical address (MAC) of the network card of the network element',
|
||||
dn: 'network identifier',
|
||||
vendorName: 'provider',
|
||||
province: 'Service Area',
|
||||
addTitle: 'New network element information',
|
||||
editTitle: 'Edit network element information',
|
||||
delTip: 'Confirm deletion of network element information data items?',
|
||||
oam: {
|
||||
title: 'OAM Configuration',
|
||||
sync: 'Sync to NE',
|
||||
oamEnable: 'Service',
|
||||
oamPort: 'Port',
|
||||
snmpEnable: 'Service',
|
||||
snmpPort: 'Port',
|
||||
kpiEnable: 'Report',
|
||||
kpiTimer: 'Reporting Cycle',
|
||||
kpiTimerPlease: 'Please enter the reporting period (in seconds)',
|
||||
},
|
||||
backConf: {
|
||||
export: 'Config Export',
|
||||
import: 'Config Import',
|
||||
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',
|
||||
},
|
||||
},
|
||||
neHost: {
|
||||
hostType: "Type",
|
||||
@@ -610,13 +690,13 @@ export default {
|
||||
privateKey: "Private Key",
|
||||
privateKeyPlease: "Please fill in the private key characters correctly ~/.ssh/id_rsa",
|
||||
passPhrase: "Private Key Cipher",
|
||||
remark: "Remark",
|
||||
createTime: "Time",
|
||||
delTip: "Confirm that you want to delete the host number [{num}]?",
|
||||
addTitle: "Add Host Connection",
|
||||
editTitle: "Edit Host Connection",
|
||||
test: "Test Connection To Host",
|
||||
test: "Test Connection",
|
||||
testOk: "Test Connection Successful",
|
||||
authRSA: 'Secret Authorization',
|
||||
authRSATip: "Do I have to configure secret-free authorization?",
|
||||
},
|
||||
neHostCmd: {
|
||||
cmdType: "Type",
|
||||
@@ -625,12 +705,129 @@ export default {
|
||||
titlePlease: "Please fill in the command name correctly",
|
||||
command: "Command",
|
||||
commandPlease: "Please enter a valid command string correctly",
|
||||
remark: "Remark",
|
||||
createTime: "Time",
|
||||
delTip: "Are you sure you want to delete the message with command number [{num}]?",
|
||||
addTitle: "New Host Commands",
|
||||
editTitle: "Edit Host Commands",
|
||||
},
|
||||
neSoftware: {
|
||||
uploadTitle: "Update Software",
|
||||
upload: "Upload",
|
||||
uploadNotFile: "No software files uploaded",
|
||||
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",
|
||||
path: "Software File",
|
||||
pathPlease: "Please upload the software package file",
|
||||
version: "Software Version",
|
||||
versionPlease: "Please enter the software version number",
|
||||
delTip: "Confirmed to remove the package?",
|
||||
downTip: "Confirmation to download package [{txt}]?",
|
||||
fileCheckType: 'The corresponding network element type is not resolved',
|
||||
fileCheckVer: 'The corresponding version number is not resolved',
|
||||
fileTypeNotEq: 'Not a specified network element type {txt}',
|
||||
fileTypeExists: 'Same type of file already exists',
|
||||
fileNameExists: 'File with same name already exists',
|
||||
fileCheckTypeDep: 'The specified dependency package type is not resolved',
|
||||
dependFile: 'Software Dependencies',
|
||||
dependFileTip: 'File name resolution is the same as above, and installation is based on the order of uploading.',
|
||||
},
|
||||
neVersion: {
|
||||
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",
|
||||
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',
|
||||
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',
|
||||
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: {
|
||||
status: "License Status",
|
||||
change: "Change License",
|
||||
reload: "Refresh Info",
|
||||
reloadTip: "Confirmed to refresh license information?",
|
||||
reloadBatch: "Batch Refresh",
|
||||
reloadBatchTip: "Do you do an information refresh on checked records?",
|
||||
updateTtile: "Update License",
|
||||
downCodeTop: "Confirmed to save the license activation code to a file?",
|
||||
activationRequestCode: "License Activation Code",
|
||||
licensePath: "License File",
|
||||
licensePathTip: "Please upload license file",
|
||||
upload: 'Upload',
|
||||
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: {
|
||||
headerTip: 'Check and save the public parameter properties of the network element before performing the installation of the network element, and make sure that the latest parameter properties are applied.',
|
||||
headerTipToPage: 'Jump Installation',
|
||||
save: 'Save',
|
||||
reload: 'Reload',
|
||||
title: 'Save Info',
|
||||
sync: 'Sync to NE',
|
||||
syncNe: 'Select NE',
|
||||
syncNeDone: 'Synchronization to network element terminals complete',
|
||||
saveOk: 'Save Success!',
|
||||
},
|
||||
neQuickSetup: {
|
||||
stepPrev: 'Previous',
|
||||
stepPrevTip: 'Confirm that you want to abandon the current change and return to the previous step?',
|
||||
stepNext: 'Next',
|
||||
stepSave: 'Save',
|
||||
startTitle: 'Service Terminal Environment',
|
||||
startDesc: 'Test connectivity to network element services',
|
||||
startStepNext: 'Confirm that you want to proceed to the next step to configure the network element information?',
|
||||
addr: 'Terminal IP',
|
||||
kernelName: 'System',
|
||||
kernelRelease: 'Kernel',
|
||||
machine: 'Framework',
|
||||
prettyName: 'Platform',
|
||||
prettyNameTip: 'Support Ubuntu',
|
||||
nodename: 'Node Name',
|
||||
auth: 'Competence Grant',
|
||||
sudo: 'sudo',
|
||||
sudoErr: 'To ensure that you have permission to install packages, configure to grant the current user permission to allow passwordless sudo privileges.',
|
||||
sshLink: 'confidentiality',
|
||||
configTitle: "Configuring Network Elements",
|
||||
configDesc: "Fill in the basic information of the network element",
|
||||
configAddTitle: 'New Tips',
|
||||
configAddTip: 'Is it added as new network element information and continue?',
|
||||
configUpdateTitle: 'Update Tips',
|
||||
configUpdateTip: 'Does it update to the already existing network element information and continue?',
|
||||
configStepNext: 'Confirm that you want to proceed to the next step for the Network Element software installation?',
|
||||
installTitle: "Network Element Installation",
|
||||
installDesc: "Installation to Service Terminal",
|
||||
installConfirmTip: 'Are you sure you want to install package [{name}]?',
|
||||
installStepNext: 'Confirm that you want to proceed to the next step for network element authorization?',
|
||||
installSource: 'Software Source',
|
||||
installSourceOption: 'Uploaded',
|
||||
installSourceUpload: 'New Upload',
|
||||
installSelect: 'Select Record',
|
||||
installUpload: 'Upload File',
|
||||
installText: 'Installed',
|
||||
licenseTitle: "Licenses",
|
||||
licenseDesc: "Network element service authorization certification",
|
||||
licenseResultTitle: "Whether to authorize activation immediately",
|
||||
licenseResultTitleOk: 'Successful Activation',
|
||||
licenseUpload: 'License',
|
||||
licenseEnd: 'Finish',
|
||||
licenseEndTip: "Confirmed to end the installation?",
|
||||
licenseCheack: 'Waiting for network element validation',
|
||||
licenseTip1: '1. Click [License] to get the license activation code, and then contact the network element vendor for activation.',
|
||||
licenseTip2: '2. Clicking [Finish] will end the installation process.',
|
||||
},
|
||||
},
|
||||
neUser: {
|
||||
auth: {
|
||||
@@ -644,7 +841,7 @@ export default {
|
||||
import: 'Import',
|
||||
loadDataConfirm: 'Are you sure you want to reload the data?',
|
||||
loadData: 'Load Data',
|
||||
loadDataTip: 'Successfully fetched load data: {num} entries, the system is internally updating the data. You can click reset to refresh the data list after the loading is finished, please don it repeat click to get update!!!!',
|
||||
loadDataTip: 'Successfully fetched load data: {num} entries, the system is internally updating the data. Please wait a moment!!!!',
|
||||
startIMSI: 'Start IMSI',
|
||||
batchAddText: 'Batch Add',
|
||||
batchDelText: 'Batch Delete',
|
||||
@@ -671,7 +868,7 @@ export default {
|
||||
import: 'Import',
|
||||
loadDataConfirm: 'Are you sure you want to reload the data?',
|
||||
loadData: 'Load Data',
|
||||
loadDataTip: 'Successfully fetched load data: {num} entries, the system is internally updating the data. You can click reset to refresh the data list after the loading is finished, please don it repeat click to get update!!!!',
|
||||
loadDataTip: 'Successfully fetched load data: {num} entries, the system is internally updating the data. Please wait a moment!!!!',
|
||||
numAdd: 'Number of releases',
|
||||
numDel: 'Number of deleted',
|
||||
checkDel: 'Check Delete',
|
||||
@@ -709,6 +906,7 @@ export default {
|
||||
addTitle: 'Adding Policy Control Information',
|
||||
updateTitle: '{imsi} Policy control information',
|
||||
startIMSI: 'Start IMSI',
|
||||
batchOper: 'Batch Operations',
|
||||
batchAddText: 'Batch Add',
|
||||
batchDelText: 'Batch Delete',
|
||||
batchUpdateText: 'Batch Modify',
|
||||
@@ -717,9 +915,19 @@ export default {
|
||||
imsiTip1: 'MCC=Mobile Country Code, consisting of three digits.',
|
||||
imsiTip2: 'MNC = Mobile Network Number, consisting of two digits',
|
||||
imsiTip3: 'MSIN = Mobile Subscriber Identification Number, consisting of 10 equal digits.',
|
||||
checkDel: 'Check Delete',
|
||||
delSure:'Are you sure you want to delete the user with IMSI number: {imsi}?',
|
||||
uploadFileOk: 'File Upload Successful',
|
||||
uploadFileErr: 'File Upload Failed',
|
||||
pccRuleTip:'PCC policy rule template (corresponding to parameter configuration -PCC Rules)',
|
||||
sessRuleTip:' Session policy rule template (corresponding to parameter configuration-session Rules)',
|
||||
qosAudioTip:' Voice call QoS(corresponding parameter configuration -QoS Template QoS ID)',
|
||||
qosVideoTip:' Video call QoS(corresponding parameter configuration -QoS Template QoS ID)',
|
||||
hdrTip:'HTTP Header enhancement (corresponding parameter configuration -Header Enrich Template)',
|
||||
ueTip:'UE policy template (example: uep_001)',
|
||||
sarTip1:' Service area Restriction ',
|
||||
sarTip2:'(corresponding parameter setting -Service Area Restriction)',
|
||||
rfsfTip:'RAT Frequency Selection Priority',
|
||||
},
|
||||
base5G: {
|
||||
neType: 'NE Object',
|
||||
@@ -755,7 +963,7 @@ export default {
|
||||
viewTask:'View Task',
|
||||
editTask:'Edit Task',
|
||||
addTask:'Add Task',
|
||||
stopTask:'Pending',
|
||||
stopTask:'Stop',
|
||||
errorTaskInfo: 'Failed to obtain task information',
|
||||
granulOptionPlease:'Please select the measurement granularity',
|
||||
letupSure:'Confirm activation of task with number [{id}]?',
|
||||
@@ -815,7 +1023,7 @@ export default {
|
||||
exportSure:'Confirm whether to export all statistical data',
|
||||
exportEmpty: "Export data is empty",
|
||||
showChartSelected: "Show All",
|
||||
realTimeData: "Real Time 5s Data",
|
||||
realTimeData: "Real Time Data",
|
||||
},
|
||||
customTarget:{
|
||||
kpiId:' Custom Indicator',
|
||||
@@ -944,7 +1152,7 @@ export default {
|
||||
alarmSeq:'Sequence Number',
|
||||
objectName:'Object Name',
|
||||
locationInfo:'Location Info',
|
||||
province:'Province',
|
||||
province:'Region',
|
||||
addInfo:'Additional Info',
|
||||
specificProblemId:'Cause ID',
|
||||
specificProblem:'Cause',
|
||||
@@ -965,6 +1173,7 @@ export default {
|
||||
showSet:'Show filter settings',
|
||||
exportSure:'Confirm whether to export all active alarm information',
|
||||
viewIdInfo:'View {alarmId} record information',
|
||||
closeModal:'Close',
|
||||
},
|
||||
historyAlarm:{
|
||||
exportSure:'Confirm whether to export all historical alarm information',
|
||||
@@ -977,13 +1186,16 @@ export default {
|
||||
noChange:'There is no change in the alarm forwarding settings.',
|
||||
forwardSet:'Alarm Forwarding Setting',
|
||||
},
|
||||
eventAlarm:{
|
||||
exportSure:'Confirm whether to export all event alarm information',
|
||||
}
|
||||
},
|
||||
logManage:{
|
||||
alarm:{
|
||||
type:'NE Type',
|
||||
neId:'NE UID',
|
||||
alarmId:'Alarm ID',
|
||||
alarmSeq:'Sequece Number',
|
||||
alarmSeq:'Sequence Number',
|
||||
alarmCode:'Alarm Code',
|
||||
alarmStatus:'Status',
|
||||
eventTime:'Event Time',
|
||||
@@ -1002,12 +1214,13 @@ export default {
|
||||
type:'NE Type',
|
||||
neId:'NE UID',
|
||||
alarmId:'Alarm ID',
|
||||
alarmSeq:'Sequece Number',
|
||||
alarmObj:'Object',
|
||||
alarmSeq:'Sequence Number',
|
||||
alarmObj:'Forward Users',
|
||||
alarmInter:'Forward Interface',
|
||||
alarmTitle:'Alarm Title',
|
||||
alarmInfo:'Alarm Content',
|
||||
eventTime:'Generation Time',
|
||||
logTime:'Record Time'
|
||||
alarmInfo:'Operation Results',
|
||||
eventTime:'Event Time',
|
||||
logTime:'Log Time'
|
||||
},
|
||||
neFile: {
|
||||
neType:'NE Type',
|
||||
@@ -1152,12 +1365,12 @@ export default {
|
||||
jobLog: {
|
||||
jobName: "Job Name",
|
||||
jobGroup: "Job Group",
|
||||
invokeTarget: "Invoke Target",
|
||||
invokeTarget: "Job Invoke",
|
||||
status: "Status",
|
||||
status0: "Failures",
|
||||
status1: "Active",
|
||||
createTime: "Create Time",
|
||||
costTime: "Cost Time",
|
||||
createTime: "Time",
|
||||
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",
|
||||
@@ -1191,7 +1404,7 @@ export default {
|
||||
cacheInfo: {
|
||||
baseInfo: "Basic Info",
|
||||
version: "Service Versions",
|
||||
mode: "Perating Mode",
|
||||
mode: "Operating Mode",
|
||||
modeStandalone: "stand-alone",
|
||||
modeClusters: "clusters",
|
||||
port: "Port",
|
||||
@@ -1392,15 +1605,15 @@ export default {
|
||||
userInfo:' User Info',
|
||||
userNum: 'User Number',
|
||||
account: 'Account',
|
||||
userName: 'User Name',
|
||||
userName: 'Nick Name',
|
||||
permission: 'Role',
|
||||
className: 'Department',
|
||||
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 can only contain letters, numbers, Chinese characters, and underscores, with no less than 2 digits',
|
||||
nickNameTip:'Nicknames no less than 2 digits',
|
||||
emailTip:'Please enter the correct email address',
|
||||
phoneTip:'Please enter the correct phone number',
|
||||
resetPwd:'Reset Password',
|
||||
@@ -1423,7 +1636,7 @@ export default {
|
||||
userWork:'User position',
|
||||
userWorkPlease: 'Please select user post',
|
||||
userTip:'User Description',
|
||||
loginPwd:'Login password',
|
||||
loginPwd:'Password',
|
||||
updateSure:'Do you want to update existing data',
|
||||
downloadObj:'Download Tpl',
|
||||
importTitle:'User Import',
|
||||
@@ -1509,6 +1722,9 @@ export default {
|
||||
i18nOpen: "Display Switch",
|
||||
i18nDefault: "Default Languages",
|
||||
i18nInstruction: 'Whether to display the internationalization switch and set the system default language',
|
||||
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?',
|
||||
},
|
||||
role:{
|
||||
allScopeOptions:'All data permissions',
|
||||
@@ -1516,11 +1732,11 @@ export default {
|
||||
onlyClassScopeOptions:'Data permissions of this department',
|
||||
classAllScopeOptions:'Data permissions for this department and the following',
|
||||
myselfScopeOptions:'Only personal data permissions',
|
||||
roleId:'Role ID',
|
||||
roleId:'Role Number',
|
||||
roleName:'Role Name',
|
||||
roleKey:'Role Key',
|
||||
roleSort:'Role Order',
|
||||
roleStatus:'Status',
|
||||
roleSort:'Role Sort',
|
||||
roleStatus:'Role Status',
|
||||
createTime:'Creation Time',
|
||||
trueValue:'Please enter {msg} correctly',
|
||||
roleInfo:'Role information',
|
||||
@@ -1533,10 +1749,10 @@ export default {
|
||||
distributeUser:'Assign Users',
|
||||
roleMark:'Role Description',
|
||||
menu:'Menu Permissions',
|
||||
roleKeyTip:"Example of permission identification: Use permission identification in dba controller, such as: @PreAuthorize({ hasRoles: ['dba'] })",
|
||||
roleKeyTip:"Privilege identifiers are used to control page controls or routing interfaces",
|
||||
openSwitch:'Expand/Collapse',
|
||||
selAllSwitch:'Select all/Deselect all',
|
||||
relationSwitch:'Father and son linkage',
|
||||
selAllSwitch:'Select All/Deselect All',
|
||||
relationSwitch:'Node Linkage',
|
||||
normal:'Active',
|
||||
stop:'Pending',
|
||||
preScope:'Scope of authority',
|
||||
@@ -1559,7 +1775,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',
|
||||
@@ -1578,7 +1794,7 @@ export default {
|
||||
positionId:'Position Number',
|
||||
positionCode:'Position Code',
|
||||
positionName:'Position Name',
|
||||
positionSort:'Position Sorting',
|
||||
positionSort:'Position Sort',
|
||||
positionStatus:'Position Status',
|
||||
positionMark:'Position Description',
|
||||
createTime:'Creation Time',
|
||||
@@ -1588,15 +1804,15 @@ export default {
|
||||
},
|
||||
log:{
|
||||
operate:{
|
||||
operId:'ID',
|
||||
operId:'Log ID',
|
||||
moduleName:'Module Name',
|
||||
workType:'Business Type',
|
||||
workType:'Operation',
|
||||
operUser:'Operator',
|
||||
requestMe:'Request Method',
|
||||
host:'Request Host',
|
||||
operStatus:'Operation Status',
|
||||
operDate:'Operation Date',
|
||||
useTime:'Consumption Time',
|
||||
operStatus:'Status',
|
||||
operDate:'Time',
|
||||
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?',
|
||||
@@ -1703,6 +1919,65 @@ export default {
|
||||
exportOk: "Completed export",
|
||||
typeDataErr: "Failed to get dictionary type information",
|
||||
},
|
||||
quickStart: {
|
||||
start: 'Start Setup',
|
||||
skip: 'Skip',
|
||||
finish: 'Complete Setup',
|
||||
stepPrev: 'Previous',
|
||||
stepNext: 'Next',
|
||||
exit: 'Exit',
|
||||
save: 'Save Info',
|
||||
sysTitle: 'System Configuration',
|
||||
sysAdmin: 'Administrator',
|
||||
sysInfo: 'System Info',
|
||||
sysLogo: 'System Logo',
|
||||
sysLogoTip: 'Show the image to the system logo area to see the effect, please use a transparent background, the size of the proportion to adapt to the size of the area',
|
||||
sysName: 'System Name',
|
||||
sysNameTip: 'Limit system name to 20 characters in length',
|
||||
sysUploadLogo: 'Confirmation of uploading the system logo file?',
|
||||
sysUploadOk: 'File uploaded successfully, please save the information',
|
||||
sysSave: 'Save',
|
||||
sysSaveOk: 'Info saved successfully!',
|
||||
sysPrevTip: 'Confirmed to go back to the previous step?',
|
||||
sysNextNe: 'Confirming that you want to do a network element installation?',
|
||||
sysNextDone: 'Confirmed to skip the network element installation?',
|
||||
stepNeInfoTitle: "Service Configuration",
|
||||
stepNeInfoDesc: "Setting the service terminal corresponding to a network element",
|
||||
stepNeInfoStepPrev: 'Confirming that you want to exit the network element installation step?',
|
||||
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",
|
||||
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",
|
||||
stepInstallDesc: "Installation of network element services to service terminals",
|
||||
stepInstallStepPrev: 'Confirm that you want to abandon the current change and return to the previous step?',
|
||||
stepInstallStepNext: 'Confirm that you want to proceed to the next step for network element license authorization?',
|
||||
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!',
|
||||
stepLicenseTitle: "Service License",
|
||||
stepLicenseDesc: "Obtaining a license activation code for authorization authentication",
|
||||
stepLicenseReload: 'Select Refresh',
|
||||
stepLicenseReloadTip: 'Confirm refreshing selected license information?',
|
||||
stepLicenseDownCode: 'Select Download Activation Code',
|
||||
stepLicenseDownCodeTip: 'Confirmed to download the selected network element license activation code to a text file?',
|
||||
stepLicenseStepPrev: 'Confirm that you want to abandon the current change and return to the previous step?',
|
||||
stepLicenseStepNext: 'Confirmed to end the network element installation step?',
|
||||
stepLicenseStepNext2: 'Please download the Net Element License Authorization Code file to save it and contact the Net Element vendor to get the authorization license',
|
||||
stepLicenseEnd: 'End',
|
||||
doneTitle: "Completing the Configuration",
|
||||
doneTip: 'Please enter the system and configure it as appropriate.',
|
||||
doneNETitle: 'Configuration of the network element installation has been performed',
|
||||
doneNEDesc: 'In case of abnormal network elements, the license can be reinstalled in the system',
|
||||
doneSkipTitle: 'No network element installation configuration',
|
||||
doneSkipDesc: 'The system will initialize the network element information by default, which can be modified or installed within the system.',
|
||||
donePrevTip: 'Confirmed to go back to the previous step?',
|
||||
doneOkTip: 'Confirm that you have completed the setup and started using it?',
|
||||
},
|
||||
},
|
||||
mmlManage: {
|
||||
cmdTitle: "Command Navigator",
|
||||
@@ -1710,14 +1985,14 @@ export default {
|
||||
cmdOpTip: "Select the item to be operated in the left command navigation!",
|
||||
cmdNoTip: "{num} no optional command operation",
|
||||
require: "Mandatory parameter: {num}",
|
||||
requireUn: "{display} input value is of unknown type",
|
||||
requireString: "The {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.",
|
||||
requireFile: "{display} is not a value that matches the parameter file type.",
|
||||
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.",
|
||||
requireFile: "[ {display} ] is not a value that matches the parameter file type.",
|
||||
cmdQuickEntry: "Command Quick Entry",
|
||||
cmdQuickEntryHelp: "Line feed (Shift + Enter), Execute (Enter)",
|
||||
cmdParamPanel: "Parameter Panel",
|
||||
|
||||
+329
-54
@@ -2,6 +2,7 @@ export default {
|
||||
// 语言
|
||||
i18n: '中文',
|
||||
hello: '你好',
|
||||
welcome: '欢迎使用,核心网管理平台',
|
||||
|
||||
// 通用
|
||||
common: {
|
||||
@@ -34,7 +35,6 @@ export default {
|
||||
unableNull:'不能为空',
|
||||
moreText: '更多',
|
||||
searchBarText: '搜索栏',
|
||||
tableStripedText: '表格斑马纹',
|
||||
reloadText: '刷新',
|
||||
columnSetText: '列设置',
|
||||
columnSetTitle: '列展示/排序',
|
||||
@@ -53,9 +53,15 @@ export default {
|
||||
fold: '折叠',
|
||||
},
|
||||
rowId: '编号',
|
||||
operate: '操作',
|
||||
createTime: '创建时间',
|
||||
updateTime: '更新时间',
|
||||
remark: '备注',
|
||||
description: '说明',
|
||||
operate: '更多操作',
|
||||
operateOk: '操作成功!',
|
||||
operateErr: '操作失败!',
|
||||
copyText: "复制",
|
||||
copyOk: '复制成功!',
|
||||
units: {
|
||||
second: '秒',
|
||||
minute: '分钟',
|
||||
@@ -124,12 +130,14 @@ export default {
|
||||
onlyAllow:'只支持上传文件格式',
|
||||
},
|
||||
LockScreen: {
|
||||
inputPlacePwd:'请输入登录密码',
|
||||
inputPlacePwd:'请输入锁屏密码',
|
||||
validSucc:'校验通过',
|
||||
validError:'校验失败',
|
||||
backLogin:'退出并重新登录',
|
||||
backReload:'正在重启,请稍等...',
|
||||
backReload2:'当准备就绪的时候,你的浏览器会自动刷新。',
|
||||
systemReset:'正在重置,请稍等...',
|
||||
systemReset2:'数据信息正在重置',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -141,6 +149,7 @@ export default {
|
||||
page403: '没有访问权限',
|
||||
page404: '找不到匹配页面',
|
||||
helpDoc: '系统使用文档',
|
||||
lockScreen: '锁屏',
|
||||
account: {
|
||||
index: "个人中心",
|
||||
profile: "个人信息",
|
||||
@@ -164,6 +173,9 @@ export default {
|
||||
codeHit: '验证码',
|
||||
codeText: '获取验证码',
|
||||
codeSmsSend: '发送成功,请注意查看短信',
|
||||
ipPlease: '请输入有效的IP地址',
|
||||
ipv4Reg: '不是有效IPv4地址',
|
||||
ipv6Reg: '不是有效IPv6地址',
|
||||
},
|
||||
|
||||
// 布局
|
||||
@@ -175,6 +187,8 @@ export default {
|
||||
rightContent: {
|
||||
lock: "锁屏",
|
||||
lockTip: "确认要进行锁屏吗?",
|
||||
lockPasswd: "解锁密码",
|
||||
lockPasswdTip: "可不设置密码",
|
||||
helpDoc: "系统使用文档",
|
||||
fullscreen: "全屏显示",
|
||||
logout: "退出登录",
|
||||
@@ -262,10 +276,10 @@ export default {
|
||||
email: "电子邮箱",
|
||||
emailPleace: "请输入正确的电子邮箱",
|
||||
phonenumber: "手机号码",
|
||||
phonenumberPleace: "请输入正确的电子邮箱",
|
||||
phonenumberPleace: "请输入正确的手机号码",
|
||||
nick: "用户昵称",
|
||||
nickPleace: "请输入用户昵称",
|
||||
nickTip: "昵称只能包含字母、数字、中文和下划线,且不少于2位",
|
||||
nickTip: "昵称少于2位",
|
||||
profileTip: "确认要提交修改用户基本信息吗?",
|
||||
profileOk: "用户基本信息修改成功!",
|
||||
know: "我知道了",
|
||||
@@ -424,15 +438,14 @@ export default {
|
||||
letUpTime:'激活时间',
|
||||
createTime:'创建时间',
|
||||
onlyAble:'只支持上传文件格式 {fileText}',
|
||||
nullData:'暂无网元列表数据',
|
||||
nullVersion:'当前网元无可回退版本',
|
||||
},
|
||||
license: {
|
||||
neTypePlease: '选择网元类型',
|
||||
neType: '网元类型',
|
||||
fileName: '文件名',
|
||||
createTime: '上传时间',
|
||||
comment: '文件说明',
|
||||
serialNum: '序列号',
|
||||
createTime: '时间',
|
||||
comment: '说明',
|
||||
updateComment: 'License说明',
|
||||
updateCommentPlease: '请输入License说明',
|
||||
updateFile: 'License文件',
|
||||
@@ -471,21 +484,21 @@ export default {
|
||||
neType: "网元类型",
|
||||
neTypePleace: "请选择网元类型",
|
||||
noConfigData: "暂无配置项数据",
|
||||
updateValue: "{num} 属性值修改成功",
|
||||
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}属性值吗?",
|
||||
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: "展开",
|
||||
@@ -549,8 +562,6 @@ export default {
|
||||
realTimeDataStart: "开启实时数据",
|
||||
realTimeDataStop: "关闭实时数据",
|
||||
cdrInfo: "CDR信息",
|
||||
neName: "网元名称",
|
||||
rmUID: "资源标识",
|
||||
time: "记录时间",
|
||||
rowInfo: "记录信息",
|
||||
type: "记录类型",
|
||||
@@ -559,30 +570,66 @@ export default {
|
||||
called: "被叫",
|
||||
result: "结果",
|
||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||
exportTip: "确认导出当前查询条件的话单数据吗?(导出最大支持一万条)",
|
||||
smfChargingID: '计费ID',
|
||||
smfSubscriptionIDData: '订阅 ID 数据',
|
||||
smfSubscriptionIDType: '订阅 ID 类型',
|
||||
smfDataVolumeUplink: '数据量上行链路',
|
||||
smfDataVolumeDownlink: '数据量下行链路',
|
||||
smfDataTotalVolume: '数据总量',
|
||||
smfDuration: '持续时间',
|
||||
smfInvocationTime: '调用时间',
|
||||
},
|
||||
ue: {
|
||||
eventType: "事件类型",
|
||||
realTimeDataStart: "开启实时数据",
|
||||
realTimeDataStop: "关闭实时数据",
|
||||
ueInfo: "UE信息",
|
||||
neName: "网元名称",
|
||||
rmUID: "资源标识",
|
||||
rowInfo: "记录信息",
|
||||
time: "记录时间",
|
||||
result: "结果",
|
||||
resultOk: "成功",
|
||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||
exportTip: "确认导出当前查询条件的事件数据吗?(导出最大支持一万条)",
|
||||
},
|
||||
},
|
||||
ne: {
|
||||
neInfo: {
|
||||
version: "网元版本",
|
||||
common: {
|
||||
neType: '网元类型',
|
||||
neTypePlease: "请选择网元类型",
|
||||
neTypeTip: '填写创建的网元类型,如:SMF',
|
||||
neId: '网元标识',
|
||||
neIdPlease: '请输入网元标识',
|
||||
neIdTip: '填写网元绑定的唯一标识',
|
||||
rmUid: '资源唯一标识',
|
||||
rmUidPlease: '请输入资源唯一标识',
|
||||
rmUidTip: "用于网元日志、告警、指标等数据上报的标记",
|
||||
neName: '网元名称',
|
||||
neNamePlease: '请输入网元名称',
|
||||
ipAddr: '服务IP',
|
||||
ipAddrPlease: '请输入网元服务IP地址',
|
||||
ipAddrTip: "支持IPV4/IPV6,同步变更配置地址",
|
||||
port: '服务端口',
|
||||
portTip: "网元服务端口,默认:33030",
|
||||
serialNum: '序列号',
|
||||
expiryDate: '许可证到期日期',
|
||||
normalcy: '正常',
|
||||
exceptions: '异常',
|
||||
restart: '重启',
|
||||
restartTip: '确认要重新启动网元服务吗?',
|
||||
start: '启动',
|
||||
startTip: '确认要启动网元服务吗?',
|
||||
stop: '停止',
|
||||
stopTip: '确认要停止网元服务吗?',
|
||||
reload: '重载',
|
||||
reloadTip: '确认要重载网元配置信息吗?',
|
||||
oam: 'OAM',
|
||||
log: '日志',
|
||||
},
|
||||
neInfo: {
|
||||
version: "网元版本",
|
||||
state: "网元状态",
|
||||
serviceState: "服务状态",
|
||||
normalcy: "正常",
|
||||
exceptions: "异常",
|
||||
serviceState: "服务状态",
|
||||
info: '状态信息',
|
||||
resourceInfo: '资源情况',
|
||||
sysMem: "系统内存",
|
||||
@@ -590,8 +637,41 @@ export default {
|
||||
sysDisk: "系统存储",
|
||||
neCpu: "网元CPU",
|
||||
hostConfig: "终端连接配置",
|
||||
rmUID: "数据资源定位标识符用于日志、告警上报等数据标记",
|
||||
ipAddr: "支持IPV4/IPV6,同步变更下方配置的配置地址",
|
||||
pvflag: '网元虚拟化标识',
|
||||
pnf: '物理网元',
|
||||
vnf: '虚拟网元',
|
||||
neAddress: '物理地址(MAC)',
|
||||
neAddressTip: '记录网元的网卡物理地址(MAC)',
|
||||
dn: '网络标识',
|
||||
vendorName: '提供厂商',
|
||||
province: '服务地域',
|
||||
addTitle: '新增网元信息',
|
||||
editTitle: '编辑网元信息',
|
||||
delTip: '确认删除网元信息数据项吗?',
|
||||
oam: {
|
||||
title: 'OAM配置',
|
||||
sync: '同步到网元',
|
||||
oamEnable: '服务',
|
||||
oamPort: '端口',
|
||||
snmpEnable: '服务',
|
||||
snmpPort: '端口',
|
||||
kpiEnable: '上报',
|
||||
kpiTimer: '上报周期',
|
||||
kpiTimerPlease: '请输入上报周期(单位秒)',
|
||||
},
|
||||
backConf: {
|
||||
export: '配置导出',
|
||||
import: '配置导入',
|
||||
title: '配置文件导入',
|
||||
importType: '文件来源',
|
||||
server:'服务器文件',
|
||||
local:'本地文件',
|
||||
localUpload:'本地上传',
|
||||
exportTip:'确认要导出网元配置信息到文件?',
|
||||
exportMsg:'导出成功,请到【备份管理】进行下载',
|
||||
filePlease: "请上传文件",
|
||||
fileNamePlease: '请选择服务器文件',
|
||||
},
|
||||
},
|
||||
neHost: {
|
||||
hostType: "主机类型",
|
||||
@@ -610,13 +690,13 @@ export default {
|
||||
privateKey: "私钥",
|
||||
privateKeyPlease: "请正确填写私钥字符内容 ~/.ssh/id_rsa",
|
||||
passPhrase: "私钥密码",
|
||||
remark: "备注信息",
|
||||
createTime: "创建时间",
|
||||
delTip: "确认要删除主机编号为【{num}】的信息吗?",
|
||||
addTitle: "新增主机连接",
|
||||
editTitle: "编辑主机连接",
|
||||
test: "测试连接",
|
||||
testOk: "测试连接成功",
|
||||
authRSA: "免密授权",
|
||||
authRSATip: "是否要配置免密授权?",
|
||||
},
|
||||
neHostCmd: {
|
||||
cmdType: "命令类型",
|
||||
@@ -625,12 +705,129 @@ export default {
|
||||
titlePlease: "请正确填写命令名称",
|
||||
command: "命令",
|
||||
commandPlease: "请正确输入有效命令字符串",
|
||||
remark: "备注",
|
||||
createTime: "创建时间",
|
||||
delTip: "确认要删除命令编号为【{num}】的信息吗?",
|
||||
addTitle: "新增主机命令",
|
||||
editTitle: "编辑主机命令",
|
||||
},
|
||||
neSoftware: {
|
||||
uploadTitle: "上传软件",
|
||||
upload: "上传",
|
||||
uploadNotFile: "未上传软件文件",
|
||||
uploadBatch: "批量上传",
|
||||
uploadBatchMax: "可上传多个软件包,最多同时选择{txt}个。",
|
||||
uploadFileName: "解析文件名称格式如: amf-r2.240x.xx-xxx",
|
||||
name: "文件名",
|
||||
path: "软件文件",
|
||||
pathPlease: "请上传软件包文件",
|
||||
version: "软件版本",
|
||||
versionPlease: "请输入软件版本号",
|
||||
delTip: "确认要删除软件包吗?",
|
||||
downTip: "确认要下载软件包【{txt}】吗?",
|
||||
fileCheckType: '未解析出对应的网元类型',
|
||||
fileCheckVer: '未解析出对应的版本号',
|
||||
fileTypeNotEq: '不是指定网元类型 {txt}',
|
||||
fileTypeExists: '已存在相同类型文件',
|
||||
fileNameExists: '已存在相同名称文件',
|
||||
fileCheckTypeDep: '未解析出对应指定的依赖包类型',
|
||||
dependFile: '软件包依赖',
|
||||
dependFileTip: '文件名解析同上,依据上传顺序安装',
|
||||
},
|
||||
neVersion: {
|
||||
upgrade: "升级到新版本",
|
||||
upgradeTip: "确认要升级到新版本吗?",
|
||||
upgradeTipEmpty: "当前没有可用的新版本",
|
||||
upgradeTipEqual: "当前版本与新版本相同",
|
||||
rollback: '切换到上一个版本',
|
||||
rollbackTip: "确认切换到上一个版本吗?",
|
||||
rollbackTipEmpty: "目前没有可用的上一个版本",
|
||||
rollbackTipEqual: '当前版本与之前版本相同',
|
||||
version: "当前版本",
|
||||
preVersion: "上一个版本",
|
||||
newVersion: "新版本",
|
||||
status: "版本状态",
|
||||
upgradeBatch: "批量更新",
|
||||
upgradeBatchTip: "对勾选的记录进行新版本升级吗?",
|
||||
upgradeNotNewVer: '没有发现新版本',
|
||||
upgradeOMCVer: '拒绝批量操作升级OMC',
|
||||
upgradeDone: '更新完成,服务正在重载',
|
||||
upgradeFail: '更新失败,请检查软件文件是否存在且服务终端环境是否可用!',
|
||||
upgradeModal: '网元版本更新',
|
||||
},
|
||||
neLicense: {
|
||||
status: "许可证状态",
|
||||
change: "变更许可证",
|
||||
reload: "刷新信息",
|
||||
reloadTip: "确认要刷新许可证信息吗?",
|
||||
reloadBatch: "批量刷新",
|
||||
reloadBatchTip: "对勾选的记录进行信息刷新吗?",
|
||||
updateTtile: "更新许可证",
|
||||
downCodeTop: "确认要将许可激活码保存到文件吗?",
|
||||
activationRequestCode: "许可激活码",
|
||||
licensePath: "许可证文件",
|
||||
licensePathTip: "请上传许可证文件",
|
||||
upload: '上传',
|
||||
uploadFile: "上传许可证",
|
||||
uploadChangeOk: '网元更新许可证成功,正在后台校验!',
|
||||
uploadChangeFail: "部分网元更新许可证失败,请检查服务终端环境是否可用!",
|
||||
},
|
||||
neConfPara5G: {
|
||||
headerTip: '进行网元安装前检查并保存网元公共参数属性,确认应用为最新参数属性',
|
||||
headerTipToPage: '跳转安装',
|
||||
save: '保存',
|
||||
reload: '刷新',
|
||||
title: '保存信息',
|
||||
sync: '同步到网元',
|
||||
syncNe: '选择网元',
|
||||
syncNeDone: '同步到网元终端完成',
|
||||
saveOk: '保存成功!',
|
||||
},
|
||||
neQuickSetup: {
|
||||
stepPrev: '上一步',
|
||||
stepPrevTip: '确认要放弃当前变更返回上一步吗?',
|
||||
stepNext: '下一步',
|
||||
stepSave: '保存信息',
|
||||
startTitle: '服务终端环境',
|
||||
startDesc: '测试连接网元服务',
|
||||
startStepNext: '确认要下一步进行配置网元信息?',
|
||||
addr: '终端IP',
|
||||
kernelName: '系统',
|
||||
kernelRelease: '内核',
|
||||
machine: '架构',
|
||||
prettyName: '平台',
|
||||
prettyNameTip: '支持 Ubuntu',
|
||||
nodename: '主机名',
|
||||
auth: '权限授予',
|
||||
sudo: '提权',
|
||||
sudoErr: '确保有权限进行软件包安装,请配置授予当前用户允许无密码 sudo 权限。',
|
||||
sshLink: '免密直连',
|
||||
configTitle: "配置网元",
|
||||
configDesc: "填写网元基础信息",
|
||||
configAddTitle: '新增提示',
|
||||
configAddTip: '是否新增为新的网元信息并继续?',
|
||||
configUpdateTitle: '更新提示',
|
||||
configUpdateTip: '是否更新到已存在网元信息并继续?',
|
||||
configStepNext: '确认要下一步进行网元软件安装?',
|
||||
installTitle: "网元安装",
|
||||
installDesc: "安装到服务终端",
|
||||
installConfirmTip: '确认要安装软件包【{name}】吗?',
|
||||
installStepNext: '确认要下一步进行网元授权吗?',
|
||||
installSource: '软件来源',
|
||||
installSourceOption: '已上传',
|
||||
installSourceUpload: '新上传',
|
||||
installSelect: '选择记录',
|
||||
installUpload: '上传文件',
|
||||
installText: '安装',
|
||||
licenseTitle: "授权许可",
|
||||
licenseDesc: "网元服务授权认证",
|
||||
licenseResultTitle: "是否立即授权激活",
|
||||
licenseResultTitleOk: '成功激活',
|
||||
licenseUpload: '许可证',
|
||||
licenseEnd: '结束',
|
||||
licenseEndTip: "确认要结束安装吗?",
|
||||
licenseCheack: '等待网元验证',
|
||||
licenseTip1: '1. 点击【许可证】可获取许可激活码,随后联系网元厂商进行激活',
|
||||
licenseTip2: '2. 点击【结束】将结束安装过程',
|
||||
},
|
||||
},
|
||||
neUser: {
|
||||
auth: {
|
||||
@@ -644,7 +841,7 @@ export default {
|
||||
import: '导入',
|
||||
loadDataConfirm: '确认要重新加载数据吗?',
|
||||
loadData: '加载数据',
|
||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新。加载结束后可点击重置刷新数据列表,请勿重复点击获取更新!!!',
|
||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,请稍候!!!',
|
||||
startIMSI: '起始IMSI',
|
||||
batchAddText: '批量新增',
|
||||
batchDelText: '批量删除',
|
||||
@@ -671,7 +868,7 @@ export default {
|
||||
import: '导入',
|
||||
loadDataConfirm: '确认要重新加载数据吗?',
|
||||
loadData: '加载数据',
|
||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新。加载结束后可点击重置刷新数据列表,请勿重复点击获取更新!!!',
|
||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,请稍候!!!',
|
||||
numAdd: '放号个数',
|
||||
numDel: '删除个数',
|
||||
checkDel:'勾选删除',
|
||||
@@ -709,6 +906,7 @@ export default {
|
||||
addTitle: '新增策略控制信息',
|
||||
updateTitle: '{imsi} 策略控制信息',
|
||||
startIMSI: '起始IMSI',
|
||||
batchOper: '批量操作',
|
||||
batchAddText: '批量新增',
|
||||
batchDelText: '批量删除',
|
||||
batchUpdateText: '批量更新',
|
||||
@@ -717,9 +915,19 @@ export default {
|
||||
imsiTip1: 'MCC=移动国家号码, 由三位数字组成',
|
||||
imsiTip2: 'MNC=移动网络号,由两位数字组成',
|
||||
imsiTip3: 'MSIN=移动客户识别码,采用等长10位数字构成',
|
||||
delSure:'确认删除IMSI编号为: {imsi} 的用户吗?',
|
||||
checkDel:'勾选删除',
|
||||
delSure:'确认删除IMSI编号为: {imsi} 的数据项吗?',
|
||||
uploadFileOk: '文件上传成功',
|
||||
uploadFileErr: '文件上传失败',
|
||||
pccRuleTip:'PCC策略规则模板(对应参数配置-PCC Rules)',
|
||||
sessRuleTip:'会话策略规则模板(对应参数配置-Session Rules)',
|
||||
qosAudioTip:'语音呼叫QoS(对应参数配置-QoS Template的QoS ID)',
|
||||
qosVideoTip:'视频呼叫QoS(对应参数配置-QoS Template的QoS ID)',
|
||||
hdrTip:'HTTP头增强(对应参数配置-Header Enrich Template)',
|
||||
ueTip:'UE策略模板(样例: uep_001)',
|
||||
sarTip1:'服务区限制',
|
||||
sarTip2:'(对应参数配置-Service Area Restriction)',
|
||||
rfsfTip:'无线频率选择优先级',
|
||||
},
|
||||
base5G: {
|
||||
neType: '网元对象',
|
||||
@@ -755,7 +963,7 @@ export default {
|
||||
viewTask:'查看任务',
|
||||
editTask:'修改任务',
|
||||
addTask:'新增任务',
|
||||
stopTask:'挂起',
|
||||
stopTask:'停止',
|
||||
errorTaskInfo: '获取任务信息失败',
|
||||
granulOptionPlease:'请选择测量粒度',
|
||||
letupSure:'确认激活编号为 【{id}】 的任务?',
|
||||
@@ -815,7 +1023,7 @@ export default {
|
||||
exportSure:'确认是否导出全部统计数据',
|
||||
exportEmpty: "导出数据为空",
|
||||
showChartSelected: "显示全部",
|
||||
realTimeData: "实时5s数据",
|
||||
realTimeData: "实时数据",
|
||||
},
|
||||
customTarget:{
|
||||
kpiId:'自定义指标项',
|
||||
@@ -965,6 +1173,7 @@ export default {
|
||||
showSet:'显示过滤设置',
|
||||
exportSure:'确认是否导出全部活动告警信息',
|
||||
viewIdInfo:'查看{alarmId} 记录信息',
|
||||
closeModal:'关闭',
|
||||
},
|
||||
historyAlarm:{
|
||||
exportSure:'确认是否导出全部历史告警信息?',
|
||||
@@ -976,6 +1185,9 @@ export default {
|
||||
save:'保存设置',
|
||||
noChange:'告警前转接口设置无变更',
|
||||
forwardSet:'告警前转接口设置',
|
||||
},
|
||||
eventAlarm:{
|
||||
exportSure:'确认是否导出全部事件告警信息?',
|
||||
}
|
||||
},
|
||||
logManage:{
|
||||
@@ -1004,8 +1216,9 @@ export default {
|
||||
alarmId:'告警唯一标识',
|
||||
alarmSeq:'告警流水号',
|
||||
alarmObj:'告警前转对象',
|
||||
alarmInter:'告警前转接口',
|
||||
alarmTitle:'告警标题',
|
||||
alarmInfo:'告警内容',
|
||||
alarmInfo:'操作结果',
|
||||
eventTime:'告警产生时间',
|
||||
logTime:'记录时间'
|
||||
},
|
||||
@@ -1398,9 +1611,9 @@ export default {
|
||||
loginIp: '登录地址',
|
||||
loginTime: '登录时间',
|
||||
status: '用户状态',
|
||||
userNameTip:'账号不能以数字开头,可包含大写小写字母,数字,且不少于5位',
|
||||
userNameTip:'账号只能包含大写字母、小写字母和数字的字符串,长度至少为6位',
|
||||
passwdTip:'密码至少包含大小写字母、数字、特殊符号,且不少于6位',
|
||||
nickNameTip:'昵称只能包含字母、数字、中文和下划线,且不少于2位',
|
||||
nickNameTip:'昵称不少于2位',
|
||||
emailTip:'请输入正确的邮箱地址',
|
||||
phoneTip:'请输入正确的手机号码',
|
||||
resetPwd:'重置密码',
|
||||
@@ -1423,7 +1636,7 @@ export default {
|
||||
userWork:'用户岗位',
|
||||
userWorkPlease: '请选择用户岗位',
|
||||
userTip:'用户说明',
|
||||
loginPwd:'登入密码',
|
||||
loginPwd:'登录密码',
|
||||
updateSure:'是否更新已经存在的数据',
|
||||
downloadObj:'下载模板',
|
||||
importTitle:'用户导入',
|
||||
@@ -1509,6 +1722,9 @@ export default {
|
||||
i18nOpen: "显示切换",
|
||||
i18nDefault: "默认语言",
|
||||
i18nInstruction: '是否显示国际化切换,设置系统默认语言',
|
||||
reset: "系统重置",
|
||||
resetInstruction: "系统重置将会清除当前系统内所有数据,请谨慎操作!!!",
|
||||
resetTipContent: '确认要清除当前系统内所有数据并坚持继续吗?',
|
||||
},
|
||||
role:{
|
||||
allScopeOptions:'全部数据权限',
|
||||
@@ -1533,10 +1749,10 @@ export default {
|
||||
distributeUser:'分配用户',
|
||||
roleMark:'角色说明',
|
||||
menu:'菜单权限',
|
||||
roleKeyTip:"权限标识示例:dba 控制器中使用权限标识,如: @PreAuthorize({ hasRoles: ['dba'] })",
|
||||
roleKeyTip:"权限标识用于控制页面控件或路由接口",
|
||||
openSwitch:'展开/折叠',
|
||||
selAllSwitch:'全选/全不选',
|
||||
relationSwitch:'父子联动',
|
||||
relationSwitch:'节点联动',
|
||||
normal:'正常',
|
||||
stop:'暂停',
|
||||
preScope:'权限范围',
|
||||
@@ -1559,7 +1775,7 @@ export default {
|
||||
className:'部门名称',
|
||||
classId:'部门编号',
|
||||
classSort:'部门排序',
|
||||
status:'岗位状态',
|
||||
status:'部门状态',
|
||||
createTime:'创建时间',
|
||||
highClass:'上级部门',
|
||||
emailTip:'请输入正确的邮箱地址',
|
||||
@@ -1590,7 +1806,7 @@ export default {
|
||||
operate:{
|
||||
operId:'日志编号',
|
||||
moduleName:'模块名称',
|
||||
workType:'业务类型',
|
||||
workType:'操作类型',
|
||||
operUser:'操作人员',
|
||||
requestMe:'请求方式',
|
||||
host:'请求主机',
|
||||
@@ -1703,6 +1919,65 @@ export default {
|
||||
exportOk: "已完成导出",
|
||||
typeDataErr: "获取字典类型信息失败",
|
||||
},
|
||||
quickStart: {
|
||||
start: '开始设置',
|
||||
skip: '跳过',
|
||||
finish: '完成设置',
|
||||
stepPrev: '上一步',
|
||||
stepNext: '下一步',
|
||||
exit: '退出',
|
||||
save: '保存信息',
|
||||
sysTitle: '系统配置',
|
||||
sysAdmin: '管理员',
|
||||
sysInfo: '系统信息',
|
||||
sysLogo: '系统LOGO',
|
||||
sysLogoTip: '将图片展示到系统LOGO区域查看效果,请使用透明背景,尺寸比例适应区域大小',
|
||||
sysName: '系统名称',
|
||||
sysNameTip: '系统名称限制20个字符长度',
|
||||
sysUploadLogo: '确认要上传系统LOGO文件吗?',
|
||||
sysUploadOk: '文件上传成功,请进行保存信息',
|
||||
sysSave: '保存',
|
||||
sysSaveOk: '信息保存成功!',
|
||||
sysPrevTip: '确认要返回上一个步骤吗?',
|
||||
sysNextNe: '确认要进行网元安装吗?',
|
||||
sysNextDone: '确认要跳过网元安装吗?',
|
||||
stepNeInfoTitle: "网元服务配置",
|
||||
stepNeInfoDesc: "设置网元对应的服务终端",
|
||||
stepNeInfoStepPrev: '确认要退出网元安装步骤吗?',
|
||||
stepNeInfoStepNext: '确认要下一步进行网元配置参数?',
|
||||
stepPara5GTitle: "网元配置参数",
|
||||
stepPara5GDesc: "设置网元全局参数信息",
|
||||
stepPara5GStepPrev: '确认要放弃当前变更返回上一步吗?',
|
||||
stepPara5GStepNext: '确认要下一步进行网元服务安装吗?',
|
||||
stepInstallTitle: "网元服务安装",
|
||||
stepInstallDesc: "将网元服务安装到服务终端",
|
||||
stepInstallStepPrev: '确认要放弃当前变更返回上一步吗?',
|
||||
stepInstallStepNext: '确认要下一步进行网元许可授权吗?',
|
||||
stepInstallText: '选择安装',
|
||||
stepInstallTip: '确认安装选择的网元新版本吗?',
|
||||
stepInstallModal: '网元进行安装',
|
||||
stepInstallNotNewVer: '没有发现新版本',
|
||||
stepInstallDone: '安装完成,服务进入初始化',
|
||||
stepInstallFail: '安装失败,请检查服务终端环境是否可用!',
|
||||
stepLicenseTitle: "网元许可授权",
|
||||
stepLicenseDesc: "获取网元许可激活码进行授权认证",
|
||||
stepLicenseReload: '选择刷新许可证',
|
||||
stepLicenseReloadTip: '确认刷新选择的许可证信息吗?',
|
||||
stepLicenseDownCode: '选择下载网元许可激活码',
|
||||
stepLicenseDownCodeTip: '确认下载选择的网元许可激活码到文本文件吗?',
|
||||
stepLicenseStepPrev: '确认要放弃当前变更返回上一步吗?',
|
||||
stepLicenseStepNext: '确认要结束网元安装步骤吗?',
|
||||
stepLicenseStepNext2: '请下载网元许可授权码文件保存,并联系网元厂商获取授权许可证',
|
||||
stepLicenseEnd: '结束',
|
||||
doneTitle: "完成配置",
|
||||
doneTip: '请进入系统后,根据情况进行更多相关配置',
|
||||
doneNETitle: '已经进行网元安装配置',
|
||||
doneNEDesc: '如有异常网元,可在系统内重新安装授权许可',
|
||||
doneSkipTitle: '未进行网元安装配置',
|
||||
doneSkipDesc: '系统将会默认初始网元信息,可在系统内自行修改或进行安装',
|
||||
donePrevTip: '确认要返回上一个步骤吗?',
|
||||
doneOkTip: '确认完成设置并开始使用吗?',
|
||||
},
|
||||
},
|
||||
mmlManage: {
|
||||
cmdTitle: "命令导航",
|
||||
@@ -1710,14 +1985,14 @@ export default {
|
||||
cmdOpTip: "左侧命令导航中选择要操作项!",
|
||||
cmdNoTip: "{num} 无可选命令操作",
|
||||
require: "必填参数:{num}",
|
||||
requireUn: "{display} 输入值是未知类型",
|
||||
requireString: "{display} 参数值不合理",
|
||||
requireInt: "{display} 参数值不在合理范围 {filter}",
|
||||
requireIpv4: "{display} 不是合法的IPV4地址",
|
||||
requireIpv6: "{display} 不是合法的IPV6地址",
|
||||
requireEnum: "{display} 不是合理的枚举值",
|
||||
requireBool: "{display} 不是合理的布尔类型的值",
|
||||
requireFile: "{display} 不是符合参数文件类型的值",
|
||||
requireUn: "【 {display} 】输入值是未知类型",
|
||||
requireString: "【 {display} 】参数值不合理",
|
||||
requireInt: "【 {display} 】参数值不在合理范围 {filter}",
|
||||
requireIpv4: "【 {display} 】不是合法的IPV4地址",
|
||||
requireIpv6: "【 {display} 】不是合法的IPV6地址",
|
||||
requireEnum: "【 {display} 】不是合理的枚举值",
|
||||
requireBool: "【 {display} 】不是合理的布尔类型的值",
|
||||
requireFile: "【 {display} 】不是符合参数文件类型的值",
|
||||
cmdQuickEntry: "命令快速输入",
|
||||
cmdQuickEntryHelp: "换行(Shift + Enter) 执行发送(Enter)",
|
||||
cmdParamPanel: "参数面板",
|
||||
|
||||
+60
-16
@@ -4,12 +4,20 @@ import {
|
||||
WaterMark,
|
||||
getMenuData,
|
||||
clearMenuItem,
|
||||
MenuDataItem,
|
||||
type MenuDataItem,
|
||||
} from 'antdv-pro-layout';
|
||||
import RightContent from './components/RightContent.vue';
|
||||
import Tabs from './components/Tabs.vue';
|
||||
import GlobalMask from '@/components/GlobalMask/index.vue';
|
||||
import { scriptUrl } from '@/assets/js/icon_font_8d5l8fzk5b87iudi';
|
||||
import { computed, reactive, watch, onMounted, onUnmounted } from 'vue';
|
||||
import {
|
||||
computed,
|
||||
reactive,
|
||||
watch,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
nextTick,
|
||||
} from 'vue';
|
||||
import useLayoutStore from '@/store/modules/layout';
|
||||
import useRouterStore from '@/store/modules/router';
|
||||
import useTabsStore from '@/store/modules/tabs';
|
||||
@@ -21,6 +29,7 @@ const { proConfig, waterMarkContent } = useLayoutStore();
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { getServerTime } from '@/api';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { parseUrlPath } from '@/plugins/file-static-url';
|
||||
const { t, currentLocale } = useI18n();
|
||||
@@ -159,8 +168,27 @@ 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');
|
||||
} else {
|
||||
text.classList.remove('app-name_scrollable');
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => appStore.appName,
|
||||
() => nextTick(fnCheckAppNameOverflow)
|
||||
);
|
||||
|
||||
//
|
||||
onMounted(() => {
|
||||
fnCheckAppNameOverflow();
|
||||
fnGetServerTime();
|
||||
useAlarmStore().fnGetActiveAlarmInfo();
|
||||
});
|
||||
@@ -224,12 +252,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 +272,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 +293,7 @@ onUnmounted(() => {
|
||||
<template #headerContentRender></template>
|
||||
|
||||
<!--插槽-顶部右侧-->
|
||||
<template #rightContentRender>
|
||||
<template #headerContentRightRender>
|
||||
<RightContent />
|
||||
</template>
|
||||
|
||||
@@ -300,9 +328,6 @@ onUnmounted(() => {
|
||||
</transition>
|
||||
</RouterView>
|
||||
|
||||
<!-- 锁屏遮罩 -->
|
||||
<LockScreen />
|
||||
|
||||
<!--插槽-内容底部-->
|
||||
<template #footerRender="{ width }">
|
||||
<footer class="footer">
|
||||
@@ -329,6 +354,9 @@ onUnmounted(() => {
|
||||
</footer>
|
||||
</template>
|
||||
</ProLayout>
|
||||
|
||||
<!-- 全局遮罩 -->
|
||||
<GlobalMask />
|
||||
</WaterMark>
|
||||
</template>
|
||||
|
||||
@@ -349,18 +377,34 @@ onUnmounted(() => {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
.app-name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
// text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 130px;
|
||||
width: 148px;
|
||||
|
||||
&_scrollable {
|
||||
// padding-left: 100%;
|
||||
display: inline-block;
|
||||
animation: scrollable-animation linear 6s infinite both;
|
||||
}
|
||||
|
||||
@keyframes scrollable-animation {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
z-index: 16;
|
||||
margin: 0px;
|
||||
width: auto;
|
||||
margin-top: 52px;
|
||||
margin-top: 32px;
|
||||
&-fixed {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import Modal from 'ant-design-vue/lib/modal/Modal';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import useAlarmStore from '@/store/modules/alarm';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
import { hasPermissions } from '@/plugins/auth-user';
|
||||
import { ref } from 'vue';
|
||||
const { isFullscreen, toggle } = useFullscreen();
|
||||
const { t, changeLocale, optionsLocale } = useI18n();
|
||||
const lockedStore = useLockedStore();
|
||||
const maskStore = useMaskStore();
|
||||
const userStore = useUserStore();
|
||||
const appStore = useAppStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
/**头像展开项点击 */
|
||||
@@ -31,15 +32,24 @@ function fnClick({ key }: MenuInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
/**锁屏确认 */
|
||||
const lockConfirm = ref<boolean>(false);
|
||||
/**锁屏密码 */
|
||||
const lockPasswd = ref<string>('');
|
||||
|
||||
/**锁屏按钮提示 */
|
||||
function fnClickLock() {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('loayouts.rightContent.lockTip'),
|
||||
onOk() {
|
||||
lockedStore.fnLock('lock');
|
||||
},
|
||||
});
|
||||
lockConfirm.value = true;
|
||||
lockPasswd.value = '';
|
||||
maskStore.lockPasswd = '';
|
||||
}
|
||||
|
||||
/**锁屏确认跳转锁屏页面 */
|
||||
function fnClickLockToPage() {
|
||||
lockConfirm.value = false;
|
||||
maskStore.lockPasswd = lockPasswd.value;
|
||||
maskStore.handleMaskType('lock');
|
||||
router.push({ name: 'LockScreen', query: { redirect: route.path } });
|
||||
}
|
||||
|
||||
/**告警数按钮提示跳转 */
|
||||
@@ -65,30 +75,58 @@ function fnChangeLocale(e: any) {
|
||||
|
||||
<template>
|
||||
<a-space :size="12" align="center">
|
||||
<a-button type="text" @click="fnClickAlarm">
|
||||
<a-button type="text" style="color: inherit" @click="fnClickAlarm">
|
||||
<template #icon>
|
||||
<a-badge
|
||||
:count="useAlarmStore().activeAlarmTotal"
|
||||
:overflow-count="99"
|
||||
status="warning"
|
||||
style="color: inherit"
|
||||
>
|
||||
<BellOutlined />
|
||||
</a-badge>
|
||||
</template>
|
||||
</a-button>
|
||||
|
||||
<!-- 锁屏操作 -->
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ t('loayouts.rightContent.lock') }}</template>
|
||||
<a-button type="text" @click="fnClickLock">
|
||||
<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>
|
||||
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ t('loayouts.rightContent.helpDoc') }}</template>
|
||||
<a-button type="text" @click="fnClickHelpDoc()">
|
||||
<a-button type="text" style="color: inherit" @click="fnClickHelpDoc()">
|
||||
<template #icon>
|
||||
<QuestionCircleOutlined />
|
||||
</template>
|
||||
@@ -97,7 +135,7 @@ function fnChangeLocale(e: any) {
|
||||
|
||||
<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 />
|
||||
@@ -107,7 +145,7 @@ function fnChangeLocale(e: any) {
|
||||
|
||||
<a-dropdown
|
||||
placement="bottom"
|
||||
:trigger="['click', 'hover']"
|
||||
trigger="click"
|
||||
v-if="appStore.i18nOpen && hasPermissions(['system:setting:i18n'])"
|
||||
>
|
||||
<a-button size="small" type="default">
|
||||
@@ -123,7 +161,7 @@ function fnChangeLocale(e: any) {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
|
||||
<a-dropdown placement="bottomRight" :trigger="['click', 'hover']">
|
||||
<a-dropdown placement="bottomRight" trigger="click">
|
||||
<div class="user">
|
||||
<a-avatar
|
||||
shape="circle"
|
||||
|
||||
@@ -95,7 +95,7 @@ function fnTabClose(path: string) {
|
||||
/**
|
||||
* 国际化翻译转换
|
||||
*/
|
||||
function fnLocale(title: string) {
|
||||
function fnLocale(title: string) {
|
||||
if (title.indexOf('router.') !== -1) {
|
||||
title = t(title);
|
||||
}
|
||||
@@ -150,7 +150,7 @@ watch(router.currentRoute, v => tabsStore.tabOpen(v), { immediate: true });
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="topRight">
|
||||
<template #title>{{ t('loayouts.tabs.more') }}</template>
|
||||
<a-dropdown :trigger="['click', 'hover']" placement="bottomRight">
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
<a-button type="ghost" shape="circle" size="small">
|
||||
<template #icon><DownOutlined /></template>
|
||||
</a-button>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
+48
-27
@@ -87,6 +87,18 @@ const constantRoutes: RouteRecordRaw[] = [
|
||||
meta: { title: 'router.helpDoc' },
|
||||
component: () => import('@/views/tool/help/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',
|
||||
@@ -136,18 +148,31 @@ router.afterEach((to, from, failure) => {
|
||||
});
|
||||
|
||||
/**无Token可访问页面地址白名单 */
|
||||
const WHITE_LIST: string[] = ['/login', '/auth-redirect', '/help', '/register'];
|
||||
const WHITE_LIST: string[] = [
|
||||
'/login',
|
||||
'/auth-redirect',
|
||||
'/help',
|
||||
'/register',
|
||||
'/quick-start',
|
||||
];
|
||||
|
||||
/**全局路由-前置守卫 */
|
||||
router.beforeEach((to, from, next) => {
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
NProgress.start();
|
||||
const token = getToken();
|
||||
|
||||
// 获取系统配置信息
|
||||
const appStore = useAppStore();
|
||||
if (!appStore.loginBackground) {
|
||||
appStore.fnSysConf();
|
||||
await appStore.fnSysConf();
|
||||
}
|
||||
|
||||
// 需要系统引导跳转
|
||||
if (appStore.bootloader && to.path !== '/quick-start') {
|
||||
next({ name: 'QuickStart' });
|
||||
}
|
||||
|
||||
const token = getToken();
|
||||
|
||||
// 没有token
|
||||
if (!token) {
|
||||
if (WHITE_LIST.includes(to.path)) {
|
||||
@@ -168,31 +193,27 @@ router.beforeEach((to, from, next) => {
|
||||
// 判断当前用户是否有角色信息
|
||||
const user = useUserStore();
|
||||
if (user.roles && user.roles.length === 0) {
|
||||
// 获取用户信息
|
||||
user
|
||||
.fnGetInfo()
|
||||
.then(() => {
|
||||
return useRouterStore().generateRoutes();
|
||||
})
|
||||
.then(accessRoutes => {
|
||||
// 根据后台配置生成可访问的路由表
|
||||
if (accessRoutes && accessRoutes.length !== 0) {
|
||||
for (const route of accessRoutes) {
|
||||
// 动态添加可访问路由表,http开头会异常
|
||||
if (!validHttp(route.path)) {
|
||||
router.addRoute(route);
|
||||
}
|
||||
try {
|
||||
// 获取用户信息
|
||||
await user.fnGetInfo();
|
||||
// 获取路由信息
|
||||
const accessRoutes = await useRouterStore().generateRoutes();
|
||||
// 根据后台配置生成可访问的路由表
|
||||
if (accessRoutes && accessRoutes.length !== 0) {
|
||||
for (const route of accessRoutes) {
|
||||
// 动态添加可访问路由表,http开头会异常
|
||||
if (!validHttp(route.path)) {
|
||||
router.addRoute(route);
|
||||
}
|
||||
}
|
||||
// 刷新替换原先路由,确保addRoutes已完成
|
||||
next({ ...to, replace: true });
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(`[${to.path}]: ${e.message}`);
|
||||
user.fnLogOut().finally(() => {
|
||||
next({ name: 'Login' });
|
||||
});
|
||||
});
|
||||
}
|
||||
// 刷新替换原先路由,确保addRoutes已完成
|
||||
next({ ...to, replace: true });
|
||||
} catch (error: any) {
|
||||
console.error(`[${to.path}]: ${error.message}`);
|
||||
await user.fnLogOut();
|
||||
next({ name: 'Login' });
|
||||
}
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getSysConf } from '@/api';
|
||||
import { CACHE_LOCAL_I18N } from '@/constants/cache-keys-constants';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { removeToken } from '@/plugins/auth-token';
|
||||
import { parseUrlPath } from '@/plugins/file-static-url';
|
||||
import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||
import { defineStore } from 'pinia';
|
||||
@@ -17,6 +18,8 @@ type AppStore = {
|
||||
/**服务版本 */
|
||||
version: string;
|
||||
buildTime: string;
|
||||
/**系统引导使用 */
|
||||
bootloader: boolean;
|
||||
// 序列号
|
||||
serialNum: string;
|
||||
/**应用版权声明 */
|
||||
@@ -48,6 +51,7 @@ const useAppStore = defineStore('app', {
|
||||
|
||||
version: `-`,
|
||||
buildTime: `-`,
|
||||
bootloader: false,
|
||||
serialNum: `-`,
|
||||
copyright: `Copyright ©2023 For ${import.meta.env.VITE_APP_NAME}`,
|
||||
logoType: 'icon',
|
||||
@@ -57,7 +61,7 @@ const useAppStore = defineStore('app', {
|
||||
loginBackground: '',
|
||||
helpDoc: '',
|
||||
officialUrl: '',
|
||||
i18nOpen: true,
|
||||
i18nOpen: false,
|
||||
i18nDefault: 'en_US',
|
||||
}),
|
||||
getters: {},
|
||||
@@ -70,16 +74,17 @@ const useAppStore = defineStore('app', {
|
||||
document.title = this.appName;
|
||||
}
|
||||
},
|
||||
/**设置版权声明 */
|
||||
setCopyright(text: string) {
|
||||
this.copyright = text;
|
||||
},
|
||||
// 获取系统配置信息
|
||||
async fnSysConf() {
|
||||
const res = await getSysConf();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
this.version = res.data.version;
|
||||
this.buildTime = res.data.buildTime;
|
||||
this.bootloader = res.data.bootloader === 'true';
|
||||
// 引导时
|
||||
if (this.bootloader) {
|
||||
removeToken();
|
||||
}
|
||||
this.serialNum = res.data.serialNum;
|
||||
this.appName = res.data.title;
|
||||
this.copyright = res.data.copyright;
|
||||
|
||||
@@ -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,51 +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' | string;
|
||||
/**lock 超时锁屏时间,秒*/
|
||||
lockTimeout: number;
|
||||
};
|
||||
|
||||
const useLockedStore = defineStore('locked', {
|
||||
state: (): Locked => ({
|
||||
type: localGet(CACHE_LOCAL_LOCK) || 'none',
|
||||
lockTimeout: 0,
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// 重启等待-轮询
|
||||
async relaodWait() {
|
||||
try {
|
||||
const res = await getSysConf();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
this.fnLock('none');
|
||||
window.location.reload();
|
||||
}
|
||||
} catch (error) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.relaodWait();
|
||||
}, 5_000);
|
||||
}
|
||||
},
|
||||
// 设置锁定
|
||||
async fnLock(type: 'none' | 'lock' | 'reload' | string) {
|
||||
this.type = type;
|
||||
localSet(CACHE_LOCAL_LOCK, type);
|
||||
if (type === 'reload') {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.relaodWait();
|
||||
}, 2_000);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default useLockedStore;
|
||||
@@ -0,0 +1,70 @@
|
||||
import { getSysConf } from '@/api';
|
||||
import {
|
||||
CACHE_LOCAL_LOCK_PASSWD,
|
||||
CACHE_LOCAL_MASK,
|
||||
} from '@/constants/cache-keys-constants';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { localGet, localRemove, localSet } from '@/utils/cache-local-utils';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
/**全局遮罩信息类型 */
|
||||
type MaskStateType = {
|
||||
/**锁屏类型 */
|
||||
type: 'none' | 'lock' | 'reload' | 'reset';
|
||||
/**lock 锁屏密码*/
|
||||
lockPasswd: string;
|
||||
/**lock 超时锁屏时间,秒*/
|
||||
lockTimeout: number;
|
||||
};
|
||||
|
||||
const useMaskStore = defineStore('mask', {
|
||||
state: (): MaskStateType => ({
|
||||
type: (localGet(CACHE_LOCAL_MASK) || 'none') as MaskStateType['type'],
|
||||
lockPasswd: localGet(CACHE_LOCAL_LOCK_PASSWD) || '',
|
||||
lockTimeout: 0,
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// 检查服务等待-轮询
|
||||
async checkServiceWait() {
|
||||
try {
|
||||
const res = await getSysConf();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.handleMaskType('none');
|
||||
window.location.reload();
|
||||
}, 2_000);
|
||||
} else {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.checkServiceWait();
|
||||
}, 5_000);
|
||||
}
|
||||
} catch (error) {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.checkServiceWait();
|
||||
}, 5_000);
|
||||
}
|
||||
},
|
||||
// 设置遮罩类型
|
||||
async handleMaskType(type: MaskStateType['type']) {
|
||||
this.type = type;
|
||||
localSet(CACHE_LOCAL_MASK, type);
|
||||
if (type === 'reload') {
|
||||
// 延迟5秒
|
||||
setTimeout(() => {
|
||||
this.checkServiceWait();
|
||||
}, 5_000);
|
||||
}
|
||||
if (type === 'lock') {
|
||||
localSet(CACHE_LOCAL_LOCK_PASSWD, this.lockPasswd);
|
||||
} else {
|
||||
localRemove(CACHE_LOCAL_LOCK_PASSWD);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default useMaskStore;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import {
|
||||
import type {
|
||||
RouteComponent,
|
||||
RouteLocationRaw,
|
||||
RouteMeta,
|
||||
|
||||
@@ -9,8 +9,8 @@ import { parseUrlPath } from '@/plugins/file-static-url';
|
||||
|
||||
/**用户信息类型 */
|
||||
type UserInfo = {
|
||||
/**授权凭证 */
|
||||
token: string;
|
||||
/**用户ID */
|
||||
userId: string;
|
||||
/**登录账号 */
|
||||
userName: string;
|
||||
/**用户角色 字符串数组 */
|
||||
@@ -27,13 +27,13 @@ type UserInfo = {
|
||||
email: string;
|
||||
/**用户性别 */
|
||||
sex: string | undefined;
|
||||
/**个人化设置 */
|
||||
/**其他信息 */
|
||||
profile: Record<string, any>;
|
||||
};
|
||||
|
||||
const useUserStore = defineStore('user', {
|
||||
state: (): UserInfo => ({
|
||||
token: getToken(),
|
||||
userId: '',
|
||||
userName: '',
|
||||
roles: [],
|
||||
permissions: [],
|
||||
@@ -104,7 +104,6 @@ const useUserStore = defineStore('user', {
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
const token = res.data[TOKEN_RESPONSE_FIELD];
|
||||
setToken(token);
|
||||
this.token = token;
|
||||
}
|
||||
return res;
|
||||
},
|
||||
@@ -113,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;
|
||||
// 用户头像
|
||||
@@ -154,7 +154,6 @@ const useUserStore = defineStore('user', {
|
||||
} catch (error) {
|
||||
throw error;
|
||||
} finally {
|
||||
this.token = '';
|
||||
this.roles = [];
|
||||
this.permissions = [];
|
||||
removeToken();
|
||||
|
||||
Vendored
+2
-2
@@ -2,6 +2,6 @@
|
||||
type DictType = {
|
||||
label: string;
|
||||
value: string;
|
||||
elTagType: string;
|
||||
elTagClass: string;
|
||||
tagType?: string;
|
||||
tagClass?: string;
|
||||
};
|
||||
@@ -19,9 +19,9 @@ export const regExpPort =
|
||||
/**
|
||||
* 有效账号格式
|
||||
*
|
||||
* 账号不能以数字开头,可包含大写小写字母,数字,且不少于5位
|
||||
* 账号只能包含大写字母、小写字母和数字的字符串,长度至少为6位
|
||||
*/
|
||||
export const regExpUserName = /^[a-zA-Z][a-z0-9A-Z]{4,}$/;
|
||||
export const regExpUserName = /^[A-Za-z0-9]{6,}$/;
|
||||
|
||||
/**
|
||||
* 有效密码格式
|
||||
@@ -34,7 +34,7 @@ export const regExpPasswd =
|
||||
/**
|
||||
* 有效手机号格式
|
||||
*/
|
||||
export const regExpMobile = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
|
||||
export const regExpMobile = /^.{3,}$/; // /^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
|
||||
|
||||
/**
|
||||
* 有效邮箱格式
|
||||
@@ -47,7 +47,7 @@ export const regExpEmail =
|
||||
*
|
||||
* 用户昵称只能包含字母、数字、中文和下划线,且不少于2位
|
||||
*/
|
||||
export const regExpNick = /^[\w\u4e00-\u9fa5-]{2,}$/;
|
||||
export const regExpNick = /^.{2,}$/; // /^[\w\u4e00-\u9fa5-]{2,}$/;
|
||||
|
||||
/**
|
||||
* 是否为http(s)://开头
|
||||
@@ -84,13 +84,14 @@ export function validURL(str: string) {
|
||||
// http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
|
||||
strTemp = 'http://' + str;
|
||||
}
|
||||
debugger;
|
||||
|
||||
let u = { host: '', pathname: '' };
|
||||
try {
|
||||
new URL(strTemp);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
const u = new URL(strTemp);
|
||||
|
||||
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: '' },
|
||||
]);
|
||||
|
||||
/**表单数据状态 */
|
||||
@@ -166,12 +166,12 @@ onMounted(() => {
|
||||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<IntlTelInput
|
||||
v-model:value="stateForm.form.phonenumber"
|
||||
allow-clear
|
||||
:maxlength="11"
|
||||
:maxlength="16"
|
||||
:placeholder="t('views.account.settings.phonenumberPleace')"
|
||||
></a-input>
|
||||
></IntlTelInput>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -227,7 +227,11 @@ function fnGetList(pageNum?: number) {
|
||||
}
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
if (tablePagination.total <=(queryParams.pageNum - 1) * tablePagination.pageSize &&queryParams.pageNum !== 1) {
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
@@ -477,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"
|
||||
@@ -501,7 +507,7 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,165 @@
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { regExpIPv4, regExpIPv6, validURL } from '@/utils/regular-utils';
|
||||
|
||||
export default function useOptions() {
|
||||
const { t } = useI18n();
|
||||
|
||||
/**规则校验 */
|
||||
function ruleVerification(row: Record<string, any>): (string | boolean)[] {
|
||||
let result = [true, ''];
|
||||
const type = row.type;
|
||||
const value = row.value;
|
||||
const filter = row.filter;
|
||||
const display = row.display;
|
||||
|
||||
// 子嵌套的不检查
|
||||
if (row.array) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// 可选的同时没有值不检查
|
||||
if (row.optional === 'true' && !value) {
|
||||
return result;
|
||||
}
|
||||
switch (type) {
|
||||
case 'int':
|
||||
// filter: "0~128"
|
||||
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
const filterArr = filter.split('~');
|
||||
const minInt = parseInt(filterArr[0]);
|
||||
const maxInt = parseInt(filterArr[1]);
|
||||
const valueInt = parseInt(value);
|
||||
if (valueInt < minInt || valueInt > maxInt) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireInt', {
|
||||
display,
|
||||
filter,
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'ipv4':
|
||||
if (!regExpIPv4.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireIpv4', { display }),
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'ipv6':
|
||||
if (!regExpIPv6.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireIpv6', { display }),
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'enum':
|
||||
if (filter && filter.indexOf('{') === 1) {
|
||||
let filterJson: Record<string, any> = {};
|
||||
try {
|
||||
filterJson = JSON.parse(filter); //string---json
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if (!Object.keys(filterJson).includes(`${value}`)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireEnum', { display }),
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'bool':
|
||||
// filter: '{"0":"false", "1":"true"}'
|
||||
|
||||
if (filter && filter.indexOf('{') === 1) {
|
||||
let filterJson: Record<string, any> = {};
|
||||
try {
|
||||
filterJson = JSON.parse(filter); //string---json
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if (!Object.values(filterJson).includes(`${value}`)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireBool', { display }),
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
// filter: "0~128"
|
||||
|
||||
// 字符串长度判断
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
try {
|
||||
const filterArr = filter.split('~');
|
||||
let rule = new RegExp(
|
||||
'^\\S{' + filterArr[0] + ',' + filterArr[1] + '}$'
|
||||
);
|
||||
if (!rule.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
// 字符串http判断
|
||||
if (value.startsWith('http')) {
|
||||
try {
|
||||
if (!validURL(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'regex':
|
||||
// filter: "^[0-9]{3}$"
|
||||
|
||||
if (filter) {
|
||||
try {
|
||||
let regex = new RegExp(filter);
|
||||
if (!regex.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireUn', { display }),
|
||||
];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return { ruleVerification };
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
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 };
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, watch, toRaw, nextTick } from 'vue';
|
||||
import { reactive, ref, onMounted, toRaw, nextTick, watch } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { Modal, message } from 'ant-design-vue/lib';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
@@ -13,11 +13,14 @@ import {
|
||||
addParamConfigInfo,
|
||||
} from '@/api/configManage/configParam';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { regExpIPv4, regExpIPv6, validURL } from '@/utils/regular-utils';
|
||||
import useOptions from './hooks/useOptions';
|
||||
import useSMFOptions from './hooks/useSMFOptions';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { DataNode } from 'ant-design-vue/lib/tree';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t } = useI18n();
|
||||
const { ruleVerification } = useOptions();
|
||||
const { initUPFIds, optionsUPFIds } = useSMFOptions();
|
||||
|
||||
/**网元参数 */
|
||||
let neCascaderOptions = ref<Record<string, any>[]>([]);
|
||||
@@ -25,6 +28,14 @@ let neCascaderOptions = ref<Record<string, any>[]>([]);
|
||||
/**网元类型选择 type,id */
|
||||
let neTypeSelect = ref<string[]>(['', '']);
|
||||
|
||||
/**左侧导航是否可收起 */
|
||||
let collapsible = ref<boolean>(true);
|
||||
|
||||
/**改变收起状态 */
|
||||
function changeCollapsible() {
|
||||
collapsible.value = !collapsible.value;
|
||||
}
|
||||
|
||||
/**对象信息状态类型 */
|
||||
type TreeStateType = {
|
||||
/**网元 loading */
|
||||
@@ -43,7 +54,7 @@ let treeState: TreeStateType = reactive({
|
||||
selectNode: {
|
||||
topDisplay: '' as string,
|
||||
topTag: '' as string,
|
||||
method: '' as string,
|
||||
method: [] as string[],
|
||||
//
|
||||
title: '' as string,
|
||||
key: '' as string,
|
||||
@@ -57,7 +68,11 @@ function fnSelectConfigNode(_: any, info: any) {
|
||||
const { title, key, method } = info.node;
|
||||
treeState.selectNode.topDisplay = title;
|
||||
treeState.selectNode.topTag = key;
|
||||
treeState.selectNode.method = method;
|
||||
if (method) {
|
||||
treeState.selectNode.method = method.split(',');
|
||||
} else {
|
||||
treeState.selectNode.method = ['post', 'put', 'delete'];
|
||||
}
|
||||
treeState.selectNode.title = title;
|
||||
treeState.selectNode.key = key;
|
||||
fnActiveConfigNode(key);
|
||||
@@ -329,14 +344,6 @@ let arrayState: ArrayStateType = reactive({
|
||||
dataRule: {},
|
||||
});
|
||||
|
||||
/**监听表格字段列排序变化关闭展开 */
|
||||
watch(
|
||||
() => arrayState.columnsDnd,
|
||||
() => {
|
||||
arrayEditClose();
|
||||
}
|
||||
);
|
||||
|
||||
/**多列表编辑 */
|
||||
function arrayEdit(rowIndex: Record<string, any>) {
|
||||
const item = arrayState.data.find((s: any) => s.key === rowIndex.value);
|
||||
@@ -941,155 +948,6 @@ function arrayAddInit(data: any[], dataRule: any) {
|
||||
return ruleFrom;
|
||||
}
|
||||
|
||||
/**规则校验 */
|
||||
function ruleVerification(row: Record<string, any>): (string | boolean)[] {
|
||||
let result = [true, ''];
|
||||
const type = row.type;
|
||||
const value = row.value;
|
||||
const filter = row.filter;
|
||||
const display = row.display;
|
||||
|
||||
// 子嵌套的不检查
|
||||
if (row.array) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// 可选的同时没有值不检查
|
||||
if (row.optional === 'true' && !value) {
|
||||
return result;
|
||||
}
|
||||
switch (type) {
|
||||
case 'int':
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
const filterArr = filter.split('~');
|
||||
const minInt = parseInt(filterArr[0]);
|
||||
const maxInt = parseInt(filterArr[1]);
|
||||
const valueInt = parseInt(value);
|
||||
if (valueInt < minInt || valueInt > maxInt) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireInt', {
|
||||
display,
|
||||
filter,
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'ipv4':
|
||||
if (!regExpIPv4.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireIpv4', { display }),
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'ipv6':
|
||||
if (!regExpIPv6.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireIpv6', { display }),
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'enum':
|
||||
if (filter && filter.indexOf('{') === 1) {
|
||||
let filterJson: Record<string, any> = {};
|
||||
try {
|
||||
filterJson = JSON.parse(filter); //string---json
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if (!Object.keys(filterJson).includes(`${value}`)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireEnum', { display }),
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'bool':
|
||||
if (filter && filter.indexOf('{') === 1) {
|
||||
let filterJson: Record<string, any> = {};
|
||||
try {
|
||||
filterJson = JSON.parse(filter); //string---json
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if (!Object.values(filterJson).includes(`${value}`)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireBool', { display }),
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
// 字符串长度判断
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
try {
|
||||
const filterArr = filter.split('~');
|
||||
let rule = new RegExp(
|
||||
'^\\S{' + filterArr[0] + ',' + filterArr[1] + '}$'
|
||||
);
|
||||
if (!rule.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
// 字符串http判断
|
||||
if (value.startsWith('http')) {
|
||||
try {
|
||||
if (!validURL(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'regex':
|
||||
if (filter) {
|
||||
try {
|
||||
let regex = new RegExp(filter);
|
||||
if (!regex.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireUn', { display }),
|
||||
];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**添加框是否显示 */
|
||||
@@ -1151,6 +1009,25 @@ function fnModalCancel() {
|
||||
modalState.data = [];
|
||||
}
|
||||
|
||||
// 监听表格字段列排序变化关闭展开
|
||||
watch(
|
||||
() => arrayState.columnsDnd,
|
||||
() => {
|
||||
arrayEditClose();
|
||||
}
|
||||
);
|
||||
|
||||
// 监听新增编辑弹窗
|
||||
watch(
|
||||
() => modalState.visible,
|
||||
val => {
|
||||
// SMF需要选择配置的UPF id
|
||||
if (val && neTypeSelect.value[0] === 'SMF') {
|
||||
initUPFIds();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
neInfoStore.fnNelist().then(res => {
|
||||
@@ -1193,7 +1070,13 @@ onMounted(() => {
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="6" :xs="24" style="margin-bottom: 24px">
|
||||
<a-col
|
||||
:lg="6"
|
||||
:md="6"
|
||||
:xs="24"
|
||||
style="margin-bottom: 24px"
|
||||
v-show="collapsible"
|
||||
>
|
||||
<!-- 网元类型 -->
|
||||
<a-card
|
||||
size="small"
|
||||
@@ -1221,7 +1104,7 @@ onMounted(() => {
|
||||
</a-form>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :lg="18" :md="18" :xs="24">
|
||||
<a-col :lg="collapsible ? 18 : 24" :md="collapsible ? 18 : 24" :xs="24">
|
||||
<a-card
|
||||
size="small"
|
||||
:bordered="false"
|
||||
@@ -1229,6 +1112,13 @@ onMounted(() => {
|
||||
:loading="treeState.selectLoading"
|
||||
>
|
||||
<template #title>
|
||||
<a-button type="text" @click.prevent="changeCollapsible()">
|
||||
<template #icon>
|
||||
<MenuFoldOutlined v-show="collapsible" />
|
||||
<MenuUnfoldOutlined v-show="!collapsible" />
|
||||
</template>
|
||||
</a-button>
|
||||
|
||||
<a-typography-text strong v-if="treeState.selectNode.topDisplay">
|
||||
{{ treeState.selectNode.topDisplay }}
|
||||
</a-typography-text>
|
||||
@@ -1349,7 +1239,9 @@ onMounted(() => {
|
||||
<EditOutlined
|
||||
class="editable-cell__icon"
|
||||
@click="listEdit(record)"
|
||||
v-if="!['read-only', 'ro'].includes(record.access)"
|
||||
v-if="
|
||||
!['read-only', 'read', 'ro'].includes(record.access)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1363,7 +1255,7 @@ onMounted(() => {
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="index"
|
||||
:columns="treeState.selectNode.method === 'get' ? arrayState.columnsDnd.filter((s:any)=>s.key !== 'index') : arrayState.columnsDnd"
|
||||
:columns="treeState.selectNode.method.includes('get') ? arrayState.columnsDnd.filter((s:any)=>s.key !== 'index') : arrayState.columnsDnd"
|
||||
:data-source="arrayState.columnsData"
|
||||
:size="arrayState.size"
|
||||
:pagination="tablePagination"
|
||||
@@ -1380,7 +1272,7 @@ onMounted(() => {
|
||||
type="primary"
|
||||
@click.prevent="arrayAdd()"
|
||||
size="small"
|
||||
v-if="treeState.selectNode.method !== 'get'"
|
||||
v-if="treeState.selectNode.method.includes('post')"
|
||||
>
|
||||
<template #icon> <PlusOutlined /> </template>
|
||||
{{ t('common.addText') }}
|
||||
@@ -1388,7 +1280,7 @@ onMounted(() => {
|
||||
<TableColumnsDnd
|
||||
type="ghost"
|
||||
:cache-id="treeState.selectNode.key"
|
||||
:columns="treeState.selectNode.method === 'get' ? [...arrayState.columns.filter((s:any)=>s.key !== 'index')] : arrayState.columns"
|
||||
:columns="treeState.selectNode.method.includes('get') ? [...arrayState.columns.filter((s:any)=>s.key !== 'index')] : arrayState.columns"
|
||||
v-model:columns-dnd="arrayState.columnsDnd"
|
||||
></TableColumnsDnd>
|
||||
</a-space>
|
||||
@@ -1398,13 +1290,17 @@ onMounted(() => {
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="column?.key === 'index'">
|
||||
<a-space :size="16" align="center">
|
||||
<a-tooltip>
|
||||
<a-tooltip
|
||||
v-if="treeState.selectNode.method.includes('put')"
|
||||
>
|
||||
<template #title>{{ t('common.editText') }}</template>
|
||||
<a-button type="link" @click.prevent="arrayEdit(text)">
|
||||
<template #icon><FormOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<a-tooltip
|
||||
v-if="treeState.selectNode.method.includes('delete')"
|
||||
>
|
||||
<template #title>{{ t('common.deleteText') }}</template>
|
||||
<a-button type="link" @click.prevent="arrayDelete(text)">
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
@@ -1509,9 +1405,9 @@ onMounted(() => {
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{
|
||||
t('common.deleteText')
|
||||
}}</template>
|
||||
<template #title>
|
||||
{{ t('common.deleteText') }}
|
||||
</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="arrayChildDelete(text)"
|
||||
@@ -1559,8 +1455,10 @@ onMounted(() => {
|
||||
</a-row>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -1598,10 +1496,24 @@ onMounted(() => {
|
||||
modalState.from[item.name] !== undefined
|
||||
"
|
||||
>
|
||||
<a-input-number
|
||||
v-if="item['type'] === 'int'"
|
||||
<!-- 特殊SMF-upfid选择 -->
|
||||
<a-select
|
||||
v-if="
|
||||
neTypeSelect[0] === 'SMF' &&
|
||||
modalState.from[item.name]['name'] === 'upfId'
|
||||
"
|
||||
v-model:value="modalState.from[item.name]['value']"
|
||||
:disabled="['read-only', 'ro'].includes(item.access)"
|
||||
:options="optionsUPFIds"
|
||||
:disabled="['read-only', 'read', 'ro'].includes(item.access)"
|
||||
:allow-clear="true"
|
||||
style="width: 100%"
|
||||
>
|
||||
</a-select>
|
||||
<!-- 常规 -->
|
||||
<a-input-number
|
||||
v-else-if="item['type'] === 'int'"
|
||||
v-model:value="modalState.from[item.name]['value']"
|
||||
:disabled="['read-only', 'read', 'ro'].includes(item.access)"
|
||||
style="width: 100%"
|
||||
></a-input-number>
|
||||
<a-switch
|
||||
@@ -1609,12 +1521,12 @@ onMounted(() => {
|
||||
v-model:checked="modalState.from[item.name]['value']"
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
:disabled="['read-only', 'ro'].includes(item.access)"
|
||||
:disabled="['read-only', 'read', 'ro'].includes(item.access)"
|
||||
></a-switch>
|
||||
<a-select
|
||||
v-else-if="item['type'] === 'enum'"
|
||||
v-model:value="modalState.from[item.name]['value']"
|
||||
:disabled="['read-only', 'ro'].includes(item.access)"
|
||||
:disabled="['read-only', 'read', 'ro'].includes(item.access)"
|
||||
:allow-clear="true"
|
||||
style="width: 100%"
|
||||
>
|
||||
@@ -1629,7 +1541,7 @@ onMounted(() => {
|
||||
<a-input
|
||||
v-else
|
||||
v-model:value="modalState.from[item.name]['value']"
|
||||
:disabled="['read-only', 'ro'].includes(item.access)"
|
||||
:disabled="['read-only', 'read', 'ro'].includes(item.access)"
|
||||
></a-input>
|
||||
</div>
|
||||
<div v-else>
|
||||
@@ -1639,7 +1551,7 @@ onMounted(() => {
|
||||
</a-tooltip>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ 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 { parseDateToStr } from '@/utils/date-utils';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -74,21 +75,25 @@ let tableColumns: ColumnsType = [
|
||||
width: 2,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.license.fileName'),
|
||||
dataIndex: 'fileName',
|
||||
title: t('views.configManage.license.serialNum'),
|
||||
dataIndex: 'serialNum',
|
||||
align: 'center',
|
||||
width: 3,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.license.comment'),
|
||||
dataIndex: 'comment',
|
||||
dataIndex: 'remark',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.license.createTime'),
|
||||
dataIndex: 'createdAt',
|
||||
dataIndex: 'createTime',
|
||||
align: 'center',
|
||||
customRender(opt) {
|
||||
if (!opt.value) return '';
|
||||
return parseDateToStr(opt.value);
|
||||
},
|
||||
width: 2,
|
||||
},
|
||||
];
|
||||
@@ -141,7 +146,11 @@ function fnGetList(pageNum?: number) {
|
||||
}
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
if (tablePagination.total <=(queryParams.pageNum - 1) * tablePagination.pageSize &&queryParams.pageNum !== 1) {
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
@@ -301,7 +310,7 @@ onMounted(() => {
|
||||
fnGetList();
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.configManage.softwareManage.nullData'),
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
@@ -421,8 +430,10 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 上传框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -478,7 +489,7 @@ onMounted(() => {
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw } from 'vue';
|
||||
import { reactive, onMounted, toRaw, ref } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { message, Modal, Form } from 'ant-design-vue/lib';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
@@ -22,8 +22,12 @@ import { updateNeConfigReload } from '@/api/configManage/configParam';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { FileType } from 'ant-design-vue/lib/upload/interface';
|
||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||
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 useMaskStore from '@/store/modules/mask';
|
||||
const maskStore = useMaskStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**表格所需option */
|
||||
@@ -86,71 +90,74 @@ let tableColumns: ColumnsType = [
|
||||
title: t('views.configManage.neManage.neType'),
|
||||
dataIndex: 'neType',
|
||||
align: 'center',
|
||||
width: 3,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.neId'),
|
||||
dataIndex: 'neId',
|
||||
align: 'center',
|
||||
width: 3,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.uid'),
|
||||
dataIndex: 'rmUid',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.neName'),
|
||||
dataIndex: 'neName',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.ip'),
|
||||
dataIndex: 'ip',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.port'),
|
||||
dataIndex: 'port',
|
||||
align: 'center',
|
||||
width: 3,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.neName'),
|
||||
dataIndex: 'neName',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.uid'),
|
||||
dataIndex: 'rmUid',
|
||||
align: 'center',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.pvflag'),
|
||||
dataIndex: 'pvFlag',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.province'),
|
||||
dataIndex: 'province',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.vendorName'),
|
||||
dataIndex: 'vendorName',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.dn'),
|
||||
dataIndex: 'dn',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'id',
|
||||
align: 'center',
|
||||
fixed: 'right',
|
||||
width: 5,
|
||||
width: 150,
|
||||
},
|
||||
];
|
||||
|
||||
/**表格字段列排序 */
|
||||
let tableColumnsDnd = ref<ColumnsType>([]);
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
@@ -215,11 +222,11 @@ let modalState: ModalStateType = reactive({
|
||||
neAddress: '',
|
||||
neId: '',
|
||||
neName: '',
|
||||
neType: 'OMC',
|
||||
port: '3030',
|
||||
neType: 'AMF',
|
||||
port: '33030',
|
||||
province: '',
|
||||
pvFlag: 'PNF',
|
||||
rmUid: '4400HX1OMC001',
|
||||
rmUid: '4400HX1AMF001',
|
||||
vendorName: '',
|
||||
sync: true,
|
||||
},
|
||||
@@ -541,6 +548,11 @@ function fnRecordRestart(row: Record<string, any>) {
|
||||
restartNf(row)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// OMC自升级
|
||||
if (row.neType.toLowerCase() === 'omc') {
|
||||
maskStore.handleMaskType('reload');
|
||||
return;
|
||||
}
|
||||
message.success({
|
||||
content: t('common.msgSuccess', {
|
||||
msg: t('views.configManage.neManage.restart'),
|
||||
@@ -785,11 +797,12 @@ onMounted(() => {
|
||||
:label="t('views.configManage.neManage.neType')"
|
||||
name="neType "
|
||||
>
|
||||
<a-input
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="NE_TYPE_LIST.map(v => ({ value: v }))"
|
||||
allow-clear
|
||||
:placeholder="t('views.configManage.neManage.neTypePlease')"
|
||||
></a-input>
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
@@ -839,6 +852,11 @@ onMounted(() => {
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<TableColumnsDnd
|
||||
cache-id="neManageData"
|
||||
:columns="tableColumns"
|
||||
v-model:columns-dnd="tableColumnsDnd"
|
||||
></TableColumnsDnd>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
@@ -870,15 +888,15 @@ onMounted(() => {
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:columns="tableColumnsDnd"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: 2000, y: 480 }"
|
||||
:scroll="{ y: 'calc(100vh - 480px)' }"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'id'">
|
||||
<template v-if="column?.key === 'id'">
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.editText') }}</template>
|
||||
@@ -902,10 +920,7 @@ onMounted(() => {
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="left">
|
||||
<template #title>{{ t('common.moreText') }}</template>
|
||||
<a-dropdown
|
||||
placement="bottomRight"
|
||||
:trigger="['hover', 'click']"
|
||||
>
|
||||
<a-dropdown placement="bottomRight" trigger="click">
|
||||
<a-button type="link">
|
||||
<template #icon><EllipsisOutlined /> </template>
|
||||
</a-button>
|
||||
@@ -919,11 +934,17 @@ onMounted(() => {
|
||||
<ImportOutlined />
|
||||
{{ t('views.configManage.neManage.import') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="start">
|
||||
<a-menu-item
|
||||
key="start"
|
||||
v-if="!['OMC'].includes(record.neType)"
|
||||
>
|
||||
<thunderbolt-outlined />
|
||||
{{ t('views.configManage.neManage.start') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="stop">
|
||||
<a-menu-item
|
||||
key="stop"
|
||||
v-if="!['OMC'].includes(record.neType)"
|
||||
>
|
||||
<pause-outlined />
|
||||
{{ t('views.configManage.neManage.stop') }}
|
||||
</a-menu-item>
|
||||
@@ -951,8 +972,10 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -974,20 +997,21 @@ onMounted(() => {
|
||||
name="neType"
|
||||
v-bind="modalStateFrom.validateInfos.neType"
|
||||
>
|
||||
<a-input
|
||||
<a-auto-complete
|
||||
v-model:value="modalState.from.neType"
|
||||
allow-clear
|
||||
:placeholder="t('views.configManage.neManage.neTypePlease')"
|
||||
:options="NE_TYPE_LIST.map(v => ({ value: v }))"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>{{
|
||||
t('views.configManage.neManage.neTypeTip')
|
||||
}}</template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
<a-input allow-clear :placeholder="t('common.inputPlease')">
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>{{
|
||||
t('views.configManage.neManage.neTypeTip')
|
||||
}}</template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-auto-complete>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1135,7 +1159,7 @@ onMounted(() => {
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.configManage.neManage.sync')"
|
||||
name="province"
|
||||
name="sync"
|
||||
>
|
||||
<a-switch
|
||||
v-model:checked="modalState.from.sync"
|
||||
@@ -1146,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"
|
||||
@@ -1237,7 +1263,7 @@ onMounted(() => {
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -167,7 +167,11 @@ function fnGetList(pageNum?: number) {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
if (tablePagination.total <=(queryParams.pageNum - 1) * tablePagination.pageSize &&queryParams.pageNum !== 1) {
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
@@ -197,15 +201,16 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="100%"
|
||||
wrap-class-name="full-modal"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:forceFullscreen="true"
|
||||
:destroyOnClose="true"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@cancel="fnModalCancel"
|
||||
:footer="null"
|
||||
:footer="false"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
@@ -265,7 +270,7 @@ watch(
|
||||
:pagination="tablePagination"
|
||||
>
|
||||
</a-table>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -273,22 +278,3 @@ watch(
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.full-modal {
|
||||
.ant-modal {
|
||||
max-width: 100%;
|
||||
top: 0;
|
||||
padding-bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.ant-modal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh);
|
||||
}
|
||||
.ant-modal-body {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -23,8 +23,8 @@ import useI18n from '@/hooks/useI18n';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { FileType } from 'ant-design-vue/lib/upload/interface';
|
||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||
import useLockedStore from '@/store/modules/locked';
|
||||
const lockedStore = useLockedStore();
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
const maskStore = useMaskStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**查询参数 */
|
||||
@@ -82,7 +82,7 @@ let tableColumns: ColumnsType = [
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.softwareManage.fileName'),
|
||||
dataIndex: 'fileName',
|
||||
dataIndex: 'name',
|
||||
align: 'center',
|
||||
width: 2,
|
||||
},
|
||||
@@ -94,7 +94,7 @@ let tableColumns: ColumnsType = [
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.softwareManage.updateTime'),
|
||||
dataIndex: 'updateTime',
|
||||
dataIndex: 'createTime',
|
||||
align: 'center',
|
||||
customRender(opt) {
|
||||
if (!opt.value) return '';
|
||||
@@ -104,7 +104,7 @@ let tableColumns: ColumnsType = [
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.softwareManage.description'),
|
||||
dataIndex: 'comment',
|
||||
dataIndex: 'name',
|
||||
align: 'center',
|
||||
width: 2,
|
||||
},
|
||||
@@ -274,6 +274,7 @@ function fnFileModalVisible(type: string | number, row: Record<string, any>) {
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnFileModalOk() {
|
||||
if (fileModalState.confirmLoading) return;
|
||||
fileModalStateFrom
|
||||
.validate()
|
||||
.then(e => {
|
||||
@@ -298,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}`,
|
||||
@@ -730,13 +731,15 @@ onMounted(() => {
|
||||
}
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.configManage.softwareManage.nullData'),
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
});
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -889,10 +892,7 @@ onMounted(() => {
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="left">
|
||||
<template #title>{{ t('common.moreText') }}</template>
|
||||
<a-dropdown
|
||||
placement="bottomRight"
|
||||
:trigger="['hover', 'click']"
|
||||
>
|
||||
<a-dropdown placement="bottomRight" trigger="click">
|
||||
<a-button type="link">
|
||||
<template #icon><EllipsisOutlined /> </template>
|
||||
</a-button>
|
||||
@@ -919,8 +919,9 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 上传框 -->
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdit"
|
||||
@@ -1012,7 +1013,7 @@ onMounted(() => {
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 上传激活历史 -->
|
||||
<SoftwareHistory
|
||||
@@ -1022,8 +1023,8 @@ onMounted(() => {
|
||||
/>
|
||||
|
||||
<!-- 文件框 下发激活 -->
|
||||
<a-modal
|
||||
width="600px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="fileModalState.visible"
|
||||
@@ -1051,11 +1052,11 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 回退框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="fileModalState.visibleByBack"
|
||||
@@ -1086,7 +1087,7 @@ onMounted(() => {
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, ref, onUnmounted } from 'vue';
|
||||
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';
|
||||
@@ -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,14 +34,22 @@ let dict: {
|
||||
ueEventCmState: [],
|
||||
});
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'AMF',
|
||||
neId: '001',
|
||||
eventType: 'auth-result',
|
||||
imsi: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
@@ -52,9 +61,13 @@ function fnQueryReset() {
|
||||
eventTypes.value = ['auth-result'];
|
||||
queryParams = Object.assign(queryParams, {
|
||||
eventType: 'auth-result',
|
||||
imsi: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
@@ -76,8 +89,6 @@ type TabeStateType = {
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**斑马纹 */
|
||||
striped: boolean;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
@@ -90,7 +101,6 @@ type TabeStateType = {
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
striped: false,
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
@@ -108,7 +118,7 @@ let tableColumns: ColumnsType = [
|
||||
title: 'IMSI',
|
||||
dataIndex: 'eventJSON',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const eventJSON = opt.value;
|
||||
return eventJSON.imsi;
|
||||
@@ -119,20 +129,20 @@ let tableColumns: ColumnsType = [
|
||||
dataIndex: 'eventType',
|
||||
key: 'eventType',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.result'),
|
||||
dataIndex: 'eventJSON',
|
||||
key: 'result',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.time'),
|
||||
dataIndex: 'eventJSON',
|
||||
key: 'time',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
@@ -175,11 +185,6 @@ function fnTableSize({ key }: MenuInfo) {
|
||||
tableState.size = key as SizeType;
|
||||
}
|
||||
|
||||
/**表格斑马纹 */
|
||||
function fnTableStriped(_record: unknown, index: number): any {
|
||||
return tableState.striped && index % 2 === 1 ? 'table-striped' : undefined;
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
@@ -247,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)) {
|
||||
// 取消勾选
|
||||
@@ -281,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);
|
||||
|
||||
@@ -296,7 +339,7 @@ function fnRealTime() {
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* UE会话事件-AMF (GroupID:1010)
|
||||
* AMF_UE会话事件(GroupID:1010)
|
||||
*/
|
||||
subGroupID: '1010',
|
||||
},
|
||||
@@ -327,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 () => {
|
||||
@@ -374,8 +417,10 @@ onMounted(() => {
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
ws.close();
|
||||
onBeforeUnmount(() => {
|
||||
if (ws.state() !== -1) {
|
||||
ws.close();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -389,20 +434,45 @@ onUnmounted(() => {
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<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="tags"
|
||||
mode="multiple"
|
||||
:options="dict.ueEventType"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
@change="fnQueryEventTypeChange"
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item label="IMSI" name="imsi ">
|
||||
<a-input
|
||||
v-model:value="queryParams.imsi"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
@@ -456,6 +526,11 @@ onUnmounted(() => {
|
||||
<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>
|
||||
|
||||
@@ -471,15 +546,6 @@ onUnmounted(() => {
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.tableStripedText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.striped"
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
@@ -522,7 +588,6 @@ onUnmounted(() => {
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:row-class-name="fnTableStriped"
|
||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
@@ -597,11 +662,11 @@ onUnmounted(() => {
|
||||
{{ 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">
|
||||
@@ -658,10 +723,6 @@ onUnmounted(() => {
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.table-striped) td {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, ref, onUnmounted } from 'vue';
|
||||
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';
|
||||
@@ -11,9 +11,14 @@ import {
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { delIMSDataCDR, listIMSDataCDR } from '@/api/neData/ims';
|
||||
import {
|
||||
delIMSDataCDR,
|
||||
exportIMSDataCDR,
|
||||
listIMSDataCDR,
|
||||
} from '@/api/neData/ims';
|
||||
import { parseDateToStr, parseDuration } from '@/utils/date-utils';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import saveAs from 'file-saver';
|
||||
import PQueue from 'p-queue';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
@@ -31,14 +36,23 @@ let dict: {
|
||||
cdrCallType: [],
|
||||
});
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'IMS',
|
||||
neId: '001',
|
||||
recordType: 'MOC',
|
||||
callerParty: '',
|
||||
calledParty: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
@@ -50,9 +64,14 @@ function fnQueryReset() {
|
||||
recordTypes.value = ['MOC'];
|
||||
queryParams = Object.assign(queryParams, {
|
||||
recordType: 'MOC',
|
||||
callerParty: '',
|
||||
calledParty: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
@@ -74,8 +93,6 @@ type TabeStateType = {
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**斑马纹 */
|
||||
striped: boolean;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
@@ -88,7 +105,6 @@ type TabeStateType = {
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
striped: false,
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
@@ -106,7 +122,7 @@ let tableColumns: ColumnsType = [
|
||||
title: t('views.dashboard.cdr.recordType'),
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.recordType;
|
||||
@@ -124,7 +140,7 @@ let tableColumns: ColumnsType = [
|
||||
dataIndex: 'cdrJSON',
|
||||
key: 'calledParty',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
width: 120,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.calledParty;
|
||||
@@ -135,7 +151,7 @@ let tableColumns: ColumnsType = [
|
||||
dataIndex: 'cdrJSON',
|
||||
key: 'callerParty',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
width: 120,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.callerParty;
|
||||
@@ -159,7 +175,7 @@ let tableColumns: ColumnsType = [
|
||||
dataIndex: 'cdrJSON',
|
||||
key: 'cause',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.time'),
|
||||
@@ -211,11 +227,6 @@ function fnTableSize({ key }: MenuInfo) {
|
||||
tableState.size = key as SizeType;
|
||||
}
|
||||
|
||||
/**表格斑马纹 */
|
||||
function fnTableStriped(_record: unknown, index: number): any {
|
||||
return tableState.striped && index % 2 === 1 ? 'table-striped' : undefined;
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
@@ -283,6 +294,11 @@ function fnGetList(pageNum?: number) {
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listIMSDataCDR(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
@@ -317,6 +333,39 @@ function fnGetList(pageNum?: number) {
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportIMSDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `ims_cdr_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
@@ -332,7 +381,7 @@ function fnRealTime() {
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* CDR会话事件-IMS (GroupID:1005)
|
||||
* IMS_CDR会话事件(GroupID:1005)
|
||||
*/
|
||||
subGroupID: '1005',
|
||||
},
|
||||
@@ -402,8 +451,10 @@ onMounted(() => {
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
ws.close();
|
||||
onBeforeUnmount(() => {
|
||||
if (ws.state() !== -1) {
|
||||
ws.close();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -417,14 +468,14 @@ onUnmounted(() => {
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<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="tags"
|
||||
mode="multiple"
|
||||
:options="
|
||||
['MOC', 'MTC', 'MOSM', 'MTSM'].map(v => ({ value: v }))
|
||||
"
|
||||
@@ -433,7 +484,47 @@ onUnmounted(() => {
|
||||
></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="t('views.dashboard.cdr.called')"
|
||||
name="calledParty "
|
||||
>
|
||||
<a-input
|
||||
v-model:value="queryParams.calledParty"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.caller')"
|
||||
name="callerParty "
|
||||
>
|
||||
<a-input
|
||||
v-model:value="queryParams.callerParty"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
@@ -486,6 +577,11 @@ onUnmounted(() => {
|
||||
<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>
|
||||
|
||||
@@ -501,15 +597,6 @@ onUnmounted(() => {
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.tableStripedText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.striped"
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
@@ -552,7 +639,6 @@ onUnmounted(() => {
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:row-class-name="fnTableStriped"
|
||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
@@ -573,7 +659,7 @@ onUnmounted(() => {
|
||||
<DictTag
|
||||
:options="dict.cdrSipCode"
|
||||
:value="record.cdrJSON.cause"
|
||||
value-option="0"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
@@ -602,11 +688,11 @@ onUnmounted(() => {
|
||||
{{ 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>
|
||||
@@ -644,7 +730,7 @@ onUnmounted(() => {
|
||||
<DictTag
|
||||
:options="dict.cdrSipCode"
|
||||
:value="record.cdrJSON.cause"
|
||||
value-option="0"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
@@ -659,10 +745,6 @@ onUnmounted(() => {
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.table-striped) td {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,693 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, ref, onBeforeUnmount } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { message, Modal } from 'ant-design-vue/lib';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import {
|
||||
RESULT_CODE_ERROR,
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { listMMEDataUE, delMMEDataUE, exportMMEDataUE } from '@/api/neData/mme';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import saveAs from 'file-saver';
|
||||
import PQueue from 'p-queue';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
const ws = new WS();
|
||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
/**UE 事件认证代码类型 */
|
||||
ueAauthCode: DictType[];
|
||||
/**UE 事件类型 */
|
||||
ueEventType: DictType[];
|
||||
/**UE 事件CM状态 */
|
||||
ueEventCmState: DictType[];
|
||||
} = reactive({
|
||||
ueAauthCode: [],
|
||||
ueEventType: [],
|
||||
ueEventCmState: [],
|
||||
});
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'MME',
|
||||
neId: '001',
|
||||
eventType: 'auth-result',
|
||||
imsi: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
eventTypes.value = ['auth-result'];
|
||||
queryParams = Object.assign(queryParams, {
|
||||
eventType: 'auth-result',
|
||||
imsi: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**记录类型 */
|
||||
const eventTypes = ref<string[]>(['auth-result']);
|
||||
|
||||
/**查询记录类型变更 */
|
||||
function fnQueryEventTypeChange(value: any) {
|
||||
if (Array.isArray(value)) {
|
||||
queryParams.eventType = value.join(',');
|
||||
}
|
||||
}
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: 'IMSI',
|
||||
dataIndex: 'eventJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const eventJSON = opt.value;
|
||||
return eventJSON.imsi;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.eventType'),
|
||||
dataIndex: 'eventType',
|
||||
key: 'eventType',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.result'),
|
||||
dataIndex: 'eventJSON',
|
||||
key: 'result',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.ue.time'),
|
||||
dataIndex: 'eventJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return parseDateToStr(+cdrJSON.timestamp * 1000);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'id',
|
||||
align: 'left',
|
||||
},
|
||||
];
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
current: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
/**默认的每页条数 */
|
||||
defaultPageSize: 20,
|
||||
/**指定每页可以显示多少条 */
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
/**只有一页时是否隐藏分页器 */
|
||||
hideOnSinglePage: false,
|
||||
/**是否可以快速跳转至某页 */
|
||||
showQuickJumper: true,
|
||||
/**是否可以改变 pageSize */
|
||||
showSizeChanger: true,
|
||||
/**数据总数 */
|
||||
total: 0,
|
||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
||||
onChange: (page: number, pageSize: number) => {
|
||||
tablePagination.current = page;
|
||||
tablePagination.pageSize = pageSize;
|
||||
queryParams.pageNum = page;
|
||||
queryParams.pageSize = pageSize;
|
||||
fnGetList();
|
||||
},
|
||||
});
|
||||
|
||||
/**表格紧凑型变更操作 */
|
||||
function fnTableSize({ key }: MenuInfo) {
|
||||
tableState.size = key as SizeType;
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
/**最大ID值 */
|
||||
maxId: number;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
confirmLoading: false,
|
||||
maxId: 0,
|
||||
});
|
||||
|
||||
/**
|
||||
* 记录删除
|
||||
* @param id 编号
|
||||
*/
|
||||
function fnRecordDelete(id: string) {
|
||||
if (!id || modalState.confirmLoading) return;
|
||||
let msg = id;
|
||||
if (id === '0') {
|
||||
msg = `${id}... ${tableState.selectedRowKeys.length}`;
|
||||
id = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.delTip', { msg }),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
delMMEDataUE(id)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
fnGetList(1);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**查询列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listMMEDataUE(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
if (tableState.selectedRowKeys.length > 0) {
|
||||
tableState.selectedRowKeys = [];
|
||||
}
|
||||
tablePagination.total = res.total;
|
||||
// 遍历处理cdr字符串数据
|
||||
tableState.data = res.rows.map(item => {
|
||||
let eventJSON = item.eventJSON;
|
||||
if (!eventJSON) {
|
||||
Reflect.set(item, 'eventJSON', {});
|
||||
}
|
||||
|
||||
try {
|
||||
eventJSON = JSON.parse(eventJSON);
|
||||
Reflect.set(item, 'eventJSON', eventJSON);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Reflect.set(item, 'eventJSON', {});
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
// 取最大值ID用作实时累加
|
||||
if (res.total > 0) {
|
||||
modalState.maxId = Number(res.rows[0].id);
|
||||
}
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportMMEDataUE(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `mme_ue_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
/**
|
||||
* 实时数据
|
||||
*/
|
||||
function fnRealTime() {
|
||||
realTimeData.value = !realTimeData.value;
|
||||
if (realTimeData.value) {
|
||||
// 建立链接
|
||||
const options: OptionsType = {
|
||||
url: '/ws',
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* MME_UE会话事件(GroupID:1011)
|
||||
*/
|
||||
subGroupID: '1011',
|
||||
},
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
};
|
||||
ws.connect(options);
|
||||
} else {
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**接收数据后回调 */
|
||||
function wsError(ev: any) {
|
||||
// 接收数据后回调
|
||||
console.error(ev);
|
||||
}
|
||||
|
||||
/**接收数据后回调 */
|
||||
function wsMessage(res: Record<string, any>) {
|
||||
const { code, requestId, data } = res;
|
||||
if (code === RESULT_CODE_ERROR) {
|
||||
console.warn(res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// 订阅组信息
|
||||
if (!data?.groupId) {
|
||||
return;
|
||||
}
|
||||
// ueEvent MME_UE会话事件
|
||||
if (data.groupId === '1011') {
|
||||
const ueEvent = data.data;
|
||||
queue.add(async () => {
|
||||
modalState.maxId += 1;
|
||||
tableState.data.unshift({
|
||||
id: modalState.maxId,
|
||||
neType: ueEvent.neType,
|
||||
neName: ueEvent.neName, // 空
|
||||
rmUID: ueEvent.rmUID, // 空
|
||||
timestamp: ueEvent.timestamp,
|
||||
eventType: ueEvent.eventType,
|
||||
eventJSON: ueEvent.eventJSON,
|
||||
});
|
||||
tablePagination.total += 1;
|
||||
if (tableState.data.length > 100) {
|
||||
tableState.data.pop();
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([
|
||||
getDict('ue_auth_code'),
|
||||
getDict('ue_event_type'),
|
||||
getDict('ue_event_cm_state'),
|
||||
])
|
||||
.then(resArr => {
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
dict.ueAauthCode = resArr[0].value;
|
||||
}
|
||||
if (resArr[1].status === 'fulfilled') {
|
||||
dict.ueEventType = resArr[1].value;
|
||||
}
|
||||
if (resArr[2].status === 'fulfilled') {
|
||||
dict.ueEventCmState = resArr[2].value;
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (ws.state() !== -1) {
|
||||
ws.close();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.ue.eventType')"
|
||||
name="eventType "
|
||||
>
|
||||
<a-select
|
||||
v-model:value="eventTypes"
|
||||
mode="multiple"
|
||||
:options="dict.ueEventType"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
@change="fnQueryEventTypeChange"
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item label="IMSI" name="imsi ">
|
||||
<a-input
|
||||
v-model:value="queryParams.imsi"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-popconfirm
|
||||
placement="bottomLeft"
|
||||
:title="
|
||||
!realTimeData
|
||||
? t('views.dashboard.ue.realTimeDataStart')
|
||||
: t('views.dashboard.ue.realTimeDataStop')
|
||||
"
|
||||
ok-text="Yes"
|
||||
cancel-text="No"
|
||||
@confirm="fnRealTime()"
|
||||
>
|
||||
<a-button type="primary" :danger="realTimeData">
|
||||
<template #icon><FundOutlined /> </template>
|
||||
{{
|
||||
!realTimeData
|
||||
? t('views.dashboard.ue.realTimeDataStart')
|
||||
: t('views.dashboard.ue.realTimeDataStop')
|
||||
}}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
<a-button type="text">
|
||||
<template #icon><ColumnHeightOutlined /></template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="middle">
|
||||
{{ t('common.size.middle') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="small">
|
||||
{{ t('common.size.small') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
columnWidth: '48px',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'eventType'">
|
||||
<DictTag :options="dict.ueEventType" :value="record.eventType" />
|
||||
</template>
|
||||
<template v-if="column.key === 'result'">
|
||||
<span v-if="record.eventType === 'auth-result'">
|
||||
<DictTag
|
||||
:options="dict.ueAauthCode"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
<span>{{ t('views.dashboard.ue.resultOk') }}</span>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
<DictTag
|
||||
:options="dict.ueEventCmState"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'id'">
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.deleteText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.id)"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
<template #expandedRowRender="{ record }">
|
||||
<div style="width: 46%; padding-left: 32px; padding-bottom: 16px">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.ue.ueInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||
<span>{{ record.neName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||
<span>{{ record.rmUID }}</span>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.ue.rowInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.time') }}: </span>
|
||||
{{ parseDateToStr(record.eventJSON.timestamp * 1000) }}
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
|
||||
<DictTag :options="dict.ueEventType" :value="record.eventType" />
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.ue.result') }}: </span>
|
||||
<span v-if="record.eventType === 'auth-result'">
|
||||
<DictTag
|
||||
:options="dict.ueAauthCode"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
<span v-if="record.eventType === 'detach'">
|
||||
{{ t('views.dashboard.ue.resultOK') }}
|
||||
</span>
|
||||
<span v-if="record.eventType === 'cm-state'">
|
||||
<DictTag
|
||||
:options="dict.ueEventCmState"
|
||||
:value="record.eventJSON.result"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,202 @@
|
||||
<script setup lang="ts">
|
||||
import * as echarts from 'echarts/core';
|
||||
import {
|
||||
TitleComponent,
|
||||
TitleComponentOption,
|
||||
TooltipComponent,
|
||||
TooltipComponentOption,
|
||||
GridComponent,
|
||||
GridComponentOption,
|
||||
LegendComponent,
|
||||
LegendComponentOption,
|
||||
} from 'echarts/components';
|
||||
import {
|
||||
PieChart,
|
||||
PieSeriesOption,
|
||||
BarChart,
|
||||
BarSeriesOption,
|
||||
} from 'echarts/charts';
|
||||
import { LabelLayout } from 'echarts/features';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
|
||||
import { markRaw, onMounted, ref } from 'vue';
|
||||
import { origGet, top3Sel } from '@/api/faultManage/actAlarm';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
echarts.use([
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
LegendComponent,
|
||||
PieChart,
|
||||
BarChart,
|
||||
CanvasRenderer,
|
||||
LabelLayout,
|
||||
]);
|
||||
|
||||
type EChartsOption = echarts.ComposeOption<
|
||||
| TitleComponentOption
|
||||
| TooltipComponentOption
|
||||
| GridComponentOption
|
||||
| LegendComponentOption
|
||||
| PieSeriesOption
|
||||
| BarSeriesOption
|
||||
>;
|
||||
|
||||
/**图DOM节点实例对象 */
|
||||
const alarmTypeBar = ref<HTMLElement | undefined>(undefined);
|
||||
|
||||
/**图实例对象 */
|
||||
const alarmTypeBarChart = ref<any>(null);
|
||||
|
||||
/**告警类型数据 */
|
||||
const alarmTypeType = ref<any>([
|
||||
{
|
||||
value: 0,
|
||||
name: t('views.index.Critical'),
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
name: t('views.index.Major'),
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
name: t('views.index.Minor'),
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
name: t('views.index.Warning'),
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
name: t('views.index.Event'),
|
||||
},
|
||||
]);
|
||||
|
||||
//
|
||||
function initPicture() {
|
||||
Promise.allSettled([origGet()])
|
||||
.then(resArr => {
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
const res0 = resArr[0].value;
|
||||
if (res0.code === RESULT_CODE_SUCCESS && Array.isArray(res0.data)) {
|
||||
for (const item of res0.data) {
|
||||
let index = 0;
|
||||
switch (item.name) {
|
||||
case 'Critical':
|
||||
index = 0;
|
||||
break;
|
||||
case 'Major':
|
||||
index = 1;
|
||||
break;
|
||||
case 'Minor':
|
||||
index = 2;
|
||||
break;
|
||||
case 'Warning':
|
||||
index = 3;
|
||||
break;
|
||||
case 'Event':
|
||||
index = 4;
|
||||
break;
|
||||
}
|
||||
alarmTypeType.value[index].value = Number(item.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
const optionData: EChartsOption = {
|
||||
title: [
|
||||
{
|
||||
show: false,
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{b} : {c}',
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: '2%',
|
||||
top: '10%',
|
||||
data: alarmTypeType.value.map((item: any) => item.name), //label数组
|
||||
textStyle: {
|
||||
color: '#A7D6F4', // 设置图例文字颜色
|
||||
},
|
||||
},
|
||||
grid: [
|
||||
{
|
||||
top: '60%',
|
||||
left: '15%',
|
||||
right: '25%',
|
||||
bottom: '10%',
|
||||
},
|
||||
],
|
||||
series: [
|
||||
//饼图:
|
||||
{
|
||||
type: 'pie',
|
||||
radius: '60%',
|
||||
color: ['#f5222d', '#fa8c16', '#fadb14', '#1677ff', '#13c2c2'],
|
||||
label: {
|
||||
show: true,
|
||||
position: 'inner',
|
||||
formatter: (params: any) => {
|
||||
if (!params.value) return '';
|
||||
return `${params.value}`;
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
center: ['30%', '40%'],
|
||||
data: alarmTypeType.value,
|
||||
zlevel: 2, // 设置zlevel为1,使得柱状图在下层显示
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
fnDesign(alarmTypeBar.value, optionData);
|
||||
});
|
||||
}
|
||||
|
||||
function fnDesign(container: HTMLElement | undefined, option: any) {
|
||||
if (!container) return;
|
||||
|
||||
alarmTypeBarChart.value = markRaw(echarts.init(container, 'light'));
|
||||
option && alarmTypeBarChart.value.setOption(option);
|
||||
|
||||
// 创建 ResizeObserver 实例
|
||||
var observer = new ResizeObserver(entries => {
|
||||
if (alarmTypeBarChart.value) {
|
||||
alarmTypeBarChart.value.resize();
|
||||
}
|
||||
});
|
||||
// 监听元素大小变化
|
||||
observer.observe(container);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initPicture();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="alarmTypeBar" class="chart-container"></div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.chart-container {
|
||||
/* 设置图表容器大小和位置 */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,91 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, toRaw, watch } from 'vue';
|
||||
import { dbGetJSON, dbSetJSON } from '@/utils/cache-db-utils';
|
||||
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '标题',
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
/**数据参数 */
|
||||
let dataState = reactive({
|
||||
/**基站数 */
|
||||
baseNum: 0,
|
||||
/**核心网数 */
|
||||
coreNetNum: 0,
|
||||
/**在线用户数 */
|
||||
onlineUserNum: 0,
|
||||
});
|
||||
|
||||
/**弹框取消按钮事件 */
|
||||
function fnModalOk() {
|
||||
dbSetJSON('tbl_mocn', `tmp`, toRaw(dataState));
|
||||
emit('ok');
|
||||
emit('update:visible', false);
|
||||
}
|
||||
|
||||
/**弹框取消按钮事件 */
|
||||
function fnModalCancel() {
|
||||
emit('cancel');
|
||||
emit('update:visible', false);
|
||||
}
|
||||
|
||||
/**显示弹框时初始数据 */
|
||||
function init() {
|
||||
// 读取数据
|
||||
dbGetJSON('tbl_mocn', `tmp`).then(data => {
|
||||
if (data) {
|
||||
Object.assign(dataState, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
watch(
|
||||
() => props.visible,
|
||||
val => {
|
||||
if (val) init();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@cancel="fnModalCancel"
|
||||
@ok="fnModalOk"
|
||||
>
|
||||
<a-form
|
||||
name="dataState"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-form-item label="baseNum" name="baseNum">
|
||||
<a-input-number v-model:value="dataState.baseNum"> </a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label="coreNetNum" name="coreNetNum">
|
||||
<a-input-number v-model:value="dataState.coreNetNum"> </a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label="onlineUserNum" name="onlineUserNum">
|
||||
<a-input-number v-model:value="dataState.onlineUserNum">
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,566 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||
import svgBase from '@/assets/svg/base.svg';
|
||||
import svgUserIMS from '@/assets/svg/userIMS.svg';
|
||||
import svgUserSMF from '@/assets/svg/userSMF.svg';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import Topology from '../overview/components/Topology/index.vue';
|
||||
import NeResources from '../overview/components/NeResources/index.vue';
|
||||
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 { listUDMSub } from '@/api/neData/udm_sub';
|
||||
import { listUENumBySMF } from '@/api/neUser/smf';
|
||||
import { listUENumByIMS } from '@/api/neUser/ims';
|
||||
import { listBase5G } from '@/api/neUser/base5G';
|
||||
import {
|
||||
graphNodeClickID,
|
||||
graphState,
|
||||
notNeNodes,
|
||||
graphNodeStateNum,
|
||||
neStateRequestMap,
|
||||
} from '../overview/hooks/useTopology';
|
||||
import { upfTotalFlow, upfTFActive } from '../overview/hooks/useUPFTotalFlow';
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import useWS from '../overview/hooks/useWS';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { dbGetJSON } from '@/utils/cache-db-utils';
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const { t } = useI18n();
|
||||
const { wsSend, userActivitySend, upfTFSend } = useWS();
|
||||
|
||||
/**概览状态类型 */
|
||||
type SkimStateType = {
|
||||
/**UDM签约用户数量 */
|
||||
udmSubNum: number;
|
||||
/**SMF在线用户数 */
|
||||
smfUeNum: number;
|
||||
/**IMS在线用户数 */
|
||||
imsUeNum: number;
|
||||
/**5G基站数量 */
|
||||
gnbNum: number;
|
||||
/**5G在线用户数量 */
|
||||
gnbUeNum: number;
|
||||
/**4G基站数量 */
|
||||
enbNum: number;
|
||||
/**4G在线用户数量 */
|
||||
enbUeNum: number;
|
||||
};
|
||||
|
||||
/**概览状态信息 */
|
||||
let skimState: SkimStateType = reactive({
|
||||
udmSubNum: 0,
|
||||
smfUeNum: 0,
|
||||
imsUeNum: 0,
|
||||
gnbNum: 0,
|
||||
gnbUeNum: 0,
|
||||
enbNum: 0,
|
||||
enbUeNum: 0,
|
||||
});
|
||||
|
||||
/**总览节点 */
|
||||
const viewportDom = ref<HTMLElement | null>(null);
|
||||
const { isFullscreen, toggle } = useFullscreen(viewportDom);
|
||||
|
||||
/**10s调度器 */
|
||||
const interval10s = ref<any>(null);
|
||||
|
||||
/**5s调度器 */
|
||||
const interval5s = ref<any>(null);
|
||||
|
||||
/**查询网元状态 */
|
||||
function fnGetNeState() {
|
||||
// 获取节点状态
|
||||
for (const node of graphState.data.nodes) {
|
||||
if (notNeNodes.includes(node.id)) continue;
|
||||
const { neType, neId } = node.neInfo;
|
||||
if (!neType || !neId) continue;
|
||||
// 请求标记检查避免重复发送
|
||||
if (neStateRequestMap.value.get(neType)) continue;
|
||||
neStateRequestMap.value.set(neType, true);
|
||||
|
||||
wsSend({
|
||||
requestId: `neState_${neType}_${neId}`,
|
||||
type: 'ne_state',
|
||||
data: {
|
||||
neType: neType,
|
||||
neId: neId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**获取概览信息 */
|
||||
async function fnGetSkim() {
|
||||
const resArr = await Promise.allSettled([
|
||||
listUDMSub({
|
||||
neid: '001',
|
||||
pageNum: 1,
|
||||
pageSize: 1,
|
||||
}),
|
||||
listUENumBySMF('001'),
|
||||
listUENumByIMS('001'),
|
||||
listBase5G({
|
||||
neType: 'AMF',
|
||||
neId: '001',
|
||||
}),
|
||||
listBase5G({
|
||||
neType: 'MME',
|
||||
neId: '001',
|
||||
}),
|
||||
]);
|
||||
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
const res0 = resArr[0].value;
|
||||
if (res0.code === RESULT_CODE_SUCCESS) {
|
||||
skimState.udmSubNum = res0.total;
|
||||
}
|
||||
}
|
||||
if (resArr[1].status === 'fulfilled') {
|
||||
const res1 = resArr[1].value;
|
||||
if (res1.code === RESULT_CODE_SUCCESS) {
|
||||
skimState.smfUeNum = res1.data;
|
||||
}
|
||||
}
|
||||
if (resArr[2].status === 'fulfilled') {
|
||||
const res2 = resArr[2].value;
|
||||
if (res2.code === RESULT_CODE_SUCCESS) {
|
||||
skimState.imsUeNum = res2.data;
|
||||
}
|
||||
}
|
||||
if (resArr[3].status === 'fulfilled') {
|
||||
const res3 = resArr[3].value;
|
||||
if (res3.code === RESULT_CODE_SUCCESS) {
|
||||
skimState.gnbNum = res3.total;
|
||||
skimState.gnbUeNum = 0;
|
||||
res3.rows.map((item: any) => {
|
||||
skimState.gnbUeNum += item.ueNum;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (resArr[4].status === 'fulfilled') {
|
||||
const res4 = resArr[4].value;
|
||||
if (res4.code === RESULT_CODE_SUCCESS) {
|
||||
skimState.enbNum = res4.total;
|
||||
skimState.enbUeNum = 0;
|
||||
res4.rows.map((item: any) => {
|
||||
skimState.enbUeNum += item.ueNum;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**初始数据函数 */
|
||||
function loadData() {
|
||||
fnGetNeState(); // 获取网元状态
|
||||
userActivitySend();
|
||||
upfTFSend(0);
|
||||
upfTFSend(7);
|
||||
upfTFSend(30);
|
||||
|
||||
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);
|
||||
}
|
||||
}, 10_000);
|
||||
|
||||
interval5s.value = setInterval(() => {
|
||||
fnGetSkim(); // 获取概览信息
|
||||
fnGetNeState(); // 获取网元状态
|
||||
}, 5_000);
|
||||
}
|
||||
|
||||
/**栏目信息跳转 */
|
||||
function fnToRouter(name: string, query?: any) {
|
||||
router.push({ name, query });
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fnGetSkim().then(() => {
|
||||
loadData();
|
||||
});
|
||||
// 读取数据
|
||||
dbGetJSON('tbl_mocn', `tmp`).then(data => {
|
||||
if (data) {
|
||||
Object.assign(mocnState.data, data);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(interval10s.value);
|
||||
clearInterval(interval5s.value);
|
||||
});
|
||||
|
||||
/**MOCN状态 */
|
||||
const mocnState = reactive({
|
||||
title: 'Set MOCN Data',
|
||||
visible: false,
|
||||
data: {
|
||||
/**基站数 */
|
||||
baseNum: 0,
|
||||
/**核心网数 */
|
||||
coreNetNum: 0,
|
||||
/**在线用户数 */
|
||||
onlineUserNum: 0,
|
||||
},
|
||||
});
|
||||
/**MOCN 右击设置 */
|
||||
function fnRightClick() {
|
||||
mocnState.visible = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="viewport" ref="viewportDom">
|
||||
<div class="brand">
|
||||
<div
|
||||
class="brand-title"
|
||||
@click="toggle"
|
||||
:title="t('views.dashboard.overview.fullscreen')"
|
||||
>
|
||||
{{ t('views.dashboard.overview.title') }}
|
||||
<FullscreenExitOutlined v-if="isFullscreen" />
|
||||
<FullscreenOutlined v-else />
|
||||
</div>
|
||||
<div class="brand-desc">{{ appStore.appName }}</div>
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<!--概览-->
|
||||
<div class="skim panel">
|
||||
<div class="inner">
|
||||
<h3>
|
||||
<IdcardOutlined style="color: #68d8fe" />
|
||||
{{ t('views.dashboard.overview.skim.userTitle') }}
|
||||
</h3>
|
||||
<div class="data">
|
||||
<div
|
||||
class="item toRouter"
|
||||
@click="fnToRouter('Sub_2010')"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<div>
|
||||
<UserOutlined
|
||||
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
|
||||
/>
|
||||
{{ skimState.udmSubNum }}
|
||||
</div>
|
||||
<span>
|
||||
{{ t('views.dashboard.overview.skim.users') }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="item toRouter"
|
||||
@click="fnToRouter('Ims_2080')"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
style="margin: 0 12px"
|
||||
>
|
||||
<div>
|
||||
<img :src="svgUserIMS" style="width: 18px; margin-right: 8px" />
|
||||
{{ skimState.imsUeNum }}
|
||||
</div>
|
||||
<span>
|
||||
{{ t('views.dashboard.overview.skim.imsUeNum') }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="item toRouter"
|
||||
@click="fnToRouter('Ue_2081')"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<div>
|
||||
<img :src="svgUserSMF" style="width: 18px; margin-right: 8px" />
|
||||
{{ skimState.smfUeNum }}
|
||||
</div>
|
||||
<span>
|
||||
{{ t('views.dashboard.overview.skim.smfUeNum') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="skim panel base">
|
||||
<div class="inner">
|
||||
<h3>
|
||||
<GlobalOutlined style="color: #68d8fe" />
|
||||
{{ t('views.dashboard.overview.skim.baseTitle') }}
|
||||
</h3>
|
||||
<div class="data">
|
||||
<div
|
||||
class="item toRouter"
|
||||
@click="fnToRouter('Base5G_2082', { neType: 'AMF' })"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<div style="align-items: flex-start">
|
||||
<img
|
||||
:src="svgBase"
|
||||
style="width: 18px; margin-right: 8px; height: 2rem"
|
||||
/>
|
||||
{{ skimState.gnbNum }}
|
||||
</div>
|
||||
<span>{{ t('views.dashboard.overview.skim.gnbBase') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="item toRouter"
|
||||
@click="fnToRouter('Base5G_2082', { neType: 'AMF' })"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<div style="align-items: flex-start">
|
||||
<UserOutlined
|
||||
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
|
||||
/>
|
||||
{{ skimState.gnbUeNum }}
|
||||
</div>
|
||||
<span>{{ t('views.dashboard.overview.skim.gnbUeNum') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data">
|
||||
<div
|
||||
class="item toRouter"
|
||||
@click="fnToRouter('Base5G_2082', { neType: 'MME' })"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<div style="align-items: flex-start">
|
||||
<img
|
||||
:src="svgBase"
|
||||
style="width: 18px; margin-right: 8px; height: 2rem"
|
||||
/>
|
||||
{{ skimState.enbNum }}
|
||||
</div>
|
||||
<span>{{ t('views.dashboard.overview.skim.enbBase') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="item toRouter"
|
||||
@click="fnToRouter('Base5G_2082', { neType: 'MME' })"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<div style="align-items: flex-start">
|
||||
<UserOutlined
|
||||
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
|
||||
/>
|
||||
{{ skimState.enbUeNum }}
|
||||
</div>
|
||||
<span>{{ t('views.dashboard.overview.skim.enbUeNum') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 用户行为 -->
|
||||
<div class="userActivity panel">
|
||||
<div class="inner">
|
||||
<h3>
|
||||
<WhatsAppOutlined style="color: #68d8fe" />
|
||||
{{ t('views.dashboard.overview.userActivity.title') }}
|
||||
</h3>
|
||||
<div class="chart">
|
||||
<UserActivity />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column" style="flex: 4; margin: 1.333rem 0.833rem 0">
|
||||
<!-- 实时流量 -->
|
||||
<div class="upfFlow panel">
|
||||
<div class="inner">
|
||||
<h3
|
||||
class="toRouter"
|
||||
@click="fnToRouter('GoldTarget_2104')"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<AreaChartOutlined style="color: #68d8fe" />
|
||||
{{ t('views.dashboard.overview.upfFlow.title') }}
|
||||
</h3>
|
||||
<div class="chart">
|
||||
<UPFFlow />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 网络拓扑 -->
|
||||
<div class="topology panel">
|
||||
<div class="inner">
|
||||
<h3
|
||||
class="toRouter"
|
||||
@click="fnToRouter('TopologyArchitecture_2128')"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<span>
|
||||
<ApartmentOutlined style="color: #68d8fe" />
|
||||
{{ t('views.dashboard.overview.topology.title') }}
|
||||
</span>
|
||||
<span>
|
||||
{{ t('views.dashboard.overview.topology.normal') }}:
|
||||
<span class="normal"> {{ graphNodeStateNum[0] }} </span>
|
||||
{{ t('views.dashboard.overview.topology.abnormal') }}:
|
||||
<span class="abnormal"> {{ graphNodeStateNum[1] }} </span>
|
||||
</span>
|
||||
</h3>
|
||||
<div class="chart">
|
||||
<Topology />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<!-- 流量统计 -->
|
||||
<div class="upfFlowTotal panel">
|
||||
<div class="inner">
|
||||
<h3>
|
||||
<span>
|
||||
<SwapOutlined style="color: #68d8fe" />
|
||||
{{ t('views.dashboard.overview.upfFlowTotal.title') }}
|
||||
</span>
|
||||
|
||||
<!-- 筛选 -->
|
||||
<div class="filter">
|
||||
<span
|
||||
:data-key="v"
|
||||
:class="{ active: upfTFActive === i }"
|
||||
v-for="(v, i) in ['0', '7', '30']"
|
||||
:key="v"
|
||||
@click="
|
||||
() => {
|
||||
upfTFActive = i;
|
||||
}
|
||||
"
|
||||
>
|
||||
{{
|
||||
v === '0'
|
||||
? '24' + t('common.units.hour')
|
||||
: v + t('common.units.day')
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</h3>
|
||||
<div class="chart">
|
||||
<!-- 数据 -->
|
||||
<div class="data">
|
||||
<div class="item">
|
||||
<span>
|
||||
<ArrowUpOutlined style="color: #597ef7" />
|
||||
{{ t('views.dashboard.overview.upfFlowTotal.up') }}
|
||||
</span>
|
||||
<h4>{{ upfTotalFlow[upfTFActive].up }}</h4>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span>
|
||||
<ArrowDownOutlined style="color: #52c41a" />
|
||||
{{ t('views.dashboard.overview.upfFlowTotal.down') }}
|
||||
</span>
|
||||
<h4>{{ upfTotalFlow[upfTFActive].down }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- MOCN -->
|
||||
<div class="skim panel mocn">
|
||||
<div class="inner">
|
||||
<h3
|
||||
class="toRouter"
|
||||
@contextmenu.prevent="fnRightClick()"
|
||||
@click="fnToRouter('GoldTarget_2104', { neType: 'MOCNGW' })"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<PieChartOutlined style="color: #68d8fe" /> MOCN
|
||||
Information
|
||||
</h3>
|
||||
<div class="chart">
|
||||
<div class="data">
|
||||
<div class="item" title="NodeB">
|
||||
<div>
|
||||
<img :src="svgBase" style="width: 18px; margin-right: 8px" />
|
||||
{{ mocnState.data.baseNum }}
|
||||
</div>
|
||||
<span> NodeB </span>
|
||||
</div>
|
||||
<div class="item" title="CoreNet">
|
||||
<div>
|
||||
<img
|
||||
:src="svgUserSMF"
|
||||
style="width: 18px; margin-right: 8px"
|
||||
/>
|
||||
{{ mocnState.data.coreNetNum }}
|
||||
</div>
|
||||
<span> CoreNet </span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data">
|
||||
<div class="item" title="OnlineUser">
|
||||
<div>
|
||||
<UserOutlined
|
||||
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
|
||||
/>
|
||||
{{ mocnState.data.onlineUserNum }}
|
||||
</div>
|
||||
<span> OnlineUser </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 告警统计 -->
|
||||
<div class="alarmType panel">
|
||||
<div class="inner">
|
||||
<h3
|
||||
class="toRouter"
|
||||
@click="fnToRouter('HistoryAlarm_2097')"
|
||||
:title="t('views.dashboard.overview.toRouter')"
|
||||
>
|
||||
<PieChartOutlined style="color: #68d8fe" />
|
||||
{{ t('views.dashboard.overview.alarmTypeBar.alarmSum') }}
|
||||
</h3>
|
||||
<div class="chart">
|
||||
<AlarnTypeBar />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 资源情况 -->
|
||||
<div class="resources panel">
|
||||
<div class="inner">
|
||||
<h3>
|
||||
<DashboardOutlined style="color: #68d8fe" />
|
||||
{{ t('views.dashboard.overview.resources.title') }}:
|
||||
{{ graphNodeClickID }}
|
||||
</h3>
|
||||
<div class="chart">
|
||||
<NeResources />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<setting
|
||||
:title="mocnState.title"
|
||||
v-model:visible="mocnState.visible"
|
||||
></setting>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import url('../overview/css/index.css');
|
||||
|
||||
.mocn {
|
||||
height: 20.6%;
|
||||
}
|
||||
.mocn .inner .chart .data {
|
||||
height: unset;
|
||||
}
|
||||
|
||||
.mocn .inner .chart .data .item {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.alarmType {
|
||||
height: 24.4%;
|
||||
}
|
||||
</style>
|
||||
@@ -70,10 +70,10 @@ const alarmTypeType = ref<any>([
|
||||
value: 0,
|
||||
name: t('views.index.Warning'),
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
name: t('views.index.Event'),
|
||||
},
|
||||
// {
|
||||
// value: 0,
|
||||
// name: t('views.index.Event'),
|
||||
// },
|
||||
]);
|
||||
|
||||
/**告警类型Top数据 */
|
||||
@@ -105,9 +105,9 @@ function initPicture() {
|
||||
case 'Warning':
|
||||
index = 3;
|
||||
break;
|
||||
case 'Event':
|
||||
index = 4;
|
||||
break;
|
||||
// case 'Event':
|
||||
// index = 4;
|
||||
// break;
|
||||
}
|
||||
alarmTypeType.value[index].value = Number(item.value);
|
||||
}
|
||||
@@ -149,7 +149,7 @@ function initPicture() {
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: '2%',
|
||||
top: '10%',
|
||||
top: '12%',
|
||||
data: alarmTypeType.value.map((item: any) => item.name), //label数组
|
||||
textStyle: {
|
||||
color: '#A7D6F4', // 设置图例文字颜色
|
||||
|
||||
@@ -277,6 +277,9 @@ function fnChangeData(data: any[], itemID: string) {
|
||||
if (men > 100) {
|
||||
men = +(men / 100).toFixed(2);
|
||||
}
|
||||
if (men > 100) {
|
||||
men = 100;
|
||||
}
|
||||
sysMemUsage = men;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ function fnGraphEvent(graph: Graph) {
|
||||
// 节点点击
|
||||
graph.on('node:click', evt => {
|
||||
// 获得鼠标当前目标节点
|
||||
const node = evt.item?.getModel();
|
||||
const node = evt.item?.getModel();
|
||||
if (node && node.id && !notNeNodes.includes(node.id)) {
|
||||
graphNodeClickID.value = node.id;
|
||||
}
|
||||
@@ -129,6 +129,9 @@ function handleRanderGraph(
|
||||
var observer = new ResizeObserver(function (entries) {
|
||||
// 当元素大小发生变化时触发回调函数
|
||||
entries.forEach(function (entry) {
|
||||
if (!graphG6.value) {
|
||||
return;
|
||||
}
|
||||
graphG6.value.changeSize(
|
||||
entry.contentRect.width,
|
||||
entry.contentRect.height - 30
|
||||
|
||||
@@ -58,11 +58,11 @@ onMounted(() => {
|
||||
<template>
|
||||
<div class="activty">
|
||||
<template v-for="item in eventData" :key="item.eId">
|
||||
<!-- CDR事件 -->
|
||||
<!-- CDR事件IMS -->
|
||||
<div
|
||||
class="card-cdr"
|
||||
:class="{ active: item.eId === eventId }"
|
||||
v-if="item.eType === 'cdr'"
|
||||
v-if="item.eType === 'ims_cdr'"
|
||||
>
|
||||
<div class="card-cdr-item">
|
||||
<div>
|
||||
@@ -104,18 +104,22 @@ onMounted(() => {
|
||||
<div>
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span v-if="item.data.callType !== 'sms'">
|
||||
<DictTag :options="dict.cdrSipCode" :value="item.data.cause" value-option="0" />
|
||||
<DictTag
|
||||
:options="dict.cdrSipCode"
|
||||
:value="item.data.cause"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ t('views.dashboard.overview.userActivity.resultOK') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- UE事件 -->
|
||||
<!-- UE事件AMF -->
|
||||
<div
|
||||
class="card-ue"
|
||||
:class="{ active: item.eId === eventId }"
|
||||
v-if="item.eType === 'ue'"
|
||||
v-if="item.eType === 'amf_ue'"
|
||||
>
|
||||
<div class="card-ue-item">
|
||||
<div>
|
||||
@@ -155,6 +159,7 @@ onMounted(() => {
|
||||
TAC ID: <span>{{ item.data.tacID }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="item.type === 'auth-result'">
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span>
|
||||
@@ -172,96 +177,59 @@ onMounted(() => {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- UE事件MME -->
|
||||
<div
|
||||
class="card-ue"
|
||||
:class="{ active: item.eId === eventId }"
|
||||
v-if="item.eType === 'mme_ue'"
|
||||
>
|
||||
<div class="card-ue-item">
|
||||
<div>
|
||||
{{ t('views.dashboard.overview.userActivity.type') }}:
|
||||
<span>
|
||||
<DictTag :options="dict.ueEventType" :value="item.type" />
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
IMSI: <span :title="item.data.imsi">{{ item.data.imsi }}</span>
|
||||
</div>
|
||||
<div>
|
||||
{{ t('views.dashboard.overview.userActivity.time') }}:
|
||||
<span :title="item.data.timestamp">
|
||||
{{ parseDateToStr(+item.data.timestamp * 1000) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-ue-w33" v-if="item.type === 'auth-result'">
|
||||
<div>
|
||||
ENB ID: <span>{{ item.data.eNBID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
Cell ID: <span>{{ item.data.cellID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
TAC ID: <span>{{ item.data.tacID }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.type === 'auth-result'">
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span>
|
||||
<DictTag :options="dict.ueAauthCode" :value="item.data.result" />
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="item.type === 'detach'">
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span>{{ t('views.dashboard.overview.userActivity.resultOK') }}</span>
|
||||
</div>
|
||||
<div class="card-ue-w33" v-if="item.type === 'cm-state'">
|
||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||
<span>
|
||||
<DictTag :options="dict.ueEventCmState" :value="item.data.result" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- <div class="card-cdr active">
|
||||
<div class="card-cdr-item">
|
||||
<div>类型: <span>video</span></div>
|
||||
<div>时长: <span>123s</span></div>
|
||||
</div>
|
||||
<div class="card-cdr-item">
|
||||
<div>主叫: <span>12307550064</span></div>
|
||||
<div>被叫: <span>12307550064</span></div>
|
||||
</div>
|
||||
<div>结果: <span>200</span></div>
|
||||
</div>
|
||||
<div class="card-cdr">
|
||||
<div class="card-cdr-item">
|
||||
<div>类型: <span>audio</span></div>
|
||||
<div>时长: <span>123s</span></div>
|
||||
</div>
|
||||
<div class="card-cdr-item">
|
||||
<div>主叫: <span>12307550064</span></div>
|
||||
<div>被叫: <span>12307550064</span></div>
|
||||
</div>
|
||||
<div>结果: <span>200</span></div>
|
||||
</div>
|
||||
<div class="card-ue">
|
||||
<div class="card-ue-item">
|
||||
<div>类型: <span>auth-result</span></div>
|
||||
<div>Time: <span>2023-01-16 07:28:11</span></div>
|
||||
</div>
|
||||
<div>IMSI: <span>4600212141</span></div>
|
||||
<div class="card-ue-auth">
|
||||
<div>GNB ID: <span>31</span></div>
|
||||
<div>Cell ID: <span>17</span></div>
|
||||
<div>Tac ID: <span>98</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-ue">
|
||||
<div class="card-ue-item">
|
||||
<div>类型: <span>cm-state</span></div>
|
||||
<div>Time: <span>2023-01-16 07:28:11</span></div>
|
||||
</div>
|
||||
<div>IMSI: <span>4600212141</span></div>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="card-cdr">
|
||||
{ "recordType":"MOC", // MOC, MTC, MOSM, MTSM
|
||||
"seqNumber":81,
|
||||
"callReference":"Y6ecb69Bj@10.25.0.210",
|
||||
"callerParty":"7112",
|
||||
"calledParty":"7108",
|
||||
"serviceResult":"ok",
|
||||
"seizureTime":1706515269,
|
||||
"answerTime":1706515273,
|
||||
"releaseTime":1706515294,
|
||||
"callDuration":21
|
||||
"callType":"audio" // audio, video
|
||||
"fwdType": "CFB" // CFU,CFB, CFNR, CFNL
|
||||
"fwdParty":"7999",
|
||||
"cause": 200 // 200, 403, 408, 500 .... }
|
||||
|
||||
{"neType":"IMS","neName":"IMS_001","rmUID":"4400HX1IMS001","timestamp":1707124616,
|
||||
"CDR":{"recordType":"MOSM","seqNumber":1,"callReference":"IIocbkeoj@10.10.91.22",
|
||||
"callerParty":"12307551241","calledParty":"+8613800755000","serviceResult":"ok",
|
||||
"seizureTime":1707124616,"answerTime":1707124616,"releaseTime":1707124616,
|
||||
"callDuration":0,"callType":"text","fwdType":"","fwdParty":"","cause":200}}
|
||||
|
||||
https://telnyx.com/resources/sip-response-codes-need-know-2-minutes
|
||||
主叫:callerParty
|
||||
被叫:calledParty
|
||||
时长:callDuration
|
||||
呼叫类型:callType
|
||||
原因:cause
|
||||
信息: 主叫 -> 被叫
|
||||
</div>
|
||||
<div class="card-ue">ue
|
||||
事件类型:auth-result
|
||||
imei
|
||||
GNB ID
|
||||
Cell ID
|
||||
Tac ID
|
||||
authTime
|
||||
|
||||
事件类型:detach
|
||||
imsi
|
||||
detachTime
|
||||
|
||||
事件类型:cm-state
|
||||
imsi
|
||||
changeTime
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@
|
||||
.upfFlowTotal .inner .chart {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-top: 1rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
.upfFlowTotal .inner .chart .data {
|
||||
display: flex;
|
||||
|
||||
@@ -158,3 +158,15 @@ export function neStateParse(neType: string, data: Record<string, any>) {
|
||||
// 请求标记复位
|
||||
neStateRequestMap.value.set(neType, false);
|
||||
}
|
||||
|
||||
/**属性复位 */
|
||||
export function topologyReset() {
|
||||
graphState.data = {
|
||||
combos: [],
|
||||
edges: [],
|
||||
nodes: [],
|
||||
};
|
||||
graphG6.value = null;
|
||||
graphNodeClickID.value = 'UPF';
|
||||
neStateRequestMap.value = new Map();
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils';
|
||||
import { ref } from 'vue';
|
||||
|
||||
/**UPF-流量数据 */
|
||||
export const upfFlowData = ref<{
|
||||
type FDType = {
|
||||
/**时间 */
|
||||
lineXTime: string[];
|
||||
/**上行 N3 */
|
||||
@@ -11,7 +10,10 @@ export const upfFlowData = ref<{
|
||||
lineYDown: number[];
|
||||
/**容量 */
|
||||
cap: number;
|
||||
}>({
|
||||
};
|
||||
|
||||
/**UPF-流量数据 */
|
||||
export const upfFlowData = ref<FDType>({
|
||||
lineXTime: [],
|
||||
lineYUp: [],
|
||||
lineYDown: [],
|
||||
@@ -74,3 +76,32 @@ export function upfTFParse(data: Record<string, string>) {
|
||||
|
||||
/**UPF-总流量数 选中 */
|
||||
export const upfTFActive = ref<number>(0);
|
||||
|
||||
/**属性复位 */
|
||||
export function upfTotalFlowReset() {
|
||||
upfFlowData.value = {
|
||||
lineXTime: [],
|
||||
lineYUp: [],
|
||||
lineYDown: [],
|
||||
cap: 0,
|
||||
};
|
||||
upfTotalFlow.value = [
|
||||
// 0天 当天24小时
|
||||
{
|
||||
up: '0 B',
|
||||
down: '0 B',
|
||||
requestFlag: false,
|
||||
},
|
||||
{
|
||||
up: '0 B',
|
||||
down: '0 B',
|
||||
requestFlag: false,
|
||||
},
|
||||
{
|
||||
up: '0 B',
|
||||
down: '0 B',
|
||||
requestFlag: false,
|
||||
},
|
||||
];
|
||||
upfTFActive.value = 0;
|
||||
}
|
||||
@@ -1,16 +1,9 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
/**UE事件数据 */
|
||||
export const ueEventData = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**UE事件总量 */
|
||||
export const ueEventTotal = ref<number>(0);
|
||||
|
||||
/**UE事件推送id */
|
||||
export const ueEventId = ref<string>('');
|
||||
|
||||
/**ueEvent UE会话事件 数据解析 */
|
||||
export function ueEventParse(item: Record<string, any>) {
|
||||
/**ueEventAMFParse UE会话事件AMF 数据解析 */
|
||||
function ueEventAMFParse(
|
||||
item: Record<string, any>
|
||||
): false | Record<string, any> {
|
||||
let evData: Record<string, any> = item.eventJSON;
|
||||
if (typeof evData === 'string') {
|
||||
try {
|
||||
@@ -21,25 +14,42 @@ export function ueEventParse(item: Record<string, any>) {
|
||||
}
|
||||
|
||||
return {
|
||||
eType: 'ue',
|
||||
eId: `ue_${item.id}_${Date.now()}`,
|
||||
eType: 'amf_ue',
|
||||
eId: `amf_ue_${item.id}_${Date.now()}`,
|
||||
eTime: +item.timestamp,
|
||||
id: item.id,
|
||||
type: item.eventType,
|
||||
data: evData,
|
||||
};
|
||||
}
|
||||
|
||||
/**CDR事件数据 */
|
||||
export const cdrEventData = ref<Record<string, any>[]>([]);
|
||||
/**ueEventMMEParse UE会话事件MME 数据解析 */
|
||||
function ueEventMMEParse(
|
||||
item: Record<string, any>
|
||||
): false | Record<string, any> {
|
||||
let evData: Record<string, any> = item.eventJSON;
|
||||
if (typeof evData === 'string') {
|
||||
try {
|
||||
evData = JSON.parse(evData);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**CDR事件总量 */
|
||||
export const cdrEventTotal = ref<number>(0);
|
||||
return {
|
||||
eType: 'mme_ue',
|
||||
eId: `mme_ue_${item.id}_${Date.now()}`,
|
||||
eTime: +item.timestamp,
|
||||
id: item.id,
|
||||
type: item.eventType,
|
||||
data: evData,
|
||||
};
|
||||
}
|
||||
|
||||
/**CDR事件推送id */
|
||||
export const cdrEventId = ref<string>('');
|
||||
|
||||
/**cdrEvent CDR会话事件 数据解析 */
|
||||
export function cdrEventParse(item: Record<string, any>) {
|
||||
/**cdrEventIMSParse CDR会话事件IMS 数据解析 */
|
||||
function cdrEventIMSParse(
|
||||
item: Record<string, any>
|
||||
): false | Record<string, any> {
|
||||
let evData: Record<string, any> = item.cdrJSON || item.CDR;
|
||||
if (typeof evData === 'string') {
|
||||
try {
|
||||
@@ -56,16 +66,83 @@ export function cdrEventParse(item: Record<string, any>) {
|
||||
}
|
||||
|
||||
return {
|
||||
eType: 'cdr',
|
||||
eId: `cdr_${item.id}_${Date.now()}`,
|
||||
eType: 'ims_cdr',
|
||||
eId: `ims_cdr_${item.id}_${Date.now()}`,
|
||||
eTime: +item.timestamp,
|
||||
id: item.id,
|
||||
data: evData,
|
||||
};
|
||||
}
|
||||
|
||||
/**eventListParse 事件列表解析 */
|
||||
export function eventListParse(
|
||||
type: 'ims_cdr' | 'amf_ue' | 'mme_ue',
|
||||
data: any
|
||||
) {
|
||||
eventTotal.value += data.total;
|
||||
for (const item of data.rows) {
|
||||
let v: false | Record<string, any> = false;
|
||||
if (type === 'ims_cdr') {
|
||||
v = cdrEventIMSParse(item);
|
||||
}
|
||||
if (type === 'amf_ue') {
|
||||
v = ueEventAMFParse(item);
|
||||
}
|
||||
if (type === 'mme_ue') {
|
||||
v = ueEventMMEParse(item);
|
||||
}
|
||||
|
||||
if (v) {
|
||||
eventData.value.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
// 有数据进行排序
|
||||
if (eventData.value.length > 5) {
|
||||
eventData.value.sort((a, b) => b.eTime - a.eTime);
|
||||
}
|
||||
if (eventData.value.length > 0) {
|
||||
eventId.value = eventData.value[0].eId;
|
||||
}
|
||||
}
|
||||
|
||||
/**eventItemParseAndPush 事件项解析并添加 */
|
||||
export async function eventItemParseAndPush(
|
||||
type: 'ims_cdr' | 'amf_ue' | 'mme_ue',
|
||||
item: any
|
||||
) {
|
||||
let v: false | Record<string, any> = false;
|
||||
if (type === 'ims_cdr') {
|
||||
v = cdrEventIMSParse(item);
|
||||
}
|
||||
if (type === 'amf_ue') {
|
||||
v = ueEventAMFParse(item);
|
||||
}
|
||||
if (type === 'mme_ue') {
|
||||
v = ueEventMMEParse(item);
|
||||
}
|
||||
|
||||
if (v) {
|
||||
eventData.value.unshift(v);
|
||||
eventTotal.value += 1;
|
||||
eventId.value = v.eId;
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
if (eventData.value.length > 20) {
|
||||
eventData.value.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**CDR+UE事件数据 */
|
||||
export const eventData = ref<Record<string, any>[]>([]);
|
||||
/**CDR+UE事件总量 */
|
||||
export const eventTotal = ref<number>(0);
|
||||
/**CDR/UE事件推送id */
|
||||
export const eventId = ref<string>('');
|
||||
|
||||
/**属性复位 */
|
||||
export function userActivityReset() {
|
||||
eventData.value = [];
|
||||
eventTotal.value = 0;
|
||||
eventId.value = '';
|
||||
}
|
||||
@@ -2,14 +2,17 @@ import { RESULT_CODE_ERROR } from '@/constants/result-constants';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import { onBeforeUnmount, onMounted } from 'vue';
|
||||
import {
|
||||
ueEventParse,
|
||||
cdrEventParse,
|
||||
eventData,
|
||||
eventTotal,
|
||||
eventId,
|
||||
eventListParse,
|
||||
eventItemParseAndPush,
|
||||
userActivityReset,
|
||||
} from './useUserActivity';
|
||||
import { upfTotalFlow, upfTFParse, upfFlowParse } from './useUPFTotalFlow';
|
||||
import { neStateParse } from './useTopology';
|
||||
import {
|
||||
upfTotalFlow,
|
||||
upfTFParse,
|
||||
upfFlowParse,
|
||||
upfTotalFlowReset,
|
||||
} from './useUPFTotalFlow';
|
||||
import { topologyReset, neStateParse } from './useTopology';
|
||||
import PQueue from 'p-queue';
|
||||
|
||||
/**websocket连接 */
|
||||
@@ -46,34 +49,22 @@ export default function useWS() {
|
||||
|
||||
// 普通信息
|
||||
switch (requestId) {
|
||||
// ueEvent UE会话事件
|
||||
// AMF_UE会话事件
|
||||
case '1010':
|
||||
if (Array.isArray(data.rows)) {
|
||||
eventTotal.value += data.total;
|
||||
for (const item of data.rows) {
|
||||
const v = ueEventParse(item);
|
||||
if (v) {
|
||||
eventData.value.push(v);
|
||||
}
|
||||
}
|
||||
if (eventData.value.length > 0) {
|
||||
eventId.value = eventData.value[0].eId;
|
||||
}
|
||||
eventListParse('amf_ue', data);
|
||||
}
|
||||
break;
|
||||
//cdrEvent CDR会话事件
|
||||
// MME_UE会话事件
|
||||
case '1011':
|
||||
if (Array.isArray(data.rows)) {
|
||||
eventListParse('mme_ue', data);
|
||||
}
|
||||
break;
|
||||
// IMS_CDR会话事件
|
||||
case '1005':
|
||||
if (Array.isArray(data.rows)) {
|
||||
eventTotal.value += data.total;
|
||||
for (const item of data.rows) {
|
||||
const v = cdrEventParse(item);
|
||||
if (v) {
|
||||
eventData.value.push(v);
|
||||
}
|
||||
}
|
||||
if (eventData.value.length > 0) {
|
||||
eventId.value = eventData.value[0].eId;
|
||||
}
|
||||
eventListParse('ims_cdr', data);
|
||||
}
|
||||
break;
|
||||
//UPF-总流量数
|
||||
@@ -108,38 +99,22 @@ export default function useWS() {
|
||||
upfFlowParse(data.data);
|
||||
}
|
||||
break;
|
||||
// ueEvent UE会话事件
|
||||
// AMF_UE会话事件
|
||||
case '1010':
|
||||
if (data.data) {
|
||||
queue.add(async () => {
|
||||
const v = ueEventParse(data.data);
|
||||
if (v) {
|
||||
eventData.value.unshift(v);
|
||||
eventTotal.value += 1;
|
||||
eventId.value = v.eId;
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
if (eventData.value.length > 20) {
|
||||
eventData.value.pop();
|
||||
}
|
||||
}
|
||||
});
|
||||
queue.add(() => eventItemParseAndPush('amf_ue', data.data));
|
||||
}
|
||||
break;
|
||||
// cdrEvent CDR会话事件
|
||||
// MME_UE会话事件
|
||||
case '1011':
|
||||
if (data.data) {
|
||||
queue.add(() => eventItemParseAndPush('mme_ue', data.data));
|
||||
}
|
||||
break;
|
||||
// IMS_CDR会话事件
|
||||
case '1005':
|
||||
if (data.data) {
|
||||
queue.add(async () => {
|
||||
const v = cdrEventParse(data.data);
|
||||
if (v) {
|
||||
eventData.value.unshift(v);
|
||||
eventTotal.value += 1;
|
||||
eventId.value = v.eId;
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
if (eventData.value.length > 20) {
|
||||
eventData.value.pop();
|
||||
}
|
||||
}
|
||||
});
|
||||
queue.add(() => eventItemParseAndPush('ims_cdr', data.data));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -172,27 +147,38 @@ export default function useWS() {
|
||||
});
|
||||
}
|
||||
|
||||
/**ueEvent UE会话事件 发消息*/
|
||||
function ueEventSend() {
|
||||
/**userActivitySend 用户行为事件基础列表数据 发消息*/
|
||||
function userActivitySend() {
|
||||
// AMF_UE会话事件
|
||||
ws.send({
|
||||
requestId: '1010',
|
||||
type: 'ue',
|
||||
type: 'amf_ue',
|
||||
data: {
|
||||
neType: 'AMF',
|
||||
neId: '001',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 5,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**cdrEvent CDR会话事件 发消息*/
|
||||
function cdrEventSend() {
|
||||
// MME_UE会话事件
|
||||
ws.send({
|
||||
requestId: '1011',
|
||||
type: 'mme_ue',
|
||||
data: {
|
||||
neType: 'MME',
|
||||
neId: '001',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
pageNum: 1,
|
||||
pageSize: 5,
|
||||
},
|
||||
});
|
||||
// IMS_CDR会话事件
|
||||
ws.send({
|
||||
requestId: '1005',
|
||||
type: 'cdr',
|
||||
type: 'ims_cdr',
|
||||
data: {
|
||||
neType: 'IMS',
|
||||
neId: '001',
|
||||
@@ -200,7 +186,7 @@ export default function useWS() {
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 5,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -212,10 +198,11 @@ export default function useWS() {
|
||||
/**订阅通道组
|
||||
*
|
||||
* 指标UPF (GroupID:12)
|
||||
* UE会话事件-AMF (GroupID:1010)
|
||||
* CDR会话事件-IMS (GroupID:1005)
|
||||
* AMF_UE会话事件(GroupID:1010)
|
||||
* MME_UE会话事件(GroupID:1011)
|
||||
* IMS_CDR会话事件(GroupID:1005)
|
||||
*/
|
||||
subGroupID: '12,1010,1005',
|
||||
subGroupID: '12,1010,1011,1005',
|
||||
},
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
@@ -225,12 +212,14 @@ export default function useWS() {
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
ws.close();
|
||||
userActivityReset();
|
||||
upfTotalFlowReset();
|
||||
topologyReset();
|
||||
});
|
||||
|
||||
return {
|
||||
wsSend,
|
||||
cdrEventSend,
|
||||
ueEventSend,
|
||||
userActivitySend,
|
||||
upfTFSend,
|
||||
};
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import NeResources from './components/NeResources/index.vue';
|
||||
import UserActivity from './components/UserActivity/index.vue';
|
||||
import AlarnTypeBar from './components/AlarnTypeBar/index.vue';
|
||||
import UPFFlow from './components/UPFFlow/index.vue';
|
||||
import { listSub } from '@/api/neUser/sub';
|
||||
import { listUDMSub } from '@/api/neData/udm_sub';
|
||||
import { listUENumBySMF } from '@/api/neUser/smf';
|
||||
import { listUENumByIMS } from '@/api/neUser/ims';
|
||||
import { listBase5G } from '@/api/neUser/base5G';
|
||||
@@ -29,7 +29,7 @@ import { useRouter } from 'vue-router';
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const { t } = useI18n();
|
||||
const { wsSend, cdrEventSend, ueEventSend, upfTFSend } = useWS();
|
||||
const { wsSend, userActivitySend, upfTFSend } = useWS();
|
||||
|
||||
/**概览状态类型 */
|
||||
type SkimStateType = {
|
||||
@@ -95,7 +95,7 @@ function fnGetNeState() {
|
||||
/**获取概览信息 */
|
||||
async function fnGetSkim() {
|
||||
const resArr = await Promise.allSettled([
|
||||
listSub({
|
||||
listUDMSub({
|
||||
neid: '001',
|
||||
pageNum: 1,
|
||||
pageSize: 1,
|
||||
@@ -155,12 +155,12 @@ async function fnGetSkim() {
|
||||
/**初始数据函数 */
|
||||
function loadData() {
|
||||
fnGetNeState(); // 获取网元状态
|
||||
cdrEventSend();
|
||||
ueEventSend();
|
||||
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) {
|
||||
@@ -172,6 +172,7 @@ function loadData() {
|
||||
}
|
||||
}, 10_000);
|
||||
|
||||
clearInterval(interval5s.value);
|
||||
interval5s.value = setInterval(() => {
|
||||
fnGetSkim(); // 获取概览信息
|
||||
fnGetNeState(); // 获取网元状态
|
||||
@@ -191,7 +192,9 @@ onMounted(() => {
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(interval10s.value);
|
||||
interval10s.value = null;
|
||||
clearInterval(interval5s.value);
|
||||
interval5s.value = null;
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,785 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, onBeforeUnmount, ref } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { Modal, message } from 'ant-design-vue/lib';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import {
|
||||
RESULT_CODE_ERROR,
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import {
|
||||
delSMFDataCDR,
|
||||
exportSMFDataCDR,
|
||||
listSMFDataCDR,
|
||||
} from '@/api/neData/smf';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import PQueue from 'p-queue';
|
||||
import saveAs from 'file-saver';
|
||||
const { t } = useI18n();
|
||||
const ws = new WS();
|
||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: 'SMF',
|
||||
neId: '001',
|
||||
subscriberID: '',
|
||||
sortField: 'timestamp',
|
||||
sortOrder: 'desc',
|
||||
/**开始时间 */
|
||||
startTime: '',
|
||||
/**结束时间 */
|
||||
endTime: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
queryParams = Object.assign(queryParams, {
|
||||
subscriberID: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfChargingID'), // 计费ID
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.chargingID;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfSubscriptionIDType'), // 订阅 ID 类型
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.subscriberIdentifier?.subscriptionIDType;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfSubscriptionIDData'), // 订阅 ID 数据
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.subscriberIdentifier?.subscriptionIDData;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfDataVolumeUplink'), // 数据量上行链路
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
const listOfMultipleUnitUsage = cdrJSON.listOfMultipleUnitUsage;
|
||||
if (
|
||||
!Array.isArray(listOfMultipleUnitUsage) ||
|
||||
listOfMultipleUnitUsage.length < 1
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
const usedUnitContainer = listOfMultipleUnitUsage[0].usedUnitContainer;
|
||||
if (!Array.isArray(usedUnitContainer) || usedUnitContainer.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
return usedUnitContainer[0].dataVolumeUplink;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfDataVolumeDownlink'), // 数据量下行链路
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 180,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
const listOfMultipleUnitUsage = cdrJSON.listOfMultipleUnitUsage;
|
||||
if (
|
||||
!Array.isArray(listOfMultipleUnitUsage) ||
|
||||
listOfMultipleUnitUsage.length < 1
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
const usedUnitContainer = listOfMultipleUnitUsage[0].usedUnitContainer;
|
||||
if (!Array.isArray(usedUnitContainer) || usedUnitContainer.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
return usedUnitContainer[0].dataVolumeDownlink;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfDataTotalVolume'), // 数据总量
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
const listOfMultipleUnitUsage = cdrJSON.listOfMultipleUnitUsage;
|
||||
if (
|
||||
!Array.isArray(listOfMultipleUnitUsage) ||
|
||||
listOfMultipleUnitUsage.length < 1
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
const usedUnitContainer = listOfMultipleUnitUsage[0].usedUnitContainer;
|
||||
if (!Array.isArray(usedUnitContainer) || usedUnitContainer.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
return usedUnitContainer[0].dataTotalVolume;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfDuration'), // 持续时间
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.duration;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.smfInvocationTime'), // 调用时间
|
||||
dataIndex: 'cdrJSON',
|
||||
align: 'left',
|
||||
width: 250,
|
||||
customRender(opt) {
|
||||
const cdrJSON = opt.value;
|
||||
return cdrJSON.invocationTimestamp;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'id',
|
||||
align: 'left',
|
||||
},
|
||||
];
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
current: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
/**默认的每页条数 */
|
||||
defaultPageSize: 20,
|
||||
/**指定每页可以显示多少条 */
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
/**只有一页时是否隐藏分页器 */
|
||||
hideOnSinglePage: false,
|
||||
/**是否可以快速跳转至某页 */
|
||||
showQuickJumper: true,
|
||||
/**是否可以改变 pageSize */
|
||||
showSizeChanger: true,
|
||||
/**数据总数 */
|
||||
total: 0,
|
||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
||||
onChange: (page: number, pageSize: number) => {
|
||||
tablePagination.current = page;
|
||||
tablePagination.pageSize = pageSize;
|
||||
queryParams.pageNum = page;
|
||||
queryParams.pageSize = pageSize;
|
||||
fnGetList();
|
||||
},
|
||||
});
|
||||
|
||||
/**表格紧凑型变更操作 */
|
||||
function fnTableSize({ key }: MenuInfo) {
|
||||
tableState.size = key as SizeType;
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
/**最大ID值 */
|
||||
maxId: number;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
confirmLoading: false,
|
||||
maxId: 0,
|
||||
});
|
||||
|
||||
/**
|
||||
* 记录删除
|
||||
* @param id 编号
|
||||
*/
|
||||
function fnRecordDelete(id: string) {
|
||||
if (!id || modalState.confirmLoading) return;
|
||||
let msg = id;
|
||||
if (id === '0') {
|
||||
msg = `${id}... ${tableState.selectedRowKeys.length}`;
|
||||
id = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.delTip', { msg }),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
delSMFDataCDR(id)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
fnGetList(1);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**查询列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.startTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listSMFDataCDR(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
if (tableState.selectedRowKeys.length > 0) {
|
||||
tableState.selectedRowKeys = [];
|
||||
}
|
||||
tablePagination.total = res.total;
|
||||
// 遍历处理cdr字符串数据
|
||||
tableState.data = res.rows.map(item => {
|
||||
let cdrJSON = item.cdrJSON;
|
||||
if (!cdrJSON) {
|
||||
Reflect.set(item, 'cdrJSON', {});
|
||||
}
|
||||
|
||||
try {
|
||||
cdrJSON = JSON.parse(cdrJSON);
|
||||
Reflect.set(item, 'cdrJSON', cdrJSON);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Reflect.set(item, 'cdrJSON', {});
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
// 取最大值ID用作实时累加
|
||||
if (res.total > 0) {
|
||||
modalState.maxId = Number(res.rows[0].id);
|
||||
}
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
if (modalState.confirmLoading) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
exportSMFDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `smf_cdr_event_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
/**
|
||||
* 实时数据
|
||||
*/
|
||||
function fnRealTime() {
|
||||
realTimeData.value = !realTimeData.value;
|
||||
if (realTimeData.value) {
|
||||
// 建立链接
|
||||
const options: OptionsType = {
|
||||
url: '/ws',
|
||||
params: {
|
||||
/**订阅通道组
|
||||
*
|
||||
* CDR会话事件-SMF (GroupID:1006)
|
||||
*/
|
||||
subGroupID: '1006',
|
||||
},
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
};
|
||||
ws.connect(options);
|
||||
} else {
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**接收数据后回调 */
|
||||
function wsError(ev: any) {
|
||||
// 接收数据后回调
|
||||
console.error(ev);
|
||||
}
|
||||
|
||||
/**接收数据后回调 */
|
||||
function wsMessage(res: Record<string, any>) {
|
||||
const { code, requestId, data } = res;
|
||||
if (code === RESULT_CODE_ERROR) {
|
||||
console.warn(res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// 订阅组信息
|
||||
if (!data?.groupId) {
|
||||
return;
|
||||
}
|
||||
// cdrEvent CDR会话事件
|
||||
if (data.groupId === '1006') {
|
||||
const cdrEvent = data.data;
|
||||
queue.add(async () => {
|
||||
modalState.maxId += 1;
|
||||
tableState.data.unshift({
|
||||
id: modalState.maxId,
|
||||
neType: cdrEvent.neType,
|
||||
neName: cdrEvent.neName,
|
||||
rmUID: cdrEvent.rmUID,
|
||||
timestamp: cdrEvent.timestamp,
|
||||
cdrJSON: cdrEvent.CDR,
|
||||
});
|
||||
tablePagination.total += 1;
|
||||
if (tableState.data.length > 100) {
|
||||
tableState.data.pop();
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (ws.state() !== -1) {
|
||||
ws.close();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.smfSubscriptionIDData')"
|
||||
name="calledParty "
|
||||
>
|
||||
<a-input
|
||||
v-model:value="queryParams.subscriberID"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="40"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.dashboard.cdr.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-popconfirm
|
||||
placement="bottomLeft"
|
||||
:title="
|
||||
!realTimeData
|
||||
? t('views.dashboard.cdr.realTimeDataStart')
|
||||
: t('views.dashboard.cdr.realTimeDataStop')
|
||||
"
|
||||
ok-text="Yes"
|
||||
cancel-text="No"
|
||||
@confirm="fnRealTime()"
|
||||
>
|
||||
<a-button type="primary" :danger="realTimeData">
|
||||
<template #icon><FundOutlined /> </template>
|
||||
{{
|
||||
!realTimeData
|
||||
? t('views.dashboard.cdr.realTimeDataStart')
|
||||
: t('views.dashboard.cdr.realTimeDataStop')
|
||||
}}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
<a-button type="text">
|
||||
<template #icon><ColumnHeightOutlined /></template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="middle">
|
||||
{{ t('common.size.middle') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="small">
|
||||
{{ t('common.size.small') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 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 === 'id'">
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.deleteText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.id)"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
<template #expandedRowRender="{ record }">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="8" :md="12" :xs="24" :offset="2">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.cdr.cdrInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||
<span>{{ record.neName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||
<span>{{ record.rmUID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.cdr.time') }}: </span>
|
||||
<span>{{ parseDateToStr(+record.timestamp * 1000) }}</span>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.dashboard.cdr.rowInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>Record Network Function ID: </span>
|
||||
<span>{{ record.cdrJSON.recordingNetworkFunctionID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Record Type: </span>
|
||||
<span>{{ record.cdrJSON.recordType }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Record Opening Time: </span>
|
||||
<span>{{ record.cdrJSON.recordOpeningTime }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Charging ID: </span>
|
||||
<span>{{ record.cdrJSON.chargingID }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Duration: </span>
|
||||
<span>{{ record.cdrJSON.duration }}</span>
|
||||
</div>
|
||||
<a-divider orientation="left"> Subscriber Identifier </a-divider>
|
||||
<div>
|
||||
<span>Subscription ID Type: </span>
|
||||
<span>
|
||||
{{ record.cdrJSON.subscriberIdentifier?.subscriptionIDType }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Subscription ID Data: </span>
|
||||
<span>
|
||||
{{ record.cdrJSON.subscriberIdentifier?.subscriptionIDData }}
|
||||
</span>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-divider orientation="left">
|
||||
List Of Multiple Unit Usage
|
||||
</a-divider>
|
||||
<div v-for="u in record.cdrJSON.listOfMultipleUnitUsage">
|
||||
<div>RatingGroup: {{ u.ratingGroup }}</div>
|
||||
<div v-for="udata in u.usedUnitContainer">
|
||||
<div>
|
||||
<span>Data Total Volume: </span>
|
||||
<span>{{ udata.dataTotalVolume }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Data Volume Downlink: </span>
|
||||
<span>{{ udata.dataVolumeDownlink }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Data Volume Uplink: </span>
|
||||
<span>{{ udata.dataVolumeUplink }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Time: </span>
|
||||
<span>{{ udata.time }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
PDU Session Charging Information
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>User Identifier: </span>
|
||||
<span>{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.userIdentifier
|
||||
}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>SSC Mode: </span>
|
||||
<span>{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.sSCMode
|
||||
}}</span>
|
||||
|
||||
<span>RAT Type: </span>
|
||||
<span>{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.rATType
|
||||
}}</span>
|
||||
|
||||
<span>DNN ID: </span>
|
||||
<span>
|
||||
{{ record.cdrJSON.pDUSessionChargingInformation?.dNNID }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>PDU Type: </span>
|
||||
<span>
|
||||
{{ record.cdrJSON.pDUSessionChargingInformation?.pDUType }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>PDU IPv4 Address: </span>
|
||||
<span>
|
||||
{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.pDUAddress
|
||||
?.pDUIPv4Address
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>PDU IPv6 Addres Swith Prefix: </span>
|
||||
<span>
|
||||
{{
|
||||
record.cdrJSON.pDUSessionChargingInformation?.pDUAddress
|
||||
?.pDUIPv6AddresswithPrefix
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -16,12 +16,14 @@ import {
|
||||
exportAll,
|
||||
} from '@/api/faultManage/actAlarm';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import saveAs from 'file-saver';
|
||||
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
||||
import { writeSheet } from '@/utils/execl-utils';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { readLoalXlsx } from '@/utils/execl-utils';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { getDict } = useDictStore();
|
||||
const { t, currentLocale } = useI18n();
|
||||
|
||||
@@ -741,6 +743,8 @@ onMounted(() => {
|
||||
dict.activeAlarmSeverity = resArr[3].value;
|
||||
}
|
||||
});
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore().fnNelist();
|
||||
fnGetList();
|
||||
});
|
||||
</script>
|
||||
@@ -758,9 +762,14 @@ onMounted(() => {
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.neType')"
|
||||
name="ne_type"
|
||||
name="neType"
|
||||
>
|
||||
<a-input v-model:value="queryParams.neType" allow-clear></a-input>
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="neInfoStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
@@ -1036,15 +1045,17 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 帮助文档 -->
|
||||
<a-modal
|
||||
width="100%"
|
||||
wrap-class-name="full-modal"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:forceFullscreen="true"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.helpShowView"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
:footer="null"
|
||||
:body-style="{ padding: '0px' }"
|
||||
:footer="false"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-table
|
||||
@@ -1055,14 +1066,15 @@ onMounted(() => {
|
||||
:data-source="alarmTableState.data"
|
||||
:size="alarmTableState.size"
|
||||
:pagination="false"
|
||||
:scroll="{ x: 1700, y: '82vh' }"
|
||||
:scroll="{ x: 1700, y: '88vh' }"
|
||||
>
|
||||
</a-table>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 详情框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:body-style="{ height: '520px', overflowY: 'scroll' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -1265,11 +1277,12 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 显示过滤框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByShowSet"
|
||||
@@ -1286,11 +1299,12 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.neType')"
|
||||
name="neType"
|
||||
>
|
||||
<a-input
|
||||
<a-auto-complete
|
||||
v-model:value="modalState.showSetFrom.ne_type"
|
||||
:options="neInfoStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1363,11 +1377,12 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
|
||||
<!-- 个性化设置框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByMyselfSet"
|
||||
@@ -1461,7 +1476,7 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
Loaded 100 of 195 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user